VirtualBox

Changeset 1903 in vbox for trunk/include/iprt/asm.h


Ignore:
Timestamp:
Apr 3, 2007 9:04:57 PM (18 years ago)
Author:
vboxsync
Message:

use pure assembler for ASMMultU64ByU32DivByU32 to prevent spurious libgcc references

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/asm.h

    r1888 r1903  
    28732873 * Multiple a 64-bit by a 32-bit integer and divide the result by a 32-bit integer
    28742874 * using a 96 bit intermediate result.
     2875 * @note    Don't use 64-bit C arithmetic here since some gcc compilers generate references to
     2876 *          __udivdi3 and __umoddi3 even if this inline function is not used.
    28752877 *
    28762878 * @returns (u64A * u32B) / u32C.
     
    28842886DECLINLINE(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C)
    28852887{
    2886 # if RT_INLINE_ASM_GNU_STYLE && defined(__AMD64__)
     2888# if RT_INLINE_ASM_GNU_STYLE
     2889#  ifdef __AMD64__
    28872890    uint64_t u64Result, u64Spill;
    28882891    __asm__ __volatile__("mulq %2\n\t"
     
    28952898                           "1" (0));
    28962899    return u64Result;
     2900#  else
     2901    uint32_t dummy;
     2902    uint64_t u64D;
     2903    __asm__ __volatile__("mull %%ecx       \n\t" /* eax = u64Lo.lo = (u64A.lo * u32B).lo
     2904                                                    edx = u64Lo.hi = (u64A.lo * u32B).hi */
     2905                         "xchg %%eax,%%esi \n\t" /* esi = u64Lo.lo
     2906                                                    eax = u64A.hi */
     2907                         "xchg %%edx,%%edi \n\t" /* edi = u64Low.hi
     2908                                                    edx = u32C */
     2909                         "xchg %%edx,%%ecx \n\t" /* ecx = u32C
     2910                                                    edx = u32B */
     2911                         "mull %%edx       \n\t" /* eax = u64Hi.lo = (u64A.hi * u32B).lo
     2912                                                    edx = u64Hi.hi = (u64A.hi * u32B).hi */
     2913                         "addl %%edi,%%eax \n\t" /* u64Hi.lo += u64Lo.hi */
     2914                         "adcl $0,%%edx    \n\t" /* u64Hi.hi += carry */
     2915                         "divl %%ecx       \n\t" /* eax = u64Hi / u32C
     2916                                                    edx = u64Hi % u32C */
     2917                         "movl %%eax,%%edi \n\t" /* edi = u64D.hi = u64Hi / u32C */
     2918                         "movl %%esi,%%eax \n\t" /* eax = u64Lo.lo */
     2919                         "divl %%ecx       \n\t" /* u64D.lo */
     2920                         "movl %%edi,%%edx \n\t" /* u64D.hi */
     2921                         : "=A"(u64D),
     2922                           "=S"(dummy), "=D"(dummy)
     2923                         : "a"((uint32_t)u64A),
     2924                           "S"((uint32_t)(u64A >> 32)),
     2925                           "c"(u32B),
     2926                           "D"(u32C));
     2927    return u64D;
     2928#  endif
    28972929# else
    28982930    RTUINT64U   u;
    2899     uint64_t    u64Low = (uint64_t)(u64A & 0xffffffff) * u32B;
    2900     uint64_t    u64Hi  = (uint64_t)(u64A >> 32)        * u32B;
    2901     u64Hi  += (u64Low >> 32);
     2931    uint64_t    u64Lo = (uint64_t)(u64A & 0xffffffff) * u32B;
     2932    uint64_t    u64Hi = (uint64_t)(u64A >> 32)        * u32B;
     2933    u64Hi  += (u64Lo >> 32);
    29022934    u.s.Hi = (uint32_t)(u64Hi / u32C);
    2903     u.s.Lo = (uint32_t)((((u64Hi % u32C) << 32) + (u64Low & 0xffffffff)) / u32C);
     2935    u.s.Lo = (uint32_t)((((u64Hi % u32C) << 32) + (u64Lo & 0xffffffff)) / u32C);
    29042936    return u.u;
    29052937# endif
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette