--- hatari/src/uae-cpu/newcpu.c 2019/04/09 08:48:50 1.1.1.16 +++ hatari/src/uae-cpu/newcpu.c 2019/04/09 08:50:34 1.1.1.18 @@ -108,6 +108,8 @@ /* 2008/12/20 [NP] In m68k_run_1(), when checking interrupts and STOP mode, we should test */ /* PendingInterruptCount before regs.spcflags to have a faster evaluation of the */ /* 'while' condition (PendingInterruptCount <= 0 is true less often than STOP==0) */ +/* 2011/04/29 [NP] In Exception(), check the new PC is not on odd address ; raise an address error */ +/* exception if it's the case. */ const char NewCpu_fileid[] = "Hatari newcpu.c : " __DATE__ " " __TIME__; @@ -127,12 +129,14 @@ const char NewCpu_fileid[] = "Hatari new #include "dialog.h" #include "bios.h" #include "xbios.h" +#include "screen.h" #include "video.h" #include "options.h" #include "dsp.h" #include "log.h" #include "debugui.h" #include "debugcpu.h" +#include "68kDisass.h" //#define DEBUG_PREFETCH @@ -838,20 +842,21 @@ static void InterruptAddJitter (int Leve /* and get a conflict with 'normal' cpu exceptions. */ void Exception(int nr, uaecptr oldpc, int ExceptionSource) { - uae_u32 currpc = m68k_getpc (); + uae_u32 currpc = m68k_getpc () , newpc; /*if( nr>=2 && nr<10 ) fprintf(stderr,"Exception (-> %i bombs)!\n",nr);*/ - /* Intercept VDI exception (Trap #2 with D0 = 0x73) */ if (ExceptionSource == M68000_EXC_SRC_CPU) { - if(bUseVDIRes && nr == 0x22 && regs.regs[0] == 0x73) + if (bVdiAesIntercept && nr == 0x22) { - if(!VDI()) + /* Intercept VDI & AES exceptions (Trap #2) */ + if(VDI_AES_Entry()) { - /* Set 'PC' as address of 'VDI_OPCODE' illegal instruction - * This will call OpCode_VDI after completion of Trap call! - * Use to modify return structure from VDI */ + /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction. + * This will call OpCode_VDI() after completion of Trap call! + * This is used to modify specific VDI return vectors contents. + */ VDI_OldPC = currpc; currpc = CART_VDI_OPCODE_ADDR; } @@ -951,7 +956,7 @@ void Exception(int nr, uaecptr oldpc, in put_long (m68k_areg(regs, 7)+10, last_addr_for_exception_3); if (bExceptionDebugging) { fprintf(stderr,"Address Error at address $%x, PC=$%x\n",last_fault_for_exception_3,currpc); - DebugUI(); + DebugUI(REASON_CPU_EXCEPTION); } } else { /* Bus error */ @@ -972,16 +977,16 @@ void Exception(int nr, uaecptr oldpc, in BusErrorAddress, (long)currpc); unset_special(SPCFLAG_BUSERROR); if (bExceptionDebugging) - DebugUI(); + DebugUI(REASON_CPU_EXCEPTION); else - DlgAlert_Notice("Detected double bus error => CPU halted!\nEmulation needs to be reseted.\n"); + DlgAlert_Notice("Detected double bus error => CPU halted!\nEmulation needs to be reset.\n"); regs.intmask = 7; m68k_setstopped(true); return; } if (bExceptionDebugging && BusErrorAddress!=0xff8a00) { fprintf(stderr,"Bus Error at address $%x, PC=$%lx\n", BusErrorAddress, (long)currpc); - DebugUI(); + DebugUI(REASON_CPU_EXCEPTION); } } } @@ -989,8 +994,24 @@ void Exception(int nr, uaecptr oldpc, in /* Set PC and flags */ if (bExceptionDebugging && get_long (regs.vbr + 4*nr) == 0) { write_log("Uninitialized exception handler #%i!\n", nr); - DebugUI(); + DebugUI(REASON_CPU_EXCEPTION); } + newpc = get_long (regs.vbr + 4*nr); + if ( newpc & 1) /* check new pc is even */ + { + if ( nr==2 || nr==3 ) /* address error during bus/address error -> stop emulation */ + { + fprintf(stderr,"Address Error during exception 2/3, aborting new PC=$%x\n",newpc); + DebugUI(REASON_CPU_EXCEPTION); + } + else + { + fprintf(stderr,"Address Error during exception, new PC=$%x\n",newpc); + Exception ( 3 , m68k_getpc() , M68000_EXC_SRC_CPU ); + } + return; + } + m68k_setpc (get_long (regs.vbr + 4*nr)); fill_prefetch_0 (); /* Handle trace flags depending on current state */ @@ -1704,7 +1725,7 @@ static void m68k_run_1 (void) Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); - m68k_disasm(stderr, m68k_getpc (), NULL, 1); + Disasm(stderr, m68k_getpc (), NULL, 1, DISASM_ENGINE_EXT); } /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */ @@ -1720,6 +1741,9 @@ static void m68k_run_1 (void) /* the error to build the exception stack frame */ BusErrorPC = m68k_getpc(); + if (bDspEnabled) + Cycles_SetCounter(CYCLES_COUNTER_CPU, 0); /* to measure the total number of cycles spent in the cpu */ + cycles = (*cpufunctbl[opcode])(opcode); #ifdef DEBUG_PREFETCH @@ -1730,9 +1754,6 @@ static void m68k_run_1 (void) } #endif - if (bDspEnabled) - Cycles_SetCounter(CYCLES_COUNTER_CPU, 0); /* to measure the total number of cycles spent in the cpu */ - M68000_AddCyclesWithPairing(cycles); if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) { /* Add some extra cycles to simulate a wait state */ @@ -1770,7 +1791,7 @@ static void m68k_run_1 (void) /* Run DSP 56k code if necessary */ if (bDspEnabled) { - DSP_Run( Cycles_GetCounter(CYCLES_COUNTER_CPU) ); + DSP_Run( Cycles_GetCounter(CYCLES_COUNTER_CPU) * 2); } } } @@ -1791,7 +1812,7 @@ static void m68k_run_2 (void) Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles ); LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo ); - m68k_disasm(stderr, m68k_getpc (), NULL, 1); + Disasm(stderr, m68k_getpc (), NULL, 1, DISASM_ENGINE_EXT); } /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */ @@ -1803,6 +1824,10 @@ static void m68k_run_2 (void) instrcount[opcode]++; #endif + /* In case of a Bus Error, we need the PC of the instruction that caused */ + /* the error to build the exception stack frame */ + BusErrorPC = m68k_getpc(); + cycles = (*cpufunctbl[opcode])(opcode); if (bDspEnabled)