mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-25 05:21:08 +00:00
mips: handle delay slot better for branch instructions. this should fix issue #155
This commit is contained in:
parent
4a2092fa10
commit
53ce8f217d
|
@ -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
2
tests/regress/mips_single_step_sp.py
Normal file → Executable file
|
@ -1,3 +1,5 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
from unicorn import *
|
from unicorn import *
|
||||||
from unicorn.mips_const import *
|
from unicorn.mips_const import *
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue