mips: handle delay slot so do not duplicate calling instruction handler. this fixes issue #133
This commit is contained in:
parent
80c316026f
commit
14a01b5186
@ -1415,7 +1415,7 @@ enum {
|
|||||||
* exception condition */
|
* exception condition */
|
||||||
BS_STOP = 1, /* We want to stop translation for any reason */
|
BS_STOP = 1, /* We want to stop translation for any reason */
|
||||||
BS_BRANCH = 2, /* We reached a branch condition */
|
BS_BRANCH = 2, /* We reached a branch condition */
|
||||||
BS_EXCP = 3, /* We reached an exception condition */ // qq
|
BS_EXCP = 3, /* We reached an exception condition */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const regnames[] = {
|
static const char * const regnames[] = {
|
||||||
@ -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)
|
static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx, int is_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)
|
|||||||
n_bytes = 2;
|
n_bytes = 2;
|
||||||
|
|
||||||
// Unicorn: trace this instruction on request
|
// Unicorn: trace this instruction on request
|
||||||
if (env->uc->hook_insn) {
|
if (!is_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)
|
static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int is_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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: trace this instruction on request
|
// Unicorn: trace this instruction on request
|
||||||
if (env->uc->hook_insn) {
|
if (!is_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)
|
static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int is_slot)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
@ -18514,6 +18514,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
|||||||
uint32_t op, op1;
|
uint32_t op, op1;
|
||||||
int16_t imm;
|
int16_t imm;
|
||||||
|
|
||||||
|
|
||||||
/* make sure instructions are on a word boundary */
|
/* make sure instructions are on a word boundary */
|
||||||
if (ctx->pc & 0x3) {
|
if (ctx->pc & 0x3) {
|
||||||
env->CP0_BadVAddr = ctx->pc;
|
env->CP0_BadVAddr = ctx->pc;
|
||||||
@ -18522,7 +18523,7 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unicorn: trace this instruction on request
|
// Unicorn: trace this instruction on request
|
||||||
if (env->uc->hook_insn) {
|
if (!is_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);
|
||||||
@ -19227,7 +19228,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
|||||||
}
|
}
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
while (ctx.bstate == BS_NONE) { // qq
|
while (ctx.bstate == BS_NONE) {
|
||||||
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
||||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||||
if (bp->pc == ctx.pc) {
|
if (bp->pc == ctx.pc) {
|
||||||
@ -19268,16 +19269,16 @@ 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;
|
||||||
if (!(ctx.hflags & MIPS_HFLAG_M16)) { // qq
|
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);
|
decode_opc(env, &ctx, is_slot);
|
||||||
} else if (ctx.insn_flags & ASE_MICROMIPS) { // qq
|
} 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);
|
insn_bytes = decode_micromips_opc(env, &ctx, is_slot);
|
||||||
} else if (ctx.insn_flags & ASE_MIPS16) { // qq
|
} 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);
|
insn_bytes = decode_mips16_opc(env, &ctx, is_slot);
|
||||||
} else {
|
} else {
|
||||||
generate_exception(&ctx, EXCP_RI);
|
generate_exception(&ctx, EXCP_RI);
|
||||||
ctx.bstate = BS_STOP;
|
ctx.bstate = BS_STOP;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
from capstone import *
|
from capstone import *
|
||||||
from unicorn import *
|
from unicorn import *
|
||||||
from unicorn.mips_const import *
|
|
||||||
|
|
||||||
import regress
|
import regress
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ class MipsBranchDelay(regress.RegressTest):
|
|||||||
disas(mem, addr)
|
disas(mem, addr)
|
||||||
|
|
||||||
CODE = 0x400000
|
CODE = 0x400000
|
||||||
asm = '0000a4126a00822800000000'.decode('hex')
|
asm = '0000a4126a00822800000000'.decode('hex') # beq $a0, $s5, 0x4008a0; slti $v0, $a0, 0x6a; nop
|
||||||
|
|
||||||
print 'Input instructions:'
|
print 'Input instructions:'
|
||||||
disas(asm, CODE)
|
disas(asm, CODE)
|
||||||
|
Loading…
Reference in New Issue
Block a user