From 31cbe322db7fae1b6bf769ebd37e1b9224226717 Mon Sep 17 00:00:00 2001 From: "K.Ohta" Date: Thu, 23 May 2019 22:43:48 +0900 Subject: [PATCH] [DEBUGGER] Add features for catching EXCEPTION/FAULT by debugger.See mame/emu/cpu/i386.h and i386priv.h. --- source/src/debugger.cpp | 172 ++++++++++++++++++++++++++--- source/src/vm/common_vm/CMakeLists.txt | 2 +- source/src/vm/debugger.h | 26 ++++- source/src/vm/mame/emu/cpu/i386/i386.c | 89 ++++++++++----- source/src/vm/mame/emu/cpu/i386/i386priv.h | 19 +++- 5 files changed, 258 insertions(+), 50 deletions(-) diff --git a/source/src/debugger.cpp b/source/src/debugger.cpp index 312c2b11a..cba85b9bc 100644 --- a/source/src/debugger.cpp +++ b/source/src/debugger.cpp @@ -18,7 +18,8 @@ #include "vm/vm.h" #include "fileio.h" #include - +#include +#include #ifdef USE_DEBUGGER static FILEIO* logfile = NULL; @@ -269,6 +270,7 @@ void* debugger_thread(void *lpx) DEBUGGER *cpu_debugger = (DEBUGGER *)cpu->get_debugger(); DEVICE *target = cpu; DEBUGGER *target_debugger = cpu_debugger; + //cpu_debugger->stop_on_exception = true; cpu_debugger->set_context_child(NULL); cpu_debugger->now_going = false; @@ -306,7 +308,7 @@ void* debugger_thread(void *lpx) _TCHAR prev_command[MAX_COMMAND_LENGTH + 1]; memset(prev_command, 0, sizeof(prev_command)); - + while(!p->request_terminate) { p->emu->draw_screen(); @@ -410,7 +412,9 @@ void* debugger_thread(void *lpx) if(!p->request_terminate && enter_done) { _TCHAR *params[32], *token = NULL, *context = NULL; int num = 0; - + for(int i = 0; i < ((sizeof(params) / sizeof(_TCHAR *))); i++) { + params[i] = _T(""); + } if((token = my_tcstok_s(command, _T(" "), &context)) != NULL) { params[num++] = token; while(num < 32 && (token = my_tcstok_s(NULL, _T(" "), &context)) != NULL) { @@ -637,32 +641,141 @@ void* debugger_thread(void *lpx) } else if(_tcsicmp(params[0], _T("UT")) == 0) { if(target_debugger == NULL) { my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name); - } else if(num <= 3) { + } else if(num <= 4) { int steps = 128; + int xnum = 1; + bool logging = false; + if(num >= 2) { - steps = min((int)my_hexatoi(target, params[1]), MAX_CPU_TRACE); + if((strcasecmp(params[xnum], "0") == 0)) { + steps = MAX_CPU_TRACE; // TBD + xnum++; + } else { + steps = min((int)my_hexatoi(target, params[xnum]), MAX_CPU_TRACE); + if(steps > 0) xnum++; + } + } + _TCHAR log_path[_MAX_PATH]; + if(xnum < num) { + my_tcscpy_s(log_path, _MAX_PATH, my_absolute_path(params[xnum])); + logging = true; } - for(int i = MAX_CPU_TRACE - steps; i < MAX_CPU_TRACE; i++) { + FILEIO* log_fio = NULL; + if(logging) { + log_fio = new FILEIO(); + if(!(log_fio->Fopen((const _TCHAR*)log_path, FILEIO_WRITE_APPEND_ASCII))) { // Failed to open + delete log_fio; + log_fio = NULL; + logging = false; + my_printf(p->osd, "ERROR: Logging trace was failed for %s\n", log_path); + } else { + my_printf(p->osd, "Start logging trace for %s\n", log_path); + { + _TCHAR timestr[512] = {0}; + struct tm *timedat; + time_t nowtime; + struct timeval tv; + + nowtime = time(NULL); + gettimeofday(&tv, NULL); + timedat = localtime(&nowtime); + strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", timedat); + log_fio->Fprintf("**** Start of logging BACKTRACE %d steps for %s at %s.%06ld ****\n\n", steps, target->this_device_name, timestr, tv.tv_usec); + } + } + } + int steps_left = steps; + int max_steps = MAX_CPU_TRACE; + int begin_step = (MAX_CPU_TRACE - steps) & (MAX_CPU_TRACE - 1); + if(!(target_debugger->cpu_trace_overwrap)) { + max_steps = target_debugger->cpu_trace_ptr; + begin_step = 0; + steps_left = (max_steps > steps_left) ? steps_left : max_steps; + } + if(steps_left > 1024) { + if(logging) { + my_printf(p->osd, "** NOTE: Trace %d steps, but display only 1024 steps,more are only logging.", steps_left); + } else { + my_printf(p->osd, "** NOTE: Request to trace %d steps, but display only 1024 steps.", steps_left); + begin_step = max_steps - 1024; + if(begin_step < 0) begin_step = 0; + steps_left = 1024; + } + } + for(int i = begin_step; i < max_steps; i++) { + if(logging) { + if((log_fio != NULL)) { + if(!(log_fio->IsOpened())) { + logging = false; + } + } else { + logging = false; + } + } int index = (target_debugger->cpu_trace_ptr + i) & (MAX_CPU_TRACE - 1); + if(!(target_debugger->cpu_trace[index] & ~target->get_debug_prog_addr_mask())) { const _TCHAR *name = my_get_symbol(target, target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask()); int len = target->debug_dasm(target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask(), buffer, array_length(buffer)); + _TCHAR tmps[8192]; + _TCHAR tmps2[512]; + memset(tmps, 0x00, sizeof(tmps)); if(name != NULL) { - my_printf(p->osd, _T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask()); + my_sprintf_s(tmps2, sizeof(tmps2),_T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask()); + strncat(tmps, tmps2, sizeof(tmps) - 1); p->osd->set_console_text_attribute(OSD_CONSOLE_GREEN | OSD_CONSOLE_INTENSITY); - my_printf(p->osd, _T("%s:\n"), name); + my_sprintf_s(tmps2, sizeof(tmps2), _T("%s:\n"), name); + strncat(tmps, tmps2, sizeof(tmps) - 1); p->osd->set_console_text_attribute(OSD_CONSOLE_RED | OSD_CONSOLE_GREEN | OSD_CONSOLE_BLUE | OSD_CONSOLE_INTENSITY); } - my_printf(p->osd, _T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask()); + my_sprintf_s(tmps2, sizeof(tmps2), _T("%08X "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask()); + strncat(tmps, tmps2, sizeof(tmps) - 1); for(int i = 0; i < len; i++) { - my_printf(p->osd, _T("%02X"), target->read_debug_data8((target_debugger->cpu_trace[index] + i) & target->get_debug_prog_addr_mask())); + my_sprintf_s(tmps2, sizeof(tmps2), _T("%02X"), target->read_debug_data8((target_debugger->cpu_trace[index] + i) & target->get_debug_prog_addr_mask())); + strncat(tmps, tmps2, sizeof(tmps) - 1); } + my_sprintf_s(tmps2, sizeof(tmps2), _T(" ")); for(int i = len; i < 8; i++) { - my_printf(p->osd, _T(" ")); + strncat(tmps, tmps2, sizeof(tmps) - 1); } - my_printf(p->osd, _T(" %s\n"), buffer); + my_sprintf_s(tmps2, sizeof(tmps2), _T(" %s"), buffer); + strncat(tmps, tmps2, sizeof(tmps) - 1); + + if(target_debugger->cpu_trace_exp_map[index]) { + my_sprintf_s(tmps2, sizeof(tmps2), _T(" <== EXCEPTION 0x%08X\n"), target_debugger->cpu_trace_exp[index]); + } else { + my_sprintf_s(tmps2, sizeof(tmps2), _T("\n")); + } + strncat(tmps, tmps2, sizeof(tmps) - 1); + if(logging) { + log_fio->Fprintf("%s", tmps); + } + if(steps_left <= 1024) { + my_printf(p->osd, "%s", tmps); + } + steps_left--; } } +// if(logging) { + if(log_fio != NULL) { + if(log_fio->IsOpened()) { + { + _TCHAR timestr[512] = {0}; + struct tm *timedat; + time_t nowtime; + struct timeval tv; + + nowtime = time(NULL); + gettimeofday(&tv, NULL); + timedat = localtime(&nowtime); + strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", timedat); + log_fio->Fprintf("\n**** End of logging BACKTRACE %d steps for %s at %s.%06ld ****\n", steps, target->this_device_name, timestr, tv.tv_usec); + } + log_fio->Fclose(); + } + delete log_fio; + } +// } } else { my_printf(p->osd, _T("invalid parameter number\n")); } @@ -831,6 +944,15 @@ void* debugger_thread(void *lpx) } else { my_printf(p->osd, _T("invalid parameter number\n")); } + } else if(_tcsicmp(params[0], _T( "BX")) == 0) { + if(num > 1) { + if(_tcsicmp(params[1], _T( "ON")) == 0) { + cpu_debugger->stop_on_exception = true; + } else if(_tcsicmp(params[1], _T( "OFF")) == 0) { + cpu_debugger->stop_on_exception = false; + } + my_printf(p->osd, _T("%s\n"), (cpu_debugger->stop_on_exception) ? _T("STOP ON EXCEPTION") : _T("NOT STOP ON EXCEPTION")); + } } else if(_tcsicmp(params[0], _T( "BP")) == 0 || _tcsicmp(params[0], _T( "CP")) == 0) { if(target_debugger == NULL) { @@ -1014,17 +1136,20 @@ void* debugger_thread(void *lpx) break_points_stored = true; } RESTART_GO: + cpu_debugger->exception_happened = false; + cpu_debugger->exception_code = 0; + cpu_debugger->exception_pc = cpu->get_pc(); cpu_debugger->now_going = true; cpu_debugger->now_suspended = false; #if defined(_MSC_VER) - while(!p->request_terminate && !cpu_debugger->now_suspended) { + while(!p->request_terminate && !cpu_debugger->now_suspended && !(cpu_debugger->exception_happened && cpu_debugger->stop_on_exception)) { if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) { break; } p->osd->sleep(10); } #elif defined(OSD_QT) - while(!p->request_terminate && !cpu_debugger->now_suspended) { + while(!p->request_terminate && !cpu_debugger->now_suspended && !(cpu_debugger->exception_happened && cpu_debugger->stop_on_exception)) { if(p->osd->console_input_string() != NULL && p->osd->is_console_active()) { p->osd->clear_console_input_string(); break; @@ -1048,6 +1173,12 @@ RESTART_GO: p->osd->set_console_text_attribute(OSD_CONSOLE_GREEN | OSD_CONSOLE_BLUE | OSD_CONSOLE_INTENSITY); cpu->debug_dasm(cpu->get_pc(), buffer, array_length(buffer)); + if(cpu_debugger->exception_happened) { + my_printf(p->osd, _T("**EXCEPTION #%08X happened at %08X\n"), cpu_debugger->exception_code, cpu_debugger->exception_pc); + } + cpu_debugger->exception_happened = false; + cpu_debugger->exception_code = 0; + my_printf(p->osd, _T("done\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer); p->osd->set_console_text_attribute(OSD_CONSOLE_RED | OSD_CONSOLE_GREEN | OSD_CONSOLE_BLUE | OSD_CONSOLE_INTENSITY); @@ -1093,6 +1224,10 @@ RESTART_GO: for(int i = 0; i < steps; i++) { cpu_debugger->now_going = false; cpu_debugger->now_suspended = false; + cpu_debugger->exception_happened = false; + cpu_debugger->exception_code = 0; + cpu_debugger->exception_pc = cpu->get_pc(); + wait_count = 0; while(!p->request_terminate && !(cpu_debugger->now_suspended && cpu_debugger->now_waiting)) { if((wait_count++) == 100) { @@ -1105,6 +1240,9 @@ RESTART_GO: dasm_addr = cpu->get_next_pc(); } + if(cpu_debugger->exception_happened) { + my_printf(p->osd, _T("**EXCEPTION #%08X happened at %08X\n"), cpu_debugger->exception_code, cpu_debugger->exception_pc); + } p->osd->set_console_text_attribute(OSD_CONSOLE_GREEN | OSD_CONSOLE_BLUE | OSD_CONSOLE_INTENSITY); cpu->debug_dasm(cpu->get_pc(), buffer, array_length(buffer)); my_printf(p->osd, _T("done\t%s %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer); @@ -1325,16 +1463,14 @@ RESTART_GO: my_printf(p->osd, _T("R - edit register\n")); my_printf(p->osd, _T("S - search\n")); my_printf(p->osd, _T("U [] - unassemble\n")); - my_printf(p->osd, _T("UT [] - unassemble trace\n")); - + my_printf(p->osd, _T("UT [ | ] - unassemble back trace\n")); my_printf(p->osd, _T("H - hexadd\n")); my_printf(p->osd, _T("N - name\n")); my_printf(p->osd, _T("L [] - load binary/hex/symbol file\n")); my_printf(p->osd, _T("W - write binary/hex file\n")); - my_printf(p->osd, _T("SC - clear symbol(s)\n")); my_printf(p->osd, _T("SL - list symbol(s)\n")); - + my_printf(p->osd, _T("BX [ON|OFF] - ON/OFF to STOP ON EXCEPTION\n")); my_printf(p->osd, _T("BP
- set breakpoint\n")); my_printf(p->osd, _T("{R,W}BP
- set breakpoint (break at memory access)\n")); my_printf(p->osd, _T("{I,O}BP [] - set breakpoint (break at i/o access)\n")); diff --git a/source/src/vm/common_vm/CMakeLists.txt b/source/src/vm/common_vm/CMakeLists.txt index 056b93612..ef7af4e7d 100644 --- a/source/src/vm/common_vm/CMakeLists.txt +++ b/source/src/vm/common_vm/CMakeLists.txt @@ -1,6 +1,6 @@ message("* vm/common_vm") -SET(THIS_LIB_VERSION 2.15.1) +SET(THIS_LIB_VERSION 2.16.0) #include(cotire) set(s_vm_common_vm_srcs diff --git a/source/src/vm/debugger.h b/source/src/vm/debugger.h index b2e6f9f97..2f330beed 100644 --- a/source/src/vm/debugger.h +++ b/source/src/vm/debugger.h @@ -19,7 +19,7 @@ #define MAX_BREAK_POINTS 16 #define MAX_COMMAND_LENGTH 1024 #define MAX_COMMAND_HISTORY 32 -#define MAX_CPU_TRACE 1024 +#define MAX_CPU_TRACE 0x01000000 /* 16Msteps */ typedef struct { struct { @@ -49,6 +49,9 @@ private: } } } + if(exception_happened && stop_on_exception) { + now_suspended = true; + } if(!now_suspended && d_child != NULL) { if(d_child->is_cpu()) { d_child->check_break_points(); @@ -92,8 +95,13 @@ public: memset(history, 0, sizeof(history)); history_ptr = 0; memset(cpu_trace, 0xff, sizeof(cpu_trace)); + memset(cpu_trace_exp, 0x00, sizeof(cpu_trace_exp)); + memset(cpu_trace_exp_map, 0x00, sizeof(cpu_trace_exp_map)); + exception_happened = false; + stop_on_exception = true; prev_cpu_trace = 0xffffffff; cpu_trace_ptr = 0; + cpu_trace_overwrap = false; set_device_name(_T("Debugger")); } ~DEBUGGER() {} @@ -488,22 +496,36 @@ public: } first_symbol = last_symbol = NULL; } + void add_cpu_trace_exception(uint64_t exception_code) + { + cpu_trace_exp[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] = exception_code; + cpu_trace_exp_map[(cpu_trace_ptr - 1) & (MAX_CPU_TRACE - 1)] = true; + } void add_cpu_trace(uint32_t pc) { if(prev_cpu_trace != pc) { + cpu_trace_exp_map[cpu_trace_ptr] = false; + cpu_trace_exp[cpu_trace_ptr] = 0; cpu_trace[cpu_trace_ptr++] = prev_cpu_trace = pc; + if(cpu_trace_ptr >= MAX_CPU_TRACE) cpu_trace_overwrap = true; cpu_trace_ptr &= (MAX_CPU_TRACE - 1); } } break_point_t bp, rbp, wbp, ibp, obp; symbol_t *first_symbol, *last_symbol; _TCHAR file_path[_MAX_PATH]; - bool now_debugging, now_going, now_suspended, now_waiting; + bool now_debugging, now_going, now_suspended, now_waiting, exception_happened; + uint64_t exception_code; + uint32_t exception_pc; + bool stop_on_exception; bool now_device_debugging; // for non-cpu devices _TCHAR history[MAX_COMMAND_HISTORY][MAX_COMMAND_LENGTH + 1]; int history_ptr; uint32_t cpu_trace[MAX_CPU_TRACE], prev_cpu_trace; + uint64_t cpu_trace_exp[MAX_CPU_TRACE]; + bool cpu_trace_exp_map[MAX_CPU_TRACE]; int cpu_trace_ptr; + bool cpu_trace_overwrap; }; //#endif diff --git a/source/src/vm/mame/emu/cpu/i386/i386.c b/source/src/vm/mame/emu/cpu/i386/i386.c index 774398689..a90690544 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386.c +++ b/source/src/vm/mame/emu/cpu/i386/i386.c @@ -49,8 +49,30 @@ static void build_opcode_table(i386_state *cpustate, UINT32 features); static void zero_state(i386_state *cpustate); static void pentium_smi(i386_state* cpustate); -#define FAULT(fault,error) {logerror("FAULT(%s , %s) PC=%08x V8086=%s PROTECTED=%s SP=%08X:%08X\n", #fault, #error, cpustate->pc, (cpustate->VM) ? "YES" : "NO", (PROTECTED_MODE) ? "YES" : "NO", (PROTECTED_MODE) ? cpustate->sreg[SS].base : (cpustate->sreg[SS].selector << 4), REG32(ESP)); cpustate->ext = 1; i386_trap_with_error(cpustate,fault,0,0,error, 0); return;} -#define FAULT_EXP(fault,error) {logerror("FAULT_EXP(%s , %s) PC=%08x V8086=%s PROTECTED=%s\n", #fault, #error, cpustate->pc, (cpustate->VM) ? "YES" : "NO", (PROTECTED_MODE) ? "YES" : "NO"); cpustate->ext = 1; i386_trap_with_error(cpustate,fault,0,trap_level+1,error, 0); return;} +#define FAULT(fault,error) {\ + logerror("FAULT(%s , %s) PC=%08x V8086=%s PROTECTED=%s SP=%08X:%08X\n", #fault, #error, cpustate->pc, (cpustate->VM) ? "YES" : "NO", (PROTECTED_MODE) ? "YES" : "NO", (PROTECTED_MODE) ? cpustate->sreg[SS].base : (cpustate->sreg[SS].selector << 4), REG32(ESP)); \ + if(cpustate->is_report_exception) { \ + cpustate->exception_code = ((UINT64)error << 32) | (UINT64)fault; \ + cpustate->exception_pc = cpustate->prev_pc; \ + cpustate->exception_caused = 1; \ + cpustate->ext = 1; \ + } \ + i386_trap_with_error(cpustate,fault,0,0,error, 0); \ + return; \ + } + +#define FAULT_EXP(fault,error) { \ + logerror("FAULT_EXP(%s , %s) PC=%08x V8086=%s PROTECTED=%s\n", #fault, #error, cpustate->pc, (cpustate->VM) ? "YES" : "NO", (PROTECTED_MODE) ? "YES" : "NO"); \ + if(cpustate->is_report_exception) { \ + cpustate->exception_code = ((UINT64)error << 32) | (UINT64)fault; \ + cpustate->exception_pc = cpustate->prev_pc; \ + cpustate->exception_caused = 1; \ + cpustate->ext = 1; \ + } \ + cpustate->ext = 1; \ + i386_trap_with_error(cpustate,fault,0,trap_level+1,error, 0); \ + return; \ + } static void cpu_reset_generic(i386_state* cpustate) { @@ -3719,7 +3741,11 @@ static CPU_EXECUTE( i386 ) //#endif cpustate->cycles -= cpustate->extra_cycles; cpustate->extra_cycles = 0; - + cpustate->exception_caused = 0; + cpustate->is_report_exception = 1; // ToDo + bool exception_caused = false; + UINT32 exception_pc = 0; + UINT64 exception_code = 0; while( cpustate->cycles > 0 && !cpustate->busreq ) { //#ifdef USE_DEBUGGER @@ -3728,6 +3754,14 @@ static CPU_EXECUTE( i386 ) now_debugging = cpustate->debugger->now_debugging; } if(now_debugging) { + if(exception_caused) { + cpustate->debugger->exception_pc = exception_pc; + cpustate->debugger->exception_code = exception_code; + cpustate->debugger->exception_happened = true; + exception_caused = false; + exception_code = 0; + printf("EXCEPTION HIT PC=%08X CODE=%X\n", exception_pc, exception_code); + } cpustate->debugger->check_break_points(cpustate->pc); if(cpustate->debugger->now_suspended) { cpustate->debugger->now_waiting = true; @@ -3771,6 +3805,13 @@ static CPU_EXECUTE( i386 ) try { I386OP(decode_opcode)(cpustate); + if(cpustate->exception_caused != 0) { + exception_pc = cpustate->exception_pc; + exception_code = cpustate->exception_code; + exception_caused = true; + cpustate->exception_caused = 0; + cpustate->debugger->add_cpu_trace_exception(exception_code); + } if(cpustate->TF && old_tf) { cpustate->prev_eip = cpustate->eip; @@ -3783,19 +3824,20 @@ static CPU_EXECUTE( i386 ) catch(UINT64 e) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); + logerror("Illegal instruction at PC=%08X EIP=%08x VM8086=%s exception %08X irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); + exception_caused = true; + exception_pc = cpustate->prev_pc; + exception_code = e; i386_trap_with_error(cpustate,e&0xffffffff,0,0,e>>32, 1); - } catch(UINT32 e) - { - cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); - i386_trap_with_error(cpustate,e&0xffffffff,0,0,0, 1); } catch(...) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=UNKNOWN\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO"); - i386_trap_with_error(cpustate,0,0,0,0, 1); + logerror("UNKNOWN EXCEPTION HAPPEND AT PC=%08X EIP=%08X VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO"); + exception_caused = true; + exception_pc = cpustate->prev_pc; + exception_code = 0; } + //#ifdef SINGLE_MODE_DMA if(cpustate->dma != NULL) { cpustate->dma->do_dma(); @@ -3853,24 +3895,21 @@ static CPU_EXECUTE( i386 ) } if(cpustate->lock && (cpustate->opcode != 0xf0)) cpustate->lock = false; - } - catch(UINT64 e) + } catch(UINT64 e) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); + logerror("Illegal instruction at PC=%08X EIP=%08x VM8086=%s exception %08X irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, e >> 32); + exception_caused = true; + exception_pc = cpustate->prev_pc; + exception_code = e; + cpustate->debugger->add_cpu_trace_exception(exception_code); i386_trap_with_error(cpustate,e&0xffffffff,0,0,e>>32, 1); - } - catch(UINT32 e) - { - cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", e & 0xffffffff, 0); - i386_trap_with_error(cpustate,e,0,0,0, 1); - } - catch(...) - { + } catch(...) { cpustate->ext = 1; - logerror("Illegal instruction EIP=%08x VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->eip, (cpustate->VM) ? "YES" : "NO", 0, 0); - i386_trap_with_error(cpustate,0,0,0,0, 1); + logerror("UNKNOWN EXCEPTION HAPPEND AT PC=%08X EIP=%08X VM8086=%s exception %08x irq=0 irq_gate=0 ERROR=%08x\n", cpustate->prev_pc, cpustate->eip, (cpustate->VM) ? "YES" : "NO"); + exception_caused = true; + exception_pc = cpustate->prev_pc; + exception_code = 0; } //#ifdef SINGLE_MODE_DMA if(cpustate->dma != NULL) { diff --git a/source/src/vm/mame/emu/cpu/i386/i386priv.h b/source/src/vm/mame/emu/cpu/i386/i386priv.h index 8993814cf..2ce710ae5 100644 --- a/source/src/vm/mame/emu/cpu/i386/i386priv.h +++ b/source/src/vm/mame/emu/cpu/i386/i386priv.h @@ -558,7 +558,13 @@ struct i386_state bool lock; UINT32 waitfactor; UINT64 waitcount; - + // Below is only for debugging, no need to save/load state. + UINT64 exception_code; + UINT32 exception_pc; + int is_report_exception; + int exception_caused; + // End. + // bytes in current opcode, debug only #ifdef DEBUG_MISSING_OPCODE UINT8 opcode_bytes[16]; @@ -570,9 +576,14 @@ struct i386_state extern int i386_parity_table[256]; //static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size); -#define FAULT_THROW(fault,error) { \ - /*logerror("FAULT_THROW(%s , %s)\n", #fault , #error );*/ \ - throw (UINT64)(fault | (UINT64)error << 32); \ +#define FAULT_THROW(fault,error) { \ + if(cpustate->is_report_exception) { \ + cpustate->exception_code = (UINT64)(fault | (UINT64)error << 32); \ + cpustate->exception_pc = cpustate->prev_pc; \ + cpustate->exception_caused = 1; \ + } \ + /*logerror("FAULT_THROW(%s , %s)\n", #fault , #error );*/ \ + throw (UINT64)(fault | (UINT64)error << 32); \ } #if 0 -- 2.11.0