There's no need to raise an exception; just call the helper function directly. The test for the required surrounding insns is easier as well.
Move the load of nr inside the helper. Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/m68k/cpu.h | 2 -- target/m68k/helper.h | 1 + target/m68k/m68k-semi.c | 6 ++++-- target/m68k/op_helper.c | 10 ---------- target/m68k/translate.c | 26 +++++++++++++++++++++++++- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index 9b3bf7a448..60f88e6bc9 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -456,8 +456,6 @@ typedef enum { void m68k_set_irq_level(M68kCPU *cpu, int level, uint8_t vector); void m68k_switch_sp(CPUM68KState *env); -void do_m68k_semihosting(CPUM68KState *env, int nr); - /* * The 68000 family is defined in six main CPU classes, the 680[012346]0. * Generally each successive CPU adds enhanced data/stack/instructions. diff --git a/target/m68k/helper.h b/target/m68k/helper.h index 0a6b4146f6..0e27c27810 100644 --- a/target/m68k/helper.h +++ b/target/m68k/helper.h @@ -128,4 +128,5 @@ DEF_HELPER_4(chk2, void, env, s32, s32, s32) DEF_HELPER_3(ptest, void, env, i32, i32) DEF_HELPER_3(pflush, void, env, i32, i32) DEF_HELPER_FLAGS_1(reset, TCG_CALL_NO_RWG, void, env) +DEF_HELPER_1(semihosting, void, env) #endif diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c index 71f9d42e6c..1a36c1158d 100644 --- a/target/m68k/m68k-semi.c +++ b/target/m68k/m68k-semi.c @@ -25,6 +25,7 @@ #include "semihosting/softmmu-uaccess.h" #include "hw/boards.h" #include "qemu/log.h" +#include "exec/helper-proto.h" #define HOSTED_EXIT 0 #define HOSTED_INIT_SIM 1 @@ -84,12 +85,13 @@ static void m68k_semi_u64_cb(CPUState *cs, uint64_t ret, int err) } \ } while (0) -void do_m68k_semihosting(CPUM68KState *env, int nr) +void HELPER(semihosting)(CPUM68KState *env) { CPUState *cs = env_cpu(env); - uint32_t args; + uint32_t args, nr; target_ulong arg0, arg1, arg2, arg3; + nr = env->dregs[0]; args = env->dregs[1]; switch (nr) { case HOSTED_EXIT: diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 8decc61240..a345245612 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -22,7 +22,6 @@ #include "exec/helper-proto.h" #include "exec/exec-all.h" #include "exec/cpu_ldst.h" -#include "semihosting/semihost.h" #if !defined(CONFIG_USER_ONLY) @@ -203,15 +202,6 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw) cf_rte(env); return; case EXCP_HALT_INSN: - if (semihosting_enabled() - && (env->sr & SR_S) != 0 - && (env->pc & 3) == 0 - && cpu_lduw_code(env, env->pc - 4) == 0x4e71 - && cpu_ldl_code(env, env->pc) == 0x4e7bf000) { - env->pc += 4; - do_m68k_semihosting(env, env->dregs[0]); - return; - } cs->halted = 1; cs->exception_index = EXCP_HLT; cpu_loop_exit(cs); diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 4026572ed8..b7adc8f53d 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -33,6 +33,9 @@ #include "exec/log.h" #include "fpu/softfloat.h" +#ifndef CONFIG_USER_ONLY +#include "semihosting/semihost.h" +#endif //#define DEBUG_DISPATCH 1 @@ -313,6 +316,25 @@ static inline void gen_addr_fault(DisasContext *s) gen_exception(s, s->base.pc_next, EXCP_ADDRESS); } +#ifndef CONFIG_USER_ONLY +static bool maybe_semihosting(DisasContext *s) +{ + /* + * The semihosting insn (halt or bkpt) is preceeded by an aligned NOP + * and followed by an invalid sentinel insn (movec %sp,0). + */ + if (semihosting_enabled() + && (s->pc & 3) == 2 + && cpu_lduw_code(s->env, s->pc - 2) == 0x4e71 + && cpu_ldl_code(s->env, s->pc + 4) == 0x4e7bf000) { + gen_helper_semihosting(cpu_env); + s->pc += 4; + return true; + } + return false; +} +#endif + /* * Generate a load from the specified address. Narrow values are * sign extended to full register width. @@ -4702,7 +4724,9 @@ DISAS_INSN(halt) gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); return; } - + if (maybe_semihosting(s)) { + return; + } gen_exception(s, s->pc, EXCP_HALT_INSN); } -- 2.34.1