aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/APFloat.cpp
diff options
context:
space:
mode:
authorDale Johannesen <dalej@apple.com>2007-09-11 18:32:33 +0000
committerDale Johannesen <dalej@apple.com>2007-09-11 18:32:33 +0000
commit3f6eb7419de437436265831fce92f62498556e08 (patch)
treecb752d4a86ec5c5dd783cfc421e30d0cf7600e87 /lib/Support/APFloat.cpp
parent6320260e060ce4fc5d199d757b15a0f43be66029 (diff)
Add APInt interfaces to APFloat (allows directly
access to bits). Use them in place of float and double interfaces where appropriate. First bits of x86 long double constants handling (untested, probably does not work). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@41858 91177308-0d34-0410-b5e6-96231b3b80d8
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));
+}
+