File: /Users/paulross/dev/linux/linux-3.13/arch/x86/include/asm/div64.h

Green shading in the line number column means the source is part of the translation unit, red means it is conditionally excluded. Highlighted line numbers link to the translation unit page. Highlighted macros link to the macro page.

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