#endif
if (mmu030.atc[l].physical.bus_error || mmu030.atc[l].physical.write_protect) {
- mmu030_page_fault(addr, false, MMU030_SSW_SIZE_B, fc);
+ mmu030_page_fault(addr, false, size, fc);
return 0;
}
{
// Restore access error exception state
- uae_u16 format = get_word_mmu030 (a7 + 6);
+ uae_u16 format = get_word_mmu030(a7 + 6);
uae_u16 frame = format >> 12;
- uae_u16 ssw = get_word_mmu030 (a7 + 10);
+ uae_u16 ssw = get_word_mmu030(a7 + 10);
+ uae_u16 sr = get_word_mmu030(a7);
+ uae_u32 pc = get_long_mmu030(a7 + 2);
+ uae_u32 fault_addr = get_long_mmu030(a7 + 16);
// Fetch last word, real CPU does it to allow OS bus handler to map
// the page if frame crosses pages and following page is not resident.
get_word_mmu030(a7 + 32 - 2);
// Internal register, misc flags
- uae_u32 ps = get_long_mmu030c(a7 + 0x28);
+ uae_u32 ps = get_long_mmu030(a7 + 0x28);
// Internal register, our opcode storage area
- uae_u32 oc = get_long_mmu030c (a7 + 0x14);
+ uae_u32 oc = get_long_mmu030(a7 + 0x14);
mmu030_opcode = (ps & 0x80000000) ? -1 : (oc & 0xffff);
// Misc state data
mmu030_state[0] = get_word_mmu030 (a7 + 0x30);
write_log (_T("Software fixed stage B! opcode = %04X, opword = %04x\n"), mmu030_opcode, stageb);
}
}
- m68k_areg (regs, 7) += 92;
+
+ m68k_areg(regs, 7) += 92;
+ regs.sr = sr;
+ MakeFromSR_T0();
+ if (pc & 1) {
+ exception3i(0x4E73, pc);
+ return;
+ }
+ m68k_setpci(pc);
+
+ if (ssw & MMU030_SSW_DF) {
+ // retry faulted access
+ uaecptr addr = fault_addr;
+ bool read = (ssw & MMU030_SSW_RW) != 0;
+ int size = (ssw & MMU030_SSW_SIZE_B) ? 1 : ((ssw & MMU030_SSW_SIZE_W) ? 2 : 4);
+ int fc = ssw & 7;
+
+ if (read) {
+ uae_u32 val = 0;
+ switch (size)
+ {
+ case 1:
+ val = mmu030_get_byte(addr, fc);
+ break;
+ case 2:
+ val = mmu030_get_word(addr, fc);
+ break;
+ case 4:
+ val = mmu030_get_long(addr, fc);
+ break;
+ }
+ if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
+ mmu030_data_buffer = val;
+ mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
+ } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
+ mmu030_state[0]++;
+ } else {
+ mmu030_ad[idxsize].val = val;
+ mmu030_ad[idxsize].done = true;
+ mmu030_ad[idxsize + 1].done = false;
+ }
+ } else {
+ uae_u32 val = mmu030_ad[idxsize].val;
+ switch (size)
+ {
+ case 1:
+ mmu030_put_byte(addr, val, fc);
+ break;
+ case 2:
+ mmu030_put_word(addr, val, fc);
+ break;
+ case 4:
+ mmu030_put_long(addr, val, fc);
+ break;
+ }
+ if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
+ mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
+ } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
+ mmu030_state[0]++;
+ } else {
+ mmu030_ad[idxsize].done = true;
+ mmu030_ad[idxsize + 1].done = false;
+ }
+ }
+ }
+
} else {
m68k_areg (regs, 7) += 32;
}
uae_u16 ssw = get_word_mmu030c (a7 + 10);
uae_u16 sr = get_word_mmu030c (a7);
uae_u32 pc = get_long_mmu030c (a7 + 2);
+ uae_u32 fault_addr = get_long_mmu030c(a7 + 16);
// Fetch last word, real CPU does it to allow OS bus handler to map
// the page if frame crosses pages and following page is not resident.
}
m68k_areg (regs, 7) += 92;
-
regs.sr = sr;
MakeFromSR_T0();
if (pc & 1) {
}
}
+ if (ssw & MMU030_SSW_DF) {
+ // retry faulted access
+ uaecptr addr = fault_addr;
+ bool read = (ssw & MMU030_SSW_RW) != 0;
+ int size = (ssw & MMU030_SSW_SIZE_B) ? 1 : ((ssw & MMU030_SSW_SIZE_W) ? 2 : 4);
+ int fc = ssw & 7;
+ if (read) {
+ uae_u32 val = 0;
+ switch (size)
+ {
+ case 1:
+ val = read_dcache030_bget(addr, fc);
+ break;
+ case 2:
+ val = read_dcache030_wget(addr, fc);
+ break;
+ case 4:
+ val = read_dcache030_lget(addr, fc);
+ break;
+ }
+ if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
+ mmu030_data_buffer = val;
+ mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
+ } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
+ mmu030_state[0]++;
+ } else {
+ mmu030_ad[idxsize].val = val;
+ mmu030_ad[idxsize].done = true;
+ mmu030_ad[idxsize + 1].done = false;
+ }
+ } else {
+ uae_u32 val = mmu030_ad[idxsize].val;
+ switch (size)
+ {
+ case 1:
+ write_dcache030_bput(addr, val, fc);
+ break;
+ case 2:
+ write_dcache030_wput(addr, val, fc);
+ break;
+ case 4:
+ write_dcache030_lput(addr, val, fc);
+ break;
+ }
+ if (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) {
+ mmu030_state[1] |= MMU030_STATEFLAG1_MOVEM2;
+ } else if (mmu030_state[1] & MMU030_STATEFLAG1_SKIP_INS) {
+ mmu030_state[0]++;
+ } else {
+ mmu030_ad[idxsize].done = true;
+ mmu030_ad[idxsize + 1].done = false;
+ }
+ }
+ }
+
} else {
m68k_areg (regs, 7) += 32;
}
static int count_read, count_write, count_cycles, count_ncycles;
static int count_cycles_ce020;
static int count_read_ea, count_write_ea, count_cycles_ea;
-static const char *mmu_postfix;
+static const char *mmu_postfix, *xfc_postfix;
static int memory_cycle_cnt;
static int did_prefetch;
static int ipl_fetched;
if (using_mmu) {
if (flags & GF_FC) {
switch (size) {
- case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = sfc%s_get_byte (%sa);\n", name, mmu_postfix, name); break;
- case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = sfc%s_get_word (%sa);\n", name, mmu_postfix, name); break;
- case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = sfc%s_get_long (%sa);\n", name, mmu_postfix, name); break;
+ case sz_byte: insn_n_cycles += 4; printf ("\tuae_s8 %s = sfc%s_get_byte%s (%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
+ case sz_word: insn_n_cycles += 4; printf ("\tuae_s16 %s = sfc%s_get_word%s (%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
+ case sz_long: insn_n_cycles += 8; printf ("\tuae_s32 %s = sfc%s_get_long%s (%sa);\n", name, mmu_postfix, xfc_postfix, name); break;
default: term ();
}
} else {
case sz_byte:
insn_n_cycles += 4;
if (flags & GF_FC)
- printf ("\tdfc%s_put_byte (%sa, %s);\n", mmu_postfix, to, from);
+ printf ("\tdfc%s_put_byte%s (%sa, %s);\n", mmu_postfix, xfc_postfix, to, from);
else
printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstblrmw : (candormw ? dstbrmw : dstb), to, from);
break;
if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
term ();
if (flags & GF_FC)
- printf ("\tdfc%s_put_word (%sa, %s);\n", mmu_postfix, to, from);
+ printf ("\tdfc%s_put_word%s (%sa, %s);\n", mmu_postfix, xfc_postfix, to, from);
else
printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstwlrmw : (candormw ? dstwrmw : dstw), to, from);
break;
if (cpu_level < 2 && (mode == PC16 || mode == PC8r))
term ();
if (flags & GF_FC)
- printf ("\tdfc%s_put_long (%sa, %s);\n", mmu_postfix, to, from);
+ printf ("\tdfc%s_put_long%s (%sa, %s);\n", mmu_postfix, xfc_postfix, to, from);
else
printf ("\t%s (%sa, %s);\n", (flags & GF_LRMW) ? dstllrmw : (candormw ? dstlrmw : dstl), to, from);
break;
printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030c (a); goto %s; }\n", endlabelstr);
} else {
printf ("\t\telse if (frame == 0xa) { m68k_do_rte_mmu030 (a); break; }\n");
- printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030 (a); break; }\n");
+ printf ("\t\telse if (frame == 0xb) { m68k_do_rte_mmu030 (a); goto %s; }\n", endlabelstr);
}
} else {
printf ("\t\telse if (frame == 0xa) { m68k_areg (regs, 7) += offset + 24; break; }\n");
using_waitstates = 0;
memory_cycle_cnt = 4;
mmu_postfix = "";
+ xfc_postfix = "";
using_simple_cycles = 0;
using_indirect = 0;
cpu_generic = false;
opcode_next_clev[rp] = cpu_level;
} else if (id == 32) { // 32 = 68030 MMU
mmu_postfix = "030";
+ xfc_postfix = "_state";
cpu_level = 3;
using_mmu = 68030;
read_counts ();
opcode_next_clev[rp] = cpu_level;
} else if (id == 34) { // 34 = 68030 MMU + caches
mmu_postfix = "030c";
+ xfc_postfix = "_state";
cpu_level = 3;
using_prefetch_020 = 2;
using_mmu = 68030;
extern uae_u32 mmu030_fmovem_store[2];
extern uae_u8 mmu030_cache_state, mmu030_cache_state_default;
+#define MMU030_STATEFLAG1_SKIP_INS 0x1000
#define MMU030_STATEFLAG1_FMOVEM 0x2000
#define MMU030_STATEFLAG1_MOVEM1 0x4000
#define MMU030_STATEFLAG1_MOVEM2 0x8000
extern void REGPARAM3 mmu030_put_word_unaligned(uaecptr addr, uae_u16 val, uae_u32 fc, int flags) REGPARAM;
extern void REGPARAM3 mmu030_put_long_unaligned(uaecptr addr, uae_u32 val, uae_u32 fc, int flags) REGPARAM;
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_fc_code(void)
+{
+ return (regs.s ? 4 : 0) | 2;
+}
+
+static ALWAYS_INLINE uae_u32 uae_mmu030_get_fc_data(void)
+{
+ return (regs.s ? 4 : 0) | 1;
+}
+
static ALWAYS_INLINE uae_u32 uae_mmu030_get_ilong(uaecptr addr)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 2;
+ uae_u32 fc = uae_mmu030_get_fc_code();
if (unlikely(is_unaligned(addr, 4)))
return mmu030_get_ilong_unaligned(addr, fc, 0);
}
static ALWAYS_INLINE uae_u16 uae_mmu030_get_iword(uaecptr addr)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 2;
+ uae_u32 fc = uae_mmu030_get_fc_code();
+
return mmu030_get_iword(addr, fc);
}
static ALWAYS_INLINE uae_u16 uae_mmu030_get_ibyte(uaecptr addr)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 2;
+ uae_u32 fc = uae_mmu030_get_fc_code();
return mmu030_get_byte(addr, fc);
}
+
static ALWAYS_INLINE uae_u32 uae_mmu030_get_long(uaecptr addr)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 1;
+ uae_u32 fc = uae_mmu030_get_fc_data();
if (unlikely(is_unaligned(addr, 4)))
return mmu030_get_long_unaligned(addr, fc, 0);
}
static ALWAYS_INLINE uae_u32 uae_mmu030_get_word(uaecptr addr)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 1;
+ uae_u32 fc = uae_mmu030_get_fc_data();
if (unlikely(is_unaligned(addr, 2)))
return mmu030_get_word_unaligned(addr, fc, 0);
}
static ALWAYS_INLINE uae_u32 uae_mmu030_get_byte(uaecptr addr)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 1;
+ uae_u32 fc = uae_mmu030_get_fc_data();
return mmu030_get_byte(addr, fc);
}
+
static ALWAYS_INLINE void uae_mmu030_put_long(uaecptr addr, uae_u32 val)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 1;
-
+ uae_u32 fc = uae_mmu030_get_fc_data();
+
if (unlikely(is_unaligned(addr, 4)))
mmu030_put_long_unaligned(addr, val, fc, 0);
else
}
static ALWAYS_INLINE void uae_mmu030_put_word(uaecptr addr, uae_u32 val)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 1;
+ uae_u32 fc = uae_mmu030_get_fc_data();
if (unlikely(is_unaligned(addr, 2)))
mmu030_put_word_unaligned(addr, val, fc, 0);
}
static ALWAYS_INLINE void uae_mmu030_put_byte(uaecptr addr, uae_u32 val)
{
- uae_u32 fc = (regs.s ? 4 : 0) | 1;
+ uae_u32 fc = uae_mmu030_get_fc_data();
mmu030_put_byte(addr, val, fc);
}
mmu030_put_byte(addr, val, fc);
}
+static ALWAYS_INLINE uae_u32 sfc030_get_long_state(uaecptr addr)
+{
+ uae_u32 v;
+ ACCESS_CHECK_GET
+ v = sfc030_get_long(addr);
+ ACCESS_EXIT_GET
+ return v;
+}
+static ALWAYS_INLINE uae_u16 sfc030_get_word_state(uaecptr addr)
+{
+ uae_u32 v;
+ ACCESS_CHECK_GET
+ v = sfc030_get_word(addr);
+ ACCESS_EXIT_GET
+ return v;
+}
+static ALWAYS_INLINE uae_u8 sfc030_get_byte_state(uaecptr addr)
+{
+ uae_u32 v;
+ ACCESS_CHECK_GET
+ v = sfc030_get_byte(addr);
+ ACCESS_EXIT_GET
+ return v;
+}
+
+static ALWAYS_INLINE void dfc030_put_long_state(uaecptr addr, uae_u32 v)
+{
+ ACCESS_CHECK_PUT
+ dfc030_put_long(addr, v);
+ ACCESS_EXIT_PUT
+}
+static ALWAYS_INLINE void dfc030_put_word_state(uaecptr addr, uae_u32 v)
+{
+ ACCESS_CHECK_PUT
+ dfc030_put_word(addr, v);
+ ACCESS_EXIT_PUT
+}
+static ALWAYS_INLINE void dfc030_put_byte_state(uaecptr addr, uae_u32 v)
+{
+ ACCESS_CHECK_PUT
+ dfc030_put_byte(addr, v);
+ ACCESS_EXIT_PUT
+}
+
+
uae_u32 REGPARAM3 get_disp_ea_020_mmu030 (uae_u32 base, int idx) REGPARAM;
STATIC_INLINE void put_byte_mmu030_state (uaecptr addr, uae_u32 v)
write_data_030_fc_bput(addr, val, regs.dfc);
}
+static ALWAYS_INLINE uae_u32 sfc030c_get_long_state(uaecptr addr)
+{
+ uae_u32 v;
+ ACCESS_CHECK_GET
+ v = sfc030c_get_long(addr);
+ ACCESS_EXIT_GET
+ return v;
+}
+static ALWAYS_INLINE uae_u16 sfc030c_get_word_state(uaecptr addr)
+{
+ uae_u32 v;
+ ACCESS_CHECK_GET
+ v = sfc030c_get_word(addr);
+ ACCESS_EXIT_GET
+ return v;
+}
+static ALWAYS_INLINE uae_u8 sfc030c_get_byte_state(uaecptr addr)
+{
+ uae_u32 v;
+ ACCESS_CHECK_GET
+ v = sfc030c_get_byte(addr);
+ ACCESS_EXIT_GET
+ return v;
+}
+
+static ALWAYS_INLINE void dfc030c_put_long_state(uaecptr addr, uae_u32 v)
+{
+ ACCESS_CHECK_PUT
+ dfc030c_put_long(addr, v);
+ ACCESS_EXIT_PUT
+}
+static ALWAYS_INLINE void dfc030c_put_word_state(uaecptr addr, uae_u32 v)
+{
+ ACCESS_CHECK_PUT
+ dfc030c_put_word(addr, v);
+ ACCESS_EXIT_PUT
+}
+static ALWAYS_INLINE void dfc030c_put_byte_state(uaecptr addr, uae_u32 v)
+{
+ ACCESS_CHECK_PUT
+ dfc030c_put_byte(addr, v);
+ ACCESS_EXIT_PUT
+}
+
uae_u32 REGPARAM3 get_disp_ea_020_mmu030c (uae_u32 base, int idx) REGPARAM;
STATIC_INLINE void put_byte_mmu030c_state (uaecptr addr, uae_u32 v)