aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJohn Wehle <john@feith.com>2001-11-09 05:27:51 +0000
committerJohn Wehle <wehle@gcc.gnu.org>2001-11-09 05:27:51 +0000
commit11b161d06979925862bcbaf1945a8a03a1272625 (patch)
tree5ea49b0b7937215806e9fc55e17820acf7ca6a76 /gcc
parent702020d6585adb08b31c395ece13c9120d865549 (diff)
downloadgcc-11b161d06979925862bcbaf1945a8a03a1272625.zip
gcc-11b161d06979925862bcbaf1945a8a03a1272625.tar.gz
gcc-11b161d06979925862bcbaf1945a8a03a1272625.tar.bz2
fold-const.c (lshift_double): Honor PREC.
* fold-const.c (lshift_double): Honor PREC. (rshift_double): Likewise. From-SVN: r46872
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/fold-const.c57
2 files changed, 54 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 09d9cbd..59f6cd6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+Fri Nov 9 00:25:18 EST 2001 John Wehle (john@feith.com)
+
+ * fold-const.c (lshift_double): Honor PREC.
+ (rshift_double): Likewise.
+
2001-11-08 Kazu Hirata <kazu@hxi.com>
* config/1750a/1750a.c: Fix comment formatting.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 05be225..a60930b 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -383,6 +383,8 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
HOST_WIDE_INT *hv;
int arith;
{
+ unsigned HOST_WIDE_INT signmask;
+
if (count < 0)
{
rshift_double (l1, h1, -count, prec, lv, hv, arith);
@@ -412,6 +414,26 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
| (l1 >> (HOST_BITS_PER_WIDE_INT - count - 1) >> 1));
*lv = l1 << count;
}
+
+ /* Sign extend all bits that are beyond the precision. */
+
+ signmask = -((prec > HOST_BITS_PER_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 >= 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);
+ *lv |= signmask << prec;
+ }
}
/* Shift the doubleword integer in L1, H1 right by COUNT places
@@ -423,7 +445,7 @@ void
rshift_double (l1, h1, count, prec, lv, hv, arith)
unsigned HOST_WIDE_INT l1;
HOST_WIDE_INT h1, count;
- unsigned int prec ATTRIBUTE_UNUSED;
+ unsigned int prec;
unsigned HOST_WIDE_INT *lv;
HOST_WIDE_INT *hv;
int arith;
@@ -443,21 +465,40 @@ rshift_double (l1, h1, count, prec, lv, hv, arith)
{
/* Shifting by the host word size is undefined according to the
ANSI standard, so we must handle this as a special case. */
- *hv = signmask;
- *lv = signmask;
+ *hv = 0;
+ *lv = 0;
}
else if (count >= HOST_BITS_PER_WIDE_INT)
{
- *hv = signmask;
- *lv = ((signmask << (2 * HOST_BITS_PER_WIDE_INT - count - 1) << 1)
- | ((unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT)));
+ *hv = 0;
+ *lv = (unsigned HOST_WIDE_INT) h1 >> (count - HOST_BITS_PER_WIDE_INT);
}
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 = ((signmask << (HOST_BITS_PER_WIDE_INT - count))
- | ((unsigned HOST_WIDE_INT) h1 >> count));
+ }
+
+ /* Zero / 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)
+ ;
+ else if ((prec - count) >= 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 - count));
+ *lv |= signmask << (prec - count);
}
}