--- hatari/src/uae-cpu/newcpu.c 2019/04/09 08:47:24 1.1.1.15 +++ hatari/src/uae-cpu/newcpu.c 2019/04/09 08:49:41 1.1.1.17 @@ -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__; @@ -117,21 +119,24 @@ const char NewCpu_fileid[] = "Hatari new #include "maccess.h" #include "memory.h" #include "newcpu.h" -#include "../includes/main.h" -#include "../includes/log.h" -#include "../includes/m68000.h" -#include "../includes/int.h" -#include "../includes/mfp.h" -#include "../includes/tos.h" -#include "../includes/vdi.h" -#include "../includes/cart.h" -#include "../includes/debugui.h" -#include "../includes/dialog.h" -#include "../includes/bios.h" -#include "../includes/xbios.h" -#include "../includes/video.h" -#include "../includes/options.h" -#include "../falcon/dsp.h" +#include "main.h" +#include "m68000.h" +#include "cycInt.h" +#include "mfp.h" +#include "tos.h" +#include "vdi.h" +#include "cart.h" +#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 @@ -158,6 +163,7 @@ int fpp_movem_next[256]; cpuop_func *cpufunctbl[65536]; int OpcodeFamily; +int BusCyclePenalty = 0; #define COUNT_INSTRS 0 @@ -836,25 +842,26 @@ 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_EXCEPTION_SRC_INT_MFP ) + 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; } } - + if (bBiosIntercept) { /* Intercept BIOS or XBIOS trap (Trap #13 or #14) */ @@ -886,7 +893,8 @@ void Exception(int nr, uaecptr oldpc, in /* Build additional exception stack frame for 68010 and higher */ /* (special case for MFP) */ if (currprefs.cpu_level > 0) { - if (ExceptionSource == M68000_EXCEPTION_SRC_INT_MFP) { + if (ExceptionSource == M68000_EXC_SRC_INT_MFP + || ExceptionSource == M68000_EXC_SRC_INT_DSP) { m68k_areg(regs, 7) -= 2; put_word (m68k_areg(regs, 7), nr * 4); /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */ } @@ -933,7 +941,7 @@ void Exception(int nr, uaecptr oldpc, in nr, currpc, BusErrorPC, get_long (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3); /* 68000 bus/address errors: */ - if (currprefs.cpu_level==0 && (nr==2 || nr==3) && (ExceptionSource != M68000_EXCEPTION_SRC_INT_MFP) ) { + if (currprefs.cpu_level==0 && (nr==2 || nr==3) && ExceptionSource == M68000_EXC_SRC_CPU) { uae_u16 specialstatus = 1; /* Special status word emulation isn't perfect yet... :-( */ @@ -961,7 +969,7 @@ void Exception(int nr, uaecptr oldpc, in /* [NP] PC stored in the stack frame is not necessarily pointing to the next instruction ! */ /* FIXME : we should have a proper model for this, in the meantime we handle specific cases */ - if ( get_word(BusErrorPC) == 0x21f8 ) /* move.l $0.w,$24.w (Transbeauce 2 loader) */ + if ( get_word(BusErrorPC) == 0x21f8 ) /* move.l $0.w,$24.w (Transbeauce 2 loader) */ put_long (m68k_areg(regs, 7)+10, currpc-2); /* correct PC is 2 bytes less than usual value */ /* Check for double bus errors: */ if (regs.spcflags & SPCFLAG_BUSERROR) { @@ -971,7 +979,7 @@ void Exception(int nr, uaecptr oldpc, in if (bExceptionDebugging) DebugUI(); 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; @@ -988,13 +996,29 @@ void Exception(int nr, uaecptr oldpc, in write_log("Uninitialized exception handler #%i!\n", nr); DebugUI(); } + 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(); + } + 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 */ exception_trace (nr); /* Handle exception cycles (special case for MFP) */ - if ( ExceptionSource == M68000_EXCEPTION_SRC_INT_MFP ) + if (ExceptionSource == M68000_EXC_SRC_INT_MFP) { M68000_AddCycles(44+12); /* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */ } @@ -1032,7 +1056,7 @@ void Exception(int nr, uaecptr oldpc, in if(nr < 64) M68000_AddCycles(4); /* Coprocessor and unassigned exceptions (???) */ else - M68000_AddCycles(44+12); /* Must be a MFP interrupt, should be processed above */ + M68000_AddCycles(44+12); /* Must be a MFP or DSP interrupt */ break; } @@ -1045,10 +1069,8 @@ static void Interrupt(int nr , int Pendi /*lastint_regs = regs;*/ /*lastint_no = nr;*/ - /* [NP] On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */ - /* TODO : to be really precise, we should use a global variable to store the last ExceptionSource */ - /* passed to M68000_Exception, instead of hardcoding M68000_EXCEPTION_SRC_INT_VIDEO here */ - Exception(nr+24, 0, M68000_EXCEPTION_SRC_INT_VIDEO); + /* On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */ + Exception(nr+24, 0, M68000_EXC_SRC_AUTOVEC); regs.intmask = nr; set_special (SPCFLAG_INT); @@ -1096,7 +1118,17 @@ int m68k_move2c (int regno, uae_u32 *reg switch (regno) { case 0: regs.sfc = *regp & 7; break; case 1: regs.dfc = *regp & 7; break; - case 2: cacr = *regp & (currprefs.cpu_level < 4 ? 0x3 : 0x80008000); break; + case 2: + { + uae_u32 cacr_mask = 0; + if (currprefs.cpu_level == 2) // 68020 + cacr_mask = 0x0000000f; + else if (currprefs.cpu_level == 3) // Fake 68030 + cacr_mask = 0x00003f1f; + else if (currprefs.cpu_level == 4) // 68040 + cacr_mask = 0x80008000; + cacr = *regp & cacr_mask; + } case 3: tc = *regp & 0xc000; break; /* Mask out fields that should be zero. */ case 4: itt0 = *regp & 0xffffe364; break; @@ -1180,7 +1212,7 @@ void m68k_divl (uae_u32 opcode, uae_u32 { #if defined(uae_s64) if (src == 0) { - Exception (5, oldpc,M68000_EXCEPTION_SRC_CPU); + Exception (5, oldpc,M68000_EXC_SRC_CPU); return; } if (extra & 0x800) { @@ -1235,7 +1267,7 @@ void m68k_divl (uae_u32 opcode, uae_u32 } #else if (src == 0) { - Exception (5, oldpc,M68000_EXCEPTION_SRC_CPU); + Exception (5, oldpc,M68000_EXC_SRC_CPU); return; } if (extra & 0x800) { @@ -1416,7 +1448,7 @@ void m68k_reset (void) SET_CFLG (0); SET_VFLG (0); SET_NFLG (0); - regs.spcflags &= SPCFLAG_MODE_CHANGE; /* Clear specialflags except mode-change */ + regs.spcflags &= ( SPCFLAG_MODE_CHANGE | SPCFLAG_DEBUGGER ); /* Clear specialflags except mode-change and debugger */ regs.intmask = 7; regs.vbr = regs.sfc = regs.dfc = 0; regs.fpcr = regs.fpsr = regs.fpiar = 0; @@ -1433,17 +1465,17 @@ unsigned long REGPARAM2 op_illg (uae_u32 uaecptr pc = m68k_getpc (); #endif if ((opcode & 0xF000) == 0xF000) { - Exception(0xB,0,M68000_EXCEPTION_SRC_CPU); + Exception(0xB,0,M68000_EXC_SRC_CPU); return 4; } if ((opcode & 0xF000) == 0xA000) { - Exception(0xA,0,M68000_EXCEPTION_SRC_CPU); + Exception(0xA,0,M68000_EXC_SRC_CPU); return 4; } #if 0 write_log ("Illegal instruction: %04x at %08lx\n", opcode, (long)pc); #endif - Exception (4,0,M68000_EXCEPTION_SRC_CPU); + Exception (4,0,M68000_EXC_SRC_CPU); return 4; } @@ -1535,7 +1567,7 @@ static int do_specialties (void) * functions since the PC should point to the address of the next * instruction, so we're executing the bus errors here: */ unset_special(SPCFLAG_BUSERROR); - Exception(2,0,M68000_EXCEPTION_SRC_CPU); + Exception(2,0,M68000_EXC_SRC_CPU); } if(regs.spcflags & SPCFLAG_EXTRA_CYCLES) { @@ -1546,7 +1578,7 @@ static int do_specialties (void) } if (regs.spcflags & SPCFLAG_DOTRACE) { - Exception (9,last_trace_ad,M68000_EXCEPTION_SRC_CPU); + Exception (9,last_trace_ad,M68000_EXC_SRC_CPU); } @@ -1651,7 +1683,7 @@ static int do_specialties (void) #endif if (regs.spcflags & SPCFLAG_DEBUGGER) - DebugUI_CpuCheck(); + DebugCpu_Check(); if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { unset_special(SPCFLAG_MODE_CHANGE); @@ -1693,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)); */ @@ -1719,6 +1751,9 @@ 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 */ @@ -1756,7 +1791,7 @@ static void m68k_run_1 (void) /* Run DSP 56k code if necessary */ if (bDspEnabled) { - DSP_Run(cycles); + DSP_Run( Cycles_GetCounter(CYCLES_COUNTER_CPU) ); } } } @@ -1777,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)); */ @@ -1789,8 +1824,15 @@ 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) + Cycles_SetCounter(CYCLES_COUNTER_CPU, 0); /* to measure the total number of cycles spent in the cpu */ + M68000_AddCycles(cycles); if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) { /* Add some extra cycles to simulate a wait state */ @@ -1809,7 +1851,7 @@ static void m68k_run_2 (void) /* Run DSP 56k code if necessary */ if (bDspEnabled) { - DSP_Run(cycles); + DSP_Run( Cycles_GetCounter(CYCLES_COUNTER_CPU) ); } } } @@ -1853,13 +1895,13 @@ static void m68k_verify (uaecptr addr, u if (dp->suse) { if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) { - Exception (3, 0,M68000_EXCEPTION_SRC_CPU); + Exception (3, 0,M68000_EXC_SRC_CPU); return; } } if (dp->duse) { if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) { - Exception (3, 0,M68000_EXCEPTION_SRC_CPU); + Exception (3, 0,M68000_EXC_SRC_CPU); return; } }