aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support/APFloat.cpp')
-rw-r--r--lib/Support/APFloat.cpp164
1 files changed, 149 insertions, 15 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 9b8caa89ff..96fdc42fb2 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -339,7 +339,8 @@ APFloat::~APFloat()
unsigned int
APFloat::partCount() const
{
- return partCountForBits(semantics->precision + 1);
+ return partCountForBits(semantics->precision +
+ semantics->implicitIntegerBit ? 1 : 0);
}
unsigned int
@@ -1593,8 +1594,41 @@ APFloat::getHashValue() const {
// Denormals have exponent minExponent in APFloat, but minExponent-1 in
// the actual IEEE respresentation. We compensate for that here.
-double
-APFloat::convertToDouble() const {
+APInt
+APFloat::convertF80LongDoubleAPFloatToAPInt() const {
+ assert(semantics == (const llvm::fltSemantics* const)&x87DoubleExtended);
+ assert (partCount()==1);
+
+ uint64_t myexponent, mysignificand;
+
+ if (category==fcNormal) {
+ myexponent = exponent+16383; //bias
+ mysignificand = *significandParts();
+ if (myexponent==1 && !(mysignificand & 0x8000000000000000ULL))
+ myexponent = 0; // denormal
+ } else if (category==fcZero) {
+ myexponent = 0;
+ mysignificand = 0;
+ } else if (category==fcInfinity) {
+ myexponent = 0x7fff;
+ mysignificand = 0x8000000000000000ULL;
+ } else if (category==fcNaN) {
+ myexponent = 0x7fff;
+ mysignificand = *significandParts();
+ } else
+ assert(0);
+
+ uint64_t words[2];
+ words[0] = (((uint64_t)sign & 1) << 63) |
+ ((myexponent & 0x7fff) << 48) |
+ ((mysignificand >>16) & 0xffffffffffffLL);
+ words[1] = mysignificand & 0xffff;
+ APInt api(80, 2, words);
+ return api;
+}
+
+APInt
+APFloat::convertDoubleAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics* const)&IEEEdouble);
assert (partCount()==1);
@@ -1617,16 +1651,17 @@ APFloat::convertToDouble() const {
} else
assert(0);
- return BitsToDouble((((uint64_t)sign & 1) << 63) |
- ((myexponent & 0x7ff) << 52) |
- (mysignificand & 0xfffffffffffffLL));
+ APInt api(64, (((((uint64_t)sign & 1) << 63) |
+ ((myexponent & 0x7ff) << 52) |
+ (mysignificand & 0xfffffffffffffLL))));
+ return api;
}
-float
-APFloat::convertToFloat() const {
+APInt
+APFloat::convertFloatAPFloatToAPInt() const {
assert(semantics == (const llvm::fltSemantics* const)&IEEEsingle);
assert (partCount()==1);
-
+
uint32_t myexponent, mysignificand;
if (category==fcNormal) {
@@ -1646,12 +1681,78 @@ APFloat::convertToFloat() const {
} else
assert(0);
- return BitsToFloat(((sign&1) << 31) | ((myexponent&0xff) << 23) |
- (mysignificand & 0x7fffff));
+ APInt api(32, (((sign&1) << 31) | ((myexponent&0xff) << 23) |
+ (mysignificand & 0x7fffff)));
+ return api;
}
-APFloat::APFloat(double d) {
- uint64_t i = DoubleToBits(d);
+APInt
+APFloat::convertToAPInt() const {
+ if (semantics == (const llvm::fltSemantics* const)&IEEEsingle)
+ return convertFloatAPFloatToAPInt();
+ else if (semantics == (const llvm::fltSemantics* const)&IEEEdouble)
+ return convertDoubleAPFloatToAPInt();
+ else if (semantics == (const llvm::fltSemantics* const)&x87DoubleExtended)
+ return convertF80LongDoubleAPFloatToAPInt();
+ else
+ assert(0);
+}
+
+float
+APFloat::convertToFloat() const {
+ assert(semantics == (const llvm::fltSemantics* const)&IEEEsingle);
+ APInt api = convertToAPInt();
+ return api.bitsToFloat();
+}
+
+double
+APFloat::convertToDouble() const {
+ assert(semantics == (const llvm::fltSemantics* const)&IEEEdouble);
+ APInt api = convertToAPInt();
+ return api.bitsToDouble();
+}
+
+/// Integer bit is explicit in this format. Current Intel book does not
+/// define meaning of:
+/// exponent = all 1's, integer bit not set.
+/// exponent = 0, integer bit set. (formerly "psuedodenormals")
+/// exponent!=0 nor all 1's, integer bit not set. (formerly "unnormals")
+void
+APFloat::initFromF80LongDoubleAPInt(const APInt &api) {
+ assert(api.getBitWidth()==80);
+ uint64_t i1 = api.getRawData()[0];
+ uint64_t i2 = api.getRawData()[1];
+ uint64_t myexponent = (i1 >> 48) & 0x7fff;
+ uint64_t mysignificand = ((i1 << 16) & 0xffffffffffff0000ULL) |
+ (i2 & 0xffff);
+
+ initialize(&APFloat::x87DoubleExtended);
+ assert(partCount()==1);
+
+ sign = i1>>63;
+ if (myexponent==0 && mysignificand==0) {
+ // exponent, significand meaningless
+ category = fcZero;
+ } else if (myexponent==0x7fff && mysignificand==0x8000000000000000ULL) {
+ // exponent, significand meaningless
+ category = fcInfinity;
+ } else if (myexponent==0x7fff && mysignificand!=0x8000000000000000ULL) {
+ // exponent meaningless
+ category = fcNaN;
+ *significandParts() = mysignificand;
+ } else {
+ category = fcNormal;
+ exponent = myexponent - 16383;
+ *significandParts() = mysignificand;
+ if (myexponent==0) // denormal
+ exponent = -16382;
+ }
+}
+
+void
+APFloat::initFromDoubleAPInt(const APInt &api) {
+ assert(api.getBitWidth()==64);
+ uint64_t i = *api.getRawData();
uint64_t myexponent = (i >> 52) & 0x7ff;
uint64_t mysignificand = i & 0xfffffffffffffLL;
@@ -1680,8 +1781,10 @@ APFloat::APFloat(double d) {
}
}
-APFloat::APFloat(float f) {
- uint32_t i = FloatToBits(f);
+void
+APFloat::initFromFloatAPInt(const APInt & api) {
+ assert(api.getBitWidth()==32);
+ uint32_t i = (uint32_t)*api.getRawData();
uint32_t myexponent = (i >> 23) & 0xff;
uint32_t mysignificand = i & 0x7fffff;
@@ -1709,3 +1812,34 @@ APFloat::APFloat(float f) {
*significandParts() |= 0x800000; // integer bit
}
}
+
+/// Treat api as containing the bits of a floating point number. Currently
+/// we infer the floating point type from the size of the APInt. FIXME: This
+/// breaks when we get to PPC128 and IEEE128 (but both cannot exist in the
+/// same compile...)
+void
+APFloat::initFromAPInt(const APInt& api) {
+ if (api.getBitWidth() == 32)
+ return initFromFloatAPInt(api);
+ else if (api.getBitWidth()==64)
+ return initFromDoubleAPInt(api);
+ else if (api.getBitWidth()==80)
+ return initFromF80LongDoubleAPInt(api);
+ else
+ assert(0);
+}
+
+APFloat::APFloat(const APInt& api) {
+ initFromAPInt(api);
+}
+
+APFloat::APFloat(float f) {
+ APInt api = APInt(32, 0);
+ initFromAPInt(api.floatToBits(f));
+}
+
+APFloat::APFloat(double d) {
+ APInt api = APInt(64, 0);
+ initFromAPInt(api.doubleToBits(d));
+}
+