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
This commit is contained in:
aurel32 2008-08-29 22:32:32 +00:00
parent ba6a9d8cda
commit 1000822b03
2 changed files with 54 additions and 118 deletions

View File

@ -37,70 +37,6 @@ static inline void cond_t(int cond)
clr_t();
}
void OPPROTO op_bf_s(void)
{
env->delayed_pc = PARAM1;
if (!(env->sr & SR_T)) {
env->flags |= DELAY_SLOT_TRUE;
}
RETURN();
}
void OPPROTO op_bt_s(void)
{
env->delayed_pc = PARAM1;
if (env->sr & SR_T) {
env->flags |= DELAY_SLOT_TRUE;
}
RETURN();
}
void OPPROTO op_store_flags(void)
{
env->flags &= DELAY_SLOT_TRUE;
env->flags |= PARAM1;
RETURN();
}
void OPPROTO op_bra(void)
{
env->delayed_pc = PARAM1;
RETURN();
}
void OPPROTO op_braf_T0(void)
{
env->delayed_pc = PARAM1 + T0;
RETURN();
}
void OPPROTO op_bsr(void)
{
env->pr = PARAM1;
env->delayed_pc = PARAM2;
RETURN();
}
void OPPROTO op_bsrf_T0(void)
{
env->pr = PARAM1;
env->delayed_pc = PARAM1 + T0;
RETURN();
}
void OPPROTO op_jsr_T0(void)
{
env->pr = PARAM1;
env->delayed_pc = T0;
RETURN();
}
void OPPROTO op_rts(void)
{
env->delayed_pc = env->pr;
RETURN();
}
void OPPROTO op_ldtlb(void)
{
helper_ldtlb();
@ -119,13 +55,6 @@ void OPPROTO op_fschg(void)
RETURN();
}
void OPPROTO op_rte(void)
{
env->sr = env->ssr;
env->delayed_pc = env->spc;
RETURN();
}
void OPPROTO op_addc_T0_T1(void)
{
helper_addc_T0_T1();
@ -257,12 +186,6 @@ void OPPROTO op_trapa(void)
RETURN();
}
void OPPROTO op_jmp_T0(void)
{
env->delayed_pc = T0;
RETURN();
}
void OPPROTO op_ldcl_rMplus_rN_bank(void)
{
env->gregs[PARAM2] = env->gregs[PARAM1];
@ -568,28 +491,6 @@ void OPPROTO op_movl_FT0_fpul(void)
RETURN();
}
void OPPROTO op_jT(void)
{
if (env->sr & SR_T)
GOTO_LABEL_PARAM(1);
RETURN();
}
void OPPROTO op_jdelayed(void)
{
if (env->flags & DELAY_SLOT_TRUE) {
env->flags &= ~DELAY_SLOT_TRUE;
GOTO_LABEL_PARAM(1);
}
RETURN();
}
void OPPROTO op_movl_delayed_pc_PC(void)
{
env->pc = env->delayed_pc;
RETURN();
}
void OPPROTO op_raise_illegal_instruction(void)
{
env->exception_index = 0x180;

View File

@ -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;