summaryrefslogtreecommitdiffstats
path: root/target/m68k
diff options
context:
space:
mode:
Diffstat (limited to 'target/m68k')
-rw-r--r--target/m68k/cpu.c1
-rw-r--r--target/m68k/cpu.h68
-rw-r--r--target/m68k/op_helper.c17
-rw-r--r--target/m68k/translate.c20
4 files changed, 82 insertions, 24 deletions
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 37d2ed9dc7..a14874b4da 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -161,6 +161,7 @@ static void m68020_cpu_initfn(Object *obj)
m68k_set_feature(env, M68K_FEATURE_CAS);
m68k_set_feature(env, M68K_FEATURE_CHK2);
m68k_set_feature(env, M68K_FEATURE_MSP);
+ m68k_set_feature(env, M68K_FEATURE_UNALIGNED_DATA);
}
/*
diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h
index 7c3feeaf8a..402c86c876 100644
--- a/target/m68k/cpu.h
+++ b/target/m68k/cpu.h
@@ -475,36 +475,60 @@ void do_m68k_semihosting(CPUM68KState *env, int nr);
*/
enum m68k_features {
- M68K_FEATURE_M68000, /* Base m68k instruction set */
+ /* Base m68k instruction set */
+ M68K_FEATURE_M68000,
M68K_FEATURE_M68010,
M68K_FEATURE_M68020,
M68K_FEATURE_M68030,
M68K_FEATURE_M68040,
M68K_FEATURE_M68060,
- M68K_FEATURE_CF_ISA_A, /* Base Coldfire set Rev A. */
- M68K_FEATURE_CF_ISA_B, /* (ISA B or C). */
- M68K_FEATURE_CF_ISA_APLUSC, /* BIT/BITREV, FF1, STRLDSR (ISA A+ or C). */
- M68K_FEATURE_BRAL, /* BRA with Long branch. (680[2346]0, ISA A+ or B). */
+ /* Base Coldfire set Rev A. */
+ M68K_FEATURE_CF_ISA_A,
+ /* (ISA B or C). */
+ M68K_FEATURE_CF_ISA_B,
+ /* BIT/BITREV, FF1, STRLDSR (ISA A+ or C). */
+ M68K_FEATURE_CF_ISA_APLUSC,
+ /* BRA with Long branch. (680[2346]0, ISA A+ or B). */
+ M68K_FEATURE_BRAL,
M68K_FEATURE_CF_FPU,
M68K_FEATURE_CF_MAC,
M68K_FEATURE_CF_EMAC,
- M68K_FEATURE_CF_EMAC_B, /* Revision B EMAC (dual accumulate). */
- M68K_FEATURE_USP, /* User Stack Pointer. (680[012346]0, ISA A+, B or C).*/
- M68K_FEATURE_MSP, /* Master Stack Pointer. (680[234]0) */
- M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */
- M68K_FEATURE_WORD_INDEX, /* word sized address index registers. */
- M68K_FEATURE_SCALED_INDEX, /* scaled address index registers. */
- M68K_FEATURE_LONG_MULDIV, /* 32 bit mul/div. (680[2346]0, and CPU32) */
- M68K_FEATURE_QUAD_MULDIV, /* 64 bit mul/div. (680[2346]0, and CPU32) */
- M68K_FEATURE_BCCL, /* Bcc with Long branches. (680[2346]0, and CPU32) */
- M68K_FEATURE_BITFIELD, /* BFxxx Bit field insns. (680[2346]0) */
- M68K_FEATURE_FPU, /* fpu insn. (680[46]0) */
- M68K_FEATURE_CAS, /* CAS/CAS2[WL] insns. (680[2346]0) */
- M68K_FEATURE_BKPT, /* BKPT insn. (680[12346]0, and CPU32) */
- 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) */
+ /* Revision B EMAC (dual accumulate). */
+ M68K_FEATURE_CF_EMAC_B,
+ /* User Stack Pointer. (680[012346]0, ISA A+, B or C). */
+ M68K_FEATURE_USP,
+ /* Master Stack Pointer. (680[234]0) */
+ M68K_FEATURE_MSP,
+ /* 68020+ full extension word. */
+ M68K_FEATURE_EXT_FULL,
+ /* word sized address index registers. */
+ M68K_FEATURE_WORD_INDEX,
+ /* scaled address index registers. */
+ M68K_FEATURE_SCALED_INDEX,
+ /* 32 bit mul/div. (680[2346]0, and CPU32) */
+ M68K_FEATURE_LONG_MULDIV,
+ /* 64 bit mul/div. (680[2346]0, and CPU32) */
+ M68K_FEATURE_QUAD_MULDIV,
+ /* Bcc with Long branches. (680[2346]0, and CPU32) */
+ M68K_FEATURE_BCCL,
+ /* BFxxx Bit field insns. (680[2346]0) */
+ M68K_FEATURE_BITFIELD,
+ /* fpu insn. (680[46]0) */
+ M68K_FEATURE_FPU,
+ /* CAS/CAS2[WL] insns. (680[2346]0) */
+ M68K_FEATURE_CAS,
+ /* BKPT insn. (680[12346]0, and CPU32) */
+ M68K_FEATURE_BKPT,
+ /* RTD insn. (680[12346]0, and CPU32) */
+ M68K_FEATURE_RTD,
+ /* CHK2 insn. (680[2346]0, and CPU32) */
+ M68K_FEATURE_CHK2,
+ /* MOVEP insn. (680[01234]0, and CPU32) */
+ M68K_FEATURE_MOVEP,
+ /* MOVEC insn. (from 68010) */
+ M68K_FEATURE_MOVEC,
+ /* Unaligned data accesses (680[2346]0) */
+ M68K_FEATURE_UNALIGNED_DATA,
};
static inline int m68k_feature(CPUM68KState *env, int feature)
diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 9b0698f267..ae1ba4b437 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -348,7 +348,10 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw)
cpu_m68k_set_sr(env, sr);
sp = env->aregs[7];
- sp &= ~1;
+ if (!m68k_feature(env, M68K_FEATURE_UNALIGNED_DATA)) {
+ sp &= ~1;
+ }
+
if (cs->exception_index == EXCP_ACCESS) {
if (env->mmu.fault) {
cpu_abort(cs, "DOUBLE MMU FAULT\n");
@@ -468,7 +471,17 @@ void m68k_cpu_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr addr,
if (m68k_feature(env, M68K_FEATURE_M68040)) {
env->mmu.mmusr = 0;
- env->mmu.ssw |= M68K_ATC_040;
+
+ /*
+ * According to the MC68040 users manual the ATC bit of the SSW is
+ * used to distinguish between ATC faults and physical bus errors.
+ * In the case of a bus error e.g. during nubus read from an empty
+ * slot this bit should not be set
+ */
+ if (response != MEMTX_DECODE_ERROR) {
+ env->mmu.ssw |= M68K_ATC_040;
+ }
+
/* FIXME: manage MMU table access error */
env->mmu.ssw &= ~M68K_TM_040;
if (env->sr & SR_S) { /* SUPERVISOR */
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index ac936ebe8f..200018ae6a 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -2969,6 +2969,25 @@ DISAS_INSN(rtd)
gen_jmp(s, tmp);
}
+DISAS_INSN(rtr)
+{
+ TCGv tmp;
+ TCGv ccr;
+ TCGv sp;
+
+ sp = tcg_temp_new();
+ ccr = gen_load(s, OS_WORD, QREG_SP, 0, IS_USER(s));
+ tcg_gen_addi_i32(sp, QREG_SP, 2);
+ tmp = gen_load(s, OS_LONG, sp, 0, IS_USER(s));
+ tcg_gen_addi_i32(QREG_SP, sp, 4);
+ tcg_temp_free(sp);
+
+ gen_set_sr(s, ccr, true);
+ tcg_temp_free(ccr);
+
+ gen_jmp(s, tmp);
+}
+
DISAS_INSN(rts)
{
TCGv tmp;
@@ -6015,6 +6034,7 @@ void register_m68k_insns (CPUM68KState *env)
BASE(nop, 4e71, ffff);
INSN(rtd, 4e74, ffff, RTD);
BASE(rts, 4e75, ffff);
+ INSN(rtr, 4e77, ffff, M68000);
BASE(jump, 4e80, ffc0);
BASE(jump, 4ec0, ffc0);
INSN(addsubq, 5000, f080, M68000);