X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FSupport%2FAPFloat.cpp;h=b9b323c4242826176685eee547857b58325639e7;hb=34e992da381bf8b1a9cbcc1bde0b117207809649;hp=179cf4697f736c0cc6fb8104c362de691cccbc4b;hpb=e213f3f97241788825900a62f3fe1535ae96a1d7;p=oota-llvm.git diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 179cf4697f7..b9b323c4242 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -13,7 +13,9 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/APFloat.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include @@ -46,6 +48,7 @@ namespace llvm { unsigned int arithmeticOK; }; + const fltSemantics APFloat::IEEEhalf = { 15, -14, 11, true }; const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true }; const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true }; const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true }; @@ -122,27 +125,30 @@ assertArithmeticOK(const llvm::fltSemantics &semantics) { If the exponent overflows, returns a large exponent with the appropriate sign. */ static int -readExponent(const char *p) +readExponent(StringRef::iterator begin, StringRef::iterator end) { bool isNegative; unsigned int absExponent; const unsigned int overlargeExponent = 24000; /* FIXME. */ + StringRef::iterator p = begin; + + assert(p != end && "Exponent has no digits"); isNegative = (*p == '-'); - if (*p == '-' || *p == '+') + if (*p == '-' || *p == '+') { p++; + assert(p != end && "Exponent has no digits"); + } absExponent = decDigitValue(*p++); - assert (absExponent < 10U); + assert(absExponent < 10U && "Invalid character in exponent"); - for (;;) { + for (; p != end; ++p) { unsigned int value; value = decDigitValue(*p); - if (value >= 10U) - break; + assert(value < 10U && "Invalid character in exponent"); - p++; value += absExponent * 10; if (absExponent >= overlargeExponent) { absExponent = overlargeExponent; @@ -151,6 +157,8 @@ readExponent(const char *p) absExponent = value; } + assert(p == end && "Invalid exponent in exponent"); + if (isNegative) return -(int) absExponent; else @@ -160,28 +168,29 @@ readExponent(const char *p) /* This is ugly and needs cleaning up, but I don't immediately see how whilst remaining safe. */ static int -totalExponent(const char *p, int exponentAdjustment) +totalExponent(StringRef::iterator p, StringRef::iterator end, + int exponentAdjustment) { int unsignedExponent; bool negative, overflow; int exponent; - /* Move past the exponent letter and sign to the digits. */ - p++; + assert(p != end && "Exponent has no digits"); + negative = *p == '-'; - if(*p == '-' || *p == '+') + if(*p == '-' || *p == '+') { p++; + assert(p != end && "Exponent has no digits"); + } unsignedExponent = 0; overflow = false; - for(;;) { + for(; p != end; ++p) { unsigned int value; value = decDigitValue(*p); - if(value >= 10U) - break; + assert(value < 10U && "Invalid character in exponent"); - p++; unsignedExponent = unsignedExponent * 10 + value; if(unsignedExponent > 65535) overflow = true; @@ -205,16 +214,21 @@ totalExponent(const char *p, int exponentAdjustment) return exponent; } -static const char * -skipLeadingZeroesAndAnyDot(const char *p, const char **dot) +static StringRef::iterator +skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end, + StringRef::iterator *dot) { - *dot = 0; - while(*p == '0') + StringRef::iterator p = begin; + *dot = end; + while(*p == '0' && p != end) p++; if(*p == '.') { *dot = p++; - while(*p == '0') + + assert(end - begin != 1 && "Significand has no digits"); + + while(*p == '0' && p != end) p++; } @@ -242,41 +256,50 @@ struct decimalInfo { }; static void -interpretDecimal(const char *p, decimalInfo *D) +interpretDecimal(StringRef::iterator begin, StringRef::iterator end, + decimalInfo *D) { - const char *dot; - - p = skipLeadingZeroesAndAnyDot (p, &dot); + StringRef::iterator dot = end; + StringRef::iterator p = skipLeadingZeroesAndAnyDot (begin, end, &dot); D->firstSigDigit = p; D->exponent = 0; D->normalizedExponent = 0; - for (;;) { + for (; p != end; ++p) { if (*p == '.') { - assert(dot == 0); + assert(dot == end && "String contains multiple dots"); dot = p++; + if (p == end) + break; } if (decDigitValue(*p) >= 10U) break; - p++; } - /* If number is all zerooes accept any exponent. */ - if (p != D->firstSigDigit) { - if (*p == 'e' || *p == 'E') - D->exponent = readExponent(p + 1); + if (p != end) { + assert((*p == 'e' || *p == 'E') && "Invalid character in significand"); + assert(p != begin && "Significand has no digits"); + assert((dot == end || p - begin != 1) && "Significand has no digits"); + + /* p points to the first non-digit in the string */ + D->exponent = readExponent(p + 1, end); /* Implied decimal point? */ - if (!dot) + if (dot == end) dot = p; + } + /* If number is all zeroes accept any exponent. */ + if (p != D->firstSigDigit) { /* Drop insignificant trailing zeroes. */ - do + if (p != begin) { do - p--; - while (*p == '0'); - while (*p == '.'); + do + p--; + while (p != begin && *p == '0'); + while (p != begin && *p == '.'); + } /* Adjust the exponents for any decimal point. */ D->exponent += static_cast((dot - p) - (dot > p)); @@ -292,7 +315,8 @@ interpretDecimal(const char *p, decimalInfo *D) DIGITVALUE is the first hex digit of the fraction, P points to the next digit. */ static lostFraction -trailingHexadecimalFraction(const char *p, unsigned int digitValue) +trailingHexadecimalFraction(StringRef::iterator p, StringRef::iterator end, + unsigned int digitValue) { unsigned int hexDigit; @@ -307,6 +331,8 @@ trailingHexadecimalFraction(const char *p, unsigned int digitValue) while(*p == '0') p++; + assert(p != end && "Invalid trailing hexadecimal fraction!"); + hexDigit = hexDigitValue(*p); /* If we ran off the end it is exactly zero or one-half, otherwise @@ -395,7 +421,7 @@ ulpsFromBoundary(const integerPart *parts, unsigned int bits, bool isNearest) unsigned int count, partBits; integerPart part, boundary; - assert (bits != 0); + assert(bits != 0); bits--; count = bits / integerPartWidth; @@ -439,12 +465,12 @@ powerOf5(integerPart *dst, unsigned int power) { static const integerPart firstEightPowers[] = { 1, 5, 25, 125, 625, 3125, 15625, 78125 }; - static integerPart pow5s[maxPowerOfFiveParts * 2 + 5] = { 78125 * 5 }; - static unsigned int partsCount[16] = { 1 }; - + integerPart pow5s[maxPowerOfFiveParts * 2 + 5]; + pow5s[0] = 78125 * 5; + + unsigned int partsCount[16] = { 1 }; integerPart scratch[maxPowerOfFiveParts], *p1, *p2, *pow5; unsigned int result; - assert(power <= maxExponent); p1 = dst; @@ -511,7 +537,7 @@ partAsHex (char *dst, integerPart part, unsigned int count, { unsigned int result = count; - assert (count != 0 && count <= integerPartWidth / 4); + assert(count != 0 && count <= integerPartWidth / 4); part >>= (integerPartWidth - 4 * count); while (count--) { @@ -598,12 +624,18 @@ APFloat::copySignificand(const APFloat &rhs) /* Make this number a NaN, with an arbitrary but deterministic value for the significand. If double or longer, this is a signalling NaN, - which may not be ideal. */ + which may not be ideal. If float, this is QNaN(0). */ void -APFloat::makeNaN(void) +APFloat::makeNaN(unsigned type) { category = fcNaN; - APInt::tcSet(significandParts(), ~0U, partCount()); + // FIXME: Add double and long double support for QNaN(0). + if (semantics->precision == 24 && semantics->maxExponent == 127) { + type |= 0x7fc00000U; + type &= ~0x80000000U; + } else + type = ~0U; + APInt::tcSet(significandParts(), type, partCount()); } APFloat & @@ -661,20 +693,28 @@ APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value) normalize(rmNearestTiesToEven, lfExactlyZero); } +APFloat::APFloat(const fltSemantics &ourSemantics) { + assertArithmeticOK(ourSemantics); + initialize(&ourSemantics); + category = fcZero; + sign = false; +} + + APFloat::APFloat(const fltSemantics &ourSemantics, - fltCategory ourCategory, bool negative) + fltCategory ourCategory, bool negative, unsigned type) { assertArithmeticOK(ourSemantics); initialize(&ourSemantics); category = ourCategory; sign = negative; - if(category == fcNormal) + if (category == fcNormal) category = fcZero; else if (ourCategory == fcNaN) - makeNaN(); + makeNaN(type); } -APFloat::APFloat(const fltSemantics &ourSemantics, const char *text) +APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text) { assertArithmeticOK(ourSemantics); initialize(&ourSemantics); @@ -720,7 +760,7 @@ APFloat::significandParts() { assert(category == fcNormal || category == fcNaN); - if(partCount() > 1) + if (partCount() > 1) return significand.parts; else return &significand.part; @@ -1060,9 +1100,9 @@ APFloat::roundAwayFromZero(roundingMode rounding_mode, /* Current callers never pass this so we don't handle it. */ assert(lost_fraction != lfExactlyZero); - switch(rounding_mode) { + switch (rounding_mode) { default: - assert(0); + llvm_unreachable(0); case rmNearestTiesToAway: return lost_fraction == lfExactlyHalf || lost_fraction == lfMoreThanHalf; @@ -1199,9 +1239,9 @@ APFloat::normalize(roundingMode rounding_mode, APFloat::opStatus APFloat::addOrSubtractSpecials(const APFloat &rhs, bool subtract) { - switch(convolve(category, rhs.category)) { + switch (convolve(category, rhs.category)) { default: - assert(0); + llvm_unreachable(0); case convolve(fcNaN, fcZero): case convolve(fcNaN, fcNormal): @@ -1323,9 +1363,9 @@ APFloat::addOrSubtractSignificand(const APFloat &rhs, bool subtract) APFloat::opStatus APFloat::multiplySpecials(const APFloat &rhs) { - switch(convolve(category, rhs.category)) { + switch (convolve(category, rhs.category)) { default: - assert(0); + llvm_unreachable(0); case convolve(fcNaN, fcZero): case convolve(fcNaN, fcNormal): @@ -1365,9 +1405,9 @@ APFloat::multiplySpecials(const APFloat &rhs) APFloat::opStatus APFloat::divideSpecials(const APFloat &rhs) { - switch(convolve(category, rhs.category)) { + switch (convolve(category, rhs.category)) { default: - assert(0); + llvm_unreachable(0); case convolve(fcNaN, fcZero): case convolve(fcNaN, fcNormal): @@ -1407,9 +1447,9 @@ APFloat::divideSpecials(const APFloat &rhs) APFloat::opStatus APFloat::modSpecials(const APFloat &rhs) { - switch(convolve(category, rhs.category)) { + switch (convolve(category, rhs.category)) { default: - assert(0); + llvm_unreachable(0); case convolve(fcNaN, fcZero): case convolve(fcNaN, fcNormal): @@ -1684,9 +1724,9 @@ APFloat::compare(const APFloat &rhs) const assertArithmeticOK(*semantics); assert(semantics == rhs.semantics); - switch(convolve(category, rhs.category)) { + switch (convolve(category, rhs.category)) { default: - assert(0); + llvm_unreachable(0); case convolve(fcNaN, fcZero): case convolve(fcNaN, fcNormal): @@ -2100,13 +2140,13 @@ APFloat::convertFromZeroExtendedInteger(const integerPart *parts, } APFloat::opStatus -APFloat::convertFromHexadecimalString(const char *p, +APFloat::convertFromHexadecimalString(const StringRef &s, roundingMode rounding_mode) { - lostFraction lost_fraction; + lostFraction lost_fraction = lfExactlyZero; integerPart *significand; unsigned int bitPos, partsCount; - const char *dot, *firstSignificantDigit; + StringRef::iterator dot, firstSignificantDigit; zeroSignificand(); exponent = 0; @@ -2117,47 +2157,58 @@ APFloat::convertFromHexadecimalString(const char *p, bitPos = partsCount * integerPartWidth; /* Skip leading zeroes and any (hexa)decimal point. */ - p = skipLeadingZeroesAndAnyDot(p, &dot); + StringRef::iterator begin = s.begin(); + StringRef::iterator end = s.end(); + StringRef::iterator p = skipLeadingZeroesAndAnyDot(begin, end, &dot); firstSignificantDigit = p; - for(;;) { + for(; p != end;) { integerPart hex_value; if(*p == '.') { - assert(dot == 0); + assert(dot == end && "String contains multiple dots"); dot = p++; + if (p == end) { + break; + } } hex_value = hexDigitValue(*p); if(hex_value == -1U) { - lost_fraction = lfExactlyZero; break; } p++; - /* Store the number whilst 4-bit nibbles remain. */ - if(bitPos) { - bitPos -= 4; - hex_value <<= bitPos % integerPartWidth; - significand[bitPos / integerPartWidth] |= hex_value; - } else { - lost_fraction = trailingHexadecimalFraction(p, hex_value); - while(hexDigitValue(*p) != -1U) - p++; + if (p == end) { break; + } else { + /* Store the number whilst 4-bit nibbles remain. */ + if(bitPos) { + bitPos -= 4; + hex_value <<= bitPos % integerPartWidth; + significand[bitPos / integerPartWidth] |= hex_value; + } else { + lost_fraction = trailingHexadecimalFraction(p, end, hex_value); + while(p != end && hexDigitValue(*p) != -1U) + p++; + break; + } } } /* Hex floats require an exponent but not a hexadecimal point. */ - assert(*p == 'p' || *p == 'P'); + assert(p != end && "Hex strings require an exponent"); + assert((*p == 'p' || *p == 'P') && "Invalid character in significand"); + assert(p != begin && "Significand has no digits"); + assert((dot == end || p - begin != 1) && "Significand has no digits"); /* Ignore the exponent if we are zero. */ if(p != firstSignificantDigit) { int expAdjustment; /* Implicit hexadecimal point? */ - if(!dot) + if (dot == end) dot = p; /* Calculate the exponent adjustment implicit in the number of @@ -2173,7 +2224,7 @@ APFloat::convertFromHexadecimalString(const char *p, expAdjustment -= partsCount * integerPartWidth; /* Adjust for the given exponent. */ - exponent = totalExponent(p, expAdjustment); + exponent = totalExponent(p + 1, end, expAdjustment); } return normalize(rounding_mode, lost_fraction); @@ -2238,8 +2289,8 @@ APFloat::roundSignificandWithExponent(const integerPart *decSigParts, /* Both multiplySignificand and divideSignificand return the result with the integer bit set. */ - assert (APInt::tcExtractBit - (decSig.significandParts(), calcSemantics.precision - 1) == 1); + assert(APInt::tcExtractBit + (decSig.significandParts(), calcSemantics.precision - 1) == 1); HUerr = HUerrBound(calcLostFraction != lfExactlyZero, sigStatus != opOK, powHUerr); @@ -2265,13 +2316,14 @@ APFloat::roundSignificandWithExponent(const integerPart *decSigParts, } APFloat::opStatus -APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode) +APFloat::convertFromDecimalString(const StringRef &str, roundingMode rounding_mode) { decimalInfo D; opStatus fs; /* Scan the text. */ - interpretDecimal(p, &D); + StringRef::iterator p = str.begin(); + interpretDecimal(p, str.end(), &D); /* Handle the quick cases. First the case of no significant digits, i.e. zero, and then exponents that are obviously too large or too @@ -2326,10 +2378,14 @@ APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode) multiplier = 1; do { - if (*p == '.') + if (*p == '.') { p++; - + if (p == str.end()) { + break; + } + } decValue = decDigitValue(*p++); + assert(decValue < 10U && "Invalid character in significand"); multiplier *= 10; val = val * 10 + decValue; /* The maximum number that can be multiplied by ten with any @@ -2357,20 +2413,28 @@ APFloat::convertFromDecimalString(const char *p, roundingMode rounding_mode) } APFloat::opStatus -APFloat::convertFromString(const char *p, roundingMode rounding_mode) +APFloat::convertFromString(const StringRef &str, roundingMode rounding_mode) { assertArithmeticOK(*semantics); + assert(!str.empty() && "Invalid string length"); /* Handle a leading minus sign. */ - if(*p == '-') - sign = 1, p++; - else - sign = 0; + StringRef::iterator p = str.begin(); + size_t slen = str.size(); + sign = *p == '-' ? 1 : 0; + if(*p == '-' || *p == '+') { + p++; + slen--; + assert(slen && "String has no digits"); + } - if(p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) - return convertFromHexadecimalString(p + 2, rounding_mode); + if(slen >= 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { + assert(slen - 2 && "Invalid string"); + return convertFromHexadecimalString(StringRef(p + 2, slen - 2), + rounding_mode); + } - return convertFromDecimalString(p, rounding_mode); + return convertFromDecimalString(StringRef(p, slen), rounding_mode); } /* Write out a hexadecimal representation of the floating point value @@ -2529,7 +2593,7 @@ APFloat::convertNormalToHexString(char *dst, unsigned int hexDigits, q--; *q = hexDigitChars[hexDigitValue (*q) + 1]; } while (*q == '0'); - assert (q >= p); + assert(q >= p); } else { /* Add trailing zeroes. */ memset (dst, '0', outputDigits); @@ -2581,7 +2645,7 @@ APInt APFloat::convertF80LongDoubleAPFloatToAPInt() const { assert(semantics == (const llvm::fltSemantics*)&x87DoubleExtended); - assert (partCount()==2); + assert(partCount()==2); uint64_t myexponent, mysignificand; @@ -2603,10 +2667,9 @@ APFloat::convertF80LongDoubleAPFloatToAPInt() const } uint64_t words[2]; - words[0] = ((uint64_t)(sign & 1) << 63) | - ((myexponent & 0x7fffLL) << 48) | - ((mysignificand >>16) & 0xffffffffffffLL); - words[1] = mysignificand & 0xffff; + words[0] = mysignificand; + words[1] = ((uint64_t)(sign & 1) << 15) | + (myexponent & 0x7fffLL); return APInt(80, 2, words); } @@ -2614,7 +2677,7 @@ APInt APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const { assert(semantics == (const llvm::fltSemantics*)&PPCDoubleDouble); - assert (partCount()==2); + assert(partCount()==2); uint64_t myexponent, mysignificand, myexponent2, mysignificand2; @@ -2655,11 +2718,47 @@ APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const return APInt(128, 2, words); } +APInt +APFloat::convertQuadrupleAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEquad); + assert(partCount()==2); + + uint64_t myexponent, mysignificand, mysignificand2; + + if (category==fcNormal) { + myexponent = exponent+16383; //bias + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + if (myexponent==1 && !(mysignificand2 & 0x1000000000000LL)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = mysignificand2 = 0; + } else if (category==fcInfinity) { + myexponent = 0x7fff; + mysignificand = mysignificand2 = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x7fff; + mysignificand = significandParts()[0]; + mysignificand2 = significandParts()[1]; + } + + uint64_t words[2]; + words[0] = mysignificand; + words[1] = ((uint64_t)(sign & 1) << 63) | + ((myexponent & 0x7fff) << 48) | + (mysignificand2 & 0xffffffffffffLL); + + return APInt(128, 2, words); +} + APInt APFloat::convertDoubleAPFloatToAPInt() const { assert(semantics == (const llvm::fltSemantics*)&IEEEdouble); - assert (partCount()==1); + assert(partCount()==1); uint64_t myexponent, mysignificand; @@ -2689,7 +2788,7 @@ APInt APFloat::convertFloatAPFloatToAPInt() const { assert(semantics == (const llvm::fltSemantics*)&IEEEsingle); - assert (partCount()==1); + assert(partCount()==1); uint32_t myexponent, mysignificand; @@ -2714,6 +2813,35 @@ APFloat::convertFloatAPFloatToAPInt() const (mysignificand & 0x7fffff))); } +APInt +APFloat::convertHalfAPFloatToAPInt() const +{ + assert(semantics == (const llvm::fltSemantics*)&IEEEhalf); + assert(partCount()==1); + + uint32_t myexponent, mysignificand; + + if (category==fcNormal) { + myexponent = exponent+15; //bias + mysignificand = (uint32_t)*significandParts(); + if (myexponent == 1 && !(mysignificand & 0x400)) + myexponent = 0; // denormal + } else if (category==fcZero) { + myexponent = 0; + mysignificand = 0; + } else if (category==fcInfinity) { + myexponent = 0x1f; + mysignificand = 0; + } else { + assert(category == fcNaN && "Unknown category!"); + myexponent = 0x1f; + mysignificand = (uint32_t)*significandParts(); + } + + return APInt(16, (((sign&1) << 15) | ((myexponent&0x1f) << 10) | + (mysignificand & 0x3ff))); +} + // This function creates an APInt that is just a bit map of the floating // point constant as it would appear in memory. It is not a conversion, // and treating the result as a normal integer is unlikely to be useful. @@ -2721,12 +2849,18 @@ APFloat::convertFloatAPFloatToAPInt() const APInt APFloat::bitcastToAPInt() const { + if (semantics == (const llvm::fltSemantics*)&IEEEhalf) + return convertHalfAPFloatToAPInt(); + if (semantics == (const llvm::fltSemantics*)&IEEEsingle) return convertFloatAPFloatToAPInt(); - + if (semantics == (const llvm::fltSemantics*)&IEEEdouble) return convertDoubleAPFloatToAPInt(); + if (semantics == (const llvm::fltSemantics*)&IEEEquad) + return convertQuadrupleAPFloatToAPInt(); + if (semantics == (const llvm::fltSemantics*)&PPCDoubleDouble) return convertPPCDoubleDoubleAPFloatToAPInt(); @@ -2738,7 +2872,8 @@ APFloat::bitcastToAPInt() const float APFloat::convertToFloat() const { - assert(semantics == (const llvm::fltSemantics*)&IEEEsingle); + assert(semantics == (const llvm::fltSemantics*)&IEEEsingle && + "Float semantics are not IEEEsingle"); APInt api = bitcastToAPInt(); return api.bitsToFloat(); } @@ -2746,7 +2881,8 @@ APFloat::convertToFloat() const double APFloat::convertToDouble() const { - assert(semantics == (const llvm::fltSemantics*)&IEEEdouble); + assert(semantics == (const llvm::fltSemantics*)&IEEEdouble && + "Float semantics are not IEEEdouble"); APInt api = bitcastToAPInt(); return api.bitsToDouble(); } @@ -2764,14 +2900,13 @@ 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); + uint64_t myexponent = (i2 & 0x7fff); + uint64_t mysignificand = i1; initialize(&APFloat::x87DoubleExtended); assert(partCount()==2); - sign = static_cast(i1>>63); + sign = static_cast(i2>>15); if (myexponent==0 && mysignificand==0) { // exponent, significand meaningless category = fcZero; @@ -2843,6 +2978,46 @@ APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api) } } +void +APFloat::initFromQuadrupleAPInt(const APInt &api) +{ + assert(api.getBitWidth()==128); + uint64_t i1 = api.getRawData()[0]; + uint64_t i2 = api.getRawData()[1]; + uint64_t myexponent = (i2 >> 48) & 0x7fff; + uint64_t mysignificand = i1; + uint64_t mysignificand2 = i2 & 0xffffffffffffLL; + + initialize(&APFloat::IEEEquad); + assert(partCount()==2); + + sign = static_cast(i2>>63); + if (myexponent==0 && + (mysignificand==0 && mysignificand2==0)) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x7fff && + (mysignificand==0 && mysignificand2==0)) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x7fff && + (mysignificand!=0 || mysignificand2 !=0)) { + // exponent meaningless + category = fcNaN; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + } else { + category = fcNormal; + exponent = myexponent - 16383; + significandParts()[0] = mysignificand; + significandParts()[1] = mysignificand2; + if (myexponent==0) // denormal + exponent = -16382; + else + significandParts()[1] |= 0x1000000000000LL; // integer bit + } +} + void APFloat::initFromDoubleAPInt(const APInt &api) { @@ -2909,6 +3084,39 @@ APFloat::initFromFloatAPInt(const APInt & api) } } +void +APFloat::initFromHalfAPInt(const APInt & api) +{ + assert(api.getBitWidth()==16); + uint32_t i = (uint32_t)*api.getRawData(); + uint32_t myexponent = (i >> 10) & 0x1f; + uint32_t mysignificand = i & 0x3ff; + + initialize(&APFloat::IEEEhalf); + assert(partCount()==1); + + sign = i >> 15; + if (myexponent==0 && mysignificand==0) { + // exponent, significand meaningless + category = fcZero; + } else if (myexponent==0x1f && mysignificand==0) { + // exponent, significand meaningless + category = fcInfinity; + } else if (myexponent==0x1f && mysignificand!=0) { + // sign, exponent, significand meaningless + category = fcNaN; + *significandParts() = mysignificand; + } else { + category = fcNormal; + exponent = myexponent - 15; //bias + *significandParts() = mysignificand; + if (myexponent==0) // denormal + exponent = -14; + else + *significandParts() |= 0x400; // 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. The /// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful @@ -2916,16 +3124,19 @@ APFloat::initFromFloatAPInt(const APInt & api) void APFloat::initFromAPInt(const APInt& api, bool isIEEE) { - if (api.getBitWidth() == 32) + if (api.getBitWidth() == 16) + return initFromHalfAPInt(api); + else if (api.getBitWidth() == 32) return initFromFloatAPInt(api); else if (api.getBitWidth()==64) return initFromDoubleAPInt(api); else if (api.getBitWidth()==80) return initFromF80LongDoubleAPInt(api); - else if (api.getBitWidth()==128 && !isIEEE) - return initFromPPCDoubleDoubleAPInt(api); + else if (api.getBitWidth()==128) + return (isIEEE ? + initFromQuadrupleAPInt(api) : initFromPPCDoubleDoubleAPInt(api)); else - assert(0); + llvm_unreachable(0); } APFloat::APFloat(const APInt& api, bool isIEEE)