aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2006-01-19 18:18:57 -0500
committerDJ Delorie <dj@gcc.gnu.org>2006-01-19 18:18:57 -0500
commit2e1600563396be18ee75e09d00fabe7f52982f3b (patch)
tree7135ae416b9ec5659ee6c5f04224df0c692859d5
parent360e875934ba609e5da6c444f074d4d5e6b29fed (diff)
downloadgcc-2e1600563396be18ee75e09d00fabe7f52982f3b.zip
gcc-2e1600563396be18ee75e09d00fabe7f52982f3b.tar.gz
gcc-2e1600563396be18ee75e09d00fabe7f52982f3b.tar.bz2
m32c.c (m32c_prepare_shift): Add code to deal with the 16 bit shift limit of the m16c.
* config/m32c/m32c.c (m32c_prepare_shift): Add code to deal with the 16 bit shift limit of the m16c. From-SVN: r109987
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/m32c/m32c.c68
2 files changed, 69 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 927251a..7ed92c2 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2006-01-19 DJ Delorie <dj@redhat.com>
+
+ * config/m32c/m32c.c (m32c_prepare_shift): Add code to deal with
+ the 16 bit shift limit of the m16c.
+
2006-01-19 Andrew Pinski <pinskia@physics.uc.edu>
PR target/22099
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 24b7fff..73d75d6 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -2891,13 +2891,73 @@ m32c_prepare_shift (rtx * operands, int scale, int shift_code)
emit_insn (func (operands[0], operands[1], GEN_INT (count)));
return 1;
}
+
+ temp = gen_reg_rtx (QImode);
if (scale < 0)
- {
- temp = gen_reg_rtx (QImode);
- emit_move_insn (temp, gen_rtx_NEG (QImode, operands[2]));
- }
+ /* The pattern has a NEG that corresponds to this. */
+ emit_move_insn (temp, gen_rtx_NEG (QImode, operands[2]));
+ else if (TARGET_A16 && mode == SImode)
+ /* We do this because the code below may modify this, we don't
+ want to modify the origin of this value. */
+ emit_move_insn (temp, operands[2]);
else
+ /* We'll only use it for the shift, no point emitting a move. */
temp = operands[2];
+
+
+ if (TARGET_A16 && mode == SImode)
+ {
+ /* The m16c has a limit of -16..16 for SI shifts, even when the
+ shift count is in a register. Since there are so many targets
+ of these shifts, it's better to expand the RTL here than to
+ call a helper function.
+
+ The resulting code looks something like this:
+
+ cmp.b r1h,-16
+ jge.b 1f
+ shl.l -16,dest
+ add.b r1h,16
+ 1f: cmp.b r1h,16
+ jle.b 1f
+ shl.l 16,dest
+ sub.b r1h,16
+ 1f: shl.l r1h,dest
+
+ We take advantage of the fact that "negative" shifts are
+ undefined to skip one of the comparisons. */
+
+ rtx count;
+ rtx label, lref, insn;
+
+ count = temp;
+ label = gen_label_rtx ();
+ lref = gen_rtx_LABEL_REF (VOIDmode, label);
+ LABEL_NUSES (label) ++;
+
+ if (shift_code == ASHIFT)
+ {
+ /* This is a left shift. We only need check positive counts. */
+ emit_jump_insn (gen_cbranchqi4 (gen_rtx_LE (VOIDmode, 0, 0),
+ count, GEN_INT (16), label));
+ emit_insn (func (operands[1], operands[1], GEN_INT (8)));
+ emit_insn (func (operands[1], operands[1], GEN_INT (8)));
+ insn = emit_insn (gen_addqi3 (count, count, GEN_INT (-16)));
+ emit_label_after (label, insn);
+ }
+ else
+ {
+ /* This is a right shift. We only need check negative counts. */
+ emit_jump_insn (gen_cbranchqi4 (gen_rtx_GE (VOIDmode, 0, 0),
+ count, GEN_INT (-16), label));
+ emit_insn (func (operands[1], operands[1], GEN_INT (-8)));
+ emit_insn (func (operands[1], operands[1], GEN_INT (-8)));
+ insn = emit_insn (gen_addqi3 (count, count, GEN_INT (16)));
+ emit_label_after (label, insn);
+ }
+
+ }
+
operands[2] = temp;
return 0;
}