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