mirror of https://github.com/xemu-project/xemu.git
target-sh4: improve shld instruction
The SH4 shld instruction can shift in both direction, depending on the sign of the shift. This is currently implemented using branches, which is not really efficient and prevents the optimizer to do its job. In practice it is often used with a constant loaded in a register just before. Simplify the implementation by computing both the value shifted to the left and to the right, and then selecting the correct one with a movcond. As with a negative value the shift amount can go up to 32 which is undefined, we shift the value in two steps. Reviewed-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
eb6ca2b4a6
commit
577601616d
|
@ -867,32 +867,28 @@ static void _decode_opc(DisasContext * ctx)
|
||||||
return;
|
return;
|
||||||
case 0x400d: /* shld Rm,Rn */
|
case 0x400d: /* shld Rm,Rn */
|
||||||
{
|
{
|
||||||
TCGLabel *label1 = gen_new_label();
|
TCGv t0 = tcg_temp_new();
|
||||||
TCGLabel *label2 = gen_new_label();
|
TCGv t1 = tcg_temp_new();
|
||||||
TCGLabel *label3 = gen_new_label();
|
TCGv t2 = tcg_temp_new();
|
||||||
TCGv shift;
|
|
||||||
tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1);
|
tcg_gen_andi_i32(t0, REG(B7_4), 0x1f);
|
||||||
/* Rm positive, shift to the left */
|
|
||||||
shift = tcg_temp_new();
|
/* positive case: shift to the left */
|
||||||
tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
|
tcg_gen_shl_i32(t1, REG(B11_8), t0);
|
||||||
tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift);
|
|
||||||
tcg_temp_free(shift);
|
/* negative case: shift to the right in two steps to
|
||||||
tcg_gen_br(label3);
|
correctly handle the -32 case */
|
||||||
/* Rm negative, shift to the right */
|
tcg_gen_xori_i32(t0, t0, 0x1f);
|
||||||
gen_set_label(label1);
|
tcg_gen_shr_i32(t2, REG(B11_8), t0);
|
||||||
shift = tcg_temp_new();
|
tcg_gen_shri_i32(t2, t2, 1);
|
||||||
tcg_gen_andi_i32(shift, REG(B7_4), 0x1f);
|
|
||||||
tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2);
|
/* select between the two cases */
|
||||||
tcg_gen_not_i32(shift, REG(B7_4));
|
tcg_gen_movi_i32(t0, 0);
|
||||||
tcg_gen_andi_i32(shift, shift, 0x1f);
|
tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2);
|
||||||
tcg_gen_addi_i32(shift, shift, 1);
|
|
||||||
tcg_gen_shr_i32(REG(B11_8), REG(B11_8), shift);
|
tcg_temp_free(t0);
|
||||||
tcg_temp_free(shift);
|
tcg_temp_free(t1);
|
||||||
tcg_gen_br(label3);
|
tcg_temp_free(t2);
|
||||||
/* Rm = -32 */
|
|
||||||
gen_set_label(label2);
|
|
||||||
tcg_gen_movi_i32(REG(B11_8), 0);
|
|
||||||
gen_set_label(label3);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0x3008: /* sub Rm,Rn */
|
case 0x3008: /* sub Rm,Rn */
|
||||||
|
|
Loading…
Reference in New Issue