diff options
Diffstat (limited to 'target-m68k')
-rw-r--r-- | target-m68k/cpu.h | 13 | ||||
-rw-r--r-- | target-m68k/helper.c | 26 | ||||
-rw-r--r-- | target-m68k/op.c | 7 | ||||
-rw-r--r-- | target-m68k/op_helper.c | 18 | ||||
-rw-r--r-- | target-m68k/translate.c | 9 |
5 files changed, 60 insertions, 13 deletions
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index acbb51690d..6f29d5e5c4 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -59,6 +59,10 @@ typedef struct CPUM68KState { uint32_t pc; uint32_t sr; + /* SSP and USP. The current_sp is stored in aregs[7], the other here. */ + int current_sp; + uint32_t sp[2]; + /* Condition flags. */ uint32_t cc_op; uint32_t cc_dest; @@ -92,6 +96,7 @@ typedef struct CPUM68KState { uint32_t vbr; uint32_t mbar; uint32_t rambar0; + uint32_t cacr; uint32_t features; @@ -151,6 +156,12 @@ enum { #define SR_S 0x2000 #define SR_T 0x8000 +#define M68K_SSP 0 +#define M68K_USP 1 + +/* CACR fields are implementation defined, but some bits are common. */ +#define M68K_CACR_EUSP 0x10 + #define MACSR_PAV0 0x100 #define MACSR_OMC 0x080 #define MACSR_SU 0x040 @@ -167,6 +178,7 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name); void m68k_set_irq_level(CPUM68KState *env, int level, uint8_t vector); void m68k_set_macsr(CPUM68KState *env, uint32_t val); +void m68k_switch_sp(CPUM68KState *env); #define M68K_FPCR_PREC (1 << 6) @@ -179,6 +191,7 @@ enum m68k_features { M68K_FEATURE_CF_FPU, M68K_FEATURE_CF_MAC, M68K_FEATURE_CF_EMAC, + M68K_FEATURE_USP, M68K_FEATURE_EXT_FULL, /* 68020+ full extension word. */ M68K_FEATURE_WORD_INDEX /* word sized address index registers. */ }; diff --git a/target-m68k/helper.c b/target-m68k/helper.c index bdbc1de396..bb213a7603 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -28,6 +28,7 @@ enum m68k_cpuid { M68K_CPUID_M5206, + M68K_CPUID_M5208, M68K_CPUID_CFV4E, M68K_CPUID_ANY, }; @@ -39,6 +40,7 @@ struct m68k_def_t { static m68k_def_t m68k_cpu_defs[] = { {"m5206", M68K_CPUID_M5206}, + {"m5208", M68K_CPUID_M5208}, {"cfv4e", M68K_CPUID_CFV4E}, {"any", M68K_CPUID_ANY}, {NULL, 0}, @@ -64,12 +66,18 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) case M68K_CPUID_M5206: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); break; + case M68K_CPUID_M5208: + m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); + m68k_set_feature(env, M68K_FEATURE_CF_EMAC); + m68k_set_feature(env, M68K_FEATURE_USP); + break; case M68K_CPUID_CFV4E: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); m68k_set_feature(env, M68K_FEATURE_CF_ISA_B); m68k_set_feature(env, M68K_FEATURE_CF_ISA_C); m68k_set_feature(env, M68K_FEATURE_CF_FPU); m68k_set_feature(env, M68K_FEATURE_CF_EMAC); + m68k_set_feature(env, M68K_FEATURE_USP); break; case M68K_CPUID_ANY: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); @@ -79,6 +87,7 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) /* MAC and EMAC are mututally exclusive, so pick EMAC. It's mostly backwards compatible. */ m68k_set_feature(env, M68K_FEATURE_CF_EMAC); + m68k_set_feature(env, M68K_FEATURE_USP); m68k_set_feature(env, M68K_FEATURE_EXT_FULL); break; } @@ -215,7 +224,11 @@ void helper_movec(CPUM68KState *env, int reg, uint32_t val) { switch (reg) { case 0x02: /* CACR */ - /* Ignored. */ + env->cacr = val; + m68k_switch_sp(env); + break; + case 0x04: case 0x05: case 0x06: case 0x07: /* ACR[0-3] */ + /* TODO: Implement Access Control Registers. */ break; case 0x801: /* VBR */ env->vbr = val; @@ -261,6 +274,17 @@ void m68k_set_macsr(CPUM68KState *env, uint32_t val) env->macsr = val; } +void m68k_switch_sp(CPUM68KState *env) +{ + int new_sp; + + env->sp[env->current_sp] = env->aregs[7]; + new_sp = (env->sr & SR_S && env->cacr & M68K_CACR_EUSP) + ? M68K_SSP : M68K_USP; + env->aregs[7] = env->sp[new_sp]; + env->current_sp = new_sp; +} + /* MMU */ /* TODO: This will need fixing once the MMU is implemented. */ diff --git a/target-m68k/op.c b/target-m68k/op.c index febfe034c1..932c994357 100644 --- a/target-m68k/op.c +++ b/target-m68k/op.c @@ -478,6 +478,13 @@ OP(fp_result) FORCE_RET(); } +OP(set_sr) +{ + env->sr = get_op(PARAM1); + m68k_switch_sp(env); + FORCE_RET(); +} + OP(jmp) { GOTO_LABEL_PARAM(1); diff --git a/target-m68k/op_helper.c b/target-m68k/op_helper.c index 8086238db4..4c423ca984 100644 --- a/target-m68k/op_helper.c +++ b/target-m68k/op_helper.c @@ -87,6 +87,7 @@ static void do_rte(void) env->pc = ldl_kernel(sp + 4); sp |= (fmt >> 28) & 3; env->sr = fmt & 0xffff; + m68k_switch_sp(env); env->aregs[7] = sp + 8; } @@ -128,9 +129,6 @@ void do_interrupt(int is_hw) } } - /* TODO: Implement USP. */ - sp = env->aregs[7]; - vector = env->exception_index << 2; fmt |= 0x40000000; @@ -138,6 +136,15 @@ void do_interrupt(int is_hw) fmt |= vector << 16; fmt |= env->sr; + env->sr |= SR_S; + if (is_hw) { + env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); + env->sr &= ~SR_M; + } + m68k_switch_sp(env); + + sp = env->aregs[7]; + /* ??? This could cause MMU faults. */ sp &= ~3; sp -= 4; @@ -145,11 +152,6 @@ void do_interrupt(int is_hw) sp -= 4; stl_kernel(sp, fmt); env->aregs[7] = sp; - env->sr |= SR_S; - if (is_hw) { - env->sr = (env->sr & ~SR_I) | (env->pending_level << SR_I_SHIFT); - env->sr &= ~SR_M; - } /* Jump to vector. */ env->pc = ldl_kernel(env->vbr + vector); } diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 1d32e8f0f7..da3e72a473 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -1345,7 +1345,7 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) gen_op_logic_cc(gen_im32(val & 0xf)); gen_op_update_xflag_tst(gen_im32((val & 0x10) >> 4)); if (!ccr_only) { - gen_op_mov32(QREG_SR, gen_im32(val & 0xff00)); + gen_op_set_sr(gen_im32(val & 0xff00)); } } @@ -1365,7 +1365,7 @@ static void gen_set_sr(DisasContext *s, uint16_t insn, int ccr_only) gen_op_and32(src1, src1, gen_im32(1)); gen_op_update_xflag_tst(src1); if (!ccr_only) { - gen_op_and32(QREG_SR, reg, gen_im32(0xff00)); + gen_op_set_sr(reg); } } else if ((insn & 0x3f) == 0x3c) @@ -2797,8 +2797,8 @@ void register_m68k_insns (CPUM68KState *env) INSN(trap, 4e40, fff0, CF_ISA_A); INSN(link, 4e50, fff8, CF_ISA_A); INSN(unlk, 4e58, fff8, CF_ISA_A); - INSN(move_to_usp, 4e60, fff8, CF_ISA_B); - INSN(move_from_usp, 4e68, fff8, CF_ISA_B); + INSN(move_to_usp, 4e60, fff8, USP); + INSN(move_from_usp, 4e68, fff8, USP); INSN(nop, 4e71, ffff, CF_ISA_A); INSN(stop, 4e72, ffff, CF_ISA_A); INSN(rte, 4e73, ffff, CF_ISA_A); @@ -3261,6 +3261,7 @@ void cpu_reset(CPUM68KState *env) #if !defined (CONFIG_USER_ONLY) env->sr = 0x2700; #endif + m68k_switch_sp(env); /* ??? FP regs should be initialized to NaN. */ env->cc_op = CC_OP_FLAGS; /* TODO: We should set PC from the interrupt vector. */ |