mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-11 11:34:02 +00:00
Properly clear all the extra bits in a significand when making a NaN from an
APInt. Be certain to set the integer bit in an x87 extended-precision significand so that we don't accidentally make a pseudo-NaN. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97382 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1e7ad3993d
commit
165e96bd25
@ -631,25 +631,45 @@ void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill)
|
|||||||
category = fcNaN;
|
category = fcNaN;
|
||||||
sign = Negative;
|
sign = Negative;
|
||||||
|
|
||||||
|
integerPart *significand = significandParts();
|
||||||
|
unsigned numParts = partCount();
|
||||||
|
|
||||||
// Set the significand bits to the fill.
|
// Set the significand bits to the fill.
|
||||||
if (!fill || fill->getNumWords() < partCount())
|
if (!fill || fill->getNumWords() < numParts)
|
||||||
APInt::tcSet(significandParts(), 0, partCount());
|
APInt::tcSet(significand, 0, numParts);
|
||||||
if (fill)
|
if (fill) {
|
||||||
APInt::tcAssign(significandParts(), fill->getRawData(), partCount());
|
APInt::tcAssign(significand, fill->getRawData(), partCount());
|
||||||
|
|
||||||
|
// Zero out the excess bits of the significand.
|
||||||
|
unsigned bitsToPreserve = semantics->precision - 1;
|
||||||
|
unsigned part = bitsToPreserve / 64;
|
||||||
|
bitsToPreserve %= 64;
|
||||||
|
significand[part] &= ((1ULL << bitsToPreserve) - 1);
|
||||||
|
for (part++; part != numParts; ++part)
|
||||||
|
significand[part] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned QNaNBit = semantics->precision - 2;
|
||||||
|
|
||||||
if (SNaN) {
|
if (SNaN) {
|
||||||
// We always have to clear the QNaN bit to make it an SNaN.
|
// We always have to clear the QNaN bit to make it an SNaN.
|
||||||
APInt::tcClearBit(significandParts(), semantics->precision - 2);
|
APInt::tcClearBit(significand, QNaNBit);
|
||||||
|
|
||||||
// If there are no bits set in the payload, we have to set
|
// If there are no bits set in the payload, we have to set
|
||||||
// *something* to make it a NaN instead of an infinity;
|
// *something* to make it a NaN instead of an infinity;
|
||||||
// conventionally, this is the next bit down from the QNaN bit.
|
// conventionally, this is the next bit down from the QNaN bit.
|
||||||
if (APInt::tcIsZero(significandParts(), partCount()))
|
if (APInt::tcIsZero(significand, numParts))
|
||||||
APInt::tcSetBit(significandParts(), semantics->precision - 3);
|
APInt::tcSetBit(significand, QNaNBit - 1);
|
||||||
} else {
|
} else {
|
||||||
// We always have to set the QNaN bit to make it a QNaN.
|
// We always have to set the QNaN bit to make it a QNaN.
|
||||||
APInt::tcSetBit(significandParts(), semantics->precision - 2);
|
APInt::tcSetBit(significand, QNaNBit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For x87 extended precision, we want to make a NaN, not a
|
||||||
|
// pseudo-NaN. Maybe we should expose the ability to make
|
||||||
|
// pseudo-NaNs?
|
||||||
|
if (semantics == &APFloat::x87DoubleExtended)
|
||||||
|
APInt::tcSetBit(significand, QNaNBit + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
|
APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user