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
This commit is contained in:
parent
360e875934
commit
2e16005633
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user