X86: Finally fix a division corner case.

When doing an unsigned 64 bit division with a divisor that has its most
significant bit set, the division code would spill a bit off of the end of a
uint64_t trying to shift the dividend into position. This change adds code
that handles that case specially by purposefully letting it spill and then
going ahead assuming there was a 65th one bit.
This commit is contained in:
Gabe Black 2010-05-02 00:39:29 -07:00
parent 90820ddf02
commit 51a3d65e25

View file

@ -612,15 +612,36 @@ let {{
//If we overshot, do nothing. This lets us unrool division loops a
//little.
if (remaining) {
//Shift in bits from the low order portion of the dividend
while(dividend < divisor && remaining) {
dividend = (dividend << 1) | bits(SrcReg1, remaining - 1);
quotient <<= 1;
remaining--;
if (divisor & (ULL(1) << 63)) {
while (remaining && !(dividend & (ULL(1) << 63))) {
dividend = (dividend << 1) |
bits(SrcReg1, remaining - 1);
quotient <<= 1;
remaining--;
}
if (dividend & (ULL(1) << 63)) {
if (dividend < divisor && remaining) {
dividend = (dividend << 1) |
bits(SrcReg1, remaining - 1);
quotient <<= 1;
remaining--;
}
quotient++;
dividend -= divisor;
}
remainder = dividend;
} else {
//Shift in bits from the low order portion of the dividend
while (dividend < divisor && remaining) {
dividend = (dividend << 1) |
bits(SrcReg1, remaining - 1);
quotient <<= 1;
remaining--;
}
remainder = dividend;
//Do the division.
divide(dividend, divisor, quotient, remainder);
}
remainder = dividend;
//Do the division.
divide(dividend, divisor, quotient, remainder);
}
//Keep track of how many bits there are still to pull in.
DestReg = merge(DestReg, remaining, dataSize);