@@ -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.
@@ -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
@@ -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:
@@ -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);
@@ -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);
}
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.henderson@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(-)