|
|
1.1 root 1: /* 1.1.1.6 root 2: Hatari - m68000.c 1.1 root 3: 1.1.1.20! root 4: This file is distributed under the GNU General Public License, version 2 ! 5: or at your option any later version. Read the file gpl.txt for details. 1.1.1.6 root 6: 7: These routines originally (in WinSTon) handled exceptions as well as some 1.1.1.5 root 8: few OpCode's such as Line-F and Line-A. In Hatari it has mainly become a 9: wrapper between the WinSTon sources and the UAE CPU code. 1.1 root 10: */ 1.1.1.12 root 11: 12: /* 2007/03/xx [NP] Possibility to add several wait states for the same instruction in */ 13: /* M68000_WaitState (e.g. clr.b $fa1b.w in Decade Demo Menu). */ 14: /* 2007/04/14 [NP] Add support for instruction pairing in M68000_AddCycles, using OpcodeFamily and */ 15: /* LastOpcodeFamily (No Cooper Loader, Oh Crickey ... Hidden Screen). */ 16: /* 2007/04/24 [NP] Add pairing for BCLR/Bcc. */ 17: /* 2007/09/29 [NP] Use the new int.c and INT_CONVERT_TO_INTERNAL. */ 18: /* 2007/11/26 [NP] We set BusErrorPC in m68k_run_1 instead of M68000_BusError, else the BusErrorPC */ 19: /* will not point to the opcode that generated the bus error. */ 20: /* In M68000_BusError, if we have 'move.l $0,$24', we need to generate a bus error */ 21: /* for the read, not for the write that should occur after (TransBeauce 2 Demo). */ 22: /* 2008/01/07 [NP] Function 'M68000_InitPairing' and 'PairingArray' as a lookup table for fast */ 23: /* determination of valid pairing combinations (replace lots of 'if' tests in */ 24: /* m68000.h). */ 25: /* 2008/01/25 [NP] Add pairing for LSR/MOVE (and all other bit shifting instr) (Anomaly Demo Intro)*/ 26: /* 2008/02/02 [NP] Add pairing for CMP/Bcc (Level 16 Fullscreen (1988)). */ 27: /* 2008/02/08 [NP] Add pairing for LSL/LEA (and all other bit shifting instr) (TVI 2 - The Year */ 28: /* After Demo). */ 29: /* 2008/02/11 [NP] Add pairing for MULS/MOVEA (Delirious Demo IV Loader). */ 30: /* 2008/01/25 [NP] Add pairing for LSR/MOVEA (and all other bit shifting instr) (Decade Demo Reset)*/ 1.1.1.13 root 31: /* 2008/02/16 [NP] Add pairing for MULS/DIVS (fixes e605 demo part 3). */ 1.1.1.12 root 32: /* 2008/03/08 [NP] In M68000_Exception, we need to know if the exception was triggered by an MFP */ 33: /* interrupt or by a video interrupt. In the case MFP vector base was changed in */ 34: /* fffa17 to an other value than the default $40, testing exceptionNr is not enough*/ 35: /* to correctly process the exception. For example, if vector base is set to $10 */ 36: /* then MFP Timer A will call vector stored at address $74, which would be wrongly */ 37: /* interpreted as a level 5 int (which doesn't exist on Atari and will cause an */ 1.1.1.13 root 38: /* assert to fail in intlevel()). We use InterruptSource to correctly recognize the*/ 1.1.1.12 root 39: /* MFP interrupts (fix 'Toki' end part fullscreen which sets vector base to $10). */ 1.1.1.13 root 40: /* 2008/04/14 [NP] Add pairing for BTST/Bcc (eg btst #7,d0 + bne.s label (with branch taken)). */ 41: /* 2008/04/15 [NP] As tested on a real STF : */ 42: /* - MUL/DIV can pair (but DIV/MUL can't) */ 43: /* (eg mulu d0,d0 + divs d1,d1 with d0=0 and d1=1) */ 44: /* - MUL/MOVE can pair, but not DIV/MOVE */ 45: /* - EXG/MOVE can pair (eg exg d3,d4 + move.l 0(a3,d1.w),a4) */ 46: /* - MOVE/DBcc can't pair */ 47: /* 2008/04/16 [NP] Functions 'M68000_InitPairing_BitShift' to ease code maintenance. */ 48: /* Tested on STF : add pairing between bit shift instr and ADD/SUB/OR/AND/EOR/NOT */ 49: /* CLR/NEG (certainly some more possible, haven't tested everything) */ 50: /* (fixes lsr.w #4,d4 + add.b $f0(a4,d4),d7 used in Zoolook part of ULM New Year). */ 51: /* 2008/07/08 [NP] Add pairing between bit shift instr and ADDX/SUBX/ABCD/SBCD (fixes lsl.l #1,d0 */ 52: /* + abcd d1,d1 used in Dragonnels - Rainbow Wall). */ 53: /* 2008/10/05 [NP] Pass the 'ExceptionSource' parameter to Exception() in uae-cpu/newcpu.c */ 1.1.1.16 root 54: /* 2010/05/07 [NP] Add pairing for ADD/MOVE ; such pairing should only be possible when combined */ 55: /* with d8(an,ix) address mode (eg: add.l (a5,d1.w),d0 + move.b 7(a5,d1.w),d5) */ 56: /* (fixes Sommarhack 2010 Invitation by DHS). */ 1.1.1.17 root 57: /* 2010/11/07 [NP] Add pairing between bit shift instr and JMP (fixes lsl.w #2,d0 + jmp 2(pc,d0) */ 58: /* used in Fullparts by Hemoroids). */ 1.1.1.18 root 59: /* 2011/12/11 [NP] Add pairing between MUL and JSR (fixes muls #52,d2 + jsr 0(a1,d2.w) used in */ 60: /* Lemmings Compilation 40's Intro). */ 1.1.1.12 root 61: 62: 1.1.1.14 root 63: const char M68000_fileid[] = "Hatari m68000.c : " __DATE__ " " __TIME__; 1.1 root 64: 65: #include "main.h" 1.1.1.12 root 66: #include "configuration.h" 1.1 root 67: #include "gemdos.h" 1.1.1.6 root 68: #include "hatari-glue.h" 1.1.1.16 root 69: #include "cycInt.h" 1.1 root 70: #include "m68000.h" 71: #include "memorySnapShot.h" 72: #include "mfp.h" 1.1.1.12 root 73: #include "options.h" 74: #include "savestate.h" 1.1 root 75: #include "stMemory.h" 76: #include "tos.h" 77: 1.1.1.20! root 78: #if ENABLE_WINUAE_CPU ! 79: #include "mmu_common.h" ! 80: #endif ! 81: ! 82: /* information about current CPU instruction */ ! 83: cpu_instruction_t CpuInstruction; 1.1 root 84: 1.1.1.12 root 85: Uint32 BusErrorAddress; /* Stores the offending address for bus-/address errors */ 86: Uint32 BusErrorPC; /* Value of the PC when bus error occurs */ 1.1.1.13 root 87: bool bBusErrorReadWrite; /* 0 for write error, 1 for read error */ 1.1.1.12 root 88: int nCpuFreqShift; /* Used to emulate higher CPU frequencies: 0=8MHz, 1=16MHz, 2=32Mhz */ 89: int nWaitStateCycles; /* Used to emulate the wait state cycles of certain IO registers */ 1.1.1.14 root 90: int BusMode = BUS_MODE_CPU; /* Used to tell which part is owning the bus (cpu, blitter, ...) */ 1.1.1.20! root 91: bool CPU_IACK = false; /* Set to true during an exception when getting the interrupt's vector number */ 1.1.1.12 root 92: 1.1.1.16 root 93: int LastOpcodeFamily = i_NOP; /* see the enum in readcpu.h i_XXX */ 94: int LastInstrCycles = 0; /* number of cycles for previous instr. (not rounded to 4) */ 95: int Pairing = 0; /* set to 1 if the latest 2 intr paired */ 1.1.1.12 root 96: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ]; 97: 98: 99: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */ 100: const char *OpcodeName[] = { "ILLG", 101: "OR","AND","EOR","ORSR","ANDSR","EORSR", 102: "SUB","SUBA","SUBX","SBCD", 103: "ADD","ADDA","ADDX","ABCD", 104: "NEG","NEGX","NBCD","CLR","NOT","TST", 105: "BTST","BCHG","BCLR","BSET", 106: "CMP","CMPM","CMPA", 107: "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR", 108: "SWAP","EXG","EXT","MVMEL","MVMLE", 109: "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD", 110: "LINK","UNLK", 111: "RTS","TRAPV","RTR", 112: "JSR","JMP","BSR","Bcc", 113: "LEA","PEA","DBcc","Scc", 114: "DIVU","DIVS","MULU","MULS", 115: "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR", 116: "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW", 117: "CHK","CHK2", 118: "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL", 119: "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS", 120: "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES", 121: "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE", 122: "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16", 123: "MMUOP" 124: }; 1.1.1.8 root 125: 1.1.1.12 root 126: 127: /*-----------------------------------------------------------------------*/ 128: /** 1.1.1.13 root 129: * Add pairing between all the bit shifting instructions and a given Opcode 130: */ 131: 132: static void M68000_InitPairing_BitShift ( int OpCode ) 133: { 134: PairingArray[ i_ASR ][ OpCode ] = 1; 135: PairingArray[ i_ASL ][ OpCode ] = 1; 136: PairingArray[ i_LSR ][ OpCode ] = 1; 137: PairingArray[ i_LSL ][ OpCode ] = 1; 138: PairingArray[ i_ROL ][ OpCode ] = 1; 139: PairingArray[ i_ROR ][ OpCode ] = 1; 140: PairingArray[ i_ROXR ][ OpCode ] = 1; 141: PairingArray[ i_ROXL ][ OpCode ] = 1; 142: } 143: 144: 145: /** 1.1.1.12 root 146: * Init the pairing matrix 147: * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1 148: */ 1.1.1.16 root 149: static void M68000_InitPairing(void) 1.1.1.12 root 150: { 151: /* First, clear the matrix (pairing is false) */ 152: memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY); 153: 154: /* Set all valid pairing combinations to 1 */ 155: PairingArray[ i_EXG ][ i_DBcc ] = 1; 1.1.1.13 root 156: PairingArray[ i_EXG ][ i_MOVE ] = 1; 157: PairingArray[ i_EXG ][ i_MOVEA] = 1; 158: 1.1.1.12 root 159: PairingArray[ i_CMPA ][ i_Bcc ] = 1; 160: PairingArray[ i_CMP ][ i_Bcc ] = 1; 1.1.1.13 root 161: 162: M68000_InitPairing_BitShift ( i_DBcc ); 163: M68000_InitPairing_BitShift ( i_MOVE ); 164: M68000_InitPairing_BitShift ( i_MOVEA ); 165: M68000_InitPairing_BitShift ( i_LEA ); 1.1.1.17 root 166: M68000_InitPairing_BitShift ( i_JMP ); 1.1.1.13 root 167: 1.1.1.12 root 168: PairingArray[ i_MULU ][ i_MOVEA] = 1; 169: PairingArray[ i_MULS ][ i_MOVEA] = 1; 170: PairingArray[ i_MULU ][ i_MOVE ] = 1; 171: PairingArray[ i_MULS ][ i_MOVE ] = 1; 1.1.1.13 root 172: 173: PairingArray[ i_MULU ][ i_DIVU ] = 1; 174: PairingArray[ i_MULU ][ i_DIVS ] = 1; 175: PairingArray[ i_MULS ][ i_DIVU ] = 1; 176: PairingArray[ i_MULS ][ i_DIVS ] = 1; 177: 1.1.1.18 root 178: PairingArray[ i_MULU ][ i_JSR ] = 1; 179: PairingArray[ i_MULS ][ i_JSR ] = 1; 180: 1.1.1.13 root 181: PairingArray[ i_BTST ][ i_Bcc ] = 1; 182: 183: M68000_InitPairing_BitShift ( i_ADD ); 184: M68000_InitPairing_BitShift ( i_SUB ); 185: M68000_InitPairing_BitShift ( i_OR ); 186: M68000_InitPairing_BitShift ( i_AND ); 187: M68000_InitPairing_BitShift ( i_EOR ); 188: M68000_InitPairing_BitShift ( i_NOT ); 189: M68000_InitPairing_BitShift ( i_CLR ); 190: M68000_InitPairing_BitShift ( i_NEG ); 191: M68000_InitPairing_BitShift ( i_ADDX ); 192: M68000_InitPairing_BitShift ( i_SUBX ); 193: M68000_InitPairing_BitShift ( i_ABCD ); 194: M68000_InitPairing_BitShift ( i_SBCD ); 1.1.1.16 root 195: 196: PairingArray[ i_ADD ][ i_MOVE ] = 1; /* when using xx(an,dn) addr mode */ 197: PairingArray[ i_SUB ][ i_MOVE ] = 1; 198: } 199: 200: 201: /** 202: * One-time CPU initialization. 203: */ 204: void M68000_Init(void) 205: { 206: /* Init UAE CPU core */ 207: Init680x0(); 208: 209: /* Init the pairing matrix */ 210: M68000_InitPairing(); 1.1.1.12 root 211: } 1.1 root 212: 213: 1.1.1.3 root 214: /*-----------------------------------------------------------------------*/ 1.1.1.12 root 215: /** 216: * Reset CPU 68000 variables 217: */ 1.1.1.13 root 218: void M68000_Reset(bool bCold) 1.1 root 219: { 1.1.1.19 root 220: #if ENABLE_WINUAE_CPU 1.1.1.12 root 221: if (bCold) 222: { 1.1.1.19 root 223: /* Clear registers, but we need to keep SPCFLAG_MODE_CHANGE and SPCFLAG_BRK unchanged */ 224: int spcFlags = regs.spcflags & (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK); 1.1.1.16 root 225: memset(®s, 0, sizeof(regs)); 1.1.1.19 root 226: regs.spcflags = spcFlags; 1.1.1.12 root 227: } 1.1.1.19 root 228: /* Now reset the WINUAE CPU core */ 1.1.1.20! root 229: m68k_reset(bCold); 1.1.1.19 root 230: #else /* UAE CPU core */ 231: if (bCold) 232: { 233: /* Clear registers */ 234: memset(®s, 0, sizeof(regs)); 235: } 236: /* Now reset the UAE CPU core */ 1.1.1.12 root 237: m68k_reset(); 1.1.1.17 root 238: #endif 1.1.1.14 root 239: BusMode = BUS_MODE_CPU; 1.1.1.20! root 240: CPU_IACK = false; 1.1.1.12 root 241: } 242: 243: 244: /*-----------------------------------------------------------------------*/ 245: /** 1.1.1.16 root 246: * Start 680x0 emulation 1.1.1.12 root 247: */ 248: void M68000_Start(void) 249: { 250: /* Load initial memory snapshot */ 251: if (bLoadMemorySave) 252: { 1.1.1.15 root 253: MemorySnapShot_Restore(ConfigureParams.Memory.szMemoryCaptureFileName, false); 1.1.1.12 root 254: } 255: else if (bLoadAutoSave) 256: { 1.1.1.15 root 257: MemorySnapShot_Restore(ConfigureParams.Memory.szAutoSaveFileName, false); 1.1.1.12 root 258: } 1.1.1.7 root 259: 1.1.1.15 root 260: m68k_go(true); 1.1 root 261: } 262: 1.1.1.3 root 263: 264: /*-----------------------------------------------------------------------*/ 1.1.1.12 root 265: /** 1.1.1.17 root 266: * Check whether CPU settings have been changed. 1.1.1.12 root 267: */ 1.1.1.17 root 268: void M68000_CheckCpuSettings(void) 1.1.1.12 root 269: { 1.1.1.17 root 270: if (ConfigureParams.System.nCpuFreq < 12) 271: { 272: ConfigureParams.System.nCpuFreq = 8; 273: nCpuFreqShift = 0; 274: } 275: else if (ConfigureParams.System.nCpuFreq > 26) 276: { 277: ConfigureParams.System.nCpuFreq = 32; 278: nCpuFreqShift = 2; 279: } 280: else 281: { 282: ConfigureParams.System.nCpuFreq = 16; 283: nCpuFreqShift = 1; 284: } 1.1.1.12 root 285: changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel; 286: changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu; 1.1.1.17 root 287: 288: #if ENABLE_WINUAE_CPU 1.1.1.19 root 289: /* WinUAE core uses cpu_model instead of cpu_level, so we've got to 290: * convert these values here: */ 1.1.1.17 root 291: switch (changed_prefs.cpu_level) { 292: case 0 : changed_prefs.cpu_model = 68000; break; 293: case 1 : changed_prefs.cpu_model = 68010; break; 294: case 2 : changed_prefs.cpu_model = 68020; break; 295: case 3 : changed_prefs.cpu_model = 68030; break; 296: case 4 : changed_prefs.cpu_model = 68040; break; 297: case 5 : changed_prefs.cpu_model = 68060; break; 298: default: fprintf (stderr, "Init680x0() : Error, cpu_level unknown\n"); 299: } 1.1.1.19 root 300: currprefs.cpu_level = changed_prefs.cpu_level; 1.1.1.17 root 301: 302: changed_prefs.address_space_24 = ConfigureParams.System.bAddressSpace24; 303: changed_prefs.cpu_cycle_exact = ConfigureParams.System.bCycleExactCpu; 304: changed_prefs.fpu_model = ConfigureParams.System.n_FPUType; 305: changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU; 306: changed_prefs.mmu_model = ConfigureParams.System.bMMU; 1.1.1.12 root 307: #endif 308: if (table68k) 309: check_prefs_changed_cpu(); 310: } 311: 312: 313: /*-----------------------------------------------------------------------*/ 314: /** 315: * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type) 316: */ 1.1.1.13 root 317: void M68000_MemorySnapShot_Capture(bool bSave) 1.1 root 318: { 1.1.1.12 root 319: Uint32 savepc; 1.1.1.17 root 320: #if ENABLE_WINUAE_CPU 321: int len; 322: uae_u8 *chunk = 0; 323: #endif 1.1 root 324: 1.1.1.12 root 325: /* For the UAE CPU core: */ 326: MemorySnapShot_Store(&currprefs.address_space_24, 327: sizeof(currprefs.address_space_24)); 328: MemorySnapShot_Store(®s.regs[0], sizeof(regs.regs)); /* D0-D7 A0-A6 */ 329: 330: if (bSave) 331: { 332: savepc = M68000_GetPC(); 333: MemorySnapShot_Store(&savepc, sizeof(savepc)); /* PC */ 334: } 335: else 336: { 337: MemorySnapShot_Store(&savepc, sizeof(savepc)); /* PC */ 338: regs.pc = savepc; 339: #ifdef UAE_NEWCPU_H 340: regs.prefetch_pc = regs.pc + 128; 341: #endif 342: } 1.1.1.8 root 343: 1.1.1.12 root 344: #ifdef UAE_NEWCPU_H 345: MemorySnapShot_Store(®s.prefetch, sizeof(regs.prefetch)); /* prefetch */ 346: #else 347: uae_u32 prefetch_dummy; 348: MemorySnapShot_Store(&prefetch_dummy, sizeof(prefetch_dummy)); 349: #endif 350: 351: if (bSave) 352: { 353: MakeSR(); 354: if (regs.s) 355: { 356: MemorySnapShot_Store(®s.usp, sizeof(regs.usp)); /* USP */ 357: MemorySnapShot_Store(®s.regs[15], sizeof(regs.regs[15])); /* ISP */ 358: } 359: else 360: { 361: MemorySnapShot_Store(®s.regs[15], sizeof(regs.regs[15])); /* USP */ 362: MemorySnapShot_Store(®s.isp, sizeof(regs.isp)); /* ISP */ 363: } 364: MemorySnapShot_Store(®s.sr, sizeof(regs.sr)); /* SR/CCR */ 365: } 366: else 367: { 368: MemorySnapShot_Store(®s.usp, sizeof(regs.usp)); 369: MemorySnapShot_Store(®s.isp, sizeof(regs.isp)); 370: MemorySnapShot_Store(®s.sr, sizeof(regs.sr)); 371: } 372: MemorySnapShot_Store(®s.stopped, sizeof(regs.stopped)); 373: MemorySnapShot_Store(®s.dfc, sizeof(regs.dfc)); /* DFC */ 374: MemorySnapShot_Store(®s.sfc, sizeof(regs.sfc)); /* SFC */ 375: MemorySnapShot_Store(®s.vbr, sizeof(regs.vbr)); /* VBR */ 1.1.1.17 root 376: #if ENABLE_WINUAE_CPU 377: MemorySnapShot_Store(®s.caar, sizeof(regs.caar)); /* CAAR */ 378: MemorySnapShot_Store(®s.cacr, sizeof(regs.cacr)); /* CACR */ 379: #else 1.1.1.12 root 380: MemorySnapShot_Store(&caar, sizeof(caar)); /* CAAR */ 381: MemorySnapShot_Store(&cacr, sizeof(cacr)); /* CACR */ 1.1.1.17 root 382: #endif 1.1.1.12 root 383: MemorySnapShot_Store(®s.msp, sizeof(regs.msp)); /* MSP */ 384: 385: if (!bSave) 386: { 387: M68000_SetPC(regs.pc); 388: /* MakeFromSR() must not swap stack pointer */ 389: regs.s = (regs.sr >> 13) & 1; 390: MakeFromSR(); 391: /* set stack pointer */ 392: if (regs.s) 393: m68k_areg(regs, 7) = regs.isp; 394: else 395: m68k_areg(regs, 7) = regs.usp; 396: } 397: 1.1.1.17 root 398: #if ENABLE_WINUAE_CPU 399: if (bSave) 400: save_fpu(&len,0); 401: else 402: restore_fpu(chunk); 403: #else 1.1.1.12 root 404: if (bSave) 405: save_fpu(); 406: else 407: restore_fpu(); 1.1.1.17 root 408: #endif 1.1 root 409: } 410: 411: 1.1.1.3 root 412: /*-----------------------------------------------------------------------*/ 1.1.1.12 root 413: /** 414: * BUSERROR - Access outside valid memory range. 1.1.1.17 root 415: * Use bRead = 0 for write errors and bRead = 1 for read errors! 1.1.1.12 root 416: */ 1.1.1.17 root 417: void M68000_BusError(Uint32 addr, bool bRead) 1.1 root 418: { 1.1.1.12 root 419: /* FIXME: In prefetch mode, m68k_getpc() seems already to point to the next instruction */ 420: // BusErrorPC = M68000_GetPC(); /* [NP] We set BusErrorPC in m68k_run_1 */ 1.1.1.7 root 421: 1.1.1.15 root 422: /* Do not print message when TOS is testing for available HW or 423: * when a program just checks for the floating point co-processor. */ 424: if ((BusErrorPC < TosAddress || BusErrorPC > TosAddress + TosSize) 425: && addr != 0xfffa42) 1.1.1.12 root 426: { 1.1.1.15 root 427: /* Print bus error message */ 1.1.1.17 root 428: fprintf(stderr, "M68000 Bus Error %s at address $%x.\n", 429: bRead ? "reading" : "writing", addr); 1.1.1.12 root 430: } 431: 432: if ((regs.spcflags & SPCFLAG_BUSERROR) == 0) /* [NP] Check that the opcode has not already generated a read bus error */ 433: { 434: BusErrorAddress = addr; /* Store for exception frame */ 1.1.1.17 root 435: bBusErrorReadWrite = bRead; 1.1.1.20! root 436: #if ENABLE_WINUAE_CPU ! 437: if (currprefs.mmu_model) { ! 438: THROW(2); ! 439: return; ! 440: } ! 441: #endif 1.1.1.12 root 442: M68000_SetSpecial(SPCFLAG_BUSERROR); /* The exception will be done in newcpu.c */ 443: } 1.1 root 444: } 445: 1.1.1.3 root 446: 447: /*-----------------------------------------------------------------------*/ 1.1.1.12 root 448: /** 449: * Exception handler 450: */ 1.1.1.13 root 451: void M68000_Exception(Uint32 ExceptionVector , int ExceptionSource) 1.1.1.12 root 452: { 453: int exceptionNr = ExceptionVector/4; 454: 1.1.1.16 root 455: if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC) 456: && (exceptionNr>24 && exceptionNr<32)) /* 68k autovector interrupt? */ 1.1.1.12 root 457: { 458: /* Handle autovector interrupts the UAE's way 459: * (see intlev() and do_specialties() in UAE CPU core) */ 460: /* In our case, this part is only called for HBL and VBL interrupts */ 461: int intnr = exceptionNr - 24; 462: pendingInterrupts |= (1 << intnr); 463: M68000_SetSpecial(SPCFLAG_INT); 464: } 1.1.1.13 root 465: 466: else /* MFP or direct CPU exceptions */ 1.1.1.12 root 467: { 468: Uint16 SR; 469: 470: /* Was the CPU stopped, i.e. by a STOP instruction? */ 471: if (regs.spcflags & SPCFLAG_STOP) 472: { 473: regs.stopped = 0; 474: M68000_UnsetSpecial(SPCFLAG_STOP); /* All is go,go,go! */ 475: } 476: 477: /* 68k exceptions are handled by Exception() of the UAE CPU core */ 1.1.1.17 root 478: #if ENABLE_WINUAE_CPU 479: Exception(exceptionNr, m68k_getpc(), ExceptionSource); 480: #else 1.1.1.12 root 481: #ifdef UAE_NEWCPU_H 1.1.1.13 root 482: Exception(exceptionNr, m68k_getpc(), ExceptionSource); 1.1.1.12 root 483: #else 484: Exception(exceptionNr, ®s, m68k_getpc(®s)); 485: #endif 1.1.1.17 root 486: #endif 1.1.1.12 root 487: SR = M68000_GetSR(); 488: 489: /* Set Status Register so interrupt can ONLY be stopped by another interrupt 490: * of higher priority! */ 1.1.1.16 root 491: if (ExceptionSource == M68000_EXC_SRC_INT_MFP) 1.1.1.12 root 492: { 1.1.1.20! root 493: // FIXME : this test is useless, per design mfp.c will always give an address in the correct range 1.1.1.12 root 494: Uint32 MFPBaseVector = (unsigned int)(MFP_VR&0xf0)<<2; 495: if ( (ExceptionVector>=MFPBaseVector) && (ExceptionVector<=(MFPBaseVector+0x3c)) ) 496: SR = (SR&SR_CLEAR_IPL)|0x0600; /* MFP, level 6 */ 497: } 1.1.1.16 root 498: else if (ExceptionSource == M68000_EXC_SRC_INT_DSP) 499: { 500: SR = (SR&SR_CLEAR_IPL)|0x0600; /* DSP, level 6 */ 501: } 1.1.1.12 root 502: 503: M68000_SetSR(SR); 504: } 1.1 root 505: } 506: 1.1.1.8 root 507: 508: /*-----------------------------------------------------------------------*/ 1.1.1.12 root 509: /** 510: * There seem to be wait states when a program accesses certain hardware 511: * registers on the ST. Use this function to simulate these wait states. 512: * [NP] with some instructions like CLR, we have a read then a write at the 513: * same location, so we may have 2 wait states (read and write) to add 514: * (nWaitStateCycles should be reset to 0 after the cycles were added). 515: */ 1.1.1.11 root 516: void M68000_WaitState(int nCycles) 1.1.1.8 root 517: { 1.1.1.12 root 518: M68000_SetSpecial(SPCFLAG_EXTRA_CYCLES); 1.1.1.11 root 519: 1.1.1.12 root 520: nWaitStateCycles += nCycles; /* add all the wait states for this instruction */ 1.1.1.8 root 521: } 1.1.1.20! root 522: ! 523: ! 524: ! 525: /*-----------------------------------------------------------------------*/ ! 526: /** ! 527: * Some components (HBL/VBL interrupts, access to the ACIA) require an ! 528: * extra delay to be synchronized with the E Clock. ! 529: * E Clock's frequency is 1/10th of the CPU, ie 0.8 MHz in an STF/STE ! 530: * This delay is a multiple of 2 and will follow the pattern [ 0 8 6 4 2 ] ! 531: */ ! 532: ! 533: int M68000_WaitEClock ( void ) ! 534: { ! 535: int CyclesToNextE; ! 536: ! 537: /* We must wait for the next multiple of 10 cycles to be synchronised with E Clock */ ! 538: /* FIXME : use video counter to simulate E Clock, but we should use */ ! 539: /* a global cpu counter */ ! 540: CyclesToNextE = 10 - Cycles_GetCounter(CYCLES_COUNTER_VIDEO) % 10; ! 541: if ( CyclesToNextE == 10 ) /* we're already synchronised with E Clock */ ! 542: CyclesToNextE = 0; ! 543: return CyclesToNextE; ! 544: } ! 545: ! 546: ! 547:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.