From 367f8cc46e4ab440ca3400a838e8175e6b52e43b Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 6 Oct 2018 18:41:58 +0300 Subject: [PATCH] JIT unexpected crash detection. --- cfgfile.cpp | 3 ++ include/newcpu.h | 1 + include/options.h | 1 + jit/exception_handler.cpp | 5 +++ newcpu.cpp | 68 ++++++++++++++++++++++++----------- od-win32/resources/resource.h | 1 + od-win32/resources/winuae.rc | 23 ++++++------ od-win32/win32gui.cpp | 21 ++++++----- 8 files changed, 83 insertions(+), 40 deletions(-) diff --git a/cfgfile.cpp b/cfgfile.cpp index f10de1b6..c96691cd 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -1886,6 +1886,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) #ifdef USE_JIT_FPU cfgfile_write_bool (f, _T("compfpu"), p->compfpu); #endif + cfgfile_write_bool(f, _T("comp_catchdetect"), p->comp_catchfault); cfgfile_write (f, _T("cachesize"), _T("%d"), p->cachesize); for (i = 0; i < MAX_JPORTS; i++) { @@ -5281,6 +5282,7 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH || cfgfile_yesno (option, value, _T("fpu_strict"), &p->fpu_strict) || cfgfile_yesno (option, value, _T("comp_nf"), &p->compnf) || cfgfile_yesno (option, value, _T("comp_constjump"), &p->comp_constjump) + || cfgfile_yesno(option, value, _T("comp_catchfault"), &p->comp_catchfault) #ifdef USE_JIT_FPU || cfgfile_yesno (option, value, _T("compfpu"), &p->compfpu) #endif @@ -7548,6 +7550,7 @@ void default_prefs (struct uae_prefs *p, bool reset, int type) #else p->compfpu = 0; #endif + p->comp_catchfault = true; p->cachesize = 0; p->gfx_framerate = 1; diff --git a/include/newcpu.h b/include/newcpu.h index 3e49e9e6..572f41bb 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -703,6 +703,7 @@ extern void exception3_notinstruction(uae_u32 opcode, uaecptr addr); extern void exception3i (uae_u32 opcode, uaecptr addr); extern void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc); extern void exception2 (uaecptr addr, bool read, int size, uae_u32 fc); +extern void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc); extern void m68k_reset (void); extern void cpureset (void); extern void cpu_halt (int id); diff --git a/include/options.h b/include/options.h index cf280f24..4510ebbb 100644 --- a/include/options.h +++ b/include/options.h @@ -514,6 +514,7 @@ struct uae_prefs { bool compfpu; bool comp_hardflush; bool comp_constjump; + bool comp_catchfault; int cachesize; bool fpu_strict; int fpu_mode; diff --git a/jit/exception_handler.cpp b/jit/exception_handler.cpp index 2b3d89f3..9f4698b0 100644 --- a/jit/exception_handler.cpp +++ b/jit/exception_handler.cpp @@ -505,6 +505,11 @@ LONG WINAPI EvalException(LPEXCEPTION_POINTERS info) if (handle_access(address, info)) { return EXCEPTION_CONTINUE_EXECUTION; } + if (currprefs.comp_catchfault) { + // setup fake exception + exception2_setup(uae_p32(address) - uae_p32(NATMEM_OFFSET), info->ExceptionRecord->ExceptionInformation[0] == 0, 1, regs.s ? 4 : 0); + return EXCEPTION_EXECUTE_HANDLER; + } return EXCEPTION_CONTINUE_SEARCH; } diff --git a/newcpu.cpp b/newcpu.cpp index 28ae2b5d..eadf1018 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -3654,18 +3654,27 @@ kludge_me_do: // address = format $2 stack frame address field static void ExceptionX (int nr, uaecptr address) { + uaecptr pc = m68k_getpc(); regs.exception = nr; if (cpu_tracer) { cputrace.state = nr; } if (!regs.s) { - regs.instruction_pc_user_exception = m68k_getpc(); + regs.instruction_pc_user_exception = pc; } #ifdef JIT if (currprefs.cachesize) - regs.instruction_pc = address == -1 ? m68k_getpc () : address; + regs.instruction_pc = address == -1 ? pc : address; #endif + + if (debug_illegal && !in_rom(pc)) { + if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) { + write_log(_T("Exception %d breakpoint\n"), nr); + activate_debugger(); + } + } + #ifdef CPUEMU_13 if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010) Exception_ce000 (nr); @@ -3680,12 +3689,6 @@ static void ExceptionX (int nr, uaecptr address) Exception_normal (nr); } - if (debug_illegal && !in_rom (M68K_GETPC)) { - if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) { - write_log (_T("Exception %d breakpoint\n"), nr); - activate_debugger (); - } - } regs.exception = 0; if (cpu_tracer) { cputrace.state = 0; @@ -5595,15 +5598,35 @@ static void m68k_run_jit(void) #endif for (;;) { - ((compiled_handler*)(pushall_call_handler))(); - /* Whenever we return from that, we should check spcflags */ - check_uae_int_request(); - if (regs.spcflags) { - if (do_specialties (0)) { - return; +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING + __try { +#endif + for (;;) { + ((compiled_handler*)(pushall_call_handler))(); + /* Whenever we return from that, we should check spcflags */ + check_uae_int_request(); + if (regs.spcflags) { + if (do_specialties(0)) { + return; + } + } } + +#ifdef USE_STRUCTURED_EXCEPTION_HANDLING + } __except (EvalException(GetExceptionInformation())) { + // Something very bad happened, generate fake bus error exception + // Either emulation continues normally or crashes. + // Without this it would have crashed in any case.. + uaecptr pc = M68K_GETPC; + write_log(_T("Unhandled JIT exception! PC=%08x\n"), pc); + if (pc & 1) + Exception(3); + else + Exception(2); } +#endif } + } #endif /* JIT */ @@ -8826,6 +8849,16 @@ void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc) exception3f (opcode, addr, w, i, false, pc, true); } +void exception2_setup(uaecptr addr, bool read, int size, uae_u32 fc) +{ + last_addr_for_exception_3 = m68k_getpc() + bus_error_offset; + last_fault_for_exception_3 = addr; + last_writeaccess_for_exception_3 = read == 0; + last_instructionaccess_for_exception_3 = (fc & 1) == 0; + last_op_for_exception_3 = regs.opcode; + last_notinstruction_for_exception_3 = exception_in_exception != 0; +} + void exception2 (uaecptr addr, bool read, int size, uae_u32 fc) { if (currprefs.mmu_model) { @@ -8836,12 +8869,7 @@ void exception2 (uaecptr addr, bool read, int size, uae_u32 fc) mmu_bus_error (addr, 0, fc, read == false, size, 0, true); } } else { - last_addr_for_exception_3 = m68k_getpc() + bus_error_offset; - last_fault_for_exception_3 = addr; - last_writeaccess_for_exception_3 = read == 0; - last_instructionaccess_for_exception_3 = (fc & 1) == 0; - last_op_for_exception_3 = regs.opcode; - last_notinstruction_for_exception_3 = exception_in_exception != 0; + exception2_setup(addr, read, size, fc); THROW(2); } } diff --git a/od-win32/resources/resource.h b/od-win32/resources/resource.h index 7a9e71df..921c0061 100644 --- a/od-win32/resources/resource.h +++ b/od-win32/resources/resource.h @@ -822,6 +822,7 @@ #define IDC_SOUNDDRIVEVOLUME2 1581 #define IDC_CS_CACHE_TEXT 1582 #define IDC_SOUNDVOLUMEEXT2 1582 +#define IDC_JITCRASH 1582 #define IDC_CS_CACHE_TEXT2 1583 #define IDC_SOUNDDRIVEVOLUMEX 1583 #define IDC_COLLISIONS 1584 diff --git a/od-win32/resources/winuae.rc b/od-win32/resources/winuae.rc index 1a55e996..eab0104a 100644 --- a/od-win32/resources/winuae.rc +++ b/od-win32/resources/winuae.rc @@ -301,24 +301,25 @@ BEGIN "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,145,161,236,10 RTEXT "Stopped M68K CPU idle mode",IDC_STATIC,180,183,121,9 CONTROL "",IDC_PPC_CPUIDLE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,308,177,69,21 - GROUPBOX "x86 Bridgeboard CPU options",IDC_STATIC,136,202,258,42 + GROUPBOX "x86 Bridgeboard CPU options",IDC_STATIC,136,202,258,38 RTEXT "CPU Speed",IDC_STATIC,147,221,55,9,SS_CENTERIMAGE EDITTEXT IDC_CPUTEXT_x86,224,220,39,12,ES_CENTER | ES_READONLY CONTROL "",IDC_SPEED_x86,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,278,215,108,20 - GROUPBOX "Advanced JIT Settings",IDC_STATIC,136,245,258,70 - RTEXT "Cache size:",IDC_STATIC,143,261,66,10,SS_CENTERIMAGE - CONTROL "Slider1",IDC_CACHE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,212,255,115,20 - EDITTEXT IDC_CACHETEXT,331,260,30,12,ES_CENTER | ES_READONLY - CONTROL "FPU support",IDC_JITFPU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,143,281,71,11 - CONTROL "Constant jump",IDC_CONSTJUMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,281,71,11 - CONTROL "Hard flush",IDC_HARDFLUSH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,299,281,84,11 - CONTROL "Direct",IDC_TRUST0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,143,299,72,10 - CONTROL "Indirect",IDC_TRUST1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,221,299,72,10 - CONTROL "No flags",IDC_NOFLAGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,299,299,68,11 + GROUPBOX "Advanced JIT Settings",IDC_STATIC,136,241,258,74 + RTEXT "Cache size:",IDC_STATIC,143,260,66,10,SS_CENTERIMAGE + CONTROL "Slider1",IDC_CACHE,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | WS_TABSTOP,212,250,115,20 + EDITTEXT IDC_CACHETEXT,331,255,30,12,ES_CENTER | ES_READONLY + CONTROL "FPU support",IDC_JITFPU,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,143,273,71,11 + CONTROL "Constant jump",IDC_CONSTJUMP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,221,273,71,11 + CONTROL "Hard flush",IDC_HARDFLUSH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,299,273,84,11 + CONTROL "Direct",IDC_TRUST0,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,143,288,72,10 + CONTROL "Indirect",IDC_TRUST1,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,221,288,72,10 + CONTROL "No flags",IDC_NOFLAGS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,299,288,68,11 GROUPBOX "MMU",IDC_STATIC,2,168,129,42,BS_LEFT CONTROL "Data cache emulation [] 68030, 040 and 060 optional data cache emulation. Requires More compatible option.",IDC_CPUDATACACHE, "Button",BS_AUTOCHECKBOX | BS_LEFT | WS_GROUP | WS_TABSTOP,8,123,119,12 COMBOBOX IDC_FPU_MODE,7,299,112,75,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + CONTROL "Catch unexpected exceptions",IDC_JITCRASH,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,143,300,115,11 END IDD_FLOPPY DIALOGEX 0, 0, 396, 261 diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 070c1ab9..1410c7f2 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -12090,6 +12090,7 @@ static void enable_for_cpudlg (HWND hDlg) ew(hDlg, IDC_HARDFLUSH, enable); ew(hDlg, IDC_CONSTJUMP, enable); ew(hDlg, IDC_JITFPU, enable); + ew(hDlg, IDC_JITCRASH, enable); ew(hDlg, IDC_NOFLAGS, enable); ew(hDlg, IDC_CS_CACHE_TEXT, enable); ew(hDlg, IDC_CACHE, enable); @@ -12172,11 +12173,12 @@ static void values_to_cpudlg (HWND hDlg) _stprintf (buffer, _T("%d MB"), workprefs.cachesize / 1024 ); SetDlgItemText (hDlg, IDC_CACHETEXT, buffer); - CheckDlgButton (hDlg, IDC_NOFLAGS, workprefs.compnf); - CheckDlgButton (hDlg, IDC_JITFPU, workprefs.compfpu); - CheckDlgButton (hDlg, IDC_HARDFLUSH, workprefs.comp_hardflush); - CheckDlgButton (hDlg, IDC_CONSTJUMP, workprefs.comp_constjump); - CheckDlgButton (hDlg, IDC_JITENABLE, workprefs.cachesize > 0); + CheckDlgButton(hDlg, IDC_JITCRASH, workprefs.comp_catchfault); + CheckDlgButton(hDlg, IDC_NOFLAGS, workprefs.compnf); + CheckDlgButton(hDlg, IDC_JITFPU, workprefs.compfpu); + CheckDlgButton(hDlg, IDC_HARDFLUSH, workprefs.comp_hardflush); + CheckDlgButton(hDlg, IDC_CONSTJUMP, workprefs.comp_constjump); + CheckDlgButton(hDlg, IDC_JITENABLE, workprefs.cachesize > 0); bool mmu = ((workprefs.cpu_model == 68060 && workprefs.mmu_model == 68060) || (workprefs.cpu_model == 68040 && workprefs.mmu_model == 68040) || (workprefs.cpu_model == 68030 && workprefs.mmu_model == 68030)) && @@ -12286,10 +12288,11 @@ static void values_from_cpudlg (HWND hDlg) workprefs.comptrustlong = newtrust; workprefs.comptrustnaddr= newtrust; - workprefs.compnf = ischecked (hDlg, IDC_NOFLAGS); - workprefs.compfpu = ischecked (hDlg, IDC_JITFPU); - workprefs.comp_hardflush = ischecked (hDlg, IDC_HARDFLUSH); - workprefs.comp_constjump = ischecked (hDlg, IDC_CONSTJUMP); + workprefs.comp_catchfault = ischecked(hDlg, IDC_JITCRASH); + workprefs.compnf = ischecked(hDlg, IDC_NOFLAGS); + workprefs.compfpu = ischecked(hDlg, IDC_JITFPU); + workprefs.comp_hardflush = ischecked(hDlg, IDC_HARDFLUSH); + workprefs.comp_constjump = ischecked(hDlg, IDC_CONSTJUMP); #ifdef JIT oldcache = workprefs.cachesize; -- 2.47.3