From 7d5dfd6b535d862194cdad0a8139f1026922c62f Mon Sep 17 00:00:00 2001 From: Lucien Murray-Pitts Date: Fri, 12 Mar 2021 14:53:45 -0500 Subject: [PATCH] m68k: add MSP detection support for stack pointer swap helpers On m68k there are two varities of stack pointers: USP with SSP or ISP/MSP. Only the 68020/30/40 support the MSP register the stack swap helpers don't support this feature. This patch adds this support, as well as comments to CPUM68KState to make it clear how stacks are handled Backports 7525a9b94c0c5733b8450c9451ca1de334f71ed8 --- qemu/target/m68k/cpu.c | 20 +++++++++++++++++++- qemu/target/m68k/cpu.h | 8 +++++++- qemu/target/m68k/helper.c | 3 ++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/qemu/target/m68k/cpu.c b/qemu/target/m68k/cpu.c index 2117fa44..015791ed 100644 --- a/qemu/target/m68k/cpu.c +++ b/qemu/target/m68k/cpu.c @@ -43,6 +43,11 @@ static void m68k_set_feature(CPUM68KState *env, int feature) env->features |= (1u << feature); } +static void m68k_unset_feature(CPUM68KState *env, int feature) +{ + env->features &= (-1u - (1u << feature)); +} + /* CPUClass::reset() */ static void m68k_cpu_reset(CPUState *s) { @@ -118,6 +123,7 @@ static void m68010_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque) { M68kCPU *cpu = M68K_CPU(uc, obj); CPUM68KState *env = &cpu->env; + m68000_cpu_initfn(uc, obj, opaque); m68k_set_feature(env, M68K_FEATURE_M68010); m68k_set_feature(env, M68K_FEATURE_RTD); @@ -158,8 +164,20 @@ static void m68020_cpu_initfn(struct uc_struct *uc, Object *obj, void *opaque) M68kCPU *cpu = M68K_CPU(uc, obj); CPUM68KState *env = &cpu->env; - m680x0_cpu_common(env); + m68010_cpu_initfn(uc, obj, opaque); + m68k_unset_feature(env, M68K_FEATURE_M68010); m68k_set_feature(env, M68K_FEATURE_M68020); + m68k_set_feature(env, M68K_FEATURE_QUAD_MULDIV); + m68k_set_feature(env, M68K_FEATURE_BRAL); + m68k_set_feature(env, M68K_FEATURE_BCCL); + m68k_set_feature(env, M68K_FEATURE_BITFIELD); + m68k_set_feature(env, M68K_FEATURE_EXT_FULL); + m68k_set_feature(env, M68K_FEATURE_SCALED_INDEX); + m68k_set_feature(env, M68K_FEATURE_LONG_MULDIV); + m68k_set_feature(env, M68K_FEATURE_FPU); + m68k_set_feature(env, M68K_FEATURE_CAS); + m68k_set_feature(env, M68K_FEATURE_CHK2); + m68k_set_feature(env, M68K_FEATURE_MSP); } /* diff --git a/qemu/target/m68k/cpu.h b/qemu/target/m68k/cpu.h index 9737e98f..ed41c29e 100644 --- a/qemu/target/m68k/cpu.h +++ b/qemu/target/m68k/cpu.h @@ -87,7 +87,13 @@ typedef struct CPUM68KState { uint32_t pc; uint32_t sr; - /* SSP and USP. The current_sp is stored in aregs[7], the other here. */ + /* + * The 68020/30/40 support two supervisor stacks, ISP and MSP. + * The 68000/10, Coldfire, and CPU32 only have USP/SSP. + * + * The current_sp is stored in aregs[7], the other here. + * The USP, SSP, and if used the additional ISP for 68020/30/40. + */ int current_sp; uint32_t sp[3]; diff --git a/qemu/target/m68k/helper.c b/qemu/target/m68k/helper.c index 307a84ad..872fa912 100644 --- a/qemu/target/m68k/helper.c +++ b/qemu/target/m68k/helper.c @@ -332,7 +332,8 @@ void m68k_switch_sp(CPUM68KState *env) env->sp[env->current_sp] = env->aregs[7]; if (m68k_feature(env, M68K_FEATURE_M68000)) { if (env->sr & SR_S) { - if (env->sr & SR_M) { + /* SR:Master-Mode bit unimplemented then ISP is not available */ + if (!m68k_feature(env, M68K_FEATURE_MSP) || env->sr & SR_M) { new_sp = M68K_SSP; } else { new_sp = M68K_ISP;