mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-02 07:32:52 +00:00
Add some things needed by the llvm-gcc version supporting bit accurate integer
types: 1. Functions to compute div/rem at the same time. 2. Further assurance that an APInt with 0 bitwidth cannot be constructed. 3. Left and right rotate operations. 4. An exactLogBase2 function which requires an exact power of two or it returns -1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37025 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9273418777
commit
19dc32a2d4
@ -567,6 +567,12 @@ public:
|
|||||||
/// @brief Left-shift function.
|
/// @brief Left-shift function.
|
||||||
APInt shl(uint32_t shiftAmt) const;
|
APInt shl(uint32_t shiftAmt) const;
|
||||||
|
|
||||||
|
/// @brief Rotate left by rotateAmt.
|
||||||
|
APInt rotl(uint32_t rotateAmt) const;
|
||||||
|
|
||||||
|
/// @brief Rotate right by rotateAmt.
|
||||||
|
APInt rotr(uint32_t rotateAmt) const;
|
||||||
|
|
||||||
/// Perform an unsigned divide operation on this APInt by RHS. Both this and
|
/// Perform an unsigned divide operation on this APInt by RHS. Both this and
|
||||||
/// RHS are treated as unsigned quantities for purposes of this division.
|
/// RHS are treated as unsigned quantities for purposes of this division.
|
||||||
/// @returns a new APInt value containing the division result
|
/// @returns a new APInt value containing the division result
|
||||||
@ -608,6 +614,31 @@ public:
|
|||||||
return this->urem(RHS);
|
return this->urem(RHS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sometimes it is convenient to divide two APInt values and obtain both
|
||||||
|
/// the quotient and remainder. This function does both operations in the
|
||||||
|
/// same computation making it a little more efficient.
|
||||||
|
/// @brief Dual division/remainder interface.
|
||||||
|
static void udivrem(const APInt &LHS, const APInt &RHS,
|
||||||
|
APInt &Quotient, APInt &Remainder);
|
||||||
|
|
||||||
|
static void sdivrem(const APInt &LHS, const APInt &RHS,
|
||||||
|
APInt &Quotient, APInt &Remainder)
|
||||||
|
{
|
||||||
|
if (LHS.isNegative()) {
|
||||||
|
if (RHS.isNegative())
|
||||||
|
APInt::udivrem(-LHS, -RHS, Quotient, Remainder);
|
||||||
|
else
|
||||||
|
APInt::udivrem(-LHS, RHS, Quotient, Remainder);
|
||||||
|
Quotient = -Quotient;
|
||||||
|
Remainder = -Remainder;
|
||||||
|
} else if (RHS.isNegative()) {
|
||||||
|
APInt::udivrem(LHS, -RHS, Quotient, Remainder);
|
||||||
|
Quotient = -Quotient;
|
||||||
|
} else {
|
||||||
|
APInt::udivrem(LHS, RHS, Quotient, Remainder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns the bit value at bitPosition
|
/// @returns the bit value at bitPosition
|
||||||
/// @brief Array-indexing support.
|
/// @brief Array-indexing support.
|
||||||
bool operator[](uint32_t bitPosition) const;
|
bool operator[](uint32_t bitPosition) const;
|
||||||
@ -988,6 +1019,14 @@ public:
|
|||||||
return BitWidth - 1 - countLeadingZeros();
|
return BitWidth - 1 - countLeadingZeros();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @returns the log base 2 of this APInt if its an exact power of two, -1
|
||||||
|
/// otherwise
|
||||||
|
inline int32_t exactLogBase2() const {
|
||||||
|
if (!isPowerOf2())
|
||||||
|
return -1;
|
||||||
|
return logBase2();
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Compute the square root
|
/// @brief Compute the square root
|
||||||
APInt sqrt() const;
|
APInt sqrt() const;
|
||||||
|
|
||||||
|
@ -82,17 +82,23 @@ APInt::APInt(uint32_t numBits, uint32_t numWords, uint64_t bigVal[])
|
|||||||
APInt::APInt(uint32_t numbits, const char StrStart[], uint32_t slen,
|
APInt::APInt(uint32_t numbits, const char StrStart[], uint32_t slen,
|
||||||
uint8_t radix)
|
uint8_t radix)
|
||||||
: BitWidth(numbits), VAL(0) {
|
: BitWidth(numbits), VAL(0) {
|
||||||
|
assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
||||||
|
assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
||||||
fromString(numbits, StrStart, slen, radix);
|
fromString(numbits, StrStart, slen, radix);
|
||||||
}
|
}
|
||||||
|
|
||||||
APInt::APInt(uint32_t numbits, const std::string& Val, uint8_t radix)
|
APInt::APInt(uint32_t numbits, const std::string& Val, uint8_t radix)
|
||||||
: BitWidth(numbits), VAL(0) {
|
: BitWidth(numbits), VAL(0) {
|
||||||
|
assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
||||||
|
assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
||||||
assert(!Val.empty() && "String empty?");
|
assert(!Val.empty() && "String empty?");
|
||||||
fromString(numbits, Val.c_str(), Val.size(), radix);
|
fromString(numbits, Val.c_str(), Val.size(), radix);
|
||||||
}
|
}
|
||||||
|
|
||||||
APInt::APInt(const APInt& that)
|
APInt::APInt(const APInt& that)
|
||||||
: BitWidth(that.BitWidth), VAL(0) {
|
: BitWidth(that.BitWidth), VAL(0) {
|
||||||
|
assert(BitWidth >= IntegerType::MIN_INT_BITS && "bitwidth too small");
|
||||||
|
assert(BitWidth <= IntegerType::MAX_INT_BITS && "bitwidth too large");
|
||||||
if (isSingleWord())
|
if (isSingleWord())
|
||||||
VAL = that.VAL;
|
VAL = that.VAL;
|
||||||
else {
|
else {
|
||||||
@ -1242,6 +1248,23 @@ APInt APInt::shl(uint32_t shiftAmt) const {
|
|||||||
return APInt(val, BitWidth).clearUnusedBits();
|
return APInt(val, BitWidth).clearUnusedBits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
APInt APInt::rotl(uint32_t rotateAmt) const {
|
||||||
|
// Don't get too fancy, just use existing shift/or facilities
|
||||||
|
APInt hi(*this);
|
||||||
|
APInt lo(*this);
|
||||||
|
hi.shl(rotateAmt);
|
||||||
|
lo.lshr(BitWidth - rotateAmt);
|
||||||
|
return hi | lo;
|
||||||
|
}
|
||||||
|
|
||||||
|
APInt APInt::rotr(uint32_t rotateAmt) const {
|
||||||
|
// Don't get too fancy, just use existing shift/or facilities
|
||||||
|
APInt hi(*this);
|
||||||
|
APInt lo(*this);
|
||||||
|
lo.lshr(rotateAmt);
|
||||||
|
hi.shl(BitWidth - rotateAmt);
|
||||||
|
return hi | lo;
|
||||||
|
}
|
||||||
|
|
||||||
// Square Root - this method computes and returns the square root of "this".
|
// Square Root - this method computes and returns the square root of "this".
|
||||||
// Three mechanisms are used for computation. For small values (<= 5 bits),
|
// Three mechanisms are used for computation. For small values (<= 5 bits),
|
||||||
@ -1754,12 +1777,55 @@ APInt APInt::urem(const APInt& RHS) const {
|
|||||||
return APInt(BitWidth, pVal[0] % RHS.pVal[0]);
|
return APInt(BitWidth, pVal[0] % RHS.pVal[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to compute it the hard way. Invoke the Knute divide algorithm.
|
// We have to compute it the hard way. Invoke the Knuth divide algorithm.
|
||||||
APInt Remainder(1,0);
|
APInt Remainder(1,0);
|
||||||
divide(*this, lhsWords, RHS, rhsWords, 0, &Remainder);
|
divide(*this, lhsWords, RHS, rhsWords, 0, &Remainder);
|
||||||
return Remainder;
|
return Remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APInt::udivrem(const APInt &LHS, const APInt &RHS,
|
||||||
|
APInt &Quotient, APInt &Remainder) {
|
||||||
|
// Get some size facts about the dividend and divisor
|
||||||
|
uint32_t lhsBits = LHS.getActiveBits();
|
||||||
|
uint32_t lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1);
|
||||||
|
uint32_t rhsBits = RHS.getActiveBits();
|
||||||
|
uint32_t rhsWords = !rhsBits ? 0 : (APInt::whichWord(rhsBits - 1) + 1);
|
||||||
|
|
||||||
|
// Check the degenerate cases
|
||||||
|
if (lhsWords == 0) {
|
||||||
|
Quotient = 0; // 0 / Y ===> 0
|
||||||
|
Remainder = 0; // 0 % Y ===> 0
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhsWords < rhsWords || LHS.ult(RHS)) {
|
||||||
|
Quotient = 0; // X / Y ===> 0, iff X < Y
|
||||||
|
Remainder = LHS; // X % Y ===> X, iff X < Y
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LHS == RHS) {
|
||||||
|
Quotient = 1; // X / X ===> 1
|
||||||
|
Remainder = 0; // X % X ===> 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lhsWords == 1 && rhsWords == 1) {
|
||||||
|
// There is only one word to consider so use the native versions.
|
||||||
|
if (LHS.isSingleWord()) {
|
||||||
|
Quotient = APInt(LHS.getBitWidth(), LHS.VAL / RHS.VAL);
|
||||||
|
Remainder = APInt(LHS.getBitWidth(), LHS.VAL % RHS.VAL);
|
||||||
|
} else {
|
||||||
|
Quotient = APInt(LHS.getBitWidth(), LHS.pVal[0] / RHS.pVal[0]);
|
||||||
|
Remainder = APInt(LHS.getBitWidth(), LHS.pVal[0] % RHS.pVal[0]);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, lets do it the long way
|
||||||
|
divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder);
|
||||||
|
}
|
||||||
|
|
||||||
void APInt::fromString(uint32_t numbits, const char *str, uint32_t slen,
|
void APInt::fromString(uint32_t numbits, const char *str, uint32_t slen,
|
||||||
uint8_t radix) {
|
uint8_t radix) {
|
||||||
// Check our assumptions here
|
// Check our assumptions here
|
||||||
|
Loading…
Reference in New Issue
Block a user