Further fix MIPS delay slot
This commit is contained in:
@@ -30924,7 +30924,7 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
struct uc_struct *uc = cs->uc;
|
||||
TCGContext *tcg_ctx = uc->tcg_ctx;
|
||||
TCGOp *tcg_op, *prev_op = NULL;
|
||||
TCGOp *tcg_op, *prev_op = NULL, *slot_op = NULL;
|
||||
int insn_bytes;
|
||||
int is_slot;
|
||||
bool hook_insn = false;
|
||||
@@ -30949,11 +30949,17 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
prev_op = tcg_last_op(tcg_ctx);
|
||||
hook_insn = true;
|
||||
gen_uc_tracecode(tcg_ctx, 4, UC_HOOK_CODE_IDX, uc, ctx->base.pc_next);
|
||||
// Don't let unicorn stop at the branch delay slot.
|
||||
if (!is_slot) {
|
||||
// the callback might want to stop emulation immediately
|
||||
check_exit_request(tcg_ctx);
|
||||
}
|
||||
|
||||
// TODO: Memory hooks, maybe use icount_decr.low?
|
||||
TCGLabel *skip_label = gen_new_label(tcg_ctx);
|
||||
TCGv_i32 dyn_is_slot = tcg_const_i32(tcg_ctx, 0);
|
||||
slot_op = tcg_last_op(tcg_ctx);
|
||||
// if slot, skip exit_request
|
||||
// tcg is smart enough to optimize this branch away
|
||||
tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_GT, dyn_is_slot, 0, skip_label);
|
||||
tcg_temp_free_i32(tcg_ctx, dyn_is_slot);
|
||||
check_exit_request(tcg_ctx);
|
||||
gen_set_label(tcg_ctx, skip_label);
|
||||
}
|
||||
|
||||
if (ctx->insn_flags & ISA_NANOMIPS32) {
|
||||
@@ -30975,23 +30981,6 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
return;
|
||||
}
|
||||
|
||||
if (hook_insn) {
|
||||
// Unicorn: patch the callback to have the proper instruction size.
|
||||
if (prev_op) {
|
||||
// As explained further up in the function where prev_op is
|
||||
// assigned, we move forward in the tail queue, so we're modifying the
|
||||
// move instruction generated by gen_uc_tracecode() that contains
|
||||
// the instruction size to assign the proper size (replacing 0xF1F1F1F1).
|
||||
tcg_op = QTAILQ_NEXT(prev_op, link);
|
||||
} else {
|
||||
// this instruction is the first emulated code ever,
|
||||
// so the instruction operand is the first operand
|
||||
tcg_op = QTAILQ_FIRST(&tcg_ctx->ops);
|
||||
}
|
||||
|
||||
tcg_op->args[1] = insn_bytes;
|
||||
}
|
||||
|
||||
if (ctx->hflags & MIPS_HFLAG_BMASK) {
|
||||
if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
|
||||
MIPS_HFLAG_FBNSLOT))) {
|
||||
@@ -31010,6 +30999,28 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
|
||||
is_slot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hook_insn) {
|
||||
// Unicorn: patch the callback to have the proper instruction size.
|
||||
if (prev_op) {
|
||||
// As explained further up in the function where prev_op is
|
||||
// assigned, we move forward in the tail queue, so we're modifying the
|
||||
// move instruction generated by gen_uc_tracecode() that contains
|
||||
// the instruction size to assign the proper size (replacing 0xF1F1F1F1).
|
||||
tcg_op = QTAILQ_NEXT(prev_op, link);
|
||||
} else {
|
||||
// this instruction is the first emulated code ever,
|
||||
// so the instruction operand is the first operand
|
||||
tcg_op = QTAILQ_FIRST(&tcg_ctx->ops);
|
||||
}
|
||||
|
||||
tcg_op->args[1] = insn_bytes;
|
||||
}
|
||||
|
||||
if (slot_op) {
|
||||
slot_op->args[1] = is_slot;
|
||||
}
|
||||
|
||||
if (is_slot) {
|
||||
gen_branch(ctx, insn_bytes);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user