diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index 6f29d5e5c..2d43354e2 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -184,14 +184,20 @@ void m68k_switch_sp(CPUM68KState *env); void do_m68k_semihosting(CPUM68KState *env, int nr); +/* There are 4 ColdFire core ISA revisions: A, A+, B and C. + Each feature covers the subset of instructions common to the + ISA revisions mentioned. */ + enum m68k_features { M68K_FEATURE_CF_ISA_A, - M68K_FEATURE_CF_ISA_B, - M68K_FEATURE_CF_ISA_C, + 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, /* Long unconditional branch. (ISA A+ or B). */ M68K_FEATURE_CF_FPU, M68K_FEATURE_CF_MAC, M68K_FEATURE_CF_EMAC, - M68K_FEATURE_USP, + M68K_FEATURE_CF_EMAC_B, /* Revision B EMAC (dual accumulate). */ + M68K_FEATURE_USP, /* User Stack Pointer. (ISA A+, B or C). */ 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 bb213a760..13305220a 100644 --- a/target-m68k/helper.c +++ b/target-m68k/helper.c @@ -68,13 +68,15 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) break; case M68K_CPUID_M5208: m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); + m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC); + m68k_set_feature(env, M68K_FEATURE_BRAL); 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_BRAL); m68k_set_feature(env, M68K_FEATURE_CF_FPU); m68k_set_feature(env, M68K_FEATURE_CF_EMAC); m68k_set_feature(env, M68K_FEATURE_USP); @@ -82,13 +84,16 @@ int cpu_m68k_set_model(CPUM68KState *env, const char * name) case M68K_CPUID_ANY: 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_ISA_APLUSC); + m68k_set_feature(env, M68K_FEATURE_BRAL); m68k_set_feature(env, M68K_FEATURE_CF_FPU); /* 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_CF_EMAC_B); m68k_set_feature(env, M68K_FEATURE_USP); m68k_set_feature(env, M68K_FEATURE_EXT_FULL); + m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); break; } diff --git a/target-m68k/translate.c b/target-m68k/translate.c index da3e72a47..1c0e43135 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2473,6 +2473,10 @@ DISAS_INSN(mac) acc = ((insn >> 7) & 1) | ((ext >> 3) & 2); dual = ((insn & 0x30) != 0 && (ext & 3) != 0); + if (dual && !m68k_feature(s->env, M68K_FEATURE_CF_EMAC_B)) { + disas_undef(s, insn); + return; + } if (insn & 0x30) { /* MAC with load. */ tmp = gen_lea(s, insn, OS_LONG); @@ -2745,20 +2749,21 @@ register_opcode (disas_proc proc, uint16_t opcode, uint16_t mask) Later insn override earlier ones. */ void register_m68k_insns (CPUM68KState *env) { -#define INSN(name, opcode, mask, feature) \ +#define INSN(name, opcode, mask, feature) do { \ if (m68k_feature(env, M68K_FEATURE_##feature)) \ - register_opcode(disas_##name, 0x##opcode, 0x##mask) + register_opcode(disas_##name, 0x##opcode, 0x##mask); \ + } while(0) INSN(undef, 0000, 0000, CF_ISA_A); INSN(arith_im, 0080, fff8, CF_ISA_A); - INSN(bitrev, 00c0, fff8, CF_ISA_C); + INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC); INSN(bitop_reg, 0100, f1c0, CF_ISA_A); INSN(bitop_reg, 0140, f1c0, CF_ISA_A); INSN(bitop_reg, 0180, f1c0, CF_ISA_A); INSN(bitop_reg, 01c0, f1c0, CF_ISA_A); INSN(arith_im, 0280, fff8, CF_ISA_A); - INSN(byterev, 02c0, fff8, CF_ISA_A); + INSN(byterev, 02c0, fff8, CF_ISA_APLUSC); INSN(arith_im, 0480, fff8, CF_ISA_A); - INSN(ff1, 04c0, fff8, CF_ISA_C); + INSN(ff1, 04c0, fff8, CF_ISA_APLUSC); INSN(arith_im, 0680, fff8, CF_ISA_A); INSN(bitop_im, 0800, ffc0, CF_ISA_A); INSN(bitop_im, 0840, ffc0, CF_ISA_A); @@ -2769,7 +2774,7 @@ void register_m68k_insns (CPUM68KState *env) INSN(move, 1000, f000, CF_ISA_A); INSN(move, 2000, f000, CF_ISA_A); INSN(move, 3000, f000, CF_ISA_A); - INSN(strldsr, 40e7, ffff, CF_ISA_A); + INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC); INSN(negx, 4080, fff8, CF_ISA_A); INSN(move_from_sr, 40c0, fff8, CF_ISA_A); INSN(lea, 41c0, f1c0, CF_ISA_A); @@ -2810,7 +2815,15 @@ void register_m68k_insns (CPUM68KState *env) INSN(scc, 50c0, f0f8, CF_ISA_A); INSN(addsubq, 5080, f1c0, CF_ISA_A); INSN(tpf, 51f8, fff8, CF_ISA_A); + + /* Branch instructions. */ INSN(branch, 6000, f000, CF_ISA_A); + /* Disable long branch instructions, then add back the ones we want. */ + INSN(undef, 60ff, f0ff, CF_ISA_A); /* All long branches. */ + INSN(branch, 60ff, f0ff, CF_ISA_B); + INSN(undef, 60ff, ffff, CF_ISA_B); /* bra.l */ + INSN(branch, 60ff, ffff, BRAL); + INSN(moveq, 7000, f100, CF_ISA_A); INSN(mvzs, 7100, f100, CF_ISA_B); INSN(or, 8000, f000, CF_ISA_A);