From patchwork Thu Jan 4 16:42:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 855720 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zCDPX5T2fz9t3B for ; Fri, 5 Jan 2018 03:52:48 +1100 (AEDT) Received: from localhost ([::1]:50031 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eX8l4-0008Vx-Qg for incoming@patchwork.ozlabs.org; Thu, 04 Jan 2018 11:52:46 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55341) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eX8bc-0007ZO-0p for qemu-devel@nongnu.org; Thu, 04 Jan 2018 11:43:03 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eX8bZ-0003Yd-Dv for qemu-devel@nongnu.org; Thu, 04 Jan 2018 11:42:59 -0500 Received: from mout.kundenserver.de ([212.227.126.130]:55839) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eX8bY-0003W7-TG for qemu-devel@nongnu.org; Thu, 04 Jan 2018 11:42:57 -0500 Received: from localhost.localdomain ([78.238.229.36]) by mrelayeu.kundenserver.de (mreue003 [212.227.15.167]) with ESMTPSA (Nemesis) id 0LiGlL-1fJPnY1CR1-00nPnA; Thu, 04 Jan 2018 17:42:55 +0100 From: Laurent Vivier To: qemu-devel@nongnu.org Date: Thu, 4 Jan 2018 17:42:40 +0100 Message-Id: <20180104164251.26494-7-laurent@vivier.eu> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180104164251.26494-1-laurent@vivier.eu> References: <20180104164251.26494-1-laurent@vivier.eu> X-Provags-ID: V03:K0:yCXysh2T8JIcFP5NQ2xILwUCk4eIYa8LFSc2O4TP+K1O50Ft7DI cRyrJz83cF/IQqNaHqMi4wVftyM4e8jgdLJvCZRmq6KJd3kID5+d0Tx9pInWbWO0UKqY18x KMCH2i2TKl9U8iqWs366aQPQp9+g2/fECZR50UyhXzO6stSZZ5Nn2sxs7pbGEXrwZG68ioB qHd+JR5w6Xk6jhovy77sA== X-UI-Out-Filterresults: notjunk:1; V01:K0:5vF7mgXzPgM=:zH3htggDpgK7aCGQ21TKLP fHfSXNKT8aU6AqBoWn12y7t28egyGB7ZxP2Vcl5SCPmOoezAgJSXOl2WQtCtXu2A94OT4l1WP npI364B2J+l7RLXzxsEjta5V4WFT9vCzwoFoR4dKZwozW2GqjEBaDwXl67aUH301uRpyziO5R ubNEciAFyz1vY9/ayYCOgcHVD/K0AJQhIpTgTj1/WIsVeaqdiQuNfSGXRyDNY/k5QV7ClbALe sbTdWDYrqKH7YoSzfeQNTyXVDi5R+ykMhmLVdOf+nea68agL2kz0hZLt3G8Sa6kGy6njpGuAI ZP4nwHIqG4eIDv/zfSixWuc0NYqNmnbRJEBfJsHHUyiIaDBXNlgiiPw7Bv5eRGVX/KK7czScW VcQjXgmISONEeQVjiWHG11uPPwCoVT6xI4MpiQNuGZfKrGvOUDzNF7mLqX5F6s6EAfJVSP/I1 CdgpPyxHIaWqzVYdW282ulydZWFBlkkSXHIf/HImRyfJ/8mVR/YIYqjdkjvmqqfi1r7dfTM6w rMnviUh9WUK1HLhWmobC75hXrXGyMEsGA2lQdKvTEsCyUHptyDFm/kP+TwGKFtUFJ5APsNm/C zsU/0ogxiheVNedTN+NqpwP+7yAAyK/S/wc5Jd3Y8dorhb0USw5cTUnGJIjD7d3etC6WjnBDb /xO01hUKzVQaEWXNxIQHOfaZm03P3eX3SFQdEJDCIwm5gSAYMdCHVIqp1T8YpZLTjox5Z/ubE f1nmWT2qEKcarHV6XFxrG3n5c9dt9TggYyM3Qh8SiT7o+kPsH9mPqIjZyxw= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 212.227.126.130 Subject: [Qemu-devel] [PULL 06/17] target/m68k: manage 680x0 stack frames X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Laurent Vivier Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" 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 Reviewed-by: Richard Henderson Message-Id: <20180104012913.30763-7-laurent@vivier.eu> --- 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);