From: Laurent Vivier <laurent@vivier.eu>
To: qemu-devel@nongnu.org
Cc: Richard Henderson <richard.henderson@linaro.org>,
Thomas Huth <huth@tuxfamily.org>,
Laurent Vivier <laurent@vivier.eu>
Subject: [Qemu-devel] [PATCH v7 06/17] target/m68k: manage 680x0 stack frames
Date: Thu, 4 Jan 2018 02:29:02 +0100 [thread overview]
Message-ID: <20180104012913.30763-7-laurent@vivier.eu> (raw)
In-Reply-To: <20180104012913.30763-1-laurent@vivier.eu>
680x0 manages several stack frame formats:
- format 0: four-word stack frame
- format 1: four-word throwaway stack frame
- format 2: six-word stack frame
- format 3: Floating-Point post-instruction stack frame
- format 4: eight-word stack frame
- format 7: access-error stack frame
Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
---
Notes:
v6: update SR with the content of CCR in the logs
introduce cpu_m68k_set_sr() to set SR instead
of calling helper_set_sr().
target/m68k/cpu.h | 1 +
target/m68k/helper.c | 10 ++-
target/m68k/op_helper.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 164 insertions(+), 7 deletions(-)
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index acc2629216..cd4b3a7c7b 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -178,6 +178,7 @@ int cpu_m68k_signal_handler(int host_signum, void *pinfo,
void *puc);
uint32_t cpu_m68k_get_ccr(CPUM68KState *env);
void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t);
+void cpu_m68k_set_sr(CPUM68KState *env, uint32_t);
void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val);
diff --git a/target/m68k/helper.c b/target/m68k/helper.c
index 7e50ff5871..af57ffcea9 100644
--- a/target/m68k/helper.c
+++ b/target/m68k/helper.c
@@ -316,13 +316,17 @@ uint32_t HELPER(sats)(uint32_t val, uint32_t v)
return val;
}
-void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
+void cpu_m68k_set_sr(CPUM68KState *env, uint32_t sr)
{
- env->sr = val & 0xffe0;
- cpu_m68k_set_ccr(env, val);
+ env->sr = sr & 0xffe0;
+ cpu_m68k_set_ccr(env, sr);
m68k_switch_sp(env);
}
+void HELPER(set_sr)(CPUM68KState *env, uint32_t val)
+{
+ cpu_m68k_set_sr(env, val);
+}
/* MAC unit. */
/* FIXME: The MAC unit implementation is a bit of a mess. Some helpers
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 123981af55..5c7b27b9ca 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -54,7 +54,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
}
}
-static void do_rte(CPUM68KState *env)
+static void cf_rte(CPUM68KState *env)
{
uint32_t sp;
uint32_t fmt;
@@ -65,7 +65,46 @@ static void do_rte(CPUM68KState *env)
sp |= (fmt >> 28) & 3;
env->aregs[7] = sp + 8;
- helper_set_sr(env, fmt);
+ cpu_m68k_set_sr(env, fmt);
+}
+
+static void m68k_rte(CPUM68KState *env)
+{
+ uint32_t sp;
+ uint16_t fmt;
+ uint16_t sr;
+
+ sp = env->aregs[7];
+throwaway:
+ sr = cpu_lduw_kernel(env, sp);
+ sp += 2;
+ env->pc = cpu_ldl_kernel(env, sp);
+ sp += 4;
+ if (m68k_feature(env, M68K_FEATURE_QUAD_MULDIV)) {
+ /* all except 68000 */
+ fmt = cpu_lduw_kernel(env, sp);
+ sp += 2;
+ switch (fmt >> 12) {
+ case 0:
+ break;
+ case 1:
+ env->aregs[7] = sp;
+ cpu_m68k_set_sr(env, sr);
+ goto throwaway;
+ case 2:
+ case 3:
+ sp += 4;
+ break;
+ case 4:
+ sp += 8;
+ break;
+ case 7:
+ sp += 52;
+ break;
+ }
+ }
+ env->aregs[7] = sp;
+ cpu_m68k_set_sr(env, sr);
}
static const char *m68k_exception_name(int index)
@@ -173,7 +212,7 @@ static const char *m68k_exception_name(int index)
return "Unassigned";
}
-static void do_interrupt_all(CPUM68KState *env, int is_hw)
+static void cf_interrupt_all(CPUM68KState *env, int is_hw)
{
CPUState *cs = CPU(m68k_env_get_cpu(env));
uint32_t sp;
@@ -189,7 +228,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
switch (cs->exception_index) {
case EXCP_RTE:
/* Return from an exception. */
- do_rte(env);
+ cf_rte(env);
return;
case EXCP_HALT_INSN:
if (semihosting_enabled()
@@ -247,6 +286,119 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
env->pc = cpu_ldl_kernel(env, env->vbr + vector);
}
+static inline void do_stack_frame(CPUM68KState *env, uint32_t *sp,
+ uint16_t format, uint16_t sr,
+ uint32_t addr, uint32_t retaddr)
+{
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+ switch (format) {
+ case 4:
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, env->pc);
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, addr);
+ break;
+ case 3:
+ case 2:
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, addr);
+ break;
+ }
+ *sp -= 2;
+ cpu_stw_kernel(env, *sp, (format << 12) + (cs->exception_index << 2));
+ *sp -= 4;
+ cpu_stl_kernel(env, *sp, retaddr);
+ *sp -= 2;
+ cpu_stw_kernel(env, *sp, sr);
+}
+
+static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
+{
+ CPUState *cs = CPU(m68k_env_get_cpu(env));
+ uint32_t sp;
+ uint32_t retaddr;
+ uint32_t vector;
+ uint16_t sr, oldsr;
+
+ retaddr = env->pc;
+
+ if (!is_hw) {
+ switch (cs->exception_index) {
+ case EXCP_RTE:
+ /* Return from an exception. */
+ m68k_rte(env);
+ return;
+ case EXCP_TRAP0 ... EXCP_TRAP15:
+ /* Move the PC after the trap instruction. */
+ retaddr += 2;
+ break;
+ }
+ }
+
+ vector = cs->exception_index << 2;
+
+ sr = env->sr | cpu_m68k_get_ccr(env);
+ if (qemu_loglevel_mask(CPU_LOG_INT)) {
+ static int count;
+ qemu_log("INT %6d: %s(%#x) pc=%08x sp=%08x sr=%04x\n",
+ ++count, m68k_exception_name(cs->exception_index),
+ vector, env->pc, env->aregs[7], sr);
+ }
+
+ /*
+ * MC68040UM/AD, chapter 9.3.10
+ */
+
+ /* "the processor first make an internal copy" */
+ oldsr = sr;
+ /* "set the mode to supervisor" */
+ sr |= SR_S;
+ /* "suppress tracing" */
+ sr &= ~SR_T;
+ /* "sets the processor interrupt mask" */
+ if (is_hw) {
+ sr |= (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT);
+ }
+ cpu_m68k_set_sr(env, sr);
+ sp = env->aregs[7];
+
+ sp &= ~1;
+ if (cs->exception_index == EXCP_ADDRESS) {
+ do_stack_frame(env, &sp, 2, oldsr, 0, retaddr);
+ } else if (cs->exception_index == EXCP_ILLEGAL ||
+ cs->exception_index == EXCP_DIV0 ||
+ cs->exception_index == EXCP_CHK ||
+ cs->exception_index == EXCP_TRAPCC ||
+ cs->exception_index == EXCP_TRACE) {
+ /* FIXME: addr is not only env->pc */
+ do_stack_frame(env, &sp, 2, oldsr, env->pc, retaddr);
+ } else if (is_hw && oldsr & SR_M &&
+ cs->exception_index >= EXCP_SPURIOUS &&
+ cs->exception_index <= EXCP_INT_LEVEL_7) {
+ do_stack_frame(env, &sp, 0, oldsr, 0, retaddr);
+ oldsr = sr;
+ env->aregs[7] = sp;
+ cpu_m68k_set_sr(env, sr &= ~SR_M);
+ sp = env->aregs[7] & ~1;
+ do_stack_frame(env, &sp, 1, oldsr, 0, retaddr);
+ } else {
+ do_stack_frame(env, &sp, 0, oldsr, 0, retaddr);
+ }
+
+ env->aregs[7] = sp;
+ /* Jump to vector. */
+ env->pc = cpu_ldl_kernel(env, env->vbr + vector);
+}
+
+static void do_interrupt_all(CPUM68KState *env, int is_hw)
+{
+ if (m68k_feature(env, M68K_FEATURE_M68000)) {
+ m68k_interrupt_all(env, is_hw);
+ return;
+ }
+ cf_interrupt_all(env, is_hw);
+}
+
void m68k_cpu_do_interrupt(CPUState *cs)
{
M68kCPU *cpu = M68K_CPU(cs);
--
2.14.3
next prev parent reply other threads:[~2018-01-04 1:29 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-04 1:28 [Qemu-devel] [PATCH v7 00/17] target/m68k: supervisor mode (part 1) Laurent Vivier
2018-01-04 1:28 ` [Qemu-devel] [PATCH v7 01/17] target-m68k: sync CC_OP before gen_jmp_tb() Laurent Vivier
2018-01-04 1:28 ` [Qemu-devel] [PATCH v7 02/17] target/m68k: fix gen_get_ccr() Laurent Vivier
2018-01-04 1:28 ` [Qemu-devel] [PATCH v7 03/17] linux-user, m68k: correctly manage SR in context Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 04/17] target/m68k: use insn_pc to generate instruction fault address Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 05/17] target/m68k: add CPU_LOG_INT trace Laurent Vivier
2018-01-04 1:29 ` Laurent Vivier [this message]
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 07/17] target/m68k: add chk and chk2 Laurent Vivier
2018-01-04 7:10 ` Richard Henderson
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 08/17] target/m68k: add move16 Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 09/17] target/m68k: softmmu cleanup Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 10/17] target/m68k: add cpush/cinv Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 11/17] target/m68k: add reset Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 12/17] target/m68k: implement fsave/frestore Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 13/17] target/m68k: move CCR/SR functions Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 14/17] target/m68k: add 680x0 "move to SR" instruction Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 15/17] target/m68k: add andi/ori/eori to SR/CCR Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 16/17] target/m68k: add the Interrupt Stack Pointer Laurent Vivier
2018-01-04 1:29 ` [Qemu-devel] [PATCH v7 17/17] target/m68k: fix m68k_cpu_dump_state() Laurent Vivier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180104012913.30763-7-laurent@vivier.eu \
--to=laurent@vivier.eu \
--cc=huth@tuxfamily.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).