Rewrote the x86 64-bit division stubs, which now actually work.
This commit is contained in:
parent
a2dd8be7aa
commit
de70b1804d
|
@ -31,76 +31,57 @@ extern "C" void __cxa_pure_virtual()
|
||||||
|
|
||||||
#ifdef PLATFORM_X86
|
#ifdef PLATFORM_X86
|
||||||
|
|
||||||
// TODO: These two stubs are buggy!
|
extern "C" uint64_t __udivdi3(uint64_t a, uint64_t b)
|
||||||
|
|
||||||
// Divides two 64-bit integers in O(logN). I think.
|
|
||||||
extern "C" uint64_t __udivdi3(uint64_t A, uint64_t B)
|
|
||||||
{
|
{
|
||||||
uint64_t ACC = 0;
|
uint64_t result = 0;
|
||||||
uint64_t R = 0;
|
uint64_t power = 1;
|
||||||
uint64_t PWR = 1;
|
uint64_t remainder = a;
|
||||||
uint64_t EXP = B;
|
uint64_t divisor = b;
|
||||||
|
while ( divisor * 2 <= remainder )
|
||||||
while ( EXP <= A - ACC )
|
|
||||||
{
|
{
|
||||||
R += PWR;
|
power *= 2;
|
||||||
ACC += EXP;
|
divisor *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
if ( 2 * EXP <= A - ACC )
|
while ( divisor <= remainder )
|
||||||
|
{
|
||||||
|
remainder -= divisor;
|
||||||
|
result += power;
|
||||||
|
while ( power > 1 && remainder < divisor )
|
||||||
{
|
{
|
||||||
PWR++;
|
divisor /= 2;
|
||||||
EXP *= 2;
|
power /= 2;
|
||||||
}
|
|
||||||
else if ( A - ACC < B )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while ( A - ACC < EXP )
|
|
||||||
{
|
|
||||||
PWR--;
|
|
||||||
EXP /= 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return R;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mods two 64-bit integers in O(logN). I think.
|
extern "C" uint64_t __umoddi3(uint64_t a, uint64_t b)
|
||||||
extern "C" uint64_t __umoddi3(uint64_t A, uint64_t B)
|
|
||||||
{
|
{
|
||||||
uint64_t ACC = 0;
|
uint64_t result = 0;
|
||||||
uint64_t R = 0;
|
uint64_t power = 1;
|
||||||
uint64_t PWR = 1;
|
uint64_t remainder = a;
|
||||||
uint64_t EXP = B;
|
uint64_t divisor = b;
|
||||||
|
while ( divisor * 2 <= remainder )
|
||||||
while ( EXP <= A - ACC )
|
|
||||||
{
|
{
|
||||||
R += PWR;
|
power *= 2;
|
||||||
ACC += EXP;
|
divisor *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
if ( 2 * EXP <= A - ACC )
|
while ( divisor <= remainder )
|
||||||
|
{
|
||||||
|
remainder -= divisor;
|
||||||
|
result += power;
|
||||||
|
while ( power > 1 && remainder < divisor )
|
||||||
{
|
{
|
||||||
PWR++;
|
divisor /= 2;
|
||||||
EXP *= 2;
|
power /= 2;
|
||||||
}
|
|
||||||
else if ( A - ACC < B )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while ( A - ACC < EXP )
|
|
||||||
{
|
|
||||||
PWR--;
|
|
||||||
EXP /= 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return A - ACC;
|
return remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue