x_put_long (extra, tc_030);
else {
tc_030 = x_get_long (extra);
- if (mmu030_decode_tc(tc_030))
+ if (mmu030_decode_tc(tc_030, true))
return true;
}
break;
} ENDTRY
}
-bool mmu030_decode_tc(uae_u32 TC)
+bool mmu030_decode_tc(uae_u32 TC, bool check)
{
/* Set MMU condition */
if (TC & TC_ENABLE_TRANSLATION) {
- if (!mmu030.enabled)
+ if (!mmu030.enabled && check)
mmu030_do_fake_prefetch();
mmu030.enabled = true;
} else {
/* A CPU reset causes the E-bits of TC and TT registers to be zeroed. */
mmu030.enabled = false;
regs.mmu_page_size = 0;
- tc_030 &= ~TC_ENABLE_TRANSLATION;
- tt0_030 &= ~TT_ENABLE;
- tt1_030 &= ~TT_ENABLE;
- if (hardreset) {
+ if (hardreset >= 0) {
+ tc_030 &= ~TC_ENABLE_TRANSLATION;
+ tt0_030 &= ~TT_ENABLE;
+ tt1_030 &= ~TT_ENABLE;
+ }
+ if (hardreset > 0) {
srp_030 = crp_030 = 0;
tt0_030 = tt1_030 = tc_030 = 0;
mmusr_030 = 0;
check_prefs_changed_comp(false);
currprefs.cpu_model = changed_prefs.cpu_model;
currprefs.fpu_model = changed_prefs.fpu_model;
- currprefs.mmu_model = changed_prefs.mmu_model;
+ if (currprefs.mmu_model != changed_prefs.mmu_model) {
+ int oldmmu = currprefs.mmu_model;
+ currprefs.mmu_model = changed_prefs.mmu_model;
+ if (currprefs.mmu_model >= 68040) {
+ uae_u32 tcr = regs.tcr;
+ mmu_reset();
+ mmu_set_tc(tcr);
+ mmu_set_super(regs.s != 0);
+ mmu_tt_modified();
+ mmu_dump_tables();
+ } else if (currprefs.mmu_model == 68030) {
+ mmu030_reset(-1);
+ mmu030_flush_atc_all();
+ tc_030 = fake_tc_030;
+ tt0_030 = fake_tt0_030;
+ tt1_030 = fake_tt1_030;
+ srp_030 = fake_srp_030;
+ crp_030 = fake_crp_030;
+ mmu030_decode_tc(tc_030, false);
+ } else if (oldmmu == 68030) {
+ fake_tc_030 = tc_030;
+ fake_tt0_030 = tt0_030;
+ fake_tt1_030 = tt1_030;
+ fake_srp_030 = srp_030;
+ fake_crp_030 = crp_030;
+ }
+ }
currprefs.cpu_compatible = changed_prefs.cpu_compatible;
currprefs.address_space_24 = changed_prefs.address_space_24;
currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
if (currprefs.cpu_model == 68060) {
regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
- if (kickstart_rom)
+ if (currprefs.fpu_model == 0 || kickstart_rom)
regs.pcr |= 2; /* disable FPU */
}
// regs.ce020memcycles = 0;
}
}
+/* check if an address matches a ttr */
+static int fake_mmu_do_match_ttr(uae_u32 ttr, uaecptr addr, bool super)
+{
+ if (ttr & MMU_TTR_BIT_ENABLED) { /* TTR enabled */
+ uae_u8 msb, mask;
+
+ msb = ((addr ^ ttr) & MMU_TTR_LOGICAL_BASE) >> 24;
+ mask = (ttr & MMU_TTR_LOGICAL_MASK) >> 16;
+
+ if (!(msb & ~mask)) {
+
+ if ((ttr & MMU_TTR_BIT_SFIELD_ENABLED) == 0) {
+ if (((ttr & MMU_TTR_BIT_SFIELD_SUPER) == 0) != (super == 0)) {
+ return TTR_NO_MATCH;
+ }
+ }
+
+ return (ttr & MMU_TTR_BIT_WRITE_PROTECT) ? TTR_NO_WRITE : TTR_OK_MATCH;
+ }
+ }
+ return TTR_NO_MATCH;
+}
+
+static int fake_mmu_match_ttr(uaecptr addr, bool super, bool data)
+{
+ int res;
+
+ if (data) {
+ res = fake_mmu_do_match_ttr(regs.dtt0, addr, super);
+ if (res == TTR_NO_MATCH)
+ res = fake_mmu_do_match_ttr(regs.dtt1, addr, super);
+ } else {
+ res = fake_mmu_do_match_ttr(regs.itt0, addr, super);
+ if (res == TTR_NO_MATCH)
+ res = fake_mmu_do_match_ttr(regs.itt1, addr, super);
+ }
+ return res;
+}
+
// 68040+ MMU instructions only
void mmu_op (uae_u32 opcode, uae_u32 extra)
{
} else if ((opcode & 0x0FD8) == 0x548) {
if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
/* PTEST */
+ int regno = opcode & 7;
+ uae_u32 addr = m68k_areg(regs, regno);
+ bool write = (opcode & 32) == 0;
+ bool super = (regs.dfc & 4) != 0;
+ bool data = (regs.dfc & 3) != 2;
+
+ regs.mmusr = 0;
+ if (fake_mmu_match_ttr(addr,super,data) != TTR_NO_MATCH) {
+ regs.mmusr = MMU_MMUSR_T | MMU_MMUSR_R;
+ }
+ regs.mmusr |= addr & 0xfffff000;
#if MMUOP_DEBUG > 0
- write_log (_T("PTEST\n"));
+ write_log (_T("PTEST%c %08x\n"), write ? 'W' : 'R', addr);
#endif
return;
}
savestate_restore_finish ();
memory_map_dump ();
if (currprefs.mmu_model == 68030) {
- mmu030_decode_tc (tc_030);
+ mmu030_decode_tc (tc_030, true);
} else if (currprefs.mmu_model >= 68040) {
mmu_set_tc (regs.tcr);
}