From 8df0e6aedad33c6746f4bc2a4d0cfdd432877084 Mon Sep 17 00:00:00 2001 From: Lucien Murray-Pitts Date: Mon, 1 Feb 2021 01:01:52 +0100 Subject: [PATCH] m68k: MOVEC insn. should generate exception if wrong CR is accessed Add CPU class detection for each CR type in the m68k_move_to/from helpers, so that it throws and exception if an unsupported register is requested for that CPU class. Reclassified MOVEC insn. as only supported from 68010. Signed-off-by: Lucien Murray-Pitts Signed-off-by: BALATON Zoltan Message-Id: Signed-off-by: Laurent Vivier --- target/m68k/cpu.c | 1 + target/m68k/cpu.h | 1 + target/m68k/helper.c | 188 ++++++++++++++++++++++++++++++---------- target/m68k/translate.c | 2 +- 4 files changed, 146 insertions(+), 46 deletions(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index d0f8bd4433..ff3c4c1c98 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -132,6 +132,7 @@ static void m68010_cpu_initfn(Object *obj) m68k_set_feature(env, M68K_FEATURE_M68010); m68k_set_feature(env, M68K_FEATURE_RTD); m68k_set_feature(env, M68K_FEATURE_BKPT); + m68k_set_feature(env, M68K_FEATURE_MOVEC); } /* diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index ae34c94615..5d2cb012e5 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -497,6 +497,7 @@ enum m68k_features { M68K_FEATURE_RTD, /* RTD insn. (680[12346]0, and CPU32) */ M68K_FEATURE_CHK2, /* CHK2 insn. (680[2346]0, and CPU32) */ M68K_FEATURE_MOVEP, /* MOVEP insn. (680[01234]0, and CPU32) */ + M68K_FEATURE_MOVEC, /* MOVEC insn. (from 68010) */ }; static inline int m68k_feature(CPUM68KState *env, int feature) diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 69acdc3b35..1efd6e4f65 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -184,6 +184,14 @@ void HELPER(cf_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val) } } +static void raise_exception_ra(CPUM68KState *env, int tt, uintptr_t raddr) +{ + CPUState *cs = env_cpu(env); + + cs->exception_index = tt; + cpu_loop_exit_restore(cs, raddr); +} + void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val) { switch (reg) { @@ -209,61 +217,104 @@ void HELPER(m68k_movec_to)(CPUM68KState *env, uint32_t reg, uint32_t val) env->cacr = val & 0x80008000; } else if (m68k_feature(env, M68K_FEATURE_M68060)) { env->cacr = val & 0xf8e0e000; + } else { + break; } m68k_switch_sp(env); return; /* MC680[46]0 */ case M68K_CR_TC: - env->mmu.tcr = val; - return; + if (m68k_feature(env, M68K_FEATURE_M68040) + || m68k_feature(env, M68K_FEATURE_M68060)) { + env->mmu.tcr = val; + return; + } + break; /* MC68040 */ case M68K_CR_MMUSR: - env->mmu.mmusr = val; - return; + if (m68k_feature(env, M68K_FEATURE_M68040)) { + env->mmu.mmusr = val; + return; + } + break; /* MC680[46]0 */ case M68K_CR_SRP: - env->mmu.srp = val; - return; - case M68K_CR_URP: - env->mmu.urp = val; - return; + if (m68k_feature(env, M68K_FEATURE_M68040) + || m68k_feature(env, M68K_FEATURE_M68060)) { + env->mmu.srp = val; + return; + } + break; /* MC680[46]0 */ + case M68K_CR_URP: + if (m68k_feature(env, M68K_FEATURE_M68040) + || m68k_feature(env, M68K_FEATURE_M68060)) { + env->mmu.urp = val; + return; + } + break; + /* MC680[12346]0 */ case M68K_CR_USP: env->sp[M68K_USP] = val; return; /* MC680[234]0 */ case M68K_CR_MSP: - env->sp[M68K_SSP] = val; - return; + if (m68k_feature(env, M68K_FEATURE_M68020) + || m68k_feature(env, M68K_FEATURE_M68030) + || m68k_feature(env, M68K_FEATURE_M68040)) { + env->sp[M68K_SSP] = val; + return; + } + break; /* MC680[234]0 */ case M68K_CR_ISP: - env->sp[M68K_ISP] = val; - return; + if (m68k_feature(env, M68K_FEATURE_M68020) + || m68k_feature(env, M68K_FEATURE_M68030) + || m68k_feature(env, M68K_FEATURE_M68040)) { + env->sp[M68K_ISP] = val; + return; + } + break; /* MC68040/MC68LC040 */ - case M68K_CR_ITT0: - env->mmu.ttr[M68K_ITTR0] = val; - return; + case M68K_CR_ITT0: /* MC68EC040 only: M68K_CR_IACR0 */ + if (m68k_feature(env, M68K_FEATURE_M68040)) { + env->mmu.ttr[M68K_ITTR0] = val; + return; + } + break; /* MC68040/MC68LC040 */ - case M68K_CR_ITT1: - env->mmu.ttr[M68K_ITTR1] = val; - return; + case M68K_CR_ITT1: /* MC68EC040 only: M68K_CR_IACR1 */ + if (m68k_feature(env, M68K_FEATURE_M68040)) { + env->mmu.ttr[M68K_ITTR1] = val; + return; + } + break; /* MC68040/MC68LC040 */ - case M68K_CR_DTT0: - env->mmu.ttr[M68K_DTTR0] = val; - return; + case M68K_CR_DTT0: /* MC68EC040 only: M68K_CR_DACR0 */ + if (m68k_feature(env, M68K_FEATURE_M68040)) { + env->mmu.ttr[M68K_DTTR0] = val; + return; + } + break; /* MC68040/MC68LC040 */ - case M68K_CR_DTT1: - env->mmu.ttr[M68K_DTTR1] = val; - return; + case M68K_CR_DTT1: /* MC68EC040 only: M68K_CR_DACR1 */ + if (m68k_feature(env, M68K_FEATURE_M68040)) { + env->mmu.ttr[M68K_DTTR1] = val; + return; + } + break; /* Unimplemented Registers */ case M68K_CR_CAAR: case M68K_CR_PCR: case M68K_CR_BUSCR: - break; + cpu_abort(env_cpu(env), + "Unimplemented control register write 0x%x = 0x%x\n", + reg, val); } - cpu_abort(env_cpu(env), - "Unimplemented control register write 0x%x = 0x%x\n", - reg, val); + + /* Invalid control registers will generate an exception. */ + raise_exception_ra(env, EXCP_ILLEGAL, 0); + return; } uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg) @@ -280,48 +331,95 @@ uint32_t HELPER(m68k_movec_from)(CPUM68KState *env, uint32_t reg) return env->vbr; /* MC680[2346]0 */ case M68K_CR_CACR: - return env->cacr; + if (m68k_feature(env, M68K_FEATURE_M68020) + || m68k_feature(env, M68K_FEATURE_M68030) + || m68k_feature(env, M68K_FEATURE_M68040) + || m68k_feature(env, M68K_FEATURE_M68060)) { + return env->cacr; + } + break; /* MC680[46]0 */ case M68K_CR_TC: - return env->mmu.tcr; + if (m68k_feature(env, M68K_FEATURE_M68040) + || m68k_feature(env, M68K_FEATURE_M68060)) { + return env->mmu.tcr; + } + break; /* MC68040 */ case M68K_CR_MMUSR: - return env->mmu.mmusr; + if (m68k_feature(env, M68K_FEATURE_M68040)) { + return env->mmu.mmusr; + } + break; /* MC680[46]0 */ case M68K_CR_SRP: - return env->mmu.srp; + if (m68k_feature(env, M68K_FEATURE_M68040) + || m68k_feature(env, M68K_FEATURE_M68060)) { + return env->mmu.srp; + } + break; + /* MC68040/MC68LC040 */ + case M68K_CR_URP: + if (m68k_feature(env, M68K_FEATURE_M68040) + || m68k_feature(env, M68K_FEATURE_M68060)) { + return env->mmu.urp; + } + break; /* MC680[46]0 */ case M68K_CR_USP: return env->sp[M68K_USP]; /* MC680[234]0 */ case M68K_CR_MSP: - return env->sp[M68K_SSP]; + if (m68k_feature(env, M68K_FEATURE_M68020) + || m68k_feature(env, M68K_FEATURE_M68030) + || m68k_feature(env, M68K_FEATURE_M68040)) { + return env->sp[M68K_SSP]; + } + break; /* MC680[234]0 */ case M68K_CR_ISP: - return env->sp[M68K_ISP]; - /* MC68040/MC68LC040 */ - case M68K_CR_URP: - return env->mmu.urp; + if (m68k_feature(env, M68K_FEATURE_M68020) + || m68k_feature(env, M68K_FEATURE_M68030) + || m68k_feature(env, M68K_FEATURE_M68040)) { + return env->sp[M68K_ISP]; + } + break; /* MC68040/MC68LC040 */ case M68K_CR_ITT0: /* MC68EC040 only: M68K_CR_IACR0 */ - return env->mmu.ttr[M68K_ITTR0]; + if (m68k_feature(env, M68K_FEATURE_M68040)) { + return env->mmu.ttr[M68K_ITTR0]; + } + break; /* MC68040/MC68LC040 */ case M68K_CR_ITT1: /* MC68EC040 only: M68K_CR_IACR1 */ - return env->mmu.ttr[M68K_ITTR1]; + if (m68k_feature(env, M68K_FEATURE_M68040)) { + return env->mmu.ttr[M68K_ITTR1]; + } + break; /* MC68040/MC68LC040 */ case M68K_CR_DTT0: /* MC68EC040 only: M68K_CR_DACR0 */ - return env->mmu.ttr[M68K_DTTR0]; + if (m68k_feature(env, M68K_FEATURE_M68040)) { + return env->mmu.ttr[M68K_DTTR0]; + } + break; /* MC68040/MC68LC040 */ case M68K_CR_DTT1: /* MC68EC040 only: M68K_CR_DACR1 */ - return env->mmu.ttr[M68K_DTTR1]; + if (m68k_feature(env, M68K_FEATURE_M68040)) { + return env->mmu.ttr[M68K_DTTR1]; + } + break; /* Unimplemented Registers */ case M68K_CR_CAAR: case M68K_CR_PCR: case M68K_CR_BUSCR: - break; + cpu_abort(env_cpu(env), "Unimplemented control register read 0x%x\n", + reg); } - cpu_abort(env_cpu(env), "Unimplemented control register read 0x%x\n", - reg); + + /* Invalid control registers will generate an exception. */ + raise_exception_ra(env, EXCP_ILLEGAL, 0); + + return 0; } void HELPER(set_macsr)(CPUM68KState *env, uint32_t val) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 133a404919..ac936ebe8f 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -6010,7 +6010,7 @@ void register_m68k_insns (CPUM68KState *env) BASE(stop, 4e72, ffff); BASE(rte, 4e73, ffff); INSN(cf_movec, 4e7b, ffff, CF_ISA_A); - INSN(m68k_movec, 4e7a, fffe, M68000); + INSN(m68k_movec, 4e7a, fffe, MOVEC); #endif BASE(nop, 4e71, ffff); INSN(rtd, 4e74, ffff, RTD);