mips: handle delay slot better for branch instructions. this should fix issue #155

This commit is contained in:
Nguyen Anh Quynh 2015-09-27 15:05:40 +08:00
parent 4a2092fa10
commit 53ce8f217d
2 changed files with 17 additions and 11 deletions

View file

@ -11322,7 +11322,7 @@ static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
return 4; return 4;
} }
static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, bool is_bc_slot)
{ {
TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
@ -11343,7 +11343,7 @@ static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot)
n_bytes = 2; n_bytes = 2;
// Unicorn: trace this instruction on request // Unicorn: trace this instruction on request
if (!is_slot && env->uc->hook_insn) { if (!is_bc_slot && env->uc->hook_insn) {
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc);
if (trace) if (trace)
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data);
@ -13928,7 +13928,7 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
} }
} }
static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool is_bc_slot)
{ {
TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGContext *tcg_ctx = env->uc->tcg_ctx;
TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
@ -13943,7 +13943,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int is_sl
} }
// Unicorn: trace this instruction on request // Unicorn: trace this instruction on request
if (!is_slot && env->uc->hook_insn) { if (!is_bc_slot && env->uc->hook_insn) {
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc);
if (trace) if (trace)
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data);
@ -18503,7 +18503,7 @@ static void gen_msa(CPUMIPSState *env, DisasContext *ctx)
} }
} }
static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot) static void decode_opc (CPUMIPSState *env, DisasContext *ctx, bool is_bc_slot)
{ {
TCGContext *tcg_ctx = ctx->uc->tcg_ctx; TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
#if defined(TARGET_MIPS64) #if defined(TARGET_MIPS64)
@ -18523,7 +18523,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot)
} }
// Unicorn: trace this instruction on request // Unicorn: trace this instruction on request
if (!is_slot && env->uc->hook_insn) { if (!is_bc_slot && env->uc->hook_insn) {
struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc); struct hook_struct *trace = hook_find(env->uc, UC_HOOK_CODE, ctx->pc);
if (trace) if (trace)
gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data); gen_uc_tracecode(tcg_ctx, 0xf8f8f8f8, trace->callback, env->uc, ctx->pc, trace->user_data);
@ -19171,6 +19171,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
int max_insns; int max_insns;
int insn_bytes; int insn_bytes;
int is_slot = 0; int is_slot = 0;
bool is_bc_slot = false;
TCGContext *tcg_ctx = env->uc->tcg_ctx; TCGContext *tcg_ctx = env->uc->tcg_ctx;
TCGArg *save_opparam_ptr = NULL; TCGArg *save_opparam_ptr = NULL;
bool block_full = false; bool block_full = false;
@ -19272,16 +19273,18 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
save_opparam_ptr = tcg_ctx->gen_opparam_ptr; save_opparam_ptr = tcg_ctx->gen_opparam_ptr;
is_slot = ctx.hflags & MIPS_HFLAG_BMASK; is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
is_bc_slot = (is_slot & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BC;
if (!(ctx.hflags & MIPS_HFLAG_M16)) { if (!(ctx.hflags & MIPS_HFLAG_M16)) {
ctx.opcode = cpu_ldl_code(env, ctx.pc); ctx.opcode = cpu_ldl_code(env, ctx.pc);
insn_bytes = 4; insn_bytes = 4;
decode_opc(env, &ctx, is_slot); decode_opc(env, &ctx, is_bc_slot);
} else if (ctx.insn_flags & ASE_MICROMIPS) { } else if (ctx.insn_flags & ASE_MICROMIPS) {
ctx.opcode = cpu_lduw_code(env, ctx.pc); ctx.opcode = cpu_lduw_code(env, ctx.pc);
insn_bytes = decode_micromips_opc(env, &ctx, is_slot); insn_bytes = decode_micromips_opc(env, &ctx, is_bc_slot);
} else if (ctx.insn_flags & ASE_MIPS16) { } else if (ctx.insn_flags & ASE_MIPS16) {
ctx.opcode = cpu_lduw_code(env, ctx.pc); ctx.opcode = cpu_lduw_code(env, ctx.pc);
insn_bytes = decode_mips16_opc(env, &ctx, is_slot); insn_bytes = decode_mips16_opc(env, &ctx, is_bc_slot);
} else { } else {
generate_exception(&ctx, EXCP_RI); generate_exception(&ctx, EXCP_RI);
ctx.bstate = BS_STOP; ctx.bstate = BS_STOP;
@ -19289,18 +19292,19 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
} }
// Unicorn: patch the callback for the instruction size // Unicorn: patch the callback for the instruction size
if (env->uc->hook_insn) if (!is_bc_slot && env->uc->hook_insn)
*(save_opparam_ptr + 1) = insn_bytes; *(save_opparam_ptr + 1) = insn_bytes;
} }
if (ctx.hflags & MIPS_HFLAG_BMASK) { if (ctx.hflags & MIPS_HFLAG_BMASK) {
if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 | if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
MIPS_HFLAG_FBNSLOT))) { MIPS_HFLAG_FBNSLOT))) {
/* force to generate branch as there is neither delay nor /* force to generate branch as there is neither delay nor
forbidden slot */ forbidden slot */
is_slot = 1; is_slot = 1;
} }
} }
if (is_slot) { if (is_slot) {
gen_branch(&ctx, insn_bytes); gen_branch(&ctx, insn_bytes);
} }

2
tests/regress/mips_single_step_sp.py Normal file → Executable file
View file

@ -1,3 +1,5 @@
#!/usr/bin/python
from unicorn import * from unicorn import *
from unicorn.mips_const import * from unicorn.mips_const import *