diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-10-03 15:15:24 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2024-04-24 15:46:00 -0700 |
commit | f161e723fdfddfc820c7f19eb6ac76ac6ba6d2a8 (patch) | |
tree | 325bee8ed13149a5d18f7787492a55faabbb47db | |
parent | 5fae5110eedba1110605c88d96cd4a5f057bfca2 (diff) |
target/m68k: Perform the semihosting test during translate
Replace EXCP_HALT_INSN by EXCP_SEMIHOSTING. Perform the pre-
and post-insn tests during translate, leaving only the actual
semihosting operation for the exception.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | target/m68k/cpu.h | 2 | ||||
-rw-r--r-- | target/m68k/op_helper.c | 14 | ||||
-rw-r--r-- | target/m68k/translate.c | 45 |
3 files changed, 44 insertions, 17 deletions
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index e184239a81..b5bbeedb7a 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -66,7 +66,7 @@ #define EXCP_MMU_ACCESS 58 /* MMU Access Level Violation Error */ #define EXCP_RTE 0x100 -#define EXCP_HALT_INSN 0x101 +#define EXCP_SEMIHOSTING 0x101 #define M68K_DTTR0 0 #define M68K_DTTR1 1 diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 125f6c1b08..15bad5dd46 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -202,18 +202,8 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw) /* Return from an exception. */ 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); + case EXCP_SEMIHOSTING: + do_m68k_semihosting(env, env->dregs[0]); return; } } diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 8a194f2f21..647bd9d9be 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -26,12 +26,11 @@ #include "qemu/log.h" #include "qemu/qemu-print.h" #include "exec/translator.h" - #include "exec/helper-proto.h" #include "exec/helper-gen.h" - #include "exec/log.h" #include "fpu/softfloat.h" +#include "semihosting/semihost.h" #define HELPER_H "helper.h" #include "exec/helper-info.c.inc" @@ -1401,6 +1400,40 @@ static void gen_jmp_tb(DisasContext *s, int n, target_ulong dest, s->base.is_jmp = DISAS_NORETURN; } +#ifndef CONFIG_USER_ONLY +static bool semihosting_test(DisasContext *s) +{ + uint32_t test; + + if (!semihosting_enabled(IS_USER(s))) { + return false; + } + + /* + * "The semihosting instruction is immediately preceded by a + * nop aligned to a 4-byte boundary..." + * The preceding 2-byte (aligned) nop plus the 2-byte halt/bkpt + * means that we have advanced 4 bytes from the required nop. + */ + if (s->pc % 4 != 0) { + return false; + } + test = translator_lduw(s->env, &s->base, s->pc - 4); + if (test != 0x4e71) { + return false; + } + /* "... and followed by an invalid sentinel instruction movec %sp,0." */ + test = translator_ldl(s->env, &s->base, s->pc); + if (test != 0x4e7bf000) { + return false; + } + + /* Consume the sentinel. */ + s->pc += 4; + return true; +} +#endif /* !CONFIG_USER_ONLY */ + DISAS_INSN(scc) { DisasCompare c; @@ -4465,8 +4498,12 @@ DISAS_INSN(halt) gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); return; } - - gen_exception(s, s->pc, EXCP_HALT_INSN); + if (semihosting_test(s)) { + gen_exception(s, s->pc, EXCP_SEMIHOSTING); + return; + } + tcg_gen_movi_i32(cpu_halted, 1); + gen_exception(s, s->pc, EXCP_HLT); } DISAS_INSN(stop) |