mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-17 20:23:59 +00:00
Next PPC long double bits. First cut at constants.
No compile-time support for constant operations yet, just format transformations. Make readers and writers work. Split constants into 2 doubles in Legalize. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42865 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -126,6 +126,7 @@ namespace llvm {
|
|||||||
static const fltSemantics IEEEsingle;
|
static const fltSemantics IEEEsingle;
|
||||||
static const fltSemantics IEEEdouble;
|
static const fltSemantics IEEEdouble;
|
||||||
static const fltSemantics IEEEquad;
|
static const fltSemantics IEEEquad;
|
||||||
|
static const fltSemantics PPCDoubleDouble;
|
||||||
static const fltSemantics x87DoubleExtended;
|
static const fltSemantics x87DoubleExtended;
|
||||||
/* And this psuedo, used to construct APFloats that cannot
|
/* And this psuedo, used to construct APFloats that cannot
|
||||||
conflict with anything real. */
|
conflict with anything real. */
|
||||||
@ -175,7 +176,7 @@ namespace llvm {
|
|||||||
APFloat(const fltSemantics &, fltCategory, bool negative);
|
APFloat(const fltSemantics &, fltCategory, bool negative);
|
||||||
explicit APFloat(double d);
|
explicit APFloat(double d);
|
||||||
explicit APFloat(float f);
|
explicit APFloat(float f);
|
||||||
explicit APFloat(const APInt &);
|
explicit APFloat(const APInt &, bool isIEEE = false);
|
||||||
APFloat(const APFloat &);
|
APFloat(const APFloat &);
|
||||||
~APFloat();
|
~APFloat();
|
||||||
|
|
||||||
@ -276,10 +277,12 @@ namespace llvm {
|
|||||||
APInt convertFloatAPFloatToAPInt() const;
|
APInt convertFloatAPFloatToAPInt() const;
|
||||||
APInt convertDoubleAPFloatToAPInt() const;
|
APInt convertDoubleAPFloatToAPInt() const;
|
||||||
APInt convertF80LongDoubleAPFloatToAPInt() const;
|
APInt convertF80LongDoubleAPFloatToAPInt() const;
|
||||||
void initFromAPInt(const APInt& api);
|
APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
|
||||||
|
void initFromAPInt(const APInt& api, bool isIEEE = false);
|
||||||
void initFromFloatAPInt(const APInt& api);
|
void initFromFloatAPInt(const APInt& api);
|
||||||
void initFromDoubleAPInt(const APInt& api);
|
void initFromDoubleAPInt(const APInt& api);
|
||||||
void initFromF80LongDoubleAPInt(const APInt& api);
|
void initFromF80LongDoubleAPInt(const APInt& api);
|
||||||
|
void initFromPPCDoubleDoubleAPInt(const APInt& api);
|
||||||
|
|
||||||
void assign(const APFloat &);
|
void assign(const APFloat &);
|
||||||
void copySignificand(const APFloat &);
|
void copySignificand(const APFloat &);
|
||||||
@ -306,6 +309,13 @@ namespace llvm {
|
|||||||
|
|
||||||
/* The sign bit of this number. */
|
/* The sign bit of this number. */
|
||||||
unsigned int sign: 1;
|
unsigned int sign: 1;
|
||||||
|
|
||||||
|
/* For PPCDoubleDouble, we have a second exponent and sign (the second
|
||||||
|
significand is appended to the first one, although it would be wrong to
|
||||||
|
regard these as a single number for arithmetic purposes). These fields
|
||||||
|
are not meaningful for any other type. */
|
||||||
|
exponent_t exponent2 : 11;
|
||||||
|
unsigned int sign2: 1;
|
||||||
};
|
};
|
||||||
} /* namespace llvm */
|
} /* namespace llvm */
|
||||||
|
|
||||||
|
@ -2199,7 +2199,7 @@ YY_RULE_SETUP
|
|||||||
#line 488 "/Volumes/MacOS9/gcc/llvm/lib/AsmParser/Lexer.l"
|
#line 488 "/Volumes/MacOS9/gcc/llvm/lib/AsmParser/Lexer.l"
|
||||||
{ uint64_t Pair[2];
|
{ uint64_t Pair[2];
|
||||||
HexToIntPair(yytext+3, Pair);
|
HexToIntPair(yytext+3, Pair);
|
||||||
llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair));
|
llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair), true);
|
||||||
return FPVAL;
|
return FPVAL;
|
||||||
}
|
}
|
||||||
YY_BREAK
|
YY_BREAK
|
||||||
|
@ -487,7 +487,7 @@ shufflevector { RET_TOK(OtherOpVal, ShuffleVector, SHUFFLEVECTOR); }
|
|||||||
}
|
}
|
||||||
{HexFP128Constant} { uint64_t Pair[2];
|
{HexFP128Constant} { uint64_t Pair[2];
|
||||||
HexToIntPair(yytext+3, Pair);
|
HexToIntPair(yytext+3, Pair);
|
||||||
llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair));
|
llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair), true);
|
||||||
return FPVAL;
|
return FPVAL;
|
||||||
}
|
}
|
||||||
{HexPPC128Constant} { uint64_t Pair[2];
|
{HexPPC128Constant} { uint64_t Pair[2];
|
||||||
|
@ -487,7 +487,7 @@ shufflevector { RET_TOK(OtherOpVal, ShuffleVector, SHUFFLEVECTOR); }
|
|||||||
}
|
}
|
||||||
{HexFP128Constant} { uint64_t Pair[2];
|
{HexFP128Constant} { uint64_t Pair[2];
|
||||||
HexToIntPair(yytext+3, Pair);
|
HexToIntPair(yytext+3, Pair);
|
||||||
llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair));
|
llvmAsmlval.FPVal = new APFloat(APInt(128, 2, Pair), true);
|
||||||
return FPVAL;
|
return FPVAL;
|
||||||
}
|
}
|
||||||
{HexPPC128Constant} { uint64_t Pair[2];
|
{HexPPC128Constant} { uint64_t Pair[2];
|
||||||
|
@ -632,9 +632,9 @@ bool BitcodeReader::ParseConstants() {
|
|||||||
else if (CurTy == Type::X86_FP80Ty)
|
else if (CurTy == Type::X86_FP80Ty)
|
||||||
V = ConstantFP::get(CurTy, APFloat(APInt(80, 2, &Record[0])));
|
V = ConstantFP::get(CurTy, APFloat(APInt(80, 2, &Record[0])));
|
||||||
else if (CurTy == Type::FP128Ty)
|
else if (CurTy == Type::FP128Ty)
|
||||||
V = ConstantFP::get(CurTy, APFloat(APInt(128, 2, &Record[0])));
|
V = ConstantFP::get(CurTy, APFloat(APInt(128, 2, &Record[0]), true));
|
||||||
else if (CurTy == Type::PPC_FP128Ty)
|
else if (CurTy == Type::PPC_FP128Ty)
|
||||||
assert(0 && "PowerPC long double constants not handled yet.");
|
V = ConstantFP::get(CurTy, APFloat(APInt(128, 2, &Record[0])));
|
||||||
else
|
else
|
||||||
V = UndefValue::get(CurTy);
|
V = UndefValue::get(CurTy);
|
||||||
break;
|
break;
|
||||||
|
@ -534,13 +534,11 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
|
|||||||
const uint64_t *p = api.getRawData();
|
const uint64_t *p = api.getRawData();
|
||||||
Record.push_back(p[0]);
|
Record.push_back(p[0]);
|
||||||
Record.push_back((uint16_t)p[1]);
|
Record.push_back((uint16_t)p[1]);
|
||||||
} else if (Ty == Type::FP128Ty) {
|
} else if (Ty == Type::FP128Ty || Ty == Type::PPC_FP128Ty) {
|
||||||
APInt api = CFP->getValueAPF().convertToAPInt();
|
APInt api = CFP->getValueAPF().convertToAPInt();
|
||||||
const uint64_t *p = api.getRawData();
|
const uint64_t *p = api.getRawData();
|
||||||
Record.push_back(p[0]);
|
Record.push_back(p[0]);
|
||||||
Record.push_back(p[1]);
|
Record.push_back(p[1]);
|
||||||
} else if (Ty == Type::PPC_FP128Ty) {
|
|
||||||
assert(0 && "PowerPC long double constants not handled yet.");
|
|
||||||
} else {
|
} else {
|
||||||
assert (0 && "Unknown FP type!");
|
assert (0 && "Unknown FP type!");
|
||||||
}
|
}
|
||||||
|
@ -5196,6 +5196,14 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
|
|||||||
}
|
}
|
||||||
case ISD::ConstantFP: {
|
case ISD::ConstantFP: {
|
||||||
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node);
|
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node);
|
||||||
|
if (CFP->getValueType(0) == MVT::ppcf128) {
|
||||||
|
APInt api = CFP->getValueAPF().convertToAPInt();
|
||||||
|
Lo = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[1])),
|
||||||
|
MVT::f64);
|
||||||
|
Hi = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[0])),
|
||||||
|
MVT::f64);
|
||||||
|
break;
|
||||||
|
}
|
||||||
Lo = ExpandConstantFP(CFP, false, DAG, TLI);
|
Lo = ExpandConstantFP(CFP, false, DAG, TLI);
|
||||||
if (getTypeAction(Lo.getValueType()) == Expand)
|
if (getTypeAction(Lo.getValueType()) == Expand)
|
||||||
ExpandOp(Lo, Lo, Hi);
|
ExpandOp(Lo, Lo, Hi);
|
||||||
|
@ -50,6 +50,11 @@ namespace llvm {
|
|||||||
const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true };
|
const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true };
|
||||||
const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, false };
|
const fltSemantics APFloat::x87DoubleExtended = { 16383, -16382, 64, false };
|
||||||
const fltSemantics APFloat::Bogus = { 0, 0, 0, false };
|
const fltSemantics APFloat::Bogus = { 0, 0, 0, false };
|
||||||
|
|
||||||
|
// The PowerPC format consists of two doubles. It does not map cleanly
|
||||||
|
// onto the usual format above. For now only storage of constants of
|
||||||
|
// this type is supported, no arithmetic.
|
||||||
|
const fltSemantics APFloat::PPCDoubleDouble = { 1023, -1022, 106, true };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put a bunch of private, handy routines in an anonymous namespace. */
|
/* Put a bunch of private, handy routines in an anonymous namespace. */
|
||||||
@ -325,6 +330,8 @@ APFloat::assign(const APFloat &rhs)
|
|||||||
sign = rhs.sign;
|
sign = rhs.sign;
|
||||||
category = rhs.category;
|
category = rhs.category;
|
||||||
exponent = rhs.exponent;
|
exponent = rhs.exponent;
|
||||||
|
sign2 = rhs.sign2;
|
||||||
|
exponent2 = rhs.exponent2;
|
||||||
if(category == fcNormal || category == fcNaN)
|
if(category == fcNormal || category == fcNaN)
|
||||||
copySignificand(rhs);
|
copySignificand(rhs);
|
||||||
}
|
}
|
||||||
@ -361,10 +368,16 @@ APFloat::bitwiseIsEqual(const APFloat &rhs) const {
|
|||||||
category != rhs.category ||
|
category != rhs.category ||
|
||||||
sign != rhs.sign)
|
sign != rhs.sign)
|
||||||
return false;
|
return false;
|
||||||
|
if (semantics==(const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
sign2 != rhs.sign2)
|
||||||
|
return false;
|
||||||
if (category==fcZero || category==fcInfinity)
|
if (category==fcZero || category==fcInfinity)
|
||||||
return true;
|
return true;
|
||||||
else if (category==fcNormal && exponent!=rhs.exponent)
|
else if (category==fcNormal && exponent!=rhs.exponent)
|
||||||
return false;
|
return false;
|
||||||
|
else if (semantics==(const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
exponent2!=rhs.exponent2)
|
||||||
|
return false;
|
||||||
else {
|
else {
|
||||||
int i= partCount();
|
int i= partCount();
|
||||||
const integerPart* p=significandParts();
|
const integerPart* p=significandParts();
|
||||||
@ -379,6 +392,8 @@ APFloat::bitwiseIsEqual(const APFloat &rhs) const {
|
|||||||
|
|
||||||
APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value)
|
APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
initialize(&ourSemantics);
|
initialize(&ourSemantics);
|
||||||
sign = 0;
|
sign = 0;
|
||||||
zeroSignificand();
|
zeroSignificand();
|
||||||
@ -390,6 +405,8 @@ APFloat::APFloat(const fltSemantics &ourSemantics, integerPart value)
|
|||||||
APFloat::APFloat(const fltSemantics &ourSemantics,
|
APFloat::APFloat(const fltSemantics &ourSemantics,
|
||||||
fltCategory ourCategory, bool negative)
|
fltCategory ourCategory, bool negative)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
initialize(&ourSemantics);
|
initialize(&ourSemantics);
|
||||||
category = ourCategory;
|
category = ourCategory;
|
||||||
sign = negative;
|
sign = negative;
|
||||||
@ -399,6 +416,8 @@ APFloat::APFloat(const fltSemantics &ourSemantics,
|
|||||||
|
|
||||||
APFloat::APFloat(const fltSemantics &ourSemantics, const char *text)
|
APFloat::APFloat(const fltSemantics &ourSemantics, const char *text)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
initialize(&ourSemantics);
|
initialize(&ourSemantics);
|
||||||
convertFromString(text, rmNearestTiesToEven);
|
convertFromString(text, rmNearestTiesToEven);
|
||||||
}
|
}
|
||||||
@ -1181,6 +1200,8 @@ APFloat::addOrSubtract(const APFloat &rhs, roundingMode rounding_mode,
|
|||||||
APFloat::opStatus
|
APFloat::opStatus
|
||||||
APFloat::add(const APFloat &rhs, roundingMode rounding_mode)
|
APFloat::add(const APFloat &rhs, roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
return addOrSubtract(rhs, rounding_mode, false);
|
return addOrSubtract(rhs, rounding_mode, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1188,6 +1209,8 @@ APFloat::add(const APFloat &rhs, roundingMode rounding_mode)
|
|||||||
APFloat::opStatus
|
APFloat::opStatus
|
||||||
APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode)
|
APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
return addOrSubtract(rhs, rounding_mode, true);
|
return addOrSubtract(rhs, rounding_mode, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1195,6 +1218,8 @@ APFloat::subtract(const APFloat &rhs, roundingMode rounding_mode)
|
|||||||
APFloat::opStatus
|
APFloat::opStatus
|
||||||
APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode)
|
APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
opStatus fs;
|
opStatus fs;
|
||||||
|
|
||||||
sign ^= rhs.sign;
|
sign ^= rhs.sign;
|
||||||
@ -1214,6 +1239,8 @@ APFloat::multiply(const APFloat &rhs, roundingMode rounding_mode)
|
|||||||
APFloat::opStatus
|
APFloat::opStatus
|
||||||
APFloat::divide(const APFloat &rhs, roundingMode rounding_mode)
|
APFloat::divide(const APFloat &rhs, roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
opStatus fs;
|
opStatus fs;
|
||||||
|
|
||||||
sign ^= rhs.sign;
|
sign ^= rhs.sign;
|
||||||
@ -1233,6 +1260,8 @@ APFloat::divide(const APFloat &rhs, roundingMode rounding_mode)
|
|||||||
APFloat::opStatus
|
APFloat::opStatus
|
||||||
APFloat::mod(const APFloat &rhs, roundingMode rounding_mode)
|
APFloat::mod(const APFloat &rhs, roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
opStatus fs;
|
opStatus fs;
|
||||||
APFloat V = *this;
|
APFloat V = *this;
|
||||||
unsigned int origSign = sign;
|
unsigned int origSign = sign;
|
||||||
@ -1269,6 +1298,8 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand,
|
|||||||
const APFloat &addend,
|
const APFloat &addend,
|
||||||
roundingMode rounding_mode)
|
roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
opStatus fs;
|
opStatus fs;
|
||||||
|
|
||||||
/* Post-multiplication sign, before addition. */
|
/* Post-multiplication sign, before addition. */
|
||||||
@ -1312,6 +1343,8 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand,
|
|||||||
APFloat::cmpResult
|
APFloat::cmpResult
|
||||||
APFloat::compare(const APFloat &rhs) const
|
APFloat::compare(const APFloat &rhs) const
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
cmpResult result;
|
cmpResult result;
|
||||||
|
|
||||||
assert(semantics == rhs.semantics);
|
assert(semantics == rhs.semantics);
|
||||||
@ -1385,6 +1418,8 @@ APFloat::opStatus
|
|||||||
APFloat::convert(const fltSemantics &toSemantics,
|
APFloat::convert(const fltSemantics &toSemantics,
|
||||||
roundingMode rounding_mode)
|
roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
lostFraction lostFraction;
|
lostFraction lostFraction;
|
||||||
unsigned int newPartCount, oldPartCount;
|
unsigned int newPartCount, oldPartCount;
|
||||||
opStatus fs;
|
opStatus fs;
|
||||||
@ -1462,6 +1497,8 @@ APFloat::convertToInteger(integerPart *parts, unsigned int width,
|
|||||||
bool isSigned,
|
bool isSigned,
|
||||||
roundingMode rounding_mode) const
|
roundingMode rounding_mode) const
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
lostFraction lost_fraction;
|
lostFraction lost_fraction;
|
||||||
unsigned int msb, partsCount;
|
unsigned int msb, partsCount;
|
||||||
int bits;
|
int bits;
|
||||||
@ -1591,6 +1628,8 @@ APFloat::convertFromSignExtendedInteger(const integerPart *src,
|
|||||||
bool isSigned,
|
bool isSigned,
|
||||||
roundingMode rounding_mode)
|
roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
opStatus status;
|
opStatus status;
|
||||||
|
|
||||||
if (isSigned
|
if (isSigned
|
||||||
@ -1618,6 +1657,8 @@ APFloat::convertFromZeroExtendedInteger(const integerPart *parts,
|
|||||||
unsigned int width, bool isSigned,
|
unsigned int width, bool isSigned,
|
||||||
roundingMode rounding_mode)
|
roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
unsigned int partCount = partCountForBits(width);
|
unsigned int partCount = partCountForBits(width);
|
||||||
APInt api = APInt(width, partCount, parts);
|
APInt api = APInt(width, partCount, parts);
|
||||||
|
|
||||||
@ -1634,6 +1675,8 @@ APFloat::opStatus
|
|||||||
APFloat::convertFromHexadecimalString(const char *p,
|
APFloat::convertFromHexadecimalString(const char *p,
|
||||||
roundingMode rounding_mode)
|
roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
lostFraction lost_fraction;
|
lostFraction lost_fraction;
|
||||||
integerPart *significand;
|
integerPart *significand;
|
||||||
unsigned int bitPos, partsCount;
|
unsigned int bitPos, partsCount;
|
||||||
@ -1713,6 +1756,8 @@ APFloat::convertFromHexadecimalString(const char *p,
|
|||||||
APFloat::opStatus
|
APFloat::opStatus
|
||||||
APFloat::convertFromString(const char *p, roundingMode rounding_mode)
|
APFloat::convertFromString(const char *p, roundingMode rounding_mode)
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
/* Handle a leading minus sign. */
|
/* Handle a leading minus sign. */
|
||||||
if(*p == '-')
|
if(*p == '-')
|
||||||
sign = 1, p++;
|
sign = 1, p++;
|
||||||
@ -1754,6 +1799,8 @@ unsigned int
|
|||||||
APFloat::convertToHexString(char *dst, unsigned int hexDigits,
|
APFloat::convertToHexString(char *dst, unsigned int hexDigits,
|
||||||
bool upperCase, roundingMode rounding_mode) const
|
bool upperCase, roundingMode rounding_mode) const
|
||||||
{
|
{
|
||||||
|
assert(semantics != (const llvm::fltSemantics* const)&PPCDoubleDouble &&
|
||||||
|
"Compile-time arithmetic on PPC long double not supported yet");
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = dst;
|
p = dst;
|
||||||
@ -1961,6 +2008,51 @@ APFloat::convertF80LongDoubleAPFloatToAPInt() const
|
|||||||
return APInt(80, 2, words);
|
return APInt(80, 2, words);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
APInt
|
||||||
|
APFloat::convertPPCDoubleDoubleAPFloatToAPInt() const
|
||||||
|
{
|
||||||
|
assert(semantics == (const llvm::fltSemantics* const)&PPCDoubleDouble);
|
||||||
|
assert (partCount()==2);
|
||||||
|
|
||||||
|
uint64_t myexponent, mysignificand, myexponent2, mysignificand2;
|
||||||
|
|
||||||
|
if (category==fcNormal) {
|
||||||
|
myexponent = exponent + 1023; //bias
|
||||||
|
myexponent2 = exponent2 + 1023;
|
||||||
|
mysignificand = significandParts()[0];
|
||||||
|
mysignificand2 = significandParts()[1];
|
||||||
|
if (myexponent==1 && !(mysignificand & 0x10000000000000LL))
|
||||||
|
myexponent = 0; // denormal
|
||||||
|
if (myexponent2==1 && !(mysignificand2 & 0x10000000000000LL))
|
||||||
|
myexponent2 = 0; // denormal
|
||||||
|
} else if (category==fcZero) {
|
||||||
|
myexponent = 0;
|
||||||
|
mysignificand = 0;
|
||||||
|
myexponent2 = 0;
|
||||||
|
mysignificand2 = 0;
|
||||||
|
} else if (category==fcInfinity) {
|
||||||
|
myexponent = 0x7ff;
|
||||||
|
myexponent2 = 0;
|
||||||
|
mysignificand = 0;
|
||||||
|
mysignificand2 = 0;
|
||||||
|
} else {
|
||||||
|
assert(category == fcNaN && "Unknown category");
|
||||||
|
myexponent = 0x7ff;
|
||||||
|
mysignificand = significandParts()[0];
|
||||||
|
myexponent2 = exponent2;
|
||||||
|
mysignificand2 = significandParts()[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t words[2];
|
||||||
|
words[0] = (((uint64_t)sign & 1) << 63) |
|
||||||
|
((myexponent & 0x7ff) << 52) |
|
||||||
|
(mysignificand & 0xfffffffffffffLL);
|
||||||
|
words[1] = (((uint64_t)sign2 & 1) << 63) |
|
||||||
|
((myexponent2 & 0x7ff) << 52) |
|
||||||
|
(mysignificand2 & 0xfffffffffffffLL);
|
||||||
|
return APInt(128, 2, words);
|
||||||
|
}
|
||||||
|
|
||||||
APInt
|
APInt
|
||||||
APFloat::convertDoubleAPFloatToAPInt() const
|
APFloat::convertDoubleAPFloatToAPInt() const
|
||||||
{
|
{
|
||||||
@ -2020,6 +2112,10 @@ APFloat::convertFloatAPFloatToAPInt() const
|
|||||||
(mysignificand & 0x7fffff)));
|
(mysignificand & 0x7fffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
APInt
|
APInt
|
||||||
APFloat::convertToAPInt() const
|
APFloat::convertToAPInt() const
|
||||||
{
|
{
|
||||||
@ -2029,6 +2125,9 @@ APFloat::convertToAPInt() const
|
|||||||
if (semantics == (const llvm::fltSemantics* const)&IEEEdouble)
|
if (semantics == (const llvm::fltSemantics* const)&IEEEdouble)
|
||||||
return convertDoubleAPFloatToAPInt();
|
return convertDoubleAPFloatToAPInt();
|
||||||
|
|
||||||
|
if (semantics == (const llvm::fltSemantics* const)&PPCDoubleDouble)
|
||||||
|
return convertPPCDoubleDoubleAPFloatToAPInt();
|
||||||
|
|
||||||
assert(semantics == (const llvm::fltSemantics* const)&x87DoubleExtended &&
|
assert(semantics == (const llvm::fltSemantics* const)&x87DoubleExtended &&
|
||||||
"unknown format!");
|
"unknown format!");
|
||||||
return convertF80LongDoubleAPFloatToAPInt();
|
return convertF80LongDoubleAPFloatToAPInt();
|
||||||
@ -2090,6 +2189,56 @@ APFloat::initFromF80LongDoubleAPInt(const APInt &api)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
APFloat::initFromPPCDoubleDoubleAPInt(const APInt &api)
|
||||||
|
{
|
||||||
|
assert(api.getBitWidth()==128);
|
||||||
|
uint64_t i1 = api.getRawData()[0];
|
||||||
|
uint64_t i2 = api.getRawData()[1];
|
||||||
|
uint64_t myexponent = (i1 >> 52) & 0x7ff;
|
||||||
|
uint64_t mysignificand = i1 & 0xfffffffffffffLL;
|
||||||
|
uint64_t myexponent2 = (i2 >> 52) & 0x7ff;
|
||||||
|
uint64_t mysignificand2 = i2 & 0xfffffffffffffLL;
|
||||||
|
|
||||||
|
initialize(&APFloat::PPCDoubleDouble);
|
||||||
|
assert(partCount()==2);
|
||||||
|
|
||||||
|
sign = i1>>63;
|
||||||
|
sign2 = i2>>63;
|
||||||
|
if (myexponent==0 && mysignificand==0) {
|
||||||
|
// exponent, significand meaningless
|
||||||
|
// exponent2 and significand2 are required to be 0; we don't check
|
||||||
|
category = fcZero;
|
||||||
|
} else if (myexponent==0x7ff && mysignificand==0) {
|
||||||
|
// exponent, significand meaningless
|
||||||
|
// exponent2 and significand2 are required to be 0; we don't check
|
||||||
|
category = fcInfinity;
|
||||||
|
} else if (myexponent==0x7ff && mysignificand!=0) {
|
||||||
|
// exponent meaningless. So is the whole second word, but keep it
|
||||||
|
// for determinism.
|
||||||
|
category = fcNaN;
|
||||||
|
exponent2 = myexponent2;
|
||||||
|
significandParts()[0] = mysignificand;
|
||||||
|
significandParts()[1] = mysignificand2;
|
||||||
|
} else {
|
||||||
|
category = fcNormal;
|
||||||
|
// Note there is no category2; the second word is treated as if it is
|
||||||
|
// fcNormal, although it might be something else considered by itself.
|
||||||
|
exponent = myexponent - 1023;
|
||||||
|
exponent2 = myexponent2 - 1023;
|
||||||
|
significandParts()[0] = mysignificand;
|
||||||
|
significandParts()[1] = mysignificand2;
|
||||||
|
if (myexponent==0) // denormal
|
||||||
|
exponent = -1022;
|
||||||
|
else
|
||||||
|
significandParts()[0] |= 0x10000000000000LL; // integer bit
|
||||||
|
if (myexponent2==0)
|
||||||
|
exponent2 = -1022;
|
||||||
|
else
|
||||||
|
significandParts()[1] |= 0x10000000000000LL; // integer bit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
APFloat::initFromDoubleAPInt(const APInt &api)
|
APFloat::initFromDoubleAPInt(const APInt &api)
|
||||||
{
|
{
|
||||||
@ -2157,11 +2306,11 @@ APFloat::initFromFloatAPInt(const APInt & api)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Treat api as containing the bits of a floating point number. Currently
|
/// 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
|
/// we infer the floating point type from the size of the APInt. The
|
||||||
/// breaks when we get to PPC128 and IEEE128 (but both cannot exist in the
|
/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful
|
||||||
/// same compile...)
|
/// when the size is anything else).
|
||||||
void
|
void
|
||||||
APFloat::initFromAPInt(const APInt& api)
|
APFloat::initFromAPInt(const APInt& api, bool isIEEE)
|
||||||
{
|
{
|
||||||
if (api.getBitWidth() == 32)
|
if (api.getBitWidth() == 32)
|
||||||
return initFromFloatAPInt(api);
|
return initFromFloatAPInt(api);
|
||||||
@ -2169,13 +2318,15 @@ APFloat::initFromAPInt(const APInt& api)
|
|||||||
return initFromDoubleAPInt(api);
|
return initFromDoubleAPInt(api);
|
||||||
else if (api.getBitWidth()==80)
|
else if (api.getBitWidth()==80)
|
||||||
return initFromF80LongDoubleAPInt(api);
|
return initFromF80LongDoubleAPInt(api);
|
||||||
|
else if (api.getBitWidth()==128 && !isIEEE)
|
||||||
|
return initFromPPCDoubleDoubleAPInt(api);
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat::APFloat(const APInt& api)
|
APFloat::APFloat(const APInt& api, bool isIEEE)
|
||||||
{
|
{
|
||||||
initFromAPInt(api);
|
initFromAPInt(api, isIEEE);
|
||||||
}
|
}
|
||||||
|
|
||||||
APFloat::APFloat(float f)
|
APFloat::APFloat(float f)
|
||||||
|
@ -519,6 +519,8 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
|
|||||||
Out << 'K';
|
Out << 'K';
|
||||||
else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad)
|
else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad)
|
||||||
Out << 'L';
|
Out << 'L';
|
||||||
|
else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble)
|
||||||
|
Out << 'M';
|
||||||
else
|
else
|
||||||
assert(0 && "Unsupported floating point type");
|
assert(0 && "Unsupported floating point type");
|
||||||
// api needed to prevent premature destruction
|
// api needed to prevent premature destruction
|
||||||
@ -526,7 +528,7 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
|
|||||||
const uint64_t* p = api.getRawData();
|
const uint64_t* p = api.getRawData();
|
||||||
uint64_t word = *p;
|
uint64_t word = *p;
|
||||||
int shiftcount=60;
|
int shiftcount=60;
|
||||||
int width = CFP->getValueAPF().convertToAPInt().getBitWidth();
|
int width = api.getBitWidth();
|
||||||
for (int j=0; j<width; j+=4, shiftcount-=4) {
|
for (int j=0; j<width; j+=4, shiftcount-=4) {
|
||||||
unsigned int nibble = (word>>shiftcount) & 15;
|
unsigned int nibble = (word>>shiftcount) & 15;
|
||||||
if (nibble < 10)
|
if (nibble < 10)
|
||||||
@ -535,7 +537,7 @@ static void WriteConstantInt(std::ostream &Out, const Constant *CV,
|
|||||||
Out << (unsigned char)(nibble - 10 + 'A');
|
Out << (unsigned char)(nibble - 10 + 'A');
|
||||||
if (shiftcount == 0) {
|
if (shiftcount == 0) {
|
||||||
word = *(++p);
|
word = *(++p);
|
||||||
shiftcount = 60;
|
shiftcount = 64;
|
||||||
if (width-j-4 < 64)
|
if (width-j-4 < 64)
|
||||||
shiftcount = width-j-4;
|
shiftcount = width-j-4;
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,7 @@ Constant *Constant::getNullValue(const Type *Ty) {
|
|||||||
case Type::X86_FP80TyID:
|
case Type::X86_FP80TyID:
|
||||||
return ConstantFP::get(Ty, APFloat(APInt(80, 2, zero)));
|
return ConstantFP::get(Ty, APFloat(APInt(80, 2, zero)));
|
||||||
case Type::FP128TyID:
|
case Type::FP128TyID:
|
||||||
|
return ConstantFP::get(Ty, APFloat(APInt(128, 2, zero), true));
|
||||||
case Type::PPC_FP128TyID:
|
case Type::PPC_FP128TyID:
|
||||||
return ConstantFP::get(Ty, APFloat(APInt(128, 2, zero)));
|
return ConstantFP::get(Ty, APFloat(APInt(128, 2, zero)));
|
||||||
case Type::PointerTyID:
|
case Type::PointerTyID:
|
||||||
@ -256,6 +257,8 @@ ConstantFP::ConstantFP(const Type *Ty, const APFloat& V)
|
|||||||
assert(&V.getSemantics()==&APFloat::x87DoubleExtended);
|
assert(&V.getSemantics()==&APFloat::x87DoubleExtended);
|
||||||
else if (Ty==Type::FP128Ty)
|
else if (Ty==Type::FP128Ty)
|
||||||
assert(&V.getSemantics()==&APFloat::IEEEquad);
|
assert(&V.getSemantics()==&APFloat::IEEEquad);
|
||||||
|
else if (Ty==Type::PPC_FP128Ty)
|
||||||
|
assert(&V.getSemantics()==&APFloat::PPCDoubleDouble);
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
@ -320,6 +323,8 @@ ConstantFP *ConstantFP::get(const Type *Ty, const APFloat& V) {
|
|||||||
assert(&V.getSemantics()==&APFloat::x87DoubleExtended);
|
assert(&V.getSemantics()==&APFloat::x87DoubleExtended);
|
||||||
else if (Ty==Type::FP128Ty)
|
else if (Ty==Type::FP128Ty)
|
||||||
assert(&V.getSemantics()==&APFloat::IEEEquad);
|
assert(&V.getSemantics()==&APFloat::IEEEquad);
|
||||||
|
else if (Ty==Type::PPC_FP128Ty)
|
||||||
|
assert(&V.getSemantics()==&APFloat::PPCDoubleDouble);
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
|
|
||||||
@ -747,6 +752,10 @@ bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) {
|
|||||||
return &Val2.getSemantics() == &APFloat::IEEEsingle ||
|
return &Val2.getSemantics() == &APFloat::IEEEsingle ||
|
||||||
&Val2.getSemantics() == &APFloat::IEEEdouble ||
|
&Val2.getSemantics() == &APFloat::IEEEdouble ||
|
||||||
&Val2.getSemantics() == &APFloat::IEEEquad;
|
&Val2.getSemantics() == &APFloat::IEEEquad;
|
||||||
|
case Type::PPC_FP128TyID:
|
||||||
|
return &Val2.getSemantics() == &APFloat::IEEEsingle ||
|
||||||
|
&Val2.getSemantics() == &APFloat::IEEEdouble ||
|
||||||
|
&Val2.getSemantics() == &APFloat::PPCDoubleDouble;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user