From bab5103f564c40021117125b48d897a1f2a516ae Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Tue, 16 Sep 2025 18:59:18 +0300 Subject: [PATCH] More information added to U MMU translation debug command. --- cpummu.cpp | 84 ++++++++++++++++++++++++++++++++++---- cpummu30.cpp | 79 ++++++++++++++++++++++++++++++++---- debug.cpp | 96 +++++++++++++++++++++++++++++++------------- include/cpummu.h | 3 ++ include/cpummu030.h | 3 ++ include/mmu_common.h | 12 ++++++ 6 files changed, 234 insertions(+), 43 deletions(-) diff --git a/cpummu.cpp b/cpummu.cpp index b5ca9a3e..20e8db4f 100644 --- a/cpummu.cpp +++ b/cpummu.cpp @@ -43,6 +43,7 @@ #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]; @@ -65,6 +66,8 @@ int mmu040_movem; 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 @@ -638,7 +641,7 @@ static uae_u32 desc_get_long(uaecptr addr) 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; @@ -653,6 +656,7 @@ static void desc_put_long(uaecptr addr, uae_u32 v) 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; @@ -670,6 +674,7 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s SAVE_EXCEPTION; TRY(prb) { + desca = desc_addr; desc = desc_get_long(desc_addr); if ((desc & 2) == 0) { #if MMUDEBUG > 1 @@ -681,13 +686,14 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s } 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 @@ -698,8 +704,9 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s 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) { @@ -711,6 +718,7 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s } desc = desc_get_long(desc_addr); + descc = desc_addr; if ((desc & 3) == 2) { /* indirect */ desc_addr = desc & MMU_PAGE_INDIRECT_MASK; @@ -720,19 +728,23 @@ static uae_u32 mmu_fill_atc(uaecptr addr, bool super, uae_u32 tag, bool write, s 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; @@ -769,6 +781,12 @@ fail: 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; @@ -783,6 +801,10 @@ fail: 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 @@ -832,6 +854,52 @@ static void mmu_add_cache(uaecptr addr, uaecptr phys, bool super, bool data, boo } } +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; diff --git a/cpummu30.cpp b/cpummu30.cpp index 941f0acd..a1f80ec0 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -80,6 +80,8 @@ uae_u8 mmu030_cache_state; 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); @@ -1366,7 +1368,9 @@ static uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int lev /* 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 */ @@ -1515,7 +1519,9 @@ static uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int lev } /* 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]); + } } } @@ -1587,9 +1593,23 @@ static uae_u32 mmu030_table_search(uaecptr addr, uae_u32 fc, bool write, int lev 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 */ @@ -1818,18 +1838,26 @@ void mmu030_page_fault(uaecptr addr, bool read, int flags, uae_u32 fc) 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; @@ -2615,6 +2643,43 @@ static uaecptr mmu030_get_addr_atc(uaecptr addr, int l, uae_u32 fc, bool write) 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); diff --git a/debug.cpp b/debug.cpp index 78049616..b8e5b7ec 100644 --- a/debug.cpp +++ b/debug.cpp @@ -6535,6 +6535,73 @@ static void find_ea (TCHAR **inptr) } } +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; @@ -7294,35 +7361,8 @@ static bool debug_line (TCHAR *input) 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': diff --git a/include/cpummu.h b/include/cpummu.h index 67b1edc4..9428d4df 100644 --- a/include/cpummu.h +++ b/include/cpummu.h @@ -234,6 +234,9 @@ static ALWAYS_INLINE uaecptr mmu_get_real_address(uaecptr addr, struct mmu_atc_l 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; diff --git a/include/cpummu030.h b/include/cpummu030.h index baf6de9d..39790e3e 100644 --- a/include/cpummu030.h +++ b/include/cpummu030.h @@ -97,6 +97,9 @@ extern uae_u32 REGPARAM3 mmu030_get_lrmw_long_unaligned(uaecptr addr, uae_u32 fc 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; diff --git a/include/mmu_common.h b/include/mmu_common.h index 1fed7055..5a46e81f 100644 --- a/include/mmu_common.h +++ b/include/mmu_common.h @@ -44,6 +44,8 @@ typedef int m68k_exception; #endif +extern bool mmu_debugger; + /* special status word (access error stack frame) */ /* 68060 */ #define MMU_FSLW_MA 0x08000000 @@ -152,4 +154,14 @@ extern void(*x_phys_put_byte)(uaecptr, uae_u32); 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 */ -- 2.47.3