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:
parent
90820ddf02
commit
51a3d65e25
1 changed files with 29 additions and 8 deletions
|
@ -612,9 +612,29 @@ let {{
|
|||
//If we overshot, do nothing. This lets us unrool division loops a
|
||||
//little.
|
||||
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
|
||||
while(dividend < divisor && remaining) {
|
||||
dividend = (dividend << 1) | bits(SrcReg1, remaining - 1);
|
||||
while (dividend < divisor && remaining) {
|
||||
dividend = (dividend << 1) |
|
||||
bits(SrcReg1, remaining - 1);
|
||||
quotient <<= 1;
|
||||
remaining--;
|
||||
}
|
||||
|
@ -622,6 +642,7 @@ let {{
|
|||
//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);
|
||||
//Record the final results
|
||||
|
|
Loading…
Reference in a new issue