On Wed, 2 Aug 2023 at 17:20, Keith Packard via <qemu-devel@nongnu.org> wrote:
>
> According to the m68k semihosting spec:
>
> "The instruction used to trigger a semihosting request depends on the
>  m68k processor variant.  On ColdFire, "halt" is used; on other processors
>  (which don't implement "halt"), "bkpt #0" may be used."
>
> Add support for non-CodeFire processors by matching BKPT #0
> instructions. When semihosting is disabled, convert those
> back to illegal op exceptions.
>
> Signed-off-by: Keith Packard <kei...@keithp.com>
> ---
>  target/m68k/cpu.h       |  1 +
>  target/m68k/op_helper.c | 16 ++++++++++++++++
>  target/m68k/translate.c |  4 ++++
>  3 files changed, 21 insertions(+)
>
> diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
> index cf70282717..b741c50a8f 100644
> --- a/target/m68k/cpu.h
> +++ b/target/m68k/cpu.h
> @@ -67,6 +67,7 @@
>
>  #define EXCP_RTE            0x100
>  #define EXCP_HALT_INSN      0x101
> +#define EXCP_BKPT_INSN      0x102
>
>  #define M68K_DTTR0   0
>  #define M68K_DTTR1   1
> diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
> index 1ce850bbc5..2d89db6dde 100644
> --- a/target/m68k/op_helper.c
> +++ b/target/m68k/op_helper.c
> @@ -295,6 +295,22 @@ static void m68k_interrupt_all(CPUM68KState *env, int 
> is_hw)
>              /* Return from an exception.  */
>              m68k_rte(env);
>              return;
> +        case EXCP_BKPT_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) {

This long condition is identical to the one used for
semihosting-via-halt. It could usefully be moved out
to a function, which can then have a comment noting
what it's doing (i.e. checking for the required insns
preceding and following the bkpt or halt).

> +                env->pc += 4;
> +                do_m68k_semihosting(env, env->dregs[0]);
> +                return;
> +            }
> +            /*
> +             * When semihosting is not enabled, translate this back to
> +             * an illegal op exception.
> +             */
> +            cs->exception_index = EXCP_ILLEGAL;
> +            env->pc += 2;
> +            break;
>          }
>      }
>
> diff --git a/target/m68k/translate.c b/target/m68k/translate.c
> index e07161d76f..d037c57453 100644
> --- a/target/m68k/translate.c
> +++ b/target/m68k/translate.c
> @@ -2640,6 +2640,10 @@ DISAS_INSN(bkpt)
>  #if defined(CONFIG_USER_ONLY)
>      gen_exception(s, s->base.pc_next, EXCP_DEBUG);
>  #else
> +    if ((insn & 7) == 0) {
> +        gen_exception(s, s->pc, EXCP_BKPT_INSN);
> +        return;
> +    }
>      gen_exception(s, s->base.pc_next, EXCP_ILLEGAL);

This means that semihosting-via-bpkt will only work
in system emulation, because in user mode the
EXCP_DEBUG will take precedence. To handle that you
need to also check in linux-user/m68k/cpu_loop.c. But
this effectively also implies reverting most of
a638af09b6c6b (where we took out a lot of "m68k
usermode semihosting" because it wasn't reachable).
So it's probably not worthwhile.

-- PMM

Reply via email to