diff options
author | Gabe Black <gblack@eecs.umich.edu> | 2010-05-02 00:39:29 -0700 |
---|---|---|
committer | Gabe Black <gblack@eecs.umich.edu> | 2010-05-02 00:39:29 -0700 |
commit | 51a3d65e259fc30662ecfdac9bf7ca0068fa7da6 (patch) | |
tree | 0e209989d9e24aad2a49250db71ad2c127e6a3b4 | |
parent | 90820ddf022aab7820297318555402b4bc41ed04 (diff) | |
download | gem5-51a3d65e259fc30662ecfdac9bf7ca0068fa7da6.tar.xz |
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.
-rw-r--r-- | src/arch/x86/isa/microops/regop.isa | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/src/arch/x86/isa/microops/regop.isa b/src/arch/x86/isa/microops/regop.isa index 0b1f9a96a..f3fc1fc59 100644 --- a/src/arch/x86/isa/microops/regop.isa +++ b/src/arch/x86/isa/microops/regop.isa @@ -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); |