|
|
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.22 root 64: /* 2015/02/01 [NP] When using the new WinUAE's cpu, don't handle MFP/DSP interrupts by calling */
65: /* directly Exception(), we must set bit 6 in pendingInterrupts and use the IACK */
66: /* sequence to get the exception's vector number. */
67: /* 2015/02/05 [NP] For the new WinUAE's cpu, don't use ExceptionSource anymore when calling */
68: /* Exception(). */
69: /* 2015/02/11 [NP] Replace BusErrorPC by regs.instruction_pc, to get similar code to WinUAE's cpu */
1.1.1.23 root 70: /* 2015/10/08 [NP] Add M68000_AddCycles_CE() to handle cycles when running with WinUAE's cpu in */
71: /* 'cycle exact' mode. In that case, instruction pairing don't have to be handled */
72: /* with some tables/heuristics anymore. */
1.1.1.22 root 73:
1.1.1.12 root 74:
1.1.1.14 root 75: const char M68000_fileid[] = "Hatari m68000.c : " __DATE__ " " __TIME__;
1.1 root 76:
77: #include "main.h"
1.1.1.12 root 78: #include "configuration.h"
1.1 root 79: #include "gemdos.h"
1.1.1.6 root 80: #include "hatari-glue.h"
1.1.1.16 root 81: #include "cycInt.h"
1.1 root 82: #include "m68000.h"
83: #include "memorySnapShot.h"
84: #include "mfp.h"
1.1.1.12 root 85: #include "options.h"
86: #include "savestate.h"
1.1 root 87: #include "stMemory.h"
88: #include "tos.h"
1.1.1.23 root 89: #include "falcon/crossbar.h"
1.1.1.25! root 90: #include "cart.h"
1.1 root 91:
1.1.1.22 root 92: #if ENABLE_DSP_EMU
93: #include "dsp.h"
94: #endif
95:
1.1.1.20 root 96: #if ENABLE_WINUAE_CPU
97: #include "mmu_common.h"
98: #endif
99:
100: /* information about current CPU instruction */
101: cpu_instruction_t CpuInstruction;
1.1 root 102:
1.1.1.23 root 103: Uint32 BusErrorAddress; /* Stores the offending address for bus-/address errors */
104: bool bBusErrorReadWrite; /* 0 for write error, 1 for read error */
105: int nCpuFreqShift; /* Used to emulate higher CPU frequencies: 0=8MHz, 1=16MHz, 2=32Mhz */
106: int WaitStateCycles = 0; /* Used to emulate the wait state cycles of certain IO registers */
1.1.1.14 root 107: int BusMode = BUS_MODE_CPU; /* Used to tell which part is owning the bus (cpu, blitter, ...) */
1.1.1.20 root 108: bool CPU_IACK = false; /* Set to true during an exception when getting the interrupt's vector number */
1.1.1.25! root 109: static bool M68000_DebuggerFlag;/* Is debugger enabled or not ? */
1.1.1.12 root 110:
1.1.1.16 root 111: int LastOpcodeFamily = i_NOP; /* see the enum in readcpu.h i_XXX */
112: int LastInstrCycles = 0; /* number of cycles for previous instr. (not rounded to 4) */
113: int Pairing = 0; /* set to 1 if the latest 2 intr paired */
1.1.1.12 root 114: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ];
115:
116:
117: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */
118: const char *OpcodeName[] = { "ILLG",
119: "OR","AND","EOR","ORSR","ANDSR","EORSR",
120: "SUB","SUBA","SUBX","SBCD",
121: "ADD","ADDA","ADDX","ABCD",
122: "NEG","NEGX","NBCD","CLR","NOT","TST",
123: "BTST","BCHG","BCLR","BSET",
124: "CMP","CMPM","CMPA",
125: "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR",
126: "SWAP","EXG","EXT","MVMEL","MVMLE",
127: "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD",
128: "LINK","UNLK",
129: "RTS","TRAPV","RTR",
130: "JSR","JMP","BSR","Bcc",
131: "LEA","PEA","DBcc","Scc",
132: "DIVU","DIVS","MULU","MULS",
133: "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR",
134: "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW",
135: "CHK","CHK2",
136: "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL",
137: "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS",
138: "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES",
139: "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE",
140: "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16",
141: "MMUOP"
142: };
1.1.1.8 root 143:
1.1.1.12 root 144:
145: /*-----------------------------------------------------------------------*/
146: /**
1.1.1.13 root 147: * Add pairing between all the bit shifting instructions and a given Opcode
148: */
149:
150: static void M68000_InitPairing_BitShift ( int OpCode )
151: {
152: PairingArray[ i_ASR ][ OpCode ] = 1;
153: PairingArray[ i_ASL ][ OpCode ] = 1;
154: PairingArray[ i_LSR ][ OpCode ] = 1;
155: PairingArray[ i_LSL ][ OpCode ] = 1;
156: PairingArray[ i_ROL ][ OpCode ] = 1;
157: PairingArray[ i_ROR ][ OpCode ] = 1;
158: PairingArray[ i_ROXR ][ OpCode ] = 1;
159: PairingArray[ i_ROXL ][ OpCode ] = 1;
160: }
161:
162:
163: /**
1.1.1.12 root 164: * Init the pairing matrix
165: * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1
166: */
1.1.1.16 root 167: static void M68000_InitPairing(void)
1.1.1.12 root 168: {
169: /* First, clear the matrix (pairing is false) */
170: memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY);
171:
172: /* Set all valid pairing combinations to 1 */
173: PairingArray[ i_EXG ][ i_DBcc ] = 1;
1.1.1.13 root 174: PairingArray[ i_EXG ][ i_MOVE ] = 1;
175: PairingArray[ i_EXG ][ i_MOVEA] = 1;
176:
1.1.1.12 root 177: PairingArray[ i_CMPA ][ i_Bcc ] = 1;
178: PairingArray[ i_CMP ][ i_Bcc ] = 1;
1.1.1.13 root 179:
180: M68000_InitPairing_BitShift ( i_DBcc );
181: M68000_InitPairing_BitShift ( i_MOVE );
182: M68000_InitPairing_BitShift ( i_MOVEA );
183: M68000_InitPairing_BitShift ( i_LEA );
1.1.1.17 root 184: M68000_InitPairing_BitShift ( i_JMP );
1.1.1.13 root 185:
1.1.1.12 root 186: PairingArray[ i_MULU ][ i_MOVEA] = 1;
187: PairingArray[ i_MULS ][ i_MOVEA] = 1;
188: PairingArray[ i_MULU ][ i_MOVE ] = 1;
189: PairingArray[ i_MULS ][ i_MOVE ] = 1;
1.1.1.13 root 190:
191: PairingArray[ i_MULU ][ i_DIVU ] = 1;
192: PairingArray[ i_MULU ][ i_DIVS ] = 1;
193: PairingArray[ i_MULS ][ i_DIVU ] = 1;
194: PairingArray[ i_MULS ][ i_DIVS ] = 1;
195:
1.1.1.18 root 196: PairingArray[ i_MULU ][ i_JSR ] = 1;
197: PairingArray[ i_MULS ][ i_JSR ] = 1;
198:
1.1.1.13 root 199: PairingArray[ i_BTST ][ i_Bcc ] = 1;
200:
201: M68000_InitPairing_BitShift ( i_ADD );
202: M68000_InitPairing_BitShift ( i_SUB );
203: M68000_InitPairing_BitShift ( i_OR );
204: M68000_InitPairing_BitShift ( i_AND );
205: M68000_InitPairing_BitShift ( i_EOR );
206: M68000_InitPairing_BitShift ( i_NOT );
207: M68000_InitPairing_BitShift ( i_CLR );
208: M68000_InitPairing_BitShift ( i_NEG );
209: M68000_InitPairing_BitShift ( i_ADDX );
210: M68000_InitPairing_BitShift ( i_SUBX );
211: M68000_InitPairing_BitShift ( i_ABCD );
212: M68000_InitPairing_BitShift ( i_SBCD );
1.1.1.16 root 213:
214: PairingArray[ i_ADD ][ i_MOVE ] = 1; /* when using xx(an,dn) addr mode */
215: PairingArray[ i_SUB ][ i_MOVE ] = 1;
1.1.1.22 root 216:
217: PairingArray[ i_ABCD ][ i_DBcc ] = 1;
218: PairingArray[ i_SBCD ][ i_DBcc ] = 1;
1.1.1.16 root 219: }
220:
221:
222: /**
223: * One-time CPU initialization.
224: */
225: void M68000_Init(void)
226: {
227: /* Init UAE CPU core */
228: Init680x0();
229:
230: /* Init the pairing matrix */
231: M68000_InitPairing();
1.1.1.12 root 232: }
1.1 root 233:
234:
1.1.1.3 root 235: /*-----------------------------------------------------------------------*/
1.1.1.12 root 236: /**
237: * Reset CPU 68000 variables
238: */
1.1.1.13 root 239: void M68000_Reset(bool bCold)
1.1 root 240: {
1.1.1.25! root 241: //fprintf ( stderr,"M68000_Reset in cold=%d" , bCold );
1.1.1.19 root 242: #if ENABLE_WINUAE_CPU
1.1.1.25! root 243: UAE_Set_Quit_Reset ( bCold );
! 244: set_special(SPCFLAG_MODE_CHANGE); /* exit m68k_run_xxx() loop and check for cpu changes / reset / quit */
1.1.1.22 root 245:
1.1.1.19 root 246: #else /* UAE CPU core */
247: if (bCold)
248: {
249: /* Clear registers */
250: memset(®s, 0, sizeof(regs));
251: }
252: /* Now reset the UAE CPU core */
1.1.1.12 root 253: m68k_reset();
1.1.1.25! root 254: Cart_PatchCpuTables();
1.1.1.17 root 255: #endif
1.1.1.25! root 256:
1.1.1.14 root 257: BusMode = BUS_MODE_CPU;
1.1.1.20 root 258: CPU_IACK = false;
1.1.1.25! root 259: //fprintf ( stderr,"M68000_Reset out cold=%d\n" , bCold );
! 260: }
! 261:
! 262:
! 263: /*-----------------------------------------------------------------------*/
! 264: /**
! 265: * Enable/disable breakpoints in the debugger
! 266: */
! 267: void M68000_SetDebugger(bool debug)
! 268: {
! 269: M68000_DebuggerFlag = debug;
! 270:
! 271: if ( debug )
! 272: M68000_SetSpecial(SPCFLAG_DEBUGGER);
! 273: else
! 274: M68000_UnsetSpecial(SPCFLAG_DEBUGGER);
1.1.1.12 root 275: }
276:
277:
278: /*-----------------------------------------------------------------------*/
279: /**
1.1.1.25! root 280: * Restore debugger state (breakpoints)
! 281: * This is called from CPU core after a reset, because CPU core clears regs.spcflags
! 282: */
! 283: void M68000_RestoreDebugger(void)
! 284: {
! 285: if ( M68000_DebuggerFlag )
! 286: M68000_SetSpecial(SPCFLAG_DEBUGGER);
! 287: else
! 288: M68000_UnsetSpecial(SPCFLAG_DEBUGGER);
! 289: }
! 290:
! 291:
! 292:
! 293: /*-----------------------------------------------------------------------*/
! 294: /**
1.1.1.16 root 295: * Start 680x0 emulation
1.1.1.12 root 296: */
297: void M68000_Start(void)
298: {
1.1.1.25! root 299: //fprintf (stderr, "M68000_Start\n" );
! 300:
1.1.1.12 root 301: /* Load initial memory snapshot */
302: if (bLoadMemorySave)
303: {
1.1.1.15 root 304: MemorySnapShot_Restore(ConfigureParams.Memory.szMemoryCaptureFileName, false);
1.1.1.12 root 305: }
306: else if (bLoadAutoSave)
307: {
1.1.1.15 root 308: MemorySnapShot_Restore(ConfigureParams.Memory.szAutoSaveFileName, false);
1.1.1.12 root 309: }
1.1.1.7 root 310:
1.1.1.25! root 311: #if ENABLE_WINUAE_CPU
! 312: UAE_Set_Quit_Reset ( false );
1.1.1.15 root 313: m68k_go(true);
1.1.1.25! root 314: #else
! 315: m68k_go(true);
! 316: #endif
1.1 root 317: }
318:
1.1.1.3 root 319:
320: /*-----------------------------------------------------------------------*/
1.1.1.12 root 321: /**
1.1.1.17 root 322: * Check whether CPU settings have been changed.
1.1.1.22 root 323: * Possible values for WinUAE :
324: * cpu_model : 68000 , 68010, 68020, 68030, 68040, 68060
325: * cpu_level : not used anymore
326: * cpu_compatible : 0/false (no prefetch for 68000/20/30) 1/true (prefetch opcode for 68000/20/30)
327: * cpu_cycle_exact : 0/false 1/true (most accurate, implies cpu_compatible)
1.1.1.24 root 328: * cpu_memory_cycle_exact : 0/false 1/true (less accurate than cpu_cycle_exact)
329: * cpu_data_cache : 0/false (don't emulate caches) 1/true (emulate instr/data caches for 68020/30/40/60)
1.1.1.22 root 330: * address_space_24 : 1 (68000/10 and 68030 LC for Falcon), 0 (68020/30/40/60)
331: * fpu_model : 0, 68881 (external), 68882 (external), 68040 (cpu) , 68060 (cpu)
332: * fpu_strict : true/false (more accurate rounding)
1.1.1.25! root 333: * fpu_mode : 0 faster but less accurate, use host's cpu/fpu with 64 bit precision)
! 334: * 1 most accurate but slower, use softfloat library)
! 335: * -1 similar to 0 but with extended 80 bit precision, only for x86 CPU)
! 336: * (TODO [NP] not in Hatari for now, require fpp_native_msvc_80bit.cpp / fpux64_80.asm / fpux86_80.asm)
1.1.1.22 root 337: * mmu_model : 0, 68030, 68040, 68060
338: *
339: * m68k_speed : -1=don't adjust cycle >=0 use m68k_speed_throttle to precisely adjust cycles
340: * m68k_speed_throttle : if not 0, used to set cycles_mult. In Hatari, set it to 0
341: * cpu_frequency : in CE mode, fine control of cpu freq, set it to freq/2. Not used in Hatari, set it to 0.
342: * cpu_clock_multiplier : used to speed up/slow down clock by multiple of 2 in CE mode. In Hatari
343: * we use nCpuFreqShift, so this should always be set to 2<<8 = 512 to get the same
344: * cpucycleunit as in non CE mode.
1.1.1.23 root 345: * cachesize : size of cache in MB when using JIT. Not used in Hatari at the moment, set it to 0
1.1.1.12 root 346: */
1.1.1.17 root 347: void M68000_CheckCpuSettings(void)
1.1.1.12 root 348: {
1.1.1.25! root 349: //fprintf ( stderr,"M68000_CheckCpuSettings in\n" );
1.1.1.12 root 350: changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel;
1.1.1.17 root 351:
352: #if ENABLE_WINUAE_CPU
1.1.1.19 root 353: /* WinUAE core uses cpu_model instead of cpu_level, so we've got to
354: * convert these values here: */
1.1.1.17 root 355: switch (changed_prefs.cpu_level) {
356: case 0 : changed_prefs.cpu_model = 68000; break;
357: case 1 : changed_prefs.cpu_model = 68010; break;
358: case 2 : changed_prefs.cpu_model = 68020; break;
359: case 3 : changed_prefs.cpu_model = 68030; break;
360: case 4 : changed_prefs.cpu_model = 68040; break;
361: case 5 : changed_prefs.cpu_model = 68060; break;
1.1.1.25! root 362: default: fprintf (stderr, "M68000_CheckCpuSettings() : Error, cpu_level unknown\n");
1.1.1.17 root 363: }
1.1.1.25! root 364: currprefs.cpu_level = changed_prefs.cpu_level; /* TODO remove, not used anymore */
1.1.1.17 root 365:
1.1.1.24 root 366: /* Only 68040/60 can have 'internal' FPU */
367: if ( ( ConfigureParams.System.n_FPUType == FPU_CPU ) && ( changed_prefs.cpu_model < 68040 ) )
368: ConfigureParams.System.n_FPUType = FPU_NONE;
369:
370: /* 68000/10 can't have an FPU */
371: if ( ( ConfigureParams.System.n_FPUType != FPU_NONE ) && ( changed_prefs.cpu_model < 68020 ) )
372: {
373: Log_Printf(LOG_WARN, "FPU is not supported in 68000/010 configurations, disabling FPU\n");
374: ConfigureParams.System.n_FPUType = FPU_NONE;
375: }
376:
1.1.1.25! root 377: changed_prefs.int_no_unimplemented = true;
! 378: changed_prefs.fpu_no_unimplemented = true;
! 379: changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
1.1.1.17 root 380: changed_prefs.cpu_cycle_exact = ConfigureParams.System.bCycleExactCpu;
1.1.1.23 root 381: changed_prefs.cpu_memory_cycle_exact = ConfigureParams.System.bCycleExactCpu;
1.1.1.25! root 382: changed_prefs.address_space_24 = ConfigureParams.System.bAddressSpace24;
1.1.1.17 root 383: changed_prefs.fpu_model = ConfigureParams.System.n_FPUType;
384: changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU;
1.1.1.25! root 385: changed_prefs.fpu_mode = ( ConfigureParams.System.bSoftFloatFPU ? 1 : 0 );
1.1.1.22 root 386:
387: /* Update the MMU model by taking the same value as CPU model */
388: /* MMU is only supported for CPU >=68030, this is later checked in custom.c fixup_cpu() */
389: if ( !ConfigureParams.System.bMMU )
390: changed_prefs.mmu_model = 0; /* MMU disabled */
391: else
392: changed_prefs.mmu_model = changed_prefs.cpu_model; /* MMU enabled */
393:
1.1.1.25! root 394: /* Set cpu speed to default values (only used in WinUAE, not in Hatari) */
! 395: changed_prefs.m68k_speed = 0;
! 396: changed_prefs.cpu_clock_multiplier = 2 << 8;
1.1.1.22 root 397:
1.1.1.23 root 398: /* We don't use JIT */
1.1.1.25! root 399: changed_prefs.cachesize = 0;
1.1.1.24 root 400:
401: /* Always emulate instr/data caches for cpu >= 68020 */
1.1.1.25! root 402: /* Cache emulation requires cpu_compatible or cpu_cycle_exact mode */
! 403: if ( ( changed_prefs.cpu_model < 68020 ) ||
! 404: ( ( changed_prefs.cpu_compatible == false ) && ( changed_prefs.cpu_cycle_exact == false ) ) )
! 405: changed_prefs.cpu_data_cache = false;
! 406: else
! 407: changed_prefs.cpu_data_cache = true;
! 408:
! 409: /* Update SPCFLAG_MODE_CHANGE flag if needed */
! 410: check_prefs_changed_cpu();
! 411:
1.1.1.22 root 412: #else
1.1.1.23 root 413: if (ConfigureParams.System.nCpuLevel > 4)
414: ConfigureParams.System.nCpuLevel = 4;
415:
1.1.1.25! root 416: changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
1.1.1.22 root 417: changed_prefs.cpu_cycle_exact = 0; /* With old UAE CPU, cycle_exact is always false */
418:
1.1.1.12 root 419: if (table68k)
420: check_prefs_changed_cpu();
1.1.1.25! root 421: #endif
! 422: //fprintf ( stderr, "M68000_CheckCpuSettings out\n" );
1.1.1.12 root 423: }
424:
425:
426: /*-----------------------------------------------------------------------*/
427: /**
428: * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type)
429: */
1.1.1.13 root 430: void M68000_MemorySnapShot_Capture(bool bSave)
1.1 root 431: {
1.1.1.17 root 432: #if ENABLE_WINUAE_CPU
433: int len;
1.1.1.22 root 434: uae_u8 chunk[ 1000 ];
435:
1.1.1.25! root 436: MemorySnapShot_Store(&pendingInterrupts, sizeof(pendingInterrupts)); /* for intlev() */
! 437:
1.1.1.22 root 438: if (bSave)
439: {
440: //m68k_dumpstate_file(stderr, NULL);
441: save_cpu (&len,chunk);
442: //printf ( "save cpu done\n" );
443: save_cpu_extra (&len,chunk);
444: //printf ( "save cpux done\n" );
445: save_fpu (&len,chunk);
446: //printf ( "save fpu done\n" );
447: save_mmu (&len,chunk);
448: //printf ( "save mmu done\n" );
449: //m68k_dumpstate_file(stderr, NULL);
450: }
451: else
452: {
453: //m68k_dumpstate_file(stderr, NULL);
454: restore_cpu (chunk);
455: //printf ( "restore cpu done\n" );
456: restore_cpu_extra (chunk);
457: //printf ( "restore cpux done\n" );
458: restore_fpu (chunk);
459: //printf ( "restore fpu done\n" );
460: restore_mmu (chunk);
461: //printf ( "restore mmu done\n" );
462: //m68k_dumpstate_file(stderr, NULL);
463: }
464:
465: #else /* UAE CPU core */
466: Uint32 savepc;
1.1 root 467:
1.1.1.12 root 468: /* For the UAE CPU core: */
1.1.1.25! root 469: MemorySnapShot_Store(&pendingInterrupts, sizeof(pendingInterrupts)); /* for intlev() */
! 470:
1.1.1.12 root 471: MemorySnapShot_Store(&currprefs.address_space_24,
472: sizeof(currprefs.address_space_24));
473: MemorySnapShot_Store(®s.regs[0], sizeof(regs.regs)); /* D0-D7 A0-A6 */
474:
475: if (bSave)
476: {
477: savepc = M68000_GetPC();
478: MemorySnapShot_Store(&savepc, sizeof(savepc)); /* PC */
479: }
480: else
481: {
482: MemorySnapShot_Store(&savepc, sizeof(savepc)); /* PC */
483: regs.pc = savepc;
484: regs.prefetch_pc = regs.pc + 128;
485: }
1.1.1.8 root 486:
1.1.1.12 root 487: MemorySnapShot_Store(®s.prefetch, sizeof(regs.prefetch)); /* prefetch */
488:
489: if (bSave)
490: {
491: MakeSR();
492: if (regs.s)
493: {
494: MemorySnapShot_Store(®s.usp, sizeof(regs.usp)); /* USP */
495: MemorySnapShot_Store(®s.regs[15], sizeof(regs.regs[15])); /* ISP */
496: }
497: else
498: {
499: MemorySnapShot_Store(®s.regs[15], sizeof(regs.regs[15])); /* USP */
500: MemorySnapShot_Store(®s.isp, sizeof(regs.isp)); /* ISP */
501: }
502: MemorySnapShot_Store(®s.sr, sizeof(regs.sr)); /* SR/CCR */
503: }
504: else
505: {
506: MemorySnapShot_Store(®s.usp, sizeof(regs.usp));
507: MemorySnapShot_Store(®s.isp, sizeof(regs.isp));
508: MemorySnapShot_Store(®s.sr, sizeof(regs.sr));
509: }
1.1.1.22 root 510: MemorySnapShot_Store(®s.opcode, sizeof(regs.opcode));
511: MemorySnapShot_Store(®s.instruction_pc, sizeof(regs.instruction_pc));
1.1.1.12 root 512: MemorySnapShot_Store(®s.stopped, sizeof(regs.stopped));
513: MemorySnapShot_Store(®s.dfc, sizeof(regs.dfc)); /* DFC */
514: MemorySnapShot_Store(®s.sfc, sizeof(regs.sfc)); /* SFC */
515: MemorySnapShot_Store(®s.vbr, sizeof(regs.vbr)); /* VBR */
1.1.1.25! root 516: MemorySnapShot_Store(®s.caar, sizeof(regs.caar)); /* CAAR */
! 517: MemorySnapShot_Store(®s.cacr, sizeof(regs.cacr)); /* CACR */
1.1.1.12 root 518: MemorySnapShot_Store(®s.msp, sizeof(regs.msp)); /* MSP */
519:
520: if (!bSave)
521: {
1.1.1.25! root 522: Cart_PatchCpuTables();
! 523:
1.1.1.12 root 524: M68000_SetPC(regs.pc);
525: /* MakeFromSR() must not swap stack pointer */
526: regs.s = (regs.sr >> 13) & 1;
527: MakeFromSR();
528: /* set stack pointer */
529: if (regs.s)
530: m68k_areg(regs, 7) = regs.isp;
531: else
532: m68k_areg(regs, 7) = regs.usp;
533: }
534:
535: if (bSave)
536: save_fpu();
537: else
538: restore_fpu();
1.1.1.17 root 539: #endif
1.1 root 540: }
541:
542:
1.1.1.3 root 543: /*-----------------------------------------------------------------------*/
1.1.1.12 root 544: /**
1.1.1.25! root 545: * Check whether bus error reporting should be reported or not.
! 546: * We do not want to print messages when TOS is testing for available HW
! 547: * or when a program just checks for the floating point co-processor.
! 548: */
! 549: bool M68000_IsVerboseBusError(uint32_t pc, uint32_t addr)
! 550: {
! 551: const uint32_t nTosProbeAddrs[] =
! 552: {
! 553: 0xf00039, 0xff8900, 0xff8a00, 0xff8c83,
! 554: 0xff8e0d, 0xff8e09, 0xfffa40
! 555: };
! 556: const uint32_t nEmuTosProbeAddrs[] =
! 557: {
! 558: 0xf0001d, 0xf0005d, 0xf0009d, 0xf000dd, 0xff8006, 0xff8282,
! 559: 0xff8400, 0xff8701, 0xff8901, 0xff8943, 0xff8961, 0xff8c80,
! 560: 0xff8a3c, 0xff9201, 0xfffa81, 0xfffe00
! 561: };
! 562: int idx;
! 563:
! 564: if (ConfigureParams.Log.nTextLogLevel == LOG_DEBUG)
! 565: return true;
! 566:
! 567: if (ConfigureParams.System.bAddressSpace24
! 568: || (addr & 0xff000000) == 0xff000000)
! 569: {
! 570: addr &= 0xffffff;
! 571: }
! 572:
! 573: /* Program just probing for FPU? A lot of C startup code is always
! 574: * doing this, so reporting bus errors here would be annoying */
! 575: if (addr == 0xfffa42)
! 576: return false;
! 577:
! 578: /* Always report other bus errors from normal programs */
! 579: if (pc < TosAddress || pc > TosAddress + TosSize)
! 580: return true;
! 581:
! 582: for (idx = 0; idx < ARRAY_SIZE(nTosProbeAddrs); idx++)
! 583: {
! 584: if (nTosProbeAddrs[idx] == addr)
! 585: return false;
! 586: }
! 587:
! 588: if (bIsEmuTOS)
! 589: {
! 590: for (idx = 0; idx < ARRAY_SIZE(nEmuTosProbeAddrs); idx++)
! 591: {
! 592: if (nEmuTosProbeAddrs[idx] == addr)
! 593: return false;
! 594: }
! 595: }
! 596:
! 597: return true;
! 598: }
! 599:
! 600: /**
1.1.1.12 root 601: * BUSERROR - Access outside valid memory range.
1.1.1.17 root 602: * Use bRead = 0 for write errors and bRead = 1 for read errors!
1.1.1.12 root 603: */
1.1.1.22 root 604: void M68000_BusError ( Uint32 addr , int ReadWrite , int Size , int AccessType )
1.1 root 605: {
1.1.1.25! root 606: LOG_TRACE(TRACE_CPU_EXCEPTION, "Bus error %s at address $%x PC=$%x.\n",
! 607: ReadWrite ? "reading" : "writing", addr, M68000_InstrPC);
1.1.1.12 root 608:
1.1.1.22 root 609: #ifndef ENABLE_WINUAE_CPU
610: if ((regs.spcflags & SPCFLAG_BUSERROR) == 0) /* [NP] Check that the opcode has not already generated a read bus error */
1.1.1.12 root 611: {
612: BusErrorAddress = addr; /* Store for exception frame */
1.1.1.22 root 613: bBusErrorReadWrite = ReadWrite;
1.1.1.12 root 614: M68000_SetSpecial(SPCFLAG_BUSERROR); /* The exception will be done in newcpu.c */
615: }
1.1.1.22 root 616: #else
617: /* With WinUAE's cpu, on a bus error instruction will be correctly aborted before completing, */
618: /* so we don't need to check if the opcode already generated a bus error or not */
619: exception2 ( addr , ReadWrite , Size , AccessType );
620: #endif
1.1 root 621: }
622:
1.1.1.3 root 623:
624: /*-----------------------------------------------------------------------*/
1.1.1.12 root 625: /**
626: * Exception handler
627: */
1.1.1.22 root 628: void M68000_Exception(Uint32 ExceptionNr , int ExceptionSource)
1.1.1.12 root 629: {
1.1.1.22 root 630: #ifndef WINUAE_FOR_HATARI
1.1.1.16 root 631: if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC)
1.1.1.22 root 632: && (ExceptionNr>24 && ExceptionNr<32)) /* 68k autovector interrupt? */
1.1.1.12 root 633: {
634: /* Handle autovector interrupts the UAE's way
635: * (see intlev() and do_specialties() in UAE CPU core) */
636: /* In our case, this part is only called for HBL and VBL interrupts */
1.1.1.22 root 637: int intnr = ExceptionNr - 24;
1.1.1.12 root 638: pendingInterrupts |= (1 << intnr);
639: M68000_SetSpecial(SPCFLAG_INT);
640: }
1.1.1.13 root 641:
642: else /* MFP or direct CPU exceptions */
1.1.1.12 root 643: {
644: Uint16 SR;
645:
646: /* Was the CPU stopped, i.e. by a STOP instruction? */
647: if (regs.spcflags & SPCFLAG_STOP)
648: {
649: regs.stopped = 0;
650: M68000_UnsetSpecial(SPCFLAG_STOP); /* All is go,go,go! */
651: }
652:
653: /* 68k exceptions are handled by Exception() of the UAE CPU core */
1.1.1.22 root 654: Exception(ExceptionNr, m68k_getpc(), ExceptionSource);
1.1.1.12 root 655:
656: /* Set Status Register so interrupt can ONLY be stopped by another interrupt
1.1.1.22 root 657: * of higher priority */
658: if ( (ExceptionSource == M68000_EXC_SRC_INT_MFP)
659: || (ExceptionSource == M68000_EXC_SRC_INT_DSP) )
1.1.1.12 root 660: {
1.1.1.22 root 661: SR = M68000_GetSR();
662: SR = (SR&SR_CLEAR_IPL)|0x0600; /* MFP or DSP, level 6 */
663: M68000_SetSR(SR);
1.1.1.16 root 664: }
1.1.1.22 root 665: }
666:
667: #else
668: if ( ExceptionNr > 24 && ExceptionNr < 32 ) /* Level 1-7 interrupts */
669: {
670: /* In our case, this part is called for HBL, VBL and MFP/DSP interrupts */
1.1.1.23 root 671: /* For WinUAE CPU, we must call M68000_Update_intlev after changing pendingInterrupts */
672: /* (in order to call doint() and to update regs.ipl with regs.ipl_pin, else */
673: /* the exception might be delayed by one instruction in do_specialties()) */
674: pendingInterrupts |= (1 << ( ExceptionNr - 24 ));
675: M68000_Update_intlev();
1.1.1.22 root 676: }
1.1.1.12 root 677:
1.1.1.22 root 678: else /* direct CPU exceptions */
679: {
680: Exception(ExceptionNr);
1.1.1.12 root 681: }
1.1.1.22 root 682: #endif
1.1 root 683: }
684:
1.1.1.8 root 685:
1.1.1.22 root 686:
687:
688: /*-----------------------------------------------------------------------*/
689: /**
690: * Update the list of pending interrupts.
691: * Level 2 (HBL) and 4 (VBL) are only cleared when the interrupt is processed,
692: * but level 6 is shared between MFP and DSP and can be cleared by MFP or DSP
693: * before being processed.
694: * So, we need to check which IRQ are set/cleared at the same time
695: * and update level 6 accordingly : level 6 = MFP_IRQ OR DSP_IRQ
696: *
697: * [NP] NOTE : temporary case for interrupts with WinUAE CPU in cycle exact mode
698: * In CE mode, interrupt state should be updated on each subcycle of every opcode
699: * then ipl_fetch() is called in each opcode.
700: * For now, Hatari with WinUAE CPU in CE mode only evaluates the interrupt state
701: * after the end of each opcode. So we need to call ipl_fetch() ourselves at the moment.
702: */
703: void M68000_Update_intlev ( void )
704: {
705: #ifdef WINUAE_FOR_HATARI
706: Uint8 Level6_IRQ;
707:
708: #if ENABLE_DSP_EMU
709: Level6_IRQ = MFP_GetIRQ_CPU() | DSP_GetHREQ();
710: #else
711: Level6_IRQ = MFP_GetIRQ_CPU();
712: #endif
713: if ( Level6_IRQ == 1 )
714: pendingInterrupts |= (1 << 6);
715: else
716: pendingInterrupts &= ~(1 << 6);
717:
718: if ( pendingInterrupts )
719: doint();
720: else
721: M68000_UnsetSpecial ( SPCFLAG_INT | SPCFLAG_DOINT );
722:
723: /* Temporary case for WinUAE CPU in CE mode */
724: /* doint() will update regs.ipl_pin, so copy it into regs.ipl */
725: if ( ConfigureParams.System.bCycleExactCpu )
726: regs.ipl = regs.ipl_pin; /* See ipl_fetch() in cpu/cpu_prefetch.h */
727: #endif
728: }
729:
730:
731:
732:
1.1.1.8 root 733: /*-----------------------------------------------------------------------*/
1.1.1.12 root 734: /**
1.1.1.23 root 735: * There are some wait states when accessing certain hardware registers on the ST.
736: * This function simulates these wait states and add the corresponding cycles.
737: *
1.1.1.12 root 738: * [NP] with some instructions like CLR, we have a read then a write at the
739: * same location, so we may have 2 wait states (read and write) to add
1.1.1.23 root 740: * (WaitStateCycles should be reset to 0 after all the cycles were added
741: * in run_xx() in newcpu.c).
742: *
743: * - When CPU runs in cycle exact mode, wait states are added immediately.
744: * - For other less precise modes, all the wait states are cumulated and added
745: * after the instruction was processed.
1.1.1.12 root 746: */
1.1.1.23 root 747: void M68000_WaitState(int WaitCycles)
1.1.1.8 root 748: {
1.1.1.23 root 749: #ifndef WINUAE_FOR_HATARI
750: WaitStateCycles += WaitCycles; /* Cumulate all the wait states for this instruction */
1.1.1.11 root 751:
1.1.1.23 root 752: #else
753: if ( ConfigureParams.System.bCycleExactCpu )
754: currcycle += ( WaitCycles * CYCLE_UNIT / 2 ); /* Add wait states immediately to the CE cycles counter */
755: else
756: {
757: WaitStateCycles += WaitCycles; /* Cumulate all the wait states for this instruction */
758: }
759: #endif
1.1.1.8 root 760: }
1.1.1.20 root 761:
762:
763:
764: /*-----------------------------------------------------------------------*/
765: /**
766: * Some components (HBL/VBL interrupts, access to the ACIA) require an
767: * extra delay to be synchronized with the E Clock.
768: * E Clock's frequency is 1/10th of the CPU, ie 0.8 MHz in an STF/STE
769: * This delay is a multiple of 2 and will follow the pattern [ 0 8 6 4 2 ]
770: */
771: int M68000_WaitEClock ( void )
772: {
773: int CyclesToNextE;
774:
775: /* We must wait for the next multiple of 10 cycles to be synchronised with E Clock */
1.1.1.21 root 776: CyclesToNextE = 10 - CyclesGlobalClockCounter % 10;
1.1.1.20 root 777: if ( CyclesToNextE == 10 ) /* we're already synchronised with E Clock */
778: CyclesToNextE = 0;
779: return CyclesToNextE;
780: }
781:
782:
783:
1.1.1.22 root 784:
785: /*-----------------------------------------------------------------------*/
786: /**
1.1.1.23 root 787: * Some hardware registers can only be accessed on a 4 cycles boundary
788: * (shifter color regs and shifter res reg).
789: * An extra delay should be added when needed if current cycle
790: * count is not multiple of 4.
791: */
792: static void M68000_SyncCpuBus ( bool read )
793: {
794: Uint64 Cycles;
795: int CyclesToNextBus;
796:
797: if ( read )
798: Cycles = Cycles_GetClockCounterOnReadAccess();
799: else
800: Cycles = Cycles_GetClockCounterOnWriteAccess();
801:
802: CyclesToNextBus = Cycles & 3;
803: //fprintf ( stderr , "sync bus %lld %d\n" , Cycles, CyclesToNextBus );
804: if ( CyclesToNextBus != 0 )
805: {
806: //fprintf ( stderr , "sync bus wait %lld %d\n" ,Cycles, 4-CyclesToNextBus );
807: M68000_WaitState ( 4 - CyclesToNextBus );
808: }
809: }
810:
811:
812: void M68000_SyncCpuBus_OnReadAccess ( void )
813: {
814: M68000_SyncCpuBus ( true );
815: }
816:
817:
818: void M68000_SyncCpuBus_OnWriteAccess ( void )
819: {
820: M68000_SyncCpuBus ( false );
821: }
822:
823:
824:
825:
826: /*-----------------------------------------------------------------------*/
827: /**
1.1.1.22 root 828: * In case we modified the memory by accessing it directly (and bypassing
829: * the CPU's cache mechanism), we need to flush the instruction and data
830: * caches to force an update of the caches on the next accesses.
831: *
832: * [NP] NOTE : for now, flush_instr_caches and flush_dcache flush
833: * the whole caches, not just 'addr'
834: */
835: void M68000_Flush_All_Caches ( uaecptr addr , int size )
836: {
1.1.1.24 root 837: //fprintf ( stderr , "M68000_Flush_All_Caches\n" );
1.1.1.22 root 838: #ifdef WINUAE_FOR_HATARI
1.1.1.24 root 839: flush_cpu_caches(true);
840: invalidate_cpu_data_caches();
1.1.1.22 root 841: #endif
842: }
843:
844:
845: void M68000_Flush_Instr_Cache ( uaecptr addr , int size )
846: {
1.1.1.24 root 847: //fprintf ( stderr , "M68000_Flush_Instr_Cache\n" );
1.1.1.22 root 848: #ifdef WINUAE_FOR_HATARI
849: /* Instruction cache for cpu >= 68020 */
1.1.1.24 root 850: flush_cpu_caches(true);
1.1.1.22 root 851: #endif
852: }
853:
854:
855: void M68000_Flush_Data_Cache ( uaecptr addr , int size )
856: {
1.1.1.24 root 857: //fprintf ( stderr , "M68000_Flush_Data_Cache\n" );
1.1.1.22 root 858: #ifdef WINUAE_FOR_HATARI
1.1.1.24 root 859: /* Data cache for cpu >= 68030 */
860: invalidate_cpu_data_caches();
1.1.1.22 root 861: #endif
862: }
863:
864:
865:
1.1.1.23 root 866: /*-----------------------------------------------------------------------*/
867: /**
1.1.1.24 root 868: * When running in 68000 CE mode, allow to change the "do_cycles" functions
869: * in the cpu emulation depending on the blitter state.
870: * - if the blitter is not busy, we keep the 'normal' 68000 CE "do_cycles" functions
871: * - if the blitter is busy, we use a slightly slower "do_cycles" to accurately
872: * count bus accesses made by the blitter and the CPU
873: *
874: * This limits the overhead of emulating cycle exact blitter bus accesses when blitter is OFF.
875: */
876: void M68000_SetBlitter_CE ( bool state )
877: {
878: #ifdef WINUAE_FOR_HATARI
879: //fprintf ( stderr , "M68000_SetBlitter_CE state=%s\n" , state ? "on" : "off" );
880: if ( state )
881: {
882: set_x_funcs_hatari_blitter ( 1 ); /* on */
883: }
884: else
885: {
886: set_x_funcs_hatari_blitter ( 0 ); /* off */
887: }
888: #endif
889: }
890:
891:
892: /*-----------------------------------------------------------------------*/
893: /**
1.1.1.23 root 894: * On real STF/STE hardware, DMA accesses are restricted to 4 MB (video addresses,
895: * FDC, STE DMA sound) in the range 0 - $3fffff (22 bits of address)
896: * When STF/STE are expanded beyond 4 MB, some special '_FRB' cookies variables
897: * need to be set in TOS to allocate an intermediate buffer in lower 4 MB
898: * that will be used to transfer data in RAM between 4 MB and 16 MB.
899: * This buffer is needed because real HW can't access RAM beyond 4 MB.
900: *
901: * In Hatari, we allow DMA addresses to use 24 bits when RAM size is set
902: * to 8 or 16 MB. This way any program / TOS version can make use of extra
903: * RAM beyond 4 MB without requiring an intermediate buffer.
904: *
905: * But it should be noted that programs using 24 bits of DMA addresses would
906: * not work on real HW ; this is just to make RAM expansion more transparent
907: * under emulation.
908: *
909: * We return a mask for bits 16-23 :
910: * - 0x3f for compatibility with real HW and limit of 4 MB
911: * - 0xff to allow DMA addresses beyond 4 MB (or for Falcon / TT)
912: */
913: int DMA_MaskAddressHigh ( void )
914: {
915: if (Config_IsMachineTT() || Config_IsMachineFalcon())
916: return 0xff; /* Falcon / TT can access 24 bits with DMA */
917:
1.1.1.24 root 918: else if (ConfigureParams.Memory.STRamSize_KB > 4*1024) /* ST/STE with more than 4 MB */
1.1.1.23 root 919: return 0xff; /* Allow 'fake' 24 bits for DMA */
920:
921: else /* ST/STE with <= 4 MB */
922: return 0x3f; /* Limit DMA range to 22 bits (same as real HW) */
923: }
924:
925:
926:
927:
928: /*-----------------------------------------------------------------------*/
929: /**
930: * This function should be called when the cpu freq is changed, to update
931: * other components that depend on it.
932: *
933: * For now, only Falcon mode requires some updates for the crossbar
934: */
935: void M68000_ChangeCpuFreq ( void )
936: {
937: if ( Config_IsMachineFalcon() )
938: {
939: Crossbar_Recalculate_Clocks_Cycles();
940: }
941: }
1.1.1.24 root 942:
943:
944:
945:
946: /*-----------------------------------------------------------------------*/
947: /**
948: * Some CPU registers can't be read or modified directly, some additional
949: * actions are required.
950: */
951: Uint16 M68000_GetSR ( void )
952: {
953: MakeSR();
954: return regs.sr;
955: }
956:
957: void M68000_SetSR ( Uint16 v )
958: {
959: regs.sr = v;
960: MakeFromSR();
961: }
962:
963: void M68000_SetPC ( uaecptr v )
964: {
965: m68k_setpc ( v );
966: #ifdef WINUAE_FOR_HATARI
967: fill_prefetch();
968: #else
969: refill_prefetch (m68k_getpc(), 0);
970: #endif
971: }
972:
973:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.