Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions lib/ia32/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,115 @@ DivU64x32 (
return Dividend;
#endif
}

// gcc on IA32 emits these calls on i64 division, as it expects linking with libgcc
// NB: The assembly code was generated by Claude.
#if defined(__GNUC__) && defined(__MINGW32__)
__attribute__ ((__used__))
long long
__divmoddi4(
long long dividend,
long long divisor,
long long *remainder
)
{
long long quot, rem;
int cnt;

__asm__ (
// eax/edx = |dividend| (becomes quotient), ecx/ebx = |divisor|
"movl %[n], %%eax \n\t"
"movl %H[n], %%edx \n\t"
"movl %[d], %%ecx \n\t"
"movl %H[d], %%ebx \n\t"

"testl %%edx, %%edx \n\t"
"jns 1f \n\t"
"negl %%edx \n\t"
"negl %%eax \n\t"
"sbbl $0, %%edx \n\t"
"1: \n\t"
"testl %%ebx, %%ebx \n\t"
"jns 2f \n\t"
"negl %%ebx \n\t"
"negl %%ecx \n\t"
"sbbl $0, %%ebx \n\t"
"2: \n\t"

// edi:esi = running remainder = 0
"xorl %%esi, %%esi \n\t"
"xorl %%edi, %%edi \n\t"
"movl $64, %[c] \n\t"

// shift-subtract loop
"3: \n\t"
"shll $1, %%eax \n\t"
"rcll $1, %%edx \n\t"
"rcll $1, %%esi \n\t"
"rcll $1, %%edi \n\t"
"cmpl %%ebx, %%edi \n\t" // remainder >= divisor?
"jb 4f \n\t"
"ja 5f \n\t"
"cmpl %%ecx, %%esi \n\t"
"jb 4f \n\t"
"5: \n\t"
"subl %%ecx, %%esi \n\t"
"sbbl %%ebx, %%edi \n\t"
"orl $1, %%eax \n\t"
"4: \n\t"
"decl %[c] \n\t"
"jnz 3b \n\t"

// sign fixup: quotient negative if signs differ,
// remainder takes the sign of the dividend
"movl %H[n], %%ebx \n\t"
"movl %H[d], %%ecx \n\t"
"xorl %%ebx, %%ecx \n\t"
"jns 6f \n\t"
"negl %%edx \n\t"
"negl %%eax \n\t"
"sbbl $0, %%edx \n\t"
"6: \n\t"
"testl %%ebx, %%ebx \n\t"
"jns 7f \n\t"
"negl %%edi \n\t"
"negl %%esi \n\t"
"sbbl $0, %%edi \n\t"
"7: \n\t"

// store results
"movl %%eax, %[q] \n\t"
"movl %%edx, %H[q] \n\t"
"movl %%esi, %[r] \n\t"
"movl %%edi, %H[r] \n\t"
: [q] "=&m" (quot), [r] "=&m" (rem), [c] "=&m" (cnt)
: [n] "m" (dividend), [d] "m" (divisor)
: "eax", "ebx", "ecx", "edx", "esi", "edi", "cc"
);

if (remainder)
*remainder = rem;
return quot;
}

__attribute__ ((__used__))
long long
__divdi3(
long long dividend,
long long divisor
)
{
return __divmoddi4(dividend, divisor, 0);
}

long long
__moddi3(
long long dividend,
long long divisor
)
{
long long rem;
__divmoddi4(dividend, divisor, &rem);
return rem;
}
#endif
Loading