aboutsummaryrefslogtreecommitdiff
path: root/target-sh4/translate.c
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-08-29 22:32:32 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-08-29 22:32:32 +0000
commit1000822b03f44cc0b0e624cd60e5dce8dde7d463 (patch)
treea97a16fc4e61363a0dc912e063b56781b782b621 /target-sh4/translate.c
parentba6a9d8cdaffda76c9a8e28dc3d7b8363b48d904 (diff)
SH4: convert branch/jump instructions to TCG
(Shin-ichiro KAWASAKI) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5111 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sh4/translate.c')
-rw-r--r--target-sh4/translate.c73
1 files changed, 54 insertions, 19 deletions
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index bf82542c61..87c3f43ac8 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -62,7 +62,10 @@ static TCGv cpu_env;
static TCGv cpu_gregs[24];
static TCGv cpu_pc, cpu_sr, cpu_ssr, cpu_spc, cpu_gbr;
static TCGv cpu_vbr, cpu_sgr, cpu_dbr, cpu_mach, cpu_macl;
-static TCGv cpu_pr, cpu_fpscr, cpu_fpul;
+static TCGv cpu_pr, cpu_fpscr, cpu_fpul, cpu_flags;
+
+/* internal register indexes */
+static TCGv cpu_flags, cpu_delayed_pc;
/* dyngen register indexes */
static TCGv cpu_T[2];
@@ -120,6 +123,12 @@ static void sh4_translate_init(void)
cpu_fpul = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
offsetof(CPUState, fpul), "FPUL");
+ cpu_flags = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
+ offsetof(CPUState, flags), "_flags_");
+ cpu_delayed_pc = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
+ offsetof(CPUState, delayed_pc),
+ "_delayed_pc_");
+
/* register helpers */
#undef DEF_HELPER
#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
@@ -249,7 +258,7 @@ static void gen_jump(DisasContext * ctx)
if (ctx->delayed_pc == (uint32_t) - 1) {
/* Target is not statically known, it comes necessarily from a
delayed jump as immediate jump are conditinal jumps */
- gen_op_movl_delayed_pc_PC();
+ tcg_gen_mov_i32(cpu_pc, cpu_delayed_pc);
if (ctx->singlestep_enabled)
gen_op_debug();
tcg_gen_exit_tb(0);
@@ -258,6 +267,16 @@ static void gen_jump(DisasContext * ctx)
}
}
+static inline void gen_branch_slot(uint32_t delayed_pc, int t)
+{
+ int label = gen_new_label();
+ tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
+ tcg_gen_andi_i32(cpu_T[0], cpu_sr, SR_T);
+ tcg_gen_brcondi_i32(TCG_COND_NE, cpu_T[0], t ? SR_T : 0, label);
+ tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
+ gen_set_label(label);
+}
+
/* Immediate conditional jump (bt or bf) */
static void gen_conditional_jump(DisasContext * ctx,
target_ulong ift, target_ulong ifnott)
@@ -265,7 +284,8 @@ static void gen_conditional_jump(DisasContext * ctx,
int l1;
l1 = gen_new_label();
- gen_op_jT(l1);
+ tcg_gen_andi_i32(cpu_T[0], cpu_sr, SR_T);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], SR_T, l1);
gen_goto_tb(ctx, 0, ifnott);
gen_set_label(l1);
gen_goto_tb(ctx, 1, ift);
@@ -277,9 +297,11 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
int l1;
l1 = gen_new_label();
- gen_op_jdelayed(l1);
+ tcg_gen_andi_i32(cpu_T[0], cpu_flags, DELAY_SLOT_TRUE);
+ tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_T[0], DELAY_SLOT_TRUE, l1);
gen_goto_tb(ctx, 1, ctx->pc + 2);
gen_set_label(l1);
+ tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
gen_jump(ctx);
}
@@ -317,6 +339,12 @@ static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
gen_set_label(label2);
}
+static inline void gen_store_flags(uint32_t flags)
+{
+ tcg_gen_andi_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
+ tcg_gen_ori_i32(cpu_flags, cpu_flags, flags);
+}
+
#define B3_0 (ctx->opcode & 0xf)
#define B6_4 ((ctx->opcode >> 4) & 0x7)
#define B7_4 ((ctx->opcode >> 4) & 0xf)
@@ -353,7 +381,8 @@ void _decode_opc(DisasContext * ctx)
tcg_gen_andi_i32(cpu_sr, cpu_sr, ~(SR_M | SR_Q | SR_T));
return;
case 0x000b: /* rts */
- CHECK_NOT_DELAY_SLOT gen_op_rts();
+ CHECK_NOT_DELAY_SLOT
+ tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr);
ctx->flags |= DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
@@ -375,7 +404,9 @@ void _decode_opc(DisasContext * ctx)
#endif
return;
case 0x002b: /* rte */
- CHECK_NOT_DELAY_SLOT gen_op_rte();
+ CHECK_NOT_DELAY_SLOT
+ tcg_gen_mov_i32(cpu_sr, cpu_ssr);
+ tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc);
ctx->flags |= DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
@@ -436,13 +467,15 @@ void _decode_opc(DisasContext * ctx)
return;
case 0xa000: /* bra disp */
CHECK_NOT_DELAY_SLOT
- gen_op_bra(ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2);
+ ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
+ tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
ctx->flags |= DELAY_SLOT;
return;
case 0xb000: /* bsr disp */
CHECK_NOT_DELAY_SLOT
- gen_op_bsr(ctx->pc + 4, ctx->delayed_pc =
- ctx->pc + 4 + B11_0s * 2);
+ tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
+ ctx->delayed_pc = ctx->pc + 4 + B11_0s * 2;
+ tcg_gen_movi_i32(cpu_delayed_pc, ctx->delayed_pc);
ctx->flags |= DELAY_SLOT;
return;
}
@@ -930,7 +963,7 @@ void _decode_opc(DisasContext * ctx)
return;
case 0x8f00: /* bf/s label */
CHECK_NOT_DELAY_SLOT
- gen_op_bf_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
+ gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 0);
ctx->flags |= DELAY_SLOT_CONDITIONAL;
return;
case 0x8900: /* bt label */
@@ -941,7 +974,7 @@ void _decode_opc(DisasContext * ctx)
return;
case 0x8d00: /* bt/s label */
CHECK_NOT_DELAY_SLOT
- gen_op_bt_s(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2);
+ gen_branch_slot(ctx->delayed_pc = ctx->pc + 4 + B7_0s * 2, 1);
ctx->flags |= DELAY_SLOT_CONDITIONAL;
return;
case 0x8800: /* cmp/eq #imm,R0 */
@@ -1083,13 +1116,14 @@ void _decode_opc(DisasContext * ctx)
switch (ctx->opcode & 0xf0ff) {
case 0x0023: /* braf Rn */
CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]);
- gen_op_braf_T0(ctx->pc + 4);
+ tcg_gen_addi_i32(cpu_delayed_pc, cpu_T[0], ctx->pc + 4);
ctx->flags |= DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
case 0x0003: /* bsrf Rn */
CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]);
- gen_op_bsrf_T0(ctx->pc + 4);
+ tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
+ tcg_gen_add_i32(cpu_delayed_pc, cpu_T[0], cpu_pr);
ctx->flags |= DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
@@ -1107,13 +1141,14 @@ void _decode_opc(DisasContext * ctx)
return;
case 0x402b: /* jmp @Rn */
CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]);
- gen_op_jmp_T0();
+ tcg_gen_mov_i32(cpu_delayed_pc, cpu_T[0]);
ctx->flags |= DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
case 0x400b: /* jsr @Rn */
CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_T[0], cpu_gregs[REG(B11_8)]);
- gen_op_jsr_T0(ctx->pc + 4);
+ tcg_gen_movi_i32(cpu_pr, ctx->pc + 4);
+ tcg_gen_mov_i32(cpu_delayed_pc, cpu_T[0]);
ctx->flags |= DELAY_SLOT;
ctx->delayed_pc = (uint32_t) - 1;
return;
@@ -1332,12 +1367,12 @@ void decode_opc(DisasContext * ctx)
if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
if (ctx->flags & DELAY_SLOT_CLEARME) {
- gen_op_store_flags(0);
+ gen_store_flags(0);
} else {
/* go out of the delay slot */
uint32_t new_flags = ctx->flags;
new_flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL);
- gen_op_store_flags(new_flags);
+ gen_store_flags(new_flags);
}
ctx->flags = 0;
ctx->bstate = BS_BRANCH;
@@ -1351,7 +1386,7 @@ void decode_opc(DisasContext * ctx)
/* go into a delay slot */
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL))
- gen_op_store_flags(ctx->flags);
+ gen_store_flags(ctx->flags);
}
static inline void
@@ -1448,7 +1483,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
/* fall through */
case BS_NONE:
if (ctx.flags) {
- gen_op_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
+ gen_store_flags(ctx.flags | DELAY_SLOT_CLEARME);
}
gen_goto_tb(&ctx, 0, ctx.pc);
break;