summaryrefslogtreecommitdiffstats
path: root/lib/Support/APInt.cpp
diff options
context:
space:
mode:
authorNeil Booth <neil@daikokuya.co.uk>2007-10-08 13:47:12 +0000
committerNeil Booth <neil@daikokuya.co.uk>2007-10-08 13:47:12 +0000
commit68e53ad6cb0a9d64d256f9dcef70331cd72d795e (patch)
tree4950f89a26f58ce497e0c332a4c1d2be75dc42a2 /lib/Support/APInt.cpp
parent633360c9d9312cd159ab4ef98e918924a06cfdbd (diff)
downloadexternal_llvm-68e53ad6cb0a9d64d256f9dcef70331cd72d795e.zip
external_llvm-68e53ad6cb0a9d64d256f9dcef70331cd72d795e.tar.gz
external_llvm-68e53ad6cb0a9d64d256f9dcef70331cd72d795e.tar.bz2
Add a new function tcExtract for extracting a bignum from an
arbitrary range of bits embedded in the middle of another bignum. This kind of operation is desirable in many cases of software floating point, e.g. converting bignum integers to floating point numbers of fixed precision (you want to extract the precision most significant bits). Elsewhere, add an assertion, and exit the shift functions early if the shift count is zero. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42745 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Support/APInt.cpp')
-rw-r--r--lib/Support/APInt.cpp110
1 files changed, 76 insertions, 34 deletions
diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp
index aa6cfa7..2e537d6 100644
--- a/lib/Support/APInt.cpp
+++ b/lib/Support/APInt.cpp
@@ -2101,6 +2101,8 @@ APInt::tcSet(integerPart *dst, integerPart part, unsigned int parts)
{
unsigned int i;
+ assert (parts > 0);
+
dst[0] = part;
for(i = 1; i < parts; i++)
dst[i] = 0;
@@ -2182,6 +2184,42 @@ APInt::tcMSB(const integerPart *parts, unsigned int n)
return -1U;
}
+/* Copy the bit vector of width srcBITS from SRC, starting at bit
+ srcLSB, to DST, of dstCOUNT parts, such that the bit srcLSB becomes
+ the least significant bit of DST. All high bits above srcBITS in
+ DST are zero-filled. */
+void
+APInt::tcExtract(integerPart *dst, unsigned int dstCount, const integerPart *src,
+ unsigned int srcBits, unsigned int srcLSB)
+{
+ unsigned int firstSrcPart, dstParts, shift, n;
+
+ dstParts = (srcBits + integerPartWidth - 1) / integerPartWidth;
+ assert (dstParts <= dstCount);
+
+ firstSrcPart = srcLSB / integerPartWidth;
+ tcAssign (dst, src + firstSrcPart, dstParts);
+
+ shift = srcLSB % integerPartWidth;
+ tcShiftRight (dst, dstParts, shift);
+
+ /* We now have (dstParts * integerPartWidth - shift) bits from SRC
+ in DST. If this is less that srcBits, append the rest, else
+ clear the high bits. */
+ n = dstParts * integerPartWidth - shift;
+ if (n < srcBits) {
+ integerPart mask = lowBitMask (srcBits - n);
+ dst[dstParts - 1] |= ((src[firstSrcPart + dstParts] & mask)
+ << n % integerPartWidth);
+ } else if (n > srcBits) {
+ dst[dstParts - 1] &= lowBitMask (srcBits % integerPartWidth);
+ }
+
+ /* Clear high parts. */
+ while (dstParts < dstCount)
+ dst[dstParts++] = 0;
+}
+
/* DST += RHS + C where C is zero or one. Returns the carry flag. */
integerPart
APInt::tcAdd(integerPart *dst, const integerPart *rhs,
@@ -2451,31 +2489,33 @@ APInt::tcDivide(integerPart *lhs, const integerPart *rhs,
void
APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count)
{
- unsigned int jump, shift;
+ if (count) {
+ unsigned int jump, shift;
- /* Jump is the inter-part jump; shift is is intra-part shift. */
- jump = count / integerPartWidth;
- shift = count % integerPartWidth;
+ /* Jump is the inter-part jump; shift is is intra-part shift. */
+ jump = count / integerPartWidth;
+ shift = count % integerPartWidth;
- while (parts > jump) {
- integerPart part;
+ while (parts > jump) {
+ integerPart part;
- parts--;
+ parts--;
- /* dst[i] comes from the two parts src[i - jump] and, if we have
- an intra-part shift, src[i - jump - 1]. */
- part = dst[parts - jump];
- if (shift) {
- part <<= shift;
+ /* dst[i] comes from the two parts src[i - jump] and, if we have
+ an intra-part shift, src[i - jump - 1]. */
+ part = dst[parts - jump];
+ if (shift) {
+ part <<= shift;
if (parts >= jump + 1)
part |= dst[parts - jump - 1] >> (integerPartWidth - shift);
}
- dst[parts] = part;
- }
+ dst[parts] = part;
+ }
- while (parts > 0)
- dst[--parts] = 0;
+ while (parts > 0)
+ dst[--parts] = 0;
+ }
}
/* Shift a bignum right COUNT bits in-place. Shifted in bits are
@@ -2483,29 +2523,31 @@ APInt::tcShiftLeft(integerPart *dst, unsigned int parts, unsigned int count)
void
APInt::tcShiftRight(integerPart *dst, unsigned int parts, unsigned int count)
{
- unsigned int i, jump, shift;
+ if (count) {
+ unsigned int i, jump, shift;
- /* Jump is the inter-part jump; shift is is intra-part shift. */
- jump = count / integerPartWidth;
- shift = count % integerPartWidth;
+ /* Jump is the inter-part jump; shift is is intra-part shift. */
+ jump = count / integerPartWidth;
+ shift = count % integerPartWidth;
- /* Perform the shift. This leaves the most significant COUNT bits
- of the result at zero. */
- for(i = 0; i < parts; i++) {
- integerPart part;
+ /* Perform the shift. This leaves the most significant COUNT bits
+ of the result at zero. */
+ for(i = 0; i < parts; i++) {
+ integerPart part;
- if (i + jump >= parts) {
- part = 0;
- } else {
- part = dst[i + jump];
- if (shift) {
- part >>= shift;
- if (i + jump + 1 < parts)
- part |= dst[i + jump + 1] << (integerPartWidth - shift);
+ if (i + jump >= parts) {
+ part = 0;
+ } else {
+ part = dst[i + jump];
+ if (shift) {
+ part >>= shift;
+ if (i + jump + 1 < parts)
+ part |= dst[i + jump + 1] << (integerPartWidth - shift);
+ }
}
- }
- dst[i] = part;
+ dst[i] = part;
+ }
}
}