From 2e1600563396be18ee75e09d00fabe7f52982f3b Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Thu, 19 Jan 2006 18:18:57 -0500 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 ++++ 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 + + * 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 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; } -- 2.7.4