static void
ix86_expand_ashl_const (rtx operand, int count, enum machine_mode mode)
{
- if (count == 1)
+ rtx (*insn)(rtx, rtx, rtx);
+
+ if (count == 1
+ || (count * ix86_cost->add <= ix86_cost->shift_const
+ && !optimize_insn_for_size_p ()))
{
- emit_insn ((mode == DImode
- ? gen_addsi3
- : gen_adddi3) (operand, operand, operand));
+ insn = mode == DImode ? gen_addsi3 : gen_adddi3;
+ while (count-- > 0)
+ emit_insn (insn (operand, operand, operand));
}
- else if (!optimize_insn_for_size_p ()
- && count * ix86_cost->add <= ix86_cost->shift_const)
+ else
{
- int i;
- for (i=0; i<count; i++)
- {
- emit_insn ((mode == DImode
- ? gen_addsi3
- : gen_adddi3) (operand, operand, operand));
- }
+ insn = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
+ emit_insn (insn (operand, operand, GEN_INT (count)));
}
- else
- emit_insn ((mode == DImode
- ? gen_ashlsi3
- : gen_ashldi3) (operand, operand, GEN_INT (count)));
}
void
ix86_split_ashl (rtx *operands, rtx scratch, enum machine_mode mode)
{
+ rtx (*gen_ashl3)(rtx, rtx, rtx);
+ rtx (*gen_shld)(rtx, rtx, rtx);
+
rtx low[2], high[2];
int count;
const int single_width = mode == DImode ? 32 : 64;
}
else
{
+ gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
+
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- emit_insn ((mode == DImode
- ? gen_x86_shld
- : gen_x86_64_shld) (high[0], low[0], GEN_INT (count)));
+
+ emit_insn (gen_shld (high[0], low[0], GEN_INT (count)));
ix86_expand_ashl_const (low[0], count, mode);
}
return;
split_double_mode (mode, operands, 1, low, high);
+ gen_ashl3 = mode == DImode ? gen_ashlsi3 : gen_ashldi3;
+
if (operands[1] == const1_rtx)
{
/* Assuming we've chosen a QImode capable registers, then 1 << N
pentium4 a bit; no one else seems to care much either way. */
else
{
+ enum machine_mode half_mode;
+ rtx (*gen_lshr3)(rtx, rtx, rtx);
+ rtx (*gen_and3)(rtx, rtx, rtx);
+ rtx (*gen_xor3)(rtx, rtx, rtx);
+ HOST_WIDE_INT bits;
rtx x;
+ if (mode == DImode)
+ {
+ half_mode = SImode;
+ gen_lshr3 = gen_lshrsi3;
+ gen_and3 = gen_andsi3;
+ gen_xor3 = gen_xorsi3;
+ bits = 5;
+ }
+ else
+ {
+ half_mode = DImode;
+ gen_lshr3 = gen_lshrdi3;
+ gen_and3 = gen_anddi3;
+ gen_xor3 = gen_xordi3;
+ bits = 6;
+ }
+
if (TARGET_PARTIAL_REG_STALL && !optimize_insn_for_size_p ())
- x = gen_rtx_ZERO_EXTEND (mode == DImode ? SImode : DImode, operands[2]);
+ x = gen_rtx_ZERO_EXTEND (half_mode, operands[2]);
else
- x = gen_lowpart (mode == DImode ? SImode : DImode, operands[2]);
+ x = gen_lowpart (half_mode, operands[2]);
emit_insn (gen_rtx_SET (VOIDmode, high[0], x));
- emit_insn ((mode == DImode
- ? gen_lshrsi3
- : gen_lshrdi3) (high[0], high[0],
- GEN_INT (mode == DImode ? 5 : 6)));
- emit_insn ((mode == DImode
- ? gen_andsi3
- : gen_anddi3) (high[0], high[0], const1_rtx));
+ emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (bits)));
+ emit_insn (gen_and3 (high[0], high[0], const1_rtx));
emit_move_insn (low[0], high[0]);
- emit_insn ((mode == DImode
- ? gen_xorsi3
- : gen_xordi3) (low[0], low[0], const1_rtx));
+ emit_insn (gen_xor3 (low[0], low[0], const1_rtx));
}
- emit_insn ((mode == DImode
- ? gen_ashlsi3
- : gen_ashldi3) (low[0], low[0], operands[2]));
- emit_insn ((mode == DImode
- ? gen_ashlsi3
- : gen_ashldi3) (high[0], high[0], operands[2]));
+ emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
+ emit_insn (gen_ashl3 (high[0], high[0], operands[2]));
return;
}
}
else
{
+ gen_shld = mode == DImode ? gen_x86_shld : gen_x86_64_shld;
+
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
split_double_mode (mode, operands, 1, low, high);
- emit_insn ((mode == DImode
- ? gen_x86_shld
- : gen_x86_64_shld) (high[0], low[0], operands[2]));
+ emit_insn (gen_shld (high[0], low[0], operands[2]));
}
- emit_insn ((mode == DImode
- ? gen_ashlsi3
- : gen_ashldi3) (low[0], low[0], operands[2]));
+ emit_insn (gen_ashl3 (low[0], low[0], operands[2]));
if (TARGET_CMOVE && scratch)
{
+ rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx)
+ = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1;
+
ix86_expand_clear (scratch);
- emit_insn ((mode == DImode
- ? gen_x86_shiftsi_adj_1
- : gen_x86_shiftdi_adj_1) (high[0], low[0], operands[2],
- scratch));
+ emit_insn (gen_x86_shift_adj_1 (high[0], low[0], operands[2], scratch));
}
else
- emit_insn ((mode == DImode
- ? gen_x86_shiftsi_adj_2
- : gen_x86_shiftdi_adj_2) (high[0], low[0], operands[2]));
+ {
+ rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx)
+ = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2;
+
+ emit_insn (gen_x86_shift_adj_2 (high[0], low[0], operands[2]));
+ }
}
void
ix86_split_ashr (rtx *operands, rtx scratch, enum machine_mode mode)
{
+ rtx (*gen_ashr3)(rtx, rtx, rtx)
+ = mode == DImode ? gen_ashrsi3 : gen_ashrdi3;
+ rtx (*gen_shrd)(rtx, rtx, rtx);
+
rtx low[2], high[2];
int count;
const int single_width = mode == DImode ? 32 : 64;
if (count == single_width * 2 - 1)
{
emit_move_insn (high[0], high[1]);
- emit_insn ((mode == DImode
- ? gen_ashrsi3
- : gen_ashrdi3) (high[0], high[0],
- GEN_INT (single_width - 1)));
+ emit_insn (gen_ashr3 (high[0], high[0],
+ GEN_INT (single_width - 1)));
emit_move_insn (low[0], high[0]);
}
{
emit_move_insn (low[0], high[1]);
emit_move_insn (high[0], low[0]);
- emit_insn ((mode == DImode
- ? gen_ashrsi3
- : gen_ashrdi3) (high[0], high[0],
- GEN_INT (single_width - 1)));
+ emit_insn (gen_ashr3 (high[0], high[0],
+ GEN_INT (single_width - 1)));
+
if (count > single_width)
- emit_insn ((mode == DImode
- ? gen_ashrsi3
- : gen_ashrdi3) (low[0], low[0],
- GEN_INT (count - single_width)));
+ emit_insn (gen_ashr3 (low[0], low[0],
+ GEN_INT (count - single_width)));
}
else
{
+ gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
+
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- emit_insn ((mode == DImode
- ? gen_x86_shrd
- : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count)));
- emit_insn ((mode == DImode
- ? gen_ashrsi3
- : gen_ashrdi3) (high[0], high[0], GEN_INT (count)));
+
+ emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
+ emit_insn (gen_ashr3 (high[0], high[0], GEN_INT (count)));
}
}
else
{
- if (!rtx_equal_p (operands[0], operands[1]))
+ gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
+
+ if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
split_double_mode (mode, operands, 1, low, high);
- emit_insn ((mode == DImode
- ? gen_x86_shrd
- : gen_x86_64_shrd) (low[0], high[0], operands[2]));
- emit_insn ((mode == DImode
- ? gen_ashrsi3
- : gen_ashrdi3) (high[0], high[0], operands[2]));
+ emit_insn (gen_shrd (low[0], high[0], operands[2]));
+ emit_insn (gen_ashr3 (high[0], high[0], operands[2]));
if (TARGET_CMOVE && scratch)
{
+ rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx)
+ = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1;
+
emit_move_insn (scratch, high[0]);
- emit_insn ((mode == DImode
- ? gen_ashrsi3
- : gen_ashrdi3) (scratch, scratch,
- GEN_INT (single_width - 1)));
- emit_insn ((mode == DImode
- ? gen_x86_shiftsi_adj_1
- : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2],
- scratch));
+ emit_insn (gen_ashr3 (scratch, scratch,
+ GEN_INT (single_width - 1)));
+ emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
+ scratch));
}
else
- emit_insn ((mode == DImode
- ? gen_x86_shiftsi_adj_3
- : gen_x86_shiftdi_adj_3) (low[0], high[0], operands[2]));
+ {
+ rtx (*gen_x86_shift_adj_3)(rtx, rtx, rtx)
+ = mode == DImode ? gen_x86_shiftsi_adj_3 : gen_x86_shiftdi_adj_3;
+
+ emit_insn (gen_x86_shift_adj_3 (low[0], high[0], operands[2]));
+ }
}
}
void
ix86_split_lshr (rtx *operands, rtx scratch, enum machine_mode mode)
{
+ rtx (*gen_lshr3)(rtx, rtx, rtx)
+ = mode == DImode ? gen_lshrsi3 : gen_lshrdi3;
+ rtx (*gen_shrd)(rtx, rtx, rtx);
+
rtx low[2], high[2];
int count;
const int single_width = mode == DImode ? 32 : 64;
ix86_expand_clear (high[0]);
if (count > single_width)
- emit_insn ((mode == DImode
- ? gen_lshrsi3
- : gen_lshrdi3) (low[0], low[0],
- GEN_INT (count - single_width)));
+ emit_insn (gen_lshr3 (low[0], low[0],
+ GEN_INT (count - single_width)));
}
else
{
+ gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
+
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
- emit_insn ((mode == DImode
- ? gen_x86_shrd
- : gen_x86_64_shrd) (low[0], high[0], GEN_INT (count)));
- emit_insn ((mode == DImode
- ? gen_lshrsi3
- : gen_lshrdi3) (high[0], high[0], GEN_INT (count)));
+
+ emit_insn (gen_shrd (low[0], high[0], GEN_INT (count)));
+ emit_insn (gen_lshr3 (high[0], high[0], GEN_INT (count)));
}
}
else
{
+ gen_shrd = mode == DImode ? gen_x86_shrd : gen_x86_64_shrd;
+
if (!rtx_equal_p (operands[0], operands[1]))
emit_move_insn (operands[0], operands[1]);
split_double_mode (mode, operands, 1, low, high);
- emit_insn ((mode == DImode
- ? gen_x86_shrd
- : gen_x86_64_shrd) (low[0], high[0], operands[2]));
- emit_insn ((mode == DImode
- ? gen_lshrsi3
- : gen_lshrdi3) (high[0], high[0], operands[2]));
+ emit_insn (gen_shrd (low[0], high[0], operands[2]));
+ emit_insn (gen_lshr3 (high[0], high[0], operands[2]));
- /* Heh. By reversing the arguments, we can reuse this pattern. */
if (TARGET_CMOVE && scratch)
{
+ rtx (*gen_x86_shift_adj_1)(rtx, rtx, rtx, rtx)
+ = mode == DImode ? gen_x86_shiftsi_adj_1 : gen_x86_shiftdi_adj_1;
+
ix86_expand_clear (scratch);
- emit_insn ((mode == DImode
- ? gen_x86_shiftsi_adj_1
- : gen_x86_shiftdi_adj_1) (low[0], high[0], operands[2],
- scratch));
+ emit_insn (gen_x86_shift_adj_1 (low[0], high[0], operands[2],
+ scratch));
}
else
- emit_insn ((mode == DImode
- ? gen_x86_shiftsi_adj_2
- : gen_x86_shiftdi_adj_2) (low[0], high[0], operands[2]));
+ {
+ rtx (*gen_x86_shift_adj_2)(rtx, rtx, rtx)
+ = mode == DImode ? gen_x86_shiftsi_adj_2 : gen_x86_shiftdi_adj_2;
+
+ emit_insn (gen_x86_shift_adj_2 (low[0], high[0], operands[2]));
+ }
}
}
static void
ix86_adjust_counter (rtx countreg, HOST_WIDE_INT value)
{
- if (GET_MODE (countreg) == DImode)
- emit_insn (gen_adddi3 (countreg, countreg, GEN_INT (-value)));
- else
- emit_insn (gen_addsi3 (countreg, countreg, GEN_INT (-value)));
+ rtx (*gen_add)(rtx, rtx, rtx)
+ = GET_MODE (countreg) == DImode ? gen_adddi3 : gen_addsi3;
+
+ emit_insn (gen_add (countreg, countreg, GEN_INT (-value)));
}
/* Zero extend possibly SImode EXP to Pmode register. */