aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support
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
commit1616e90a14e8df92adb026ceb047141056862de9 (patch)
treecb752d4a86ec5c5dd783cfc421e30d0cf7600e87 /lib/Support
parentd7b1fc63e2d2af03f122d0eeeda0f6a47586122f (diff)
downloadexternal_llvm-1616e90a14e8df92adb026ceb047141056862de9.zip
external_llvm-1616e90a14e8df92adb026ceb047141056862de9.tar.gz
external_llvm-1616e90a14e8df92adb026ceb047141056862de9.tar.bz2
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')
-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 9b8caa8..96fdc42 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));
+}
+