diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 61e8f52fc7c..52c2fc01f12 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -1069,6 +1069,13 @@ public: /// Extract the given bit of a bignum; returns 0 or 1. Zero-based. static int tcExtractBit(const integerPart *, unsigned int bit); + /// 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. + static void tcExtract(integerPart *, unsigned int dstCount, const integerPart *, + unsigned int srcBits, unsigned int srcLSB); + /// Set the given bit of a bignum. Zero-based. static void tcSetBit(integerPart *, unsigned int bit); diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index aa6cfa713e8..2e537d66da7 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; + } } }