OSDN Git Service

[DEBUGGER] Add features for catching EXCEPTION/FAULT by debugger.See mame/emu/cpu...
authorK.Ohta <whatisthis.sowhat@gmail.com>
Thu, 23 May 2019 13:43:48 +0000 (22:43 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Thu, 23 May 2019 13:43:48 +0000 (22:43 +0900)
source/src/debugger.cpp
source/src/vm/common_vm/CMakeLists.txt
source/src/vm/debugger.h
source/src/vm/mame/emu/cpu/i386/i386.c
source/src/vm/mame/emu/cpu/i386/i386priv.h

index 312c2b1..cba85b9 100644 (file)
@@ -18,7 +18,8 @@
 #include "vm/vm.h"
 #include "fileio.h"
 #include <pthread.h>
-
+#include <time.h>
+#include <sys/time.h>
 #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 <reg> <value> - edit register\n"));
                                my_printf(p->osd, _T("S <range> <list> - search\n"));
                                my_printf(p->osd, _T("U [<range>] - unassemble\n"));
-                               my_printf(p->osd, _T("UT [<steps>] - unassemble trace\n"));
-                               
+                               my_printf(p->osd, _T("UT [<steps> | <steps> <logging_file>] - unassemble back trace\n"));
                                my_printf(p->osd, _T("H <value> <value> - hexadd\n"));
                                my_printf(p->osd, _T("N <filename> - name\n"));
                                my_printf(p->osd, _T("L [<range>] - load binary/hex/symbol file\n"));
                                my_printf(p->osd, _T("W <range> - 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 <address> - set breakpoint\n"));
                                my_printf(p->osd, _T("{R,W}BP <address> - set breakpoint (break at memory access)\n"));
                                my_printf(p->osd, _T("{I,O}BP <port> [<mask>] - set breakpoint (break at i/o access)\n"));
index 056b936..ef7af4e 100644 (file)
@@ -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
index b2e6f9f..2f330be 100644 (file)
@@ -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
index 7743986..a906905 100644 (file)
@@ -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) {
index 8993814..2ce710a 100644 (file)
@@ -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