- Timestamp:
- Apr 3, 2007 9:04:57 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/asm.h
r1888 r1903 2873 2873 * Multiple a 64-bit by a 32-bit integer and divide the result by a 32-bit integer 2874 2874 * 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. 2875 2877 * 2876 2878 * @returns (u64A * u32B) / u32C. … … 2884 2886 DECLINLINE(uint64_t) ASMMultU64ByU32DivByU32(uint64_t u64A, uint32_t u32B, uint32_t u32C) 2885 2887 { 2886 # if RT_INLINE_ASM_GNU_STYLE && defined(__AMD64__) 2888 # if RT_INLINE_ASM_GNU_STYLE 2889 # ifdef __AMD64__ 2887 2890 uint64_t u64Result, u64Spill; 2888 2891 __asm__ __volatile__("mulq %2\n\t" … … 2895 2898 "1" (0)); 2896 2899 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 2897 2929 # else 2898 2930 RTUINT64U u; 2899 uint64_t u64Lo w= (uint64_t)(u64A & 0xffffffff) * u32B;2900 uint64_t u64Hi 2901 u64Hi += (u64Lo w>> 32);2931 uint64_t u64Lo = (uint64_t)(u64A & 0xffffffff) * u32B; 2932 uint64_t u64Hi = (uint64_t)(u64A >> 32) * u32B; 2933 u64Hi += (u64Lo >> 32); 2902 2934 u.s.Hi = (uint32_t)(u64Hi / u32C); 2903 u.s.Lo = (uint32_t)((((u64Hi % u32C) << 32) + (u64Lo w& 0xffffffff)) / u32C);2935 u.s.Lo = (uint32_t)((((u64Hi % u32C) << 32) + (u64Lo & 0xffffffff)) / u32C); 2904 2936 return u.u; 2905 2937 # endif
Note:
See TracChangeset
for help on using the changeset viewer.