diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2012-04-03 11:15:51 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2012-04-03 11:15:51 -0700 |
commit | c924cab2fd8932bdfb107c4ca7d26128ba56f19e (patch) | |
tree | 0eea6430e211564fc331f66625373ec761837982 /gcc/double-int.c | |
parent | 4c15f6d5728cb694d7d954b2c20409fdc0400b9e (diff) | |
parent | 3cef948a814542119083003a3c35a24e036230b6 (diff) | |
download | gcc-hjl/x32/addr32.tar.gz |
Merge remote-tracking branch 'origin/master' into hjl/x32/addr32hjl/x32/addr32
Diffstat (limited to 'gcc/double-int.c')
-rw-r--r-- | gcc/double-int.c | 112 |
1 files changed, 53 insertions, 59 deletions
diff --git a/gcc/double-int.c b/gcc/double-int.c index 834eaf9d6c2..d0fde0ed89f 100644 --- a/gcc/double-int.c +++ b/gcc/double-int.c @@ -186,24 +186,22 @@ mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0; } -/* Shift the doubleword integer in L1, H1 left by COUNT places - keeping only PREC bits of result. - Shift right if COUNT is negative. - ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. +/* Shift the doubleword integer in L1, H1 right by COUNT places + keeping only PREC bits of result. ARITH nonzero specifies + arithmetic shifting; otherwise use logical shift. Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ -void -lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, - HOST_WIDE_INT count, unsigned int prec, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith) +static void +rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, + unsigned HOST_WIDE_INT count, unsigned int prec, + unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, + bool arith) { unsigned HOST_WIDE_INT signmask; - if (count < 0) - { - rshift_double (l1, h1, -count, prec, lv, hv, arith); - return; - } + signmask = (arith + ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1)) + : 0); if (SHIFT_COUNT_TRUNCATED) count %= prec; @@ -217,61 +215,58 @@ lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, } else if (count >= HOST_BITS_PER_WIDE_INT) { - *hv = l1 << (count - HOST_BITS_PER_WIDE_INT); - *lv = 0; + *hv = 0; + *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT); } else { - *hv = (((unsigned HOST_WIDE_INT) h1 << count) - | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1)); - *lv = l1 << count; + *hv = (unsigned HOST_WIDE_INT) h1 >> count; + *lv = ((l1 >> count) + | ((unsigned HOST_WIDE_INT) h1 + << (HOST_BITS_PER_WIDE_INT - count - 1) << 1)); } - /* Sign extend all bits that are beyond the precision. */ - - signmask = -((prec > HOST_BITS_PER_WIDE_INT - ? ((unsigned HOST_WIDE_INT) *hv - >> (prec - HOST_BITS_PER_WIDE_INT - 1)) - : (*lv >> (prec - 1))) & 1); + /* Zero / sign extend all bits that are beyond the precision. */ - if (prec >= 2 * HOST_BITS_PER_WIDE_INT) + if (count >= prec) + { + *hv = signmask; + *lv = signmask; + } + else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT) ; - else if (prec >= HOST_BITS_PER_WIDE_INT) + else if ((prec - count) >= HOST_BITS_PER_WIDE_INT) { - *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); - *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT); + *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT)); + *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT); } else { *hv = signmask; - *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec); - *lv |= signmask << prec; + *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count)); + *lv |= signmask << (prec - count); } } -/* Shift the doubleword integer in L1, H1 right by COUNT places - keeping only PREC bits of result. Shift left if COUNT is negative. +/* Shift the doubleword integer in L1, H1 left by COUNT places + keeping only PREC bits of result. + Shift right if COUNT is negative. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ void -rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, +lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, HOST_WIDE_INT count, unsigned int prec, - unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, - bool arith) + unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith) { unsigned HOST_WIDE_INT signmask; if (count < 0) { - lshift_double (l1, h1, -count, prec, lv, hv, arith); + rshift_double (l1, h1, absu_hwi (count), prec, lv, hv, arith); return; } - signmask = (arith - ? -((unsigned HOST_WIDE_INT) h1 >> (HOST_BITS_PER_WIDE_INT - 1)) - : 0); - if (SHIFT_COUNT_TRUNCATED) count %= prec; @@ -284,36 +279,35 @@ rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, } else if (count >= HOST_BITS_PER_WIDE_INT) { - *hv = 0; - *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT); + *hv = l1 << (count - HOST_BITS_PER_WIDE_INT); + *lv = 0; } else { - *hv = (unsigned HOST_WIDE_INT) h1 >> count; - *lv = ((l1 >> count) - | ((unsigned HOST_WIDE_INT) h1 - << (HOST_BITS_PER_WIDE_INT - count - 1) << 1)); + *hv = (((unsigned HOST_WIDE_INT) h1 << count) + | (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1)); + *lv = l1 << count; } - /* Zero / sign extend all bits that are beyond the precision. */ + /* Sign extend all bits that are beyond the precision. */ - if (count >= (HOST_WIDE_INT)prec) - { - *hv = signmask; - *lv = signmask; - } - else if ((prec - count) >= 2 * HOST_BITS_PER_WIDE_INT) + signmask = -((prec > HOST_BITS_PER_WIDE_INT + ? ((unsigned HOST_WIDE_INT) *hv + >> (prec - HOST_BITS_PER_WIDE_INT - 1)) + : (*lv >> (prec - 1))) & 1); + + if (prec >= 2 * HOST_BITS_PER_WIDE_INT) ; - else if ((prec - count) >= HOST_BITS_PER_WIDE_INT) + else if (prec >= HOST_BITS_PER_WIDE_INT) { - *hv &= ~((HOST_WIDE_INT) (-1) << (prec - count - HOST_BITS_PER_WIDE_INT)); - *hv |= signmask << (prec - count - HOST_BITS_PER_WIDE_INT); + *hv &= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT)); + *hv |= signmask << (prec - HOST_BITS_PER_WIDE_INT); } else { *hv = signmask; - *lv &= ~((unsigned HOST_WIDE_INT) (-1) << (prec - count)); - *lv |= signmask << (prec - count); + *lv &= ~((unsigned HOST_WIDE_INT) (-1) << prec); + *lv |= signmask << prec; } } @@ -895,7 +889,7 @@ double_int double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool arith) { double_int ret; - rshift_double (a.low, a.high, count, prec, &ret.low, &ret.high, arith); + lshift_double (a.low, a.high, -count, prec, &ret.low, &ret.high, arith); return ret; } |