diff options
author | DJ Delorie <dj@redhat.com> | 2006-01-19 18:18:57 -0500 |
---|---|---|
committer | DJ Delorie <dj@gcc.gnu.org> | 2006-01-19 18:18:57 -0500 |
commit | 2e1600563396be18ee75e09d00fabe7f52982f3b (patch) | |
tree | 7135ae416b9ec5659ee6c5f04224df0c692859d5 | |
parent | 360e875934ba609e5da6c444f074d4d5e6b29fed (diff) | |
download | gcc-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/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/m32c/m32c.c | 68 |
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; } |