~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/include/asm/div64.h

Version: ~ [ linux-5.15-rc6 ] ~ [ linux-5.14.14 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.75 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.155 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.213 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.252 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.287 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.289 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* SPDX-License-Identifier: GPL-2.0 */
  2 #ifndef _ASM_X86_DIV64_H
  3 #define _ASM_X86_DIV64_H
  4 
  5 #ifdef CONFIG_X86_32
  6 
  7 #include <linux/types.h>
  8 #include <linux/log2.h>
  9 
 10 /*
 11  * do_div() is NOT a C function. It wants to return
 12  * two values (the quotient and the remainder), but
 13  * since that doesn't work very well in C, what it
 14  * does is:
 15  *
 16  * - modifies the 64-bit dividend _in_place_
 17  * - returns the 32-bit remainder
 18  *
 19  * This ends up being the most efficient "calling
 20  * convention" on x86.
 21  */
 22 #define do_div(n, base)                                         \
 23 ({                                                              \
 24         unsigned long __upper, __low, __high, __mod, __base;    \
 25         __base = (base);                                        \
 26         if (__builtin_constant_p(__base) && is_power_of_2(__base)) { \
 27                 __mod = n & (__base - 1);                       \
 28                 n >>= ilog2(__base);                            \
 29         } else {                                                \
 30                 asm("" : "=a" (__low), "=d" (__high) : "A" (n));\
 31                 __upper = __high;                               \
 32                 if (__high) {                                   \
 33                         __upper = __high % (__base);            \
 34                         __high = __high / (__base);             \
 35                 }                                               \
 36                 asm("divl %2" : "=a" (__low), "=d" (__mod)      \
 37                         : "rm" (__base), "" (__low), "1" (__upper));   \
 38                 asm("" : "=A" (n) : "a" (__low), "d" (__high)); \
 39         }                                                       \
 40         __mod;                                                  \
 41 })
 42 
 43 static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
 44 {
 45         union {
 46                 u64 v64;
 47                 u32 v32[2];
 48         } d = { dividend };
 49         u32 upper;
 50 
 51         upper = d.v32[1];
 52         d.v32[1] = 0;
 53         if (upper >= divisor) {
 54                 d.v32[1] = upper / divisor;
 55                 upper %= divisor;
 56         }
 57         asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) :
 58                 "rm" (divisor), "" (d.v32[0]), "1" (upper));
 59         return d.v64;
 60 }
 61 #define div_u64_rem     div_u64_rem
 62 
 63 static inline u64 mul_u32_u32(u32 a, u32 b)
 64 {
 65         u32 high, low;
 66 
 67         asm ("mull %[b]" : "=a" (low), "=d" (high)
 68                          : [a] "a" (a), [b] "rm" (b) );
 69 
 70         return low | ((u64)high) << 32;
 71 }
 72 #define mul_u32_u32 mul_u32_u32
 73 
 74 #else
 75 # include <asm-generic/div64.h>
 76 #endif /* CONFIG_X86_32 */
 77 
 78 #endif /* _ASM_X86_DIV64_H */
 79 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp