174 Integer Optimizations Chapter 8
25112 Rev. 3.06 September 2005
Software Optimization Guide for AMD64 Processors
div ebx ; EAX = quotient_lo
mov edx, ecx ; EDX = quotient_hi (quotient in EDX:EAX)
jmp make_sign ; Make quotient signed.
big_divisor:
sub esp, 12 ; Create three local variables.
mov [esp], eax ; dividend_lo
mov [esp+4], ebx ; divisor_lo
mov [esp+8], edx ; dividend_hi
mov edi, ecx ; Save divisor_hi.
shr edx, 1 ; Shift both
rcr eax, 1 ; divisor and
ror edi, 1 ; and dividend
rcr ebx, 1 ; right by 1 bit.
bsr ecx, ecx ; ECX = number of remaining shifts
shrd ebx, edi, cl ; Scale down divisor and
shrd eax, edx, cl ; dividend such that divisor is
shr edx, cl ; less than 2^32 (that is, fits in EBX).
rol edi, 1 ; Restore original divisor_hi.
div ebx ; Compute quotient.
mov ebx, [esp] ; dividend_lo
mov ecx, eax ; Save quotient.
imul edi, eax ; quotient * divisor high word (low only)
mul DWORD PTR [esp+4] ; quotient * divisor low word
add edx, edi ; EDX:EAX = quotient * divisor
sub ebx, eax ; dividend_lo - (quot.*divisor)_lo
mov eax, ecx ; Get quotient.
mov ecx, [esp+8] ; dividend_hi
sbb ecx, edx ; Subtract (divisor * quot.) from dividend
sbb eax, 0 ; Adjust quotient if remainder is negative.
xor edx, edx ; Clear high word of quotient.
add esp, 12 ; Remove local variables.
make_sign:
xor eax, esi ; If (quotient < 0),
xor edx, esi ; compute 1's complement of result.
sub eax, esi ; If (quotient < 0),
sbb edx, esi ; compute 2's complement of result.
pop edi ; Restore EDI as per calling convention.
pop esi ; Restore ESI as per calling convention.
pop ebx ; Restore EBX as per calling convention.
ret ; Done, return to caller.
_lldiv ENDP
64-Bit Unsigned Remainder Computation
; _ullrem divides two unsigned 64-bit integers and returns the remainder.
;
; In: [ESP+8]:[ESP+4] = dividend
; [ESP+16]:[ESP+12] = divisor
;
; Out: EDX:EAX = remainder of division