summaryrefslogtreecommitdiffstats
path: root/lib/Support/APInt.cpp
diff options
context:
space:
mode:
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;
+ }
}
}