#ifdef FULLMMU
+bool mmu_debugger;
uae_u32 mmu_is_super;
uae_u32 mmu_tagmask, mmu_pagemask, mmu_pagemaski;
struct mmu_atc_line mmu_atc_array[ATC_TYPE][ATC_SLOTS][ATC_WAYS];
uaecptr mmu040_movem_ea;
uae_u32 mmu040_move16[4];
+static struct mmu_debug_data *mddm;
+
#if MMU_ICACHE
struct mmu_icache mmu_icache_data[MMU_ICACHE_SZ];
#endif
mmu_cache_state = ce_cachable[addr >>16] | CACHE_DISABLE_ALLOCATE;
return x_phys_get_long(addr);
}
-// Write accesses probably are always pushed to memomory
+// Write accesses probably are always pushed to memory
static void desc_put_long(uaecptr addr, uae_u32 v)
{
mmu_cache_state = CACHE_DISABLE_MMU;
static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, struct mmu_atc_line *l, uae_u32 *status060)
{
uae_u32 desc, desc_addr, wp;
+ uae_u32 desca = 0, descb = 0, descc = 0;
uae_u32 status = 0;
int i;
int old_s;
SAVE_EXCEPTION;
TRY(prb) {
+ desca = desc_addr;
desc = desc_get_long(desc_addr);
if ((desc & 2) == 0) {
#if MMUDEBUG > 1
}
wp |= desc;
- if ((desc & MMU_DES_USED) == 0) {
+ if ((desc & MMU_DES_USED) == 0 && !mmu_debugger) {
desc_put_long(desc_addr, desc | MMU_DES_USED);
}
/* fetch pointer table descriptor */
i = (addr >> 16) & 0x1fc;
desc_addr = (desc & MMU_ROOT_PTR_ADDR_MASK) | i;
+ descb = desc_addr;
desc = desc_get_long(desc_addr);
if ((desc & 2) == 0) {
#if MMUDEBUG > 1
goto fail;
}
wp |= desc;
- if ((desc & MMU_DES_USED) == 0)
+ if ((desc & MMU_DES_USED) == 0 && !mmu_debugger) {
desc_put_long(desc_addr, desc | MMU_DES_USED);
+ }
/* fetch page table descriptor */
if (mmu_pagesize_8k) {
}
desc = desc_get_long(desc_addr);
+ descc = desc_addr;
if ((desc & 3) == 2) {
/* indirect */
desc_addr = desc & MMU_PAGE_INDIRECT_MASK;
wp |= desc;
if (write) {
if ((wp & MMU_DES_WP) || ((desc & MMU_DES_SUPER) && !super)) {
- if ((desc & MMU_DES_USED) == 0) {
+ if ((desc & MMU_DES_USED) == 0 && !mmu_debugger) {
desc |= MMU_DES_USED;
desc_put_long(desc_addr, desc);
}
} else if ((desc & (MMU_DES_USED|MMU_DES_MODIFIED)) !=
(MMU_DES_USED|MMU_DES_MODIFIED)) {
- desc |= MMU_DES_USED|MMU_DES_MODIFIED;
- desc_put_long(desc_addr, desc);
+ desc |= MMU_DES_USED|MMU_DES_MODIFIED;
+ if (!mmu_debugger) {
+ desc_put_long(desc_addr, desc);
+ }
}
} else {
if ((desc & MMU_DES_USED) == 0) {
- desc |= MMU_DES_USED;
- desc_put_long(desc_addr, desc);
+ desc |= MMU_DES_USED;
+ if (!mmu_debugger) {
+ desc_put_long(desc_addr, desc);
+ }
}
}
desc |= wp & MMU_DES_WP;
status = l->phys | l->status;
}
+ if (mmu_debugger) {
+ mddm->descriptor[0] = desca;
+ mddm->descriptor[1] = descb;
+ mddm->descriptor[2] = descc;
+ }
+
RESTORE_EXCEPTION;
} CATCH(prb) {
RESTORE_EXCEPTION;
status = MMU_MMUSR_B;
*status060 |= MMU_FSLW_LK | MMU_FSLW_TWE;
+ if (mmu_debugger) {
+ mddm->desc_fault = true;
+ }
+
#if MMUDEBUG > 0
write_log(_T("MMU: bus error during table search.\n"));
#endif
}
}
+uaecptr debug_mmu_translate(uaecptr addr, uae_u32 val, bool super, bool data, bool write, int size, struct mmu_debug_data *mdd)
+{
+ memset(mdd, 0, sizeof(struct mmu_debug_data));
+ mddm = mdd;
+ for (int i = 0; i < MAX_MMU_DEBUG_DESCRIPTOR_LEVEL; i++) {
+ mdd->descriptor[i] = 0xffffffff;
+ }
+ mmu_debugger = true;
+ mmu_flush_atc_all(true);
+ if (!data) {
+ int res = mmu_do_match_ttr(regs.itt0, addr, super);
+ if (res == TTR_OK_MATCH) {
+ mdd->tt = 1;
+ mdd->ttdata = regs.itt0;
+ return addr;
+ }
+ res = mmu_do_match_ttr(regs.itt1, addr, super);
+ if (res == TTR_OK_MATCH) {
+ mdd->tt = 2;
+ mdd->ttdata = regs.itt1;
+ return addr;
+ }
+ } else {
+ int res = mmu_do_match_ttr(regs.dtt0, addr, super);
+ if (res == TTR_OK_MATCH) {
+ mdd->tt = 1;
+ mdd->ttdata = regs.dtt0;
+ return addr;
+ }
+ res = mmu_do_match_ttr(regs.dtt1, addr, super);
+ if (res == TTR_OK_MATCH) {
+ mdd->tt = 2;
+ mdd->ttdata = regs.dtt1;
+ return addr;
+ }
+ }
+ uaecptr v = mmu_translate(addr, val, super, data, write, size);
+ return v;
+}
+
+void debug_mmu_translate_end(void)
+{
+ mmu_debugger = false;
+ mddm = NULL;
+}
+
uaecptr mmu_translate(uaecptr addr, uae_u32 val, bool super, bool data, bool write, int size)
{
int way, i, index, way_invalid;
struct mmu030_access mmu030_ad[MAX_MMU030_ACCESS + 1];
bool ismoves030, islrmw030;
+static struct mmu_debug_data *mddm;
+
static void mmu030_ptest_atc_search(uaecptr logical_addr, uae_u32 fc, bool write);
static uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int level);
static TT_info mmu030_decode_tt(uae_u32 TT);
/* Set the updated bit */
if (!level && !(descr[0]&DESCR_U) && !super_violation) {
descr[0] |= DESCR_U;
- desc_put_long(descr_addr[descr_num], descr[0]);
+ if (!mmu_debugger) {
+ desc_put_long(descr_addr[descr_num], descr[0]);
+ }
}
/* Update status bits */
}
/* write modified descriptor if necessary */
if (descr_modified) {
- desc_put_long(descr_addr[descr_num], descr[0]);
+ if (!mmu_debugger) {
+ desc_put_long(descr_addr[descr_num], descr[0]);
+ }
}
}
mmu030.status |= (MMUSR_BUS_ERROR|MMUSR_INVALID);
write_log(_T("MMU: Bus error while %s descriptor!\n"),
bBusErrorReadWrite?_T("reading"):_T("writing"));
+
+ if (mmu_debugger) {
+ mddm->desc_fault = true;
+ }
+
} ENDTRY;
- // Restore original supervisor state
+ if (mmu_debugger) {
+ for (int i = 1; i <= descr_num; i++) {
+ mddm->descriptor[i - 1] = descr_addr[i];
+ }
+ if (descr_size > 4) {
+ mddm->descriptor8 = true;
+ }
+ }
+
+ // Restore original supervisor state
regs.s = old_s;
/* check if we have to handle ptest */
regs.mmu_ssw = MMU030_SSW_DF | (MMU030_SSW_DF << 1);
if (!(mmu030_state[1] & MMU030_STATEFLAG1_LASTWRITE)) {
regs.wb2_status = mmu030fixupreg(0);
- mmu030fixupmod(regs.wb2_status, 0, 0);
+ if (!mmu_debugger) {
+ mmu030fixupmod(regs.wb2_status, 0, 0);
+ }
regs.wb3_status = mmu030fixupreg(1);
- mmu030fixupmod(regs.wb3_status, 0, 1);
+ if (!mmu_debugger) {
+ mmu030fixupmod(regs.wb3_status, 0, 1);
+ }
}
} else {
// only used by data fault but word sounds nice
flags = MMU030_SSW_SIZE_W;
if (currprefs.cpu_compatible) {
regs.wb2_status = mmu030fixupreg(0);
- mmu030fixupmod(regs.wb2_status, 0, 0);
+ if (!mmu_debugger) {
+ mmu030fixupmod(regs.wb2_status, 0, 0);
+ }
regs.wb3_status = mmu030fixupreg(1);
- mmu030fixupmod(regs.wb3_status, 0, 1);
+ if (!mmu_debugger) {
+ mmu030fixupmod(regs.wb3_status, 0, 1);
+ }
regs.mmu_ssw = MMU030_SSW_FB | MMU030_SSW_RB;
} else {
regs.mmu_ssw = MMU030_SSW_FB | MMU030_SSW_RB;
return physical_addr;
}
+
+void debug_mmu030_translate_end(void)
+{
+ mmu_debugger = false;
+ mddm = NULL;
+}
+
+uaecptr debug_mmu030_translate(uaecptr addr, int fc, bool write, struct mmu_debug_data *mdd)
+{
+ memset(mdd, 0, sizeof(struct mmu_debug_data));
+ mddm = mdd;
+ for (int i = 0; i < MAX_MMU_DEBUG_DESCRIPTOR_LEVEL; i++) {
+ mdd->descriptor[i] = 0xffffffff;
+ }
+ mmu_debugger = true;
+ mmu030_flush_atc_all();
+ if ((fc == 7) || (mmu030_match_ttr(addr, fc, write) & TT_OK_MATCH) || (!mmu030.enabled)) {
+ if (mmu030_do_match_ttr(tt0_030, mmu030.transparent.tt0, addr, fc, write) & TT_OK_MATCH) {
+ mdd->ttdata = tt0_030;
+ mdd->tt = 1;
+ }
+ if (mmu030_do_match_ttr(tt1_030, mmu030.transparent.tt1, addr, fc, write) & TT_OK_MATCH) {
+ mdd->ttdata = tt1_030;
+ mdd->tt = 2;
+ }
+ return addr;
+ }
+ int atc_line_num = mmu030_logical_is_in_atc(addr, fc, write);
+
+ if (atc_line_num >= 0) {
+ return mmu030_get_addr_atc(addr, atc_line_num, fc, write);
+ } else {
+ mmu030_table_search(addr, fc, false, 0);
+ return mmu030_get_addr_atc(addr, mmu030_logical_is_in_atc(addr, fc, write), fc, write);
+ }
+}
+
uaecptr mmu030_translate(uaecptr addr, bool super, bool data, bool write)
{
int fc = (super ? 4 : 0) | (data ? 1 : 2);
}
}
+static void debug_do_mmu_translate(uaecptr addrl)
+{
+ struct mmu_debug_data mdd, mdd2;
+ uaecptr addrp;
+
+ console_out_f(_T("%08x translates to:\n"), addrl);
+ for (int fc = 0; fc < 7; fc++) {
+ bool super = (fc & 4) != 0;
+ bool data = (fc & 1) != 0;
+ bool ins = (fc & 2) != 0;
+ if (currprefs.mmu_model >= 68040 && fc != 5 && fc != 6 && fc != 1 && fc != 2) {
+ continue;
+ }
+ console_out_f(_T("FC%d %s: "), fc, fc == 6 ? _T("SI") : (fc == 5 ? _T("SD") : (fc == 2 ? _T("UI") : (fc == 1 ? _T("UD") : _T("--")))));
+ TRY(prb) {
+ if (currprefs.mmu_model >= 68040) {
+ addrp = debug_mmu_translate(addrl, 0, super, data, false, sz_long, &mdd);
+ } else {
+ addrp = debug_mmu030_translate(addrl, fc, false, &mdd);
+ }
+ console_out_f(_T("PHYS: %08x"), addrp);
+ TRY(prb2) {
+ if (currprefs.mmu_model >= 68040) {
+ addrp = debug_mmu_translate(addrl, 0, super, data, true, sz_long, &mdd2);
+ } else {
+ addrp = debug_mmu030_translate(addrl, fc, true, &mdd2);
+ }
+ console_out_f(_T(" RW"));
+ } CATCH(prb2) {
+ console_out_f(_T(" RO"));
+ } ENDTRY;
+ } CATCH(prb) {
+ console_out_f(_T("PHYS: ********"));
+ } ENDTRY;
+ if (mdd.tt) {
+ console_out_f(_T(" TT%d: %08x"), mdd.tt - 1, mdd.ttdata);
+ } else if (mdd.descriptor[0] != 0xffffffff) {
+ console_out_f(_T(" DESCR:"));
+ for (int i = 0; i < MAX_MMU_DEBUG_DESCRIPTOR_LEVEL; i++) {
+ uaecptr desc = mdd.descriptor[i];
+ if (desc == 0xffffffff) {
+ break;
+ }
+ if (mdd.descriptor8) {
+ uae_u32 descdata1 = get_long_debug(desc);
+ uae_u32 descdata2 = get_long_debug(desc + 4);
+ console_out_f(_T(" %08x (%08x.%08x)"), desc, descdata1, descdata2);
+ } else {
+ uae_u32 descdata = get_long_debug(desc);
+ console_out_f(_T(" %08x (%08x)"), desc, descdata);
+ }
+ }
+ } else {
+ console_out_f(_T(" DESCR: ********"));
+ }
+ if (mdd.desc_fault) {
+ console_out_f(_T(" FAULT"));
+ }
+ console_out_f(_T("\n"));
+ if (currprefs.mmu_model >= 68040) {
+ debug_mmu_translate_end();
+ } else {
+ debug_mmu030_translate_end();
+ }
+ }
+}
+
static void m68k_modify (TCHAR **inptr)
{
uae_u32 v;
break;
case 'U':
if (currprefs.mmu_model && more_params (&inptr)) {
- int i;
uaecptr addrl = readhex(&inptr, NULL);
- uaecptr addrp;
- console_out_f (_T("%08X translates to:\n"), addrl);
- for (i = 0; i < 4; i++) {
- bool super = (i & 2) != 0;
- bool data = (i & 1) != 0;
- console_out_f (_T("S%dD%d="), super, data);
- TRY(prb) {
- if (currprefs.mmu_model >= 68040)
- addrp = mmu_translate (addrl, 0, super, data, false, sz_long);
- else
- addrp = mmu030_translate (addrl, super, data, false);
- console_out_f (_T("%08X"), addrp);
- TRY(prb2) {
- if (currprefs.mmu_model >= 68040)
- addrp = mmu_translate (addrl, 0, super, data, true, sz_long);
- else
- addrp = mmu030_translate (addrl, super, data, true);
- console_out_f (_T(" RW"));
- } CATCH(prb2) {
- console_out_f (_T(" RO"));
- } ENDTRY
- } CATCH(prb) {
- console_out_f (_T("***********"));
- } ENDTRY
- console_out_f (_T(" "));
- }
- console_out_f (_T("\n"));
+ debug_do_mmu_translate(addrl);
}
break;
case 'h':
extern void mmu_get_move16(uaecptr addr, uae_u32 *v, bool data, int size);
extern void mmu_put_move16(uaecptr addr, uae_u32 *val, bool data, int size);
+extern uaecptr debug_mmu_translate(uaecptr addr, uae_u32 val, bool super, bool data, bool write, int size, struct mmu_debug_data *mdd);
+extern void debug_mmu_translate_end(void);
+
#if MMU_IPAGECACHE
extern uae_u32 atc_last_ins_laddr, atc_last_ins_paddr;
extern uae_u8 atc_last_ins_cache;
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;
+extern uaecptr debug_mmu030_translate(uaecptr addr, int fc, bool write, struct mmu_debug_data *mdd);
+extern void debug_mmu030_translate_end(void);
+
static ALWAYS_INLINE uae_u32 uae_mmu030_get_fc_code(void)
{
return (regs.s ? 4 : 0) | 2;
#endif
+extern bool mmu_debugger;
+
/* special status word (access error stack frame) */
/* 68060 */
#define MMU_FSLW_MA 0x08000000
extern void(*x_phys_put_word)(uaecptr, uae_u32);
extern void(*x_phys_put_long)(uaecptr, uae_u32);
+#define MAX_MMU_DEBUG_DESCRIPTOR_LEVEL 8
+struct mmu_debug_data
+{
+ uaecptr descriptor[MAX_MMU_DEBUG_DESCRIPTOR_LEVEL];
+ bool descriptor8;
+ bool desc_fault;
+ int tt;
+ uae_u32 ttdata;
+};
+
#endif /* UAE_MMU_COMMON_H */