mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-22 03:39:03 +00:00
Add half precision floating point support (float16) to APFloat,
patch by Peter Johnson! (PR5195) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84239 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a43fc3452b
commit
cc4287a374
@ -125,6 +125,7 @@ namespace llvm {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/* We support the following floating point semantics. */
|
/* We support the following floating point semantics. */
|
||||||
|
static const fltSemantics IEEEhalf;
|
||||||
static const fltSemantics IEEEsingle;
|
static const fltSemantics IEEEsingle;
|
||||||
static const fltSemantics IEEEdouble;
|
static const fltSemantics IEEEdouble;
|
||||||
static const fltSemantics IEEEquad;
|
static const fltSemantics IEEEquad;
|
||||||
@ -321,12 +322,14 @@ namespace llvm {
|
|||||||
opStatus roundSignificandWithExponent(const integerPart *, unsigned int,
|
opStatus roundSignificandWithExponent(const integerPart *, unsigned int,
|
||||||
int, roundingMode);
|
int, roundingMode);
|
||||||
|
|
||||||
|
APInt convertHalfAPFloatToAPInt() const;
|
||||||
APInt convertFloatAPFloatToAPInt() const;
|
APInt convertFloatAPFloatToAPInt() const;
|
||||||
APInt convertDoubleAPFloatToAPInt() const;
|
APInt convertDoubleAPFloatToAPInt() const;
|
||||||
APInt convertQuadrupleAPFloatToAPInt() const;
|
APInt convertQuadrupleAPFloatToAPInt() const;
|
||||||
APInt convertF80LongDoubleAPFloatToAPInt() const;
|
APInt convertF80LongDoubleAPFloatToAPInt() const;
|
||||||
APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
|
APInt convertPPCDoubleDoubleAPFloatToAPInt() const;
|
||||||
void initFromAPInt(const APInt& api, bool isIEEE = false);
|
void initFromAPInt(const APInt& api, bool isIEEE = false);
|
||||||
|
void initFromHalfAPInt(const APInt& api);
|
||||||
void initFromFloatAPInt(const APInt& api);
|
void initFromFloatAPInt(const APInt& api);
|
||||||
void initFromDoubleAPInt(const APInt& api);
|
void initFromDoubleAPInt(const APInt& api);
|
||||||
void initFromQuadrupleAPInt(const APInt &api);
|
void initFromQuadrupleAPInt(const APInt &api);
|
||||||
|
@ -48,6 +48,7 @@ namespace llvm {
|
|||||||
unsigned int arithmeticOK;
|
unsigned int arithmeticOK;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fltSemantics APFloat::IEEEhalf = { 15, -14, 11, true };
|
||||||
const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true };
|
const fltSemantics APFloat::IEEEsingle = { 127, -126, 24, true };
|
||||||
const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true };
|
const fltSemantics APFloat::IEEEdouble = { 1023, -1022, 53, true };
|
||||||
const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true };
|
const fltSemantics APFloat::IEEEquad = { 16383, -16382, 113, true };
|
||||||
@ -2812,6 +2813,35 @@ APFloat::convertFloatAPFloatToAPInt() const
|
|||||||
(mysignificand & 0x7fffff)));
|
(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 = 0xff;
|
||||||
|
mysignificand = 0;
|
||||||
|
} else {
|
||||||
|
assert(category == fcNaN && "Unknown category!");
|
||||||
|
myexponent = 0xff;
|
||||||
|
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
|
// 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,
|
// 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.
|
// and treating the result as a normal integer is unlikely to be useful.
|
||||||
@ -2819,6 +2849,9 @@ APFloat::convertFloatAPFloatToAPInt() const
|
|||||||
APInt
|
APInt
|
||||||
APFloat::bitcastToAPInt() const
|
APFloat::bitcastToAPInt() const
|
||||||
{
|
{
|
||||||
|
if (semantics == (const llvm::fltSemantics*)&IEEEhalf)
|
||||||
|
return convertHalfAPFloatToAPInt();
|
||||||
|
|
||||||
if (semantics == (const llvm::fltSemantics*)&IEEEsingle)
|
if (semantics == (const llvm::fltSemantics*)&IEEEsingle)
|
||||||
return convertFloatAPFloatToAPInt();
|
return convertFloatAPFloatToAPInt();
|
||||||
|
|
||||||
@ -3051,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 >> 15) & 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
|
/// 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
|
/// we infer the floating point type from the size of the APInt. The
|
||||||
/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful
|
/// isIEEE argument distinguishes between PPC128 and IEEE128 (not meaningful
|
||||||
@ -3058,7 +3124,9 @@ APFloat::initFromFloatAPInt(const APInt & api)
|
|||||||
void
|
void
|
||||||
APFloat::initFromAPInt(const APInt& api, bool isIEEE)
|
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);
|
return initFromFloatAPInt(api);
|
||||||
else if (api.getBitWidth()==64)
|
else if (api.getBitWidth()==64)
|
||||||
return initFromDoubleAPInt(api);
|
return initFromDoubleAPInt(api);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user