diff mbox series

[3/3] target/m68k: Support semihosting on non-ColdFire targets

Message ID 20230802161914.395443-4-keithp@keithp.com (mailing list archive)
State New, archived
Headers show
Series target/m68k: Fix a few semihosting bugs | expand

Commit Message

Keith Packard Aug. 2, 2023, 4:19 p.m. UTC
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 <keithp@keithp.com>
---
 target/m68k/cpu.h       |  1 +
 target/m68k/op_helper.c | 16 ++++++++++++++++
 target/m68k/translate.c |  4 ++++
 3 files changed, 21 insertions(+)

Comments

Peter Maydell Aug. 3, 2023, 10:45 a.m. UTC | #1
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 <keithp@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
diff mbox series

Patch

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) {
+                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);
 #endif
 }