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,9 +612,29 @@ let {{
//If we overshot, do nothing. This lets us unrool division loops a //If we overshot, do nothing. This lets us unrool division loops a
//little. //little.
if (remaining) { if (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 //Shift in bits from the low order portion of the dividend
while (dividend < divisor && remaining) { while (dividend < divisor && remaining) {
dividend = (dividend << 1) | bits(SrcReg1, remaining - 1); dividend = (dividend << 1) |
bits(SrcReg1, remaining - 1);
quotient <<= 1; quotient <<= 1;
remaining--; remaining--;
} }
@ -622,6 +642,7 @@ let {{
//Do the division. //Do the division.
divide(dividend, divisor, quotient, remainder); divide(dividend, divisor, quotient, remainder);
} }
}
//Keep track of how many bits there are still to pull in. //Keep track of how many bits there are still to pull in.
DestReg = merge(DestReg, remaining, dataSize); DestReg = merge(DestReg, remaining, dataSize);
//Record the final results //Record the final results