mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-02 07:32:52 +00:00
1. Make APInt::shl work correctly and more efficiently.
2. Add functions to support the numberical conversion between APInt and double/float. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34201 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
21ba3d7c2b
commit
d93f00c35d
@ -289,6 +289,9 @@ public:
|
|||||||
inline uint64_t getValue() {
|
inline uint64_t getValue() {
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
return VAL;
|
return VAL;
|
||||||
|
unsigned n = getNumWords() * 64 - CountLeadingZeros();
|
||||||
|
if (n <= 64)
|
||||||
|
return pVal[0];
|
||||||
assert(0 && "This APInt's bitwidth > 64");
|
assert(0 && "This APInt's bitwidth > 64");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,6 +388,9 @@ public:
|
|||||||
CountLeadingZeros();
|
CountLeadingZeros();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Converts this APInt to a double value.
|
||||||
|
double APIntRoundToDouble(bool isSigned = false) const;
|
||||||
|
|
||||||
/// Arithmetic right-shift this APInt by shiftAmt.
|
/// Arithmetic right-shift this APInt by shiftAmt.
|
||||||
/// @brief Arithmetic right-shift function.
|
/// @brief Arithmetic right-shift function.
|
||||||
APInt ashr(unsigned shiftAmt) const;
|
APInt ashr(unsigned shiftAmt) const;
|
||||||
@ -456,6 +462,24 @@ inline unsigned LogBase2(const APInt& APIVal) {
|
|||||||
/// using Euclid's algorithm.
|
/// using Euclid's algorithm.
|
||||||
APInt GreatestCommonDivisor(const APInt& API1, const APInt& API2);
|
APInt GreatestCommonDivisor(const APInt& API1, const APInt& API2);
|
||||||
|
|
||||||
|
/// @brief Converts the given APInt to a double value.
|
||||||
|
inline double APIntRoundToDouble(const APInt& APIVal, bool isSigned = false) {
|
||||||
|
return APIVal.APIntRoundToDouble(isSigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Converts the given APInt to a float vlalue.
|
||||||
|
inline float APIntRoundToFloat(const APInt& APIVal) {
|
||||||
|
return float(APIntRoundToDouble(APIVal));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Converts the given double value into a APInt.
|
||||||
|
APInt DoubleRoundToAPInt(double Double);
|
||||||
|
|
||||||
|
/// @brief Converts the given float value into a APInt.
|
||||||
|
inline APInt FloatRoundToAPInt(float Float) {
|
||||||
|
return DoubleRoundToAPInt(double(Float));
|
||||||
|
}
|
||||||
|
|
||||||
/// Arithmetic right-shift the APInt by shiftAmt.
|
/// Arithmetic right-shift the APInt by shiftAmt.
|
||||||
/// @brief Arithmetic right-shift function.
|
/// @brief Arithmetic right-shift function.
|
||||||
inline APInt ashr(const APInt& LHS, unsigned shiftAmt) {
|
inline APInt ashr(const APInt& LHS, unsigned shiftAmt) {
|
||||||
|
@ -955,6 +955,69 @@ APInt llvm::APIntOps::GreatestCommonDivisor(const APInt& API1,
|
|||||||
return A;
|
return A;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// DoubleRoundToAPInt - This function convert a double value to
|
||||||
|
/// a APInt value.
|
||||||
|
APInt llvm::APIntOps::DoubleRoundToAPInt(double Double) {
|
||||||
|
union {
|
||||||
|
double D;
|
||||||
|
uint64_t I;
|
||||||
|
} T;
|
||||||
|
T.D = Double;
|
||||||
|
bool isNeg = T.I >> 63;
|
||||||
|
int64_t exp = ((T.I >> 52) & 0x7ff) - 1023;
|
||||||
|
if (exp < 0)
|
||||||
|
return APInt(0);
|
||||||
|
uint64_t mantissa = ((T.I << 12) >> 12) | (1ULL << 52);
|
||||||
|
if (exp < 52)
|
||||||
|
return isNeg ? -APInt(mantissa >> (52 - exp)) :
|
||||||
|
APInt(mantissa >> (52 - exp));
|
||||||
|
APInt Tmp(mantissa, exp + 1);
|
||||||
|
Tmp = Tmp.shl(exp - 52);
|
||||||
|
return isNeg ? -Tmp : Tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// APIntRoundToDouble - This function convert this APInt to a double.
|
||||||
|
/// The layout for double is as following (IEEE Standard 754):
|
||||||
|
/// --------------------------------------
|
||||||
|
/// | Sign Exponent Fraction Bias |
|
||||||
|
/// |-------------------------------------- |
|
||||||
|
/// | 1[63] 11[62-52] 52[51-00] 1023 |
|
||||||
|
/// --------------------------------------
|
||||||
|
double APInt::APIntRoundToDouble(bool isSigned) const {
|
||||||
|
bool isNeg = isSigned ? (*this)[BitsNum-1] : false;
|
||||||
|
APInt Tmp(isNeg ? -(*this) : (*this));
|
||||||
|
if (Tmp.isSingleWord())
|
||||||
|
return isSigned ? double(int64_t(Tmp.VAL)) : double(Tmp.VAL);
|
||||||
|
unsigned n = Tmp.getNumWords() * 64 - Tmp.CountLeadingZeros();
|
||||||
|
if (n <= 64)
|
||||||
|
return isSigned ? double(int64_t(Tmp.pVal[0])) : double(Tmp.pVal[0]);
|
||||||
|
// Exponent when normalized to have decimal point directly after
|
||||||
|
// leading one. This is stored excess 1023 in the exponent bit field.
|
||||||
|
uint64_t exp = n - 1;
|
||||||
|
|
||||||
|
// Gross overflow.
|
||||||
|
assert(exp <= 1023 && "Infinity value!");
|
||||||
|
|
||||||
|
// Number of bits in mantissa including the leading one
|
||||||
|
// equals to 53.
|
||||||
|
uint64_t mantissa;
|
||||||
|
if (n % 64 >= 53)
|
||||||
|
mantissa = Tmp.pVal[whichWord(n - 1)] >> (n % 64 - 53);
|
||||||
|
else
|
||||||
|
mantissa = (Tmp.pVal[whichWord(n - 1)] << (53 - n % 64)) |
|
||||||
|
(Tmp.pVal[whichWord(n - 1) - 1] >> (11 + n % 64));
|
||||||
|
// The leading bit of mantissa is implicit, so get rid of it.
|
||||||
|
mantissa &= ~(1ULL << 52);
|
||||||
|
uint64_t sign = isNeg ? (1ULL << 63) : 0;
|
||||||
|
exp += 1023;
|
||||||
|
union {
|
||||||
|
double D;
|
||||||
|
uint64_t I;
|
||||||
|
} T;
|
||||||
|
T.I = sign | (exp << 52) | mantissa;
|
||||||
|
return T.D;
|
||||||
|
}
|
||||||
|
|
||||||
/// Arithmetic right-shift this APInt by shiftAmt.
|
/// Arithmetic right-shift this APInt by shiftAmt.
|
||||||
/// @brief Arithmetic right-shift function.
|
/// @brief Arithmetic right-shift function.
|
||||||
APInt APInt::ashr(unsigned shiftAmt) const {
|
APInt APInt::ashr(unsigned shiftAmt) const {
|
||||||
@ -1004,17 +1067,22 @@ APInt APInt::lshr(unsigned shiftAmt) const {
|
|||||||
/// @brief Left-shift function.
|
/// @brief Left-shift function.
|
||||||
APInt APInt::shl(unsigned shiftAmt) const {
|
APInt APInt::shl(unsigned shiftAmt) const {
|
||||||
APInt API(*this);
|
APInt API(*this);
|
||||||
if (shiftAmt >= API.BitsNum) {
|
if (API.isSingleWord())
|
||||||
if (API.isSingleWord())
|
API.VAL <<= shiftAmt;
|
||||||
API.VAL = 0;
|
else if (shiftAmt >= API.BitsNum)
|
||||||
else
|
memset(API.pVal, 0, API.getNumWords() * 8);
|
||||||
memset(API.pVal, 0, API.getNumWords() * 8);
|
else {
|
||||||
} else {
|
if (unsigned offset = shiftAmt / 64) {
|
||||||
for (unsigned i = 0; i < shiftAmt; ++i) API.clear(i);
|
for (unsigned i = API.getNumWords() - 1; i > offset - 1; --i)
|
||||||
for (unsigned i = shiftAmt; i < API.BitsNum; ++i) {
|
API.pVal[i] = API.pVal[i-offset];
|
||||||
if (API[i-shiftAmt]) API.set(i);
|
memset(API.pVal, 0, offset * 8);
|
||||||
else API.clear(i);
|
|
||||||
}
|
}
|
||||||
|
shiftAmt %= 64;
|
||||||
|
unsigned i;
|
||||||
|
for (i = API.getNumWords() - 1; i > 0; --i)
|
||||||
|
API.pVal[i] = (API.pVal[i] << shiftAmt) |
|
||||||
|
(API.pVal[i-1] >> (64-shiftAmt));
|
||||||
|
API.pVal[i] <<= shiftAmt;
|
||||||
}
|
}
|
||||||
return API;
|
return API;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user