aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNick Clifton <nickc@cygnus.com>1998-09-24 17:08:41 +0000
committerNick Clifton <nickc@gcc.gnu.org>1998-09-24 17:08:41 +0000
commitda9599506e3b26ec501e9023deb7f336df1e65e8 (patch)
tree04ca4df25701333d88b04340c9c9cd6a42deba5b /gcc
parent3c6088d24f6b5a92950a9a4bd52dfce50671a2f2 (diff)
downloadgcc-da9599506e3b26ec501e9023deb7f336df1e65e8.zip
gcc-da9599506e3b26ec501e9023deb7f336df1e65e8.tar.gz
gcc-da9599506e3b26ec501e9023deb7f336df1e65e8.tar.bz2
Applied Jim's patch to "insv" pattern
From-SVN: r22574
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/arm/arm.md51
2 files changed, 38 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 900fedd..ce01df3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+Thu Sep 24 17:05:30 1998 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/arm.md (insv): Add comment. In CONST_INT case, and
+ operand3 with mask before using it. Patch provided by Jim Wilson.
+
Thu Sep 24 15:08:08 1998 Jakub Jelinek <jj@sunsite.ms.mff.cuni.cz>
* config/sparc/sparc.c (function_value): Perform the equivalent of
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 18093c7..20b8d57 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -1199,6 +1199,15 @@
[(set_attr "conds" "set")
(set_attr "length" "8")])
+;;; ??? This pattern is bogus. If operand3 has bits outside the range
+;;; represented by the bitfield, then this will produce incorrect results.
+;;; Somewhere, the value needs to be truncated. On targets like the m68k,
+;;; which have a real bitfield insert instruction, the truncation happens
+;;; in the bitfield insert instruction itself. Since arm does not have a
+;;; bitfield insert instruction, we would have to emit code here to truncate
+;;; the value before we insert. This loses some of the advantage of having
+;;; this insv pattern, so this pattern needs to be reevalutated.
+
(define_expand "insv"
[(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
(match_operand:SI 1 "general_operand" "")
@@ -1207,9 +1216,11 @@
""
"
{
- HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << INTVAL (operands[1])) - 1;
+ int start_bit = INTVAL (operands[2]);
+ int width = INTVAL (operands[1]);
+ HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
rtx target, subtarget;
-
+
target = operands[0];
/* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
subreg as the final target. */
@@ -1228,16 +1239,19 @@
/* Since we are inserting a known constant, we may be able to
reduce the number of bits that we have to clear so that
the mask becomes simple. */
+ /* ??? This code does not check to see if the new mask is actually
+ simpler. It may not be. */
rtx op1 = gen_reg_rtx (SImode);
- HOST_WIDE_INT mask2 = ((mask & ~INTVAL (operands[3]))
- << INTVAL (operands[2]));
+ /* ??? Truncate operand3 to fit in the bitfield. See comment before
+ start of this pattern. */
+ HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
+ HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
emit_insn (gen_iorsi3 (subtarget, op1,
- GEN_INT (INTVAL (operands[3])
- << INTVAL (operands[2]))));
+ GEN_INT (op3_value << start_bit)));
}
- else if (INTVAL (operands[2]) == 0
+ else if (start_bit == 0
&& ! (const_ok_for_arm (mask)
|| const_ok_for_arm (~mask)))
{
@@ -1245,18 +1259,18 @@
we can shift operand[3] up, operand[0] down, OR them together
and rotate the result back again. This takes 3 insns, and
the third might be mergable into another op. */
-
+ /* The shift up copes with the possibility that operand[3] is
+ wider than the bitfield. */
rtx op0 = gen_reg_rtx (SImode);
rtx op1 = gen_reg_rtx (SImode);
- emit_insn (gen_ashlsi3 (op0, operands[3],
- GEN_INT (32 - INTVAL (operands[1]))));
+ emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
emit_insn (gen_iorsi3 (op1, gen_rtx (LSHIFTRT, SImode, operands[0],
operands[1]),
op0));
emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
}
- else if ((INTVAL (operands[1]) + INTVAL (operands[2]) == 32)
+ else if ((width + start_bit == 32)
&& ! (const_ok_for_arm (mask)
|| const_ok_for_arm (~mask)))
{
@@ -1265,8 +1279,7 @@
rtx op0 = gen_reg_rtx (SImode);
rtx op1 = gen_reg_rtx (SImode);
- emit_insn (gen_ashlsi3 (op0, operands[3],
- GEN_INT (32 - INTVAL (operands[1]))));
+ emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
emit_insn (gen_iorsi3 (subtarget,
gen_rtx (LSHIFTRT, SImode, op1,
@@ -1286,13 +1299,14 @@
op0 = tmp;
}
+ /* Mask out any bits in operand[3] that are not needed. */
emit_insn (gen_andsi3 (op1, operands[3], op0));
if (GET_CODE (op0) == CONST_INT
- && (const_ok_for_arm (mask << INTVAL (operands[2]))
- || const_ok_for_arm (~ (mask << INTVAL (operands[2])))))
+ && (const_ok_for_arm (mask << start_bit)
+ || const_ok_for_arm (~ (mask << start_bit))))
{
- op0 = GEN_INT (~(mask << INTVAL (operands[2])));
+ op0 = GEN_INT (~(mask << start_bit));
emit_insn (gen_andsi3 (op2, operands[0], op0));
}
else
@@ -1305,12 +1319,13 @@
op0 = tmp;
}
- if (INTVAL (operands[2]) != 0)
+ if (start_bit != 0)
op0 = gen_rtx (ASHIFT, SImode, op0, operands[2]);
+
emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
}
- if (INTVAL (operands[2]) != 0)
+ if (start_bit != 0)
op1 = gen_rtx (ASHIFT, SImode, op1, operands[2]);
emit_insn (gen_iorsi3 (subtarget, op1, op2));