diff options
Diffstat (limited to 'target-sh4/translate.c')
-rw-r--r-- | target-sh4/translate.c | 126 |
1 files changed, 51 insertions, 75 deletions
diff --git a/target-sh4/translate.c b/target-sh4/translate.c index be0cb321cf..724c0e7106 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -612,15 +612,11 @@ static void _decode_opc(DisasContext * ctx) return; case 0x6008: /* swap.b Rm,Rn */ { - TCGv high, low; - high = tcg_temp_new(); - tcg_gen_andi_i32(high, REG(B7_4), 0xffff0000); - low = tcg_temp_new(); + TCGv low = tcg_temp_new();; tcg_gen_ext16u_i32(low, REG(B7_4)); tcg_gen_bswap16_i32(low, low); - tcg_gen_or_i32(REG(B11_8), high, low); + tcg_gen_deposit_i32(REG(B11_8), REG(B7_4), low, 0, 16); tcg_temp_free(low); - tcg_temp_free(high); } return; case 0x6009: /* swap.w Rm,Rn */ @@ -692,18 +688,11 @@ static void _decode_opc(DisasContext * ctx) { TCGv cmp1 = tcg_temp_new(); TCGv cmp2 = tcg_temp_new(); - tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8)); - tcg_gen_andi_i32(cmp2, cmp1, 0xff000000); - tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, cmp2, 0); - tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000); - tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0); - tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2); - tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00); - tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0); - tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2); - tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff); - tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0); - tcg_gen_or_i32(cpu_sr_t, cpu_sr_t, cmp2); + tcg_gen_xor_i32(cmp2, REG(B7_4), REG(B11_8)); + tcg_gen_subi_i32(cmp1, cmp2, 0x01010101); + tcg_gen_andc_i32(cmp1, cmp1, cmp2); + tcg_gen_andi_i32(cmp1, cmp1, 0x80808080); + tcg_gen_setcondi_i32(TCG_COND_NE, cpu_sr_t, cmp1, 0); tcg_temp_free(cmp2); tcg_temp_free(cmp1); } @@ -843,67 +832,54 @@ static void _decode_opc(DisasContext * ctx) return; case 0x400c: /* shad Rm,Rn */ { - TCGLabel *label1 = gen_new_label(); - TCGLabel *label2 = gen_new_label(); - TCGLabel *label3 = gen_new_label(); - TCGLabel *label4 = gen_new_label(); - TCGv shift; - tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1); - /* Rm positive, shift to the left */ - shift = tcg_temp_new(); - tcg_gen_andi_i32(shift, REG(B7_4), 0x1f); - tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift); - tcg_temp_free(shift); - tcg_gen_br(label4); - /* Rm negative, shift to the right */ - gen_set_label(label1); - shift = tcg_temp_new(); - tcg_gen_andi_i32(shift, REG(B7_4), 0x1f); - tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2); - tcg_gen_not_i32(shift, REG(B7_4)); - tcg_gen_andi_i32(shift, shift, 0x1f); - tcg_gen_addi_i32(shift, shift, 1); - tcg_gen_sar_i32(REG(B11_8), REG(B11_8), shift); - tcg_temp_free(shift); - tcg_gen_br(label4); - /* Rm = -32 */ - gen_set_label(label2); - tcg_gen_brcondi_i32(TCG_COND_LT, REG(B11_8), 0, label3); - tcg_gen_movi_i32(REG(B11_8), 0); - tcg_gen_br(label4); - gen_set_label(label3); - tcg_gen_movi_i32(REG(B11_8), 0xffffffff); - gen_set_label(label4); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + + tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); + + /* positive case: shift to the left */ + tcg_gen_shl_i32(t1, REG(B11_8), t0); + + /* negative case: shift to the right in two steps to + correctly handle the -32 case */ + tcg_gen_xori_i32(t0, t0, 0x1f); + tcg_gen_sar_i32(t2, REG(B11_8), t0); + tcg_gen_sari_i32(t2, t2, 1); + + /* select between the two cases */ + tcg_gen_movi_i32(t0, 0); + tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); } return; case 0x400d: /* shld Rm,Rn */ { - TCGLabel *label1 = gen_new_label(); - TCGLabel *label2 = gen_new_label(); - TCGLabel *label3 = gen_new_label(); - TCGv shift; - tcg_gen_brcondi_i32(TCG_COND_LT, REG(B7_4), 0, label1); - /* Rm positive, shift to the left */ - shift = tcg_temp_new(); - tcg_gen_andi_i32(shift, REG(B7_4), 0x1f); - tcg_gen_shl_i32(REG(B11_8), REG(B11_8), shift); - tcg_temp_free(shift); - tcg_gen_br(label3); - /* Rm negative, shift to the right */ - gen_set_label(label1); - shift = tcg_temp_new(); - tcg_gen_andi_i32(shift, REG(B7_4), 0x1f); - tcg_gen_brcondi_i32(TCG_COND_EQ, shift, 0, label2); - tcg_gen_not_i32(shift, REG(B7_4)); - tcg_gen_andi_i32(shift, shift, 0x1f); - tcg_gen_addi_i32(shift, shift, 1); - tcg_gen_shr_i32(REG(B11_8), REG(B11_8), shift); - tcg_temp_free(shift); - tcg_gen_br(label3); - /* Rm = -32 */ - gen_set_label(label2); - tcg_gen_movi_i32(REG(B11_8), 0); - gen_set_label(label3); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + + tcg_gen_andi_i32(t0, REG(B7_4), 0x1f); + + /* positive case: shift to the left */ + tcg_gen_shl_i32(t1, REG(B11_8), t0); + + /* negative case: shift to the right in two steps to + correctly handle the -32 case */ + tcg_gen_xori_i32(t0, t0, 0x1f); + tcg_gen_shr_i32(t2, REG(B11_8), t0); + tcg_gen_shri_i32(t2, t2, 1); + + /* select between the two cases */ + tcg_gen_movi_i32(t0, 0); + tcg_gen_movcond_i32(TCG_COND_GE, REG(B11_8), REG(B7_4), t0, t1, t2); + + tcg_temp_free(t0); + tcg_temp_free(t1); + tcg_temp_free(t2); } return; case 0x3008: /* sub Rm,Rn */ |