diff --git a/qemu/target/tricore/helper.h b/qemu/target/tricore/helper.h index e1ee5fa0..e0712597 100644 --- a/qemu/target/tricore/helper.h +++ b/qemu/target/tricore/helper.h @@ -22,6 +22,7 @@ DEF_HELPER_4(uc_tracecode, void, i32, i32, ptr, i64) DEF_HELPER_6(uc_traceopcode, void, ptr, i64, i64, i32, ptr, i64) +DEF_HELPER_1(uc_tricore_exit,void, env) /* Arithmetic */ DEF_HELPER_3(add_ssov, i32, env, i32, i32) diff --git a/qemu/target/tricore/op_helper.c b/qemu/target/tricore/op_helper.c index 57ad816f..6bb7b3a0 100644 --- a/qemu/target/tricore/op_helper.c +++ b/qemu/target/tricore/op_helper.c @@ -2793,3 +2793,12 @@ uint32_t helper_psw_read(CPUTriCoreState *env) { return psw_read(env); } + +void helper_uc_tricore_exit(CPUTriCoreState *env) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = EXCP_HLT; + cs->halted = 1; + cpu_loop_exit(cs); +} \ No newline at end of file diff --git a/qemu/target/tricore/translate.c b/qemu/target/tricore/translate.c index 112f2eb0..016306fb 100644 --- a/qemu/target/tricore/translate.c +++ b/qemu/target/tricore/translate.c @@ -33,6 +33,11 @@ #include "exec/translator.h" #include "exec/gen-icount.h" +/* + * Unicorn: Special disas state for exiting in the middle of tb. + */ +#define DISAS_UC_EXIT DISAS_TARGET_6 + static const char *regnames_a[] = { "a0" , "a1" , "a2" , "a3" , "a4" , "a5" , "a6" , "a7" , "a8" , "a9" , "sp" , "a11" , @@ -9227,11 +9232,7 @@ static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) // Unicorn: end address tells us to stop emulation if (uc_addr_is_exit(uc, ctx->base.pc_next)) { - gen_helper_rfe(tcg_ctx, tcg_ctx->cpu_env); - tcg_gen_exit_tb(tcg_ctx, NULL, 0); - cpu->exception_index = EXCP_HLT; - cpu->halted = 1; - ctx->base.is_jmp = DISAS_NORETURN; + ctx->base.is_jmp = DISAS_UC_EXIT; } else { insn_lo = cpu_lduw_code(env, ctx->base.pc_next); is_16bit = tricore_insn_is_16bit(insn_lo); @@ -9239,6 +9240,9 @@ static void tricore_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) insn_size = is_16bit ? 2 : 4; // Unicorn: trace this instruction on request if (HOOK_EXISTS_BOUNDED(ctx->uc, UC_HOOK_CODE, ctx->base.pc_next)) { + // Sync PC in advance + gen_save_pc(ctx, ctx->base.pc_next); + gen_uc_tracecode(tcg_ctx, insn_size, UC_HOOK_CODE_IDX, ctx->uc, ctx->base.pc_next); // the callback might want to stop emulation immediately @@ -9282,6 +9286,10 @@ static void tricore_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) case DISAS_TOO_MANY: gen_goto_tb(ctx, 0, ctx->base.pc_next); break; + case DISAS_UC_EXIT: + gen_save_pc(ctx, ctx->base.pc_next); + gen_helper_uc_tricore_exit(ctx->uc->tcg_ctx, ctx->uc->tcg_ctx->cpu_env); + break; case DISAS_NORETURN: break; default: @@ -9371,4 +9379,4 @@ void tricore_tcg_init(struct uc_struct *uc) tcg_ctx->cpu_PSW_SAV = tcg_global_mem_new(uc->tcg_ctx, tcg_ctx->cpu_env, offsetof(CPUTriCoreState, PSW_USB_SAV), "PSW_SAV"); -} \ No newline at end of file +} diff --git a/qemu/tricore.h b/qemu/tricore.h index 6603175f..3f41fc76 100644 --- a/qemu/tricore.h +++ b/qemu/tricore.h @@ -1286,4 +1286,5 @@ #define helper_pack helper_pack_tricore #define gen_intermediate_code gen_intermediate_code_tricore #define restore_state_to_opc restore_state_to_opc_tricore +#define helper_uc_tricore_exit helper_uc_tricore_exit_tricore #endif diff --git a/symbols.sh b/symbols.sh index 0d426c00..f2d0a114 100755 --- a/symbols.sh +++ b/symbols.sh @@ -6292,6 +6292,7 @@ helper_fmsub \ helper_pack \ gen_intermediate_code \ restore_state_to_opc \ +helper_uc_tricore_exit \ " ARCHS="x86_64 arm aarch64 riscv32 riscv64 mips mipsel mips64 mips64el sparc sparc64 m68k ppc ppc64 s390x tricore"