From: Toni Wilen Date: Sun, 10 Mar 2019 08:28:36 +0000 (+0200) Subject: 68030 MMU: FC 11xxx field is invalid and generates f-line exception. Add invalid... X-Git-Tag: 4200~26 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=e9181ae7c8048c10189de862a3a4fc646a1e97f9;p=francis%2Fwinuae.git 68030 MMU: FC 11xxx field is invalid and generates f-line exception. Add invalid instruction checks to 68030 MMU disassembler. --- diff --git a/cpummu30.cpp b/cpummu30.cpp index 2317dc9a..3eef9a26 100644 --- a/cpummu30.cpp +++ b/cpummu30.cpp @@ -290,21 +290,24 @@ void mmu030_flush_atc_all(void) { } /* -- Helper function for MMU instructions -- */ -static uae_u32 mmu_op30_helper_get_fc(uae_u16 next) { +static bool mmu_op30_helper_get_fc(uae_u16 next, uae_u32 *fc) { switch (next & 0x0018) { case 0x0010: - return (next & 0x7); + *fc = next & 0x7; + return true; case 0x0008: - return (m68k_dreg(regs, next & 0x7) & 0x7); + *fc = m68k_dreg(regs, next & 0x7) & 0x7; + return true; case 0x0000: if (next & 1) { - return (regs.dfc); + *fc = regs.dfc; } else { - return (regs.sfc); + *fc = regs.sfc; } + return true; default: write_log(_T("MMU_OP30 ERROR: bad fc source! (%04X)\n"), next & 0x0018); - return 0; + return false; } } @@ -452,13 +455,15 @@ bool mmu_op30_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) int rw = (next >> 9) & 1; int a = (next >> 8) & 1; int areg = (next&0xE0)>>5; - uae_u32 fc = mmu_op30_helper_get_fc(next); - bool write = rw ? false : true; + uae_u32 fc; + bool write = rw ? false : true; uae_u32 ret = 0; if (mmu_op30_invea(opcode)) return true; - if (!level && a) { + if (!mmu_op30_helper_get_fc(next, &fc)) + return true; + if (!level && a) { write_log(_T("PTEST: Bad instruction causing F-line unimplemented instruction exception!\n")); return true; } @@ -497,13 +502,15 @@ static bool mmu_op30_pload (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr ex { int rw = (next >> 9) & 1; int unused = (next & (0x100 | 0x80 | 0x40 | 0x20)); - uae_u32 fc = mmu_op30_helper_get_fc(next); + uae_u32 fc; bool write = rw ? false : true; if (mmu_op30_invea(opcode)) return true; if (unused) return true; + if (!mmu_op30_helper_get_fc(next, &fc)) + return true; #if 0 write_log (_T("PLOAD%c: Create ATC entry for %08X, FC = %i\n"), write?'W':'R', extra, fc); @@ -517,8 +524,8 @@ static bool mmu_op30_pload (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr ex bool mmu_op30_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) { uae_u16 mode = (next >> 8) & 31; - uae_u32 fc_mask = (uae_u32)(next & 0x00E0) >> 5; - uae_u32 fc_base = mmu_op30_helper_get_fc(next); + uae_u32 fc_mask = (next & 0x00E0) >> 5; + uae_u32 fc_base; uae_u32 fc_bits = next & 0x7f; #if 0 @@ -550,12 +557,16 @@ bool mmu_op30_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra) mmu030_flush_atc_all(); break; case 0x10: + if (!mmu_op30_helper_get_fc(next, &fc_base)) + return true; mmu030_flush_atc_fc(fc_base, fc_mask); break; case 0x18: if (mmu_op30_invea(opcode)) return true; - mmu030_flush_atc_page_fc(extra, fc_base, fc_mask); + if (!mmu_op30_helper_get_fc(next, &fc_base)) + return true; + mmu030_flush_atc_page_fc(extra, fc_base, fc_mask); break; default: write_log(_T("PFLUSH %04x-%04x ERROR: bad mode! (%i)\n"), opcode, next, mode); diff --git a/newcpu.cpp b/newcpu.cpp index 744be7ad..8b781e1e 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -7659,25 +7659,24 @@ static void resolve_if_jmp(TCHAR *s, uae_u32 addr) } } -static void mmu_op30_helper_get_fc(uae_u16 extra, TCHAR *out) +static bool mmu_op30_helper_get_fc(uae_u16 extra, TCHAR *out) { switch (extra & 0x0018) { case 0x0010: _stprintf(out, _T("#%d"), extra & 7); - return; + return true; case 0x0008: _stprintf(out, _T("D%d"), extra & 7); - return; + return true; case 0x0000: if (extra & 1) { _tcscpy(out, _T("DFC")); } else { _tcscpy(out, _T("SFC")); } - return; + return true; default: - _tcscpy(out, _T("??")); - return; + return false; } } @@ -7685,7 +7684,9 @@ static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct i { int type = extra >> 13; + _tcscpy(instrname, _T("F-LINE (MMU 68030)")); pc += 2; + switch (type) { case 0: @@ -7699,15 +7700,12 @@ static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct i int unused = (extra & 0xff); TCHAR *r = NULL; - _tcscpy(instrname, _T("PMOVE")); - if (fd) - _tcscat(instrname, _T("FD")); - _tcscat(instrname, _T(" ")); - - if (!rw) { - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); - _tcscat(instrname, _T(",")); - } + if (mmu_op30_invea(opcode)) + break; + if (unused) + break; + if (rw && fd) + break; switch (preg) { case 0x10: @@ -7728,9 +7726,18 @@ static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct i case 0x03: r = _T("TT1"); break; - default: - r = _T("??"); + } + if (!r) break; + + _tcscpy(instrname, _T("PMOVE")); + if (fd) + _tcscat(instrname, _T("FD")); + _tcscat(instrname, _T(" ")); + + if (!rw) { + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); + _tcscat(instrname, _T(",")); } _tcscat(instrname, r); if (rw) { @@ -7743,30 +7750,40 @@ static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct i { // PLOAD/PFLUSH uae_u16 mode = (extra >> 8) & 31; + int unused = (extra & (0x100 | 0x80 | 0x40 | 0x20)); uae_u16 fc_mask = (extra & 0x00E0) >> 5; uae_u16 fc_bits = extra & 0x7f; TCHAR fc[10]; - mmu_op30_helper_get_fc(extra, fc); + if (unused) + break; + switch (mode) { case 0x00: // PLOAD W case 0x02: // PLOAD R + if (mmu_op30_invea(opcode)) + break; _stprintf(instrname, _T("PLOAD%c %s,"), mode == 0 ? 'W' : 'R', fc); pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); break; case 0x04: // PFLUSHA + if (fc_bits) + break; _tcscpy(instrname, _T("PFLUSHA")); break; case 0x10: // FC - case 0x18: // FC + EA + if (!mmu_op30_helper_get_fc(extra, fc)) + break; _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask); - if (mode == 0x18) { - _tcscat(instrname, _T(",")); - pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); - } break; - default: - _tcscpy(instrname, _T("PFLUSH??")); + case 0x18: // FC + EA + if (mmu_op30_invea(opcode)) + break; + if (!mmu_op30_helper_get_fc(extra, fc)) + break; + _stprintf(instrname, _T("PFLUSH %s,%d"), fc, fc_mask); + _tcscat(instrname, _T(",")); + pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); break; } break; @@ -7780,7 +7797,12 @@ static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct i int areg = (extra & 0xE0) >> 5; TCHAR fc[10]; - mmu_op30_helper_get_fc(extra, fc); + if (mmu_op30_invea(opcode)) + break; + if (!mmu_op30_helper_get_fc(extra, fc)) + break; + if (!level && a) + break; _stprintf(instrname, _T("PTEST%c %s,"), rw ? 'R' : 'W', fc); pc = ShowEA(NULL, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr2, safemode); _stprintf(instrname + _tcslen(instrname), _T(",#%d"), level); @@ -7788,9 +7810,6 @@ static uaecptr disasm_mmu030(uaecptr pc, uae_u16 opcode, uae_u16 extra, struct i _stprintf(instrname + _tcslen(instrname), _T(",A%d"), areg); break; } - default: - _tcscpy(instrname, _T("F-LINE")); - break; } return pc; }