|
|
1.1 root 1: /*
2: Hatari - m68000.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: */
8:
9:
10: const char M68000_fileid[] = "Hatari m68000.c : " __DATE__ " " __TIME__;
11:
12: #include "main.h"
13: #include "configuration.h"
14: #include "hatari-glue.h"
15: #include "cycInt.h"
16: #include "m68000.h"
17: #include "options.h"
18: #include "nextMemory.h"
19:
1.1.1.3 root 20: #include "mmu_common.h"
1.1 root 21:
22: Uint32 BusErrorAddress; /* Stores the offending address for bus-/address errors */
23: Uint32 BusErrorPC; /* Value of the PC when bus error occurs */
24: bool bBusErrorReadWrite; /* 0 for write error, 1 for read error */
25: int BusMode = BUS_MODE_CPU; /* Used to tell which part is owning the bus (cpu, blitter, ...) */
26:
27: int LastOpcodeFamily = i_NOP; /* see the enum in readcpu.h i_XXX */
28: int LastInstrCycles = 0; /* number of cycles for previous instr. (not rounded to 4) */
29: int Pairing = 0; /* set to 1 if the latest 2 intr paired */
30: char PairingArray[ MAX_OPCODE_FAMILY ][ MAX_OPCODE_FAMILY ];
31:
32:
33: /* to convert the enum from OpcodeFamily to a readable value for pairing's debug */
34: const char *OpcodeName[] = { "ILLG",
35: "OR","AND","EOR","ORSR","ANDSR","EORSR",
36: "SUB","SUBA","SUBX","SBCD",
37: "ADD","ADDA","ADDX","ABCD",
38: "NEG","NEGX","NBCD","CLR","NOT","TST",
39: "BTST","BCHG","BCLR","BSET",
40: "CMP","CMPM","CMPA",
41: "MVPRM","MVPMR","MOVE","MOVEA","MVSR2","MV2SR",
42: "SWAP","EXG","EXT","MVMEL","MVMLE",
43: "TRAP","MVR2USP","MVUSP2R","RESET","NOP","STOP","RTE","RTD",
44: "LINK","UNLK",
45: "RTS","TRAPV","RTR",
46: "JSR","JMP","BSR","Bcc",
47: "LEA","PEA","DBcc","Scc",
48: "DIVU","DIVS","MULU","MULS",
49: "ASR","ASL","LSR","LSL","ROL","ROR","ROXL","ROXR",
50: "ASRW","ASLW","LSRW","LSLW","ROLW","RORW","ROXLW","ROXRW",
51: "CHK","CHK2",
52: "MOVEC2","MOVE2C","CAS","CAS2","DIVL","MULL",
53: "BFTST","BFEXTU","BFCHG","BFEXTS","BFCLR","BFFFO","BFSET","BFINS",
54: "PACK","UNPK","TAS","BKPT","CALLM","RTM","TRAPcc","MOVES",
55: "FPP","FDBcc","FScc","FTRAPcc","FBcc","FSAVE","FRESTORE",
56: "CINVL","CINVP","CINVA","CPUSHL","CPUSHP","CPUSHA","MOVE16",
57: "MMUOP"
58: };
59:
60:
61: /*-----------------------------------------------------------------------*/
62: /**
63: * Add pairing between all the bit shifting instructions and a given Opcode
64: */
65:
66: static void M68000_InitPairing_BitShift ( int OpCode )
67: {
68: PairingArray[ i_ASR ][ OpCode ] = 1;
69: PairingArray[ i_ASL ][ OpCode ] = 1;
70: PairingArray[ i_LSR ][ OpCode ] = 1;
71: PairingArray[ i_LSL ][ OpCode ] = 1;
72: PairingArray[ i_ROL ][ OpCode ] = 1;
73: PairingArray[ i_ROR ][ OpCode ] = 1;
74: PairingArray[ i_ROXR ][ OpCode ] = 1;
75: PairingArray[ i_ROXL ][ OpCode ] = 1;
76: }
77:
78:
79: /**
80: * Init the pairing matrix
81: * Two instructions can pair if PairingArray[ LastOpcodeFamily ][ OpcodeFamily ] == 1
82: */
83: static void M68000_InitPairing(void)
84: {
85: /* First, clear the matrix (pairing is false) */
86: memset(PairingArray , 0 , MAX_OPCODE_FAMILY * MAX_OPCODE_FAMILY);
87:
88: /* Set all valid pairing combinations to 1 */
89: PairingArray[ i_EXG ][ i_DBcc ] = 1;
90: PairingArray[ i_EXG ][ i_MOVE ] = 1;
91: PairingArray[ i_EXG ][ i_MOVEA] = 1;
92:
93: PairingArray[ i_CMPA ][ i_Bcc ] = 1;
94: PairingArray[ i_CMP ][ i_Bcc ] = 1;
95:
96: M68000_InitPairing_BitShift ( i_DBcc );
97: M68000_InitPairing_BitShift ( i_MOVE );
98: M68000_InitPairing_BitShift ( i_MOVEA );
99: M68000_InitPairing_BitShift ( i_LEA );
1.1.1.2 root 100: M68000_InitPairing_BitShift ( i_JMP );
1.1 root 101:
102: PairingArray[ i_MULU ][ i_MOVEA] = 1;
103: PairingArray[ i_MULS ][ i_MOVEA] = 1;
104: PairingArray[ i_MULU ][ i_MOVE ] = 1;
105: PairingArray[ i_MULS ][ i_MOVE ] = 1;
106:
107: PairingArray[ i_MULU ][ i_DIVU ] = 1;
108: PairingArray[ i_MULU ][ i_DIVS ] = 1;
109: PairingArray[ i_MULS ][ i_DIVU ] = 1;
110: PairingArray[ i_MULS ][ i_DIVS ] = 1;
111:
112: PairingArray[ i_BTST ][ i_Bcc ] = 1;
113:
114: M68000_InitPairing_BitShift ( i_ADD );
115: M68000_InitPairing_BitShift ( i_SUB );
116: M68000_InitPairing_BitShift ( i_OR );
117: M68000_InitPairing_BitShift ( i_AND );
118: M68000_InitPairing_BitShift ( i_EOR );
119: M68000_InitPairing_BitShift ( i_NOT );
120: M68000_InitPairing_BitShift ( i_CLR );
121: M68000_InitPairing_BitShift ( i_NEG );
122: M68000_InitPairing_BitShift ( i_ADDX );
123: M68000_InitPairing_BitShift ( i_SUBX );
124: M68000_InitPairing_BitShift ( i_ABCD );
125: M68000_InitPairing_BitShift ( i_SBCD );
126:
127: PairingArray[ i_ADD ][ i_MOVE ] = 1; /* when using xx(an,dn) addr mode */
128: PairingArray[ i_SUB ][ i_MOVE ] = 1;
129: }
130:
131:
132: /**
133: * One-time CPU initialization.
134: */
135: void M68000_Init(void)
136: {
137: /* Init UAE CPU core */
138: Init680x0();
139:
140: /* Init the pairing matrix */
141: M68000_InitPairing();
142: }
143:
1.1.1.5 ! root 144: static int pendingInterrupts = 0;
1.1 root 145:
146: /*-----------------------------------------------------------------------*/
147: /**
148: * Reset CPU 68000 variables
149: */
1.1.1.5 ! root 150: void M68000_Reset(bool bCold) {
! 151: pendingInterrupts = 0;
! 152: if (bCold) {
1.1.1.3 root 153: /* Clear registers, but we need to keep SPCFLAG_MODE_CHANGE and SPCFLAG_BRK unchanged */
154: int spcFlags = regs.spcflags & (SPCFLAG_MODE_CHANGE | SPCFLAG_BRK);
155: memset(®s, 0, sizeof(regs));
156: regs.spcflags = spcFlags;
157: }
158: /* Now reset the WINUAE CPU core */
159: m68k_reset(bCold);
160: BusMode = BUS_MODE_CPU;
1.1 root 161: }
162:
163:
164: /*-----------------------------------------------------------------------*/
165: /**
1.1.1.4 root 166: * Stop 680x0 emulation
167: */
168: void M68000_Stop(void)
169: {
170: M68000_SetSpecial(SPCFLAG_BRK);
171: }
172:
173:
174: /*-----------------------------------------------------------------------*/
175: /**
1.1 root 176: * Start 680x0 emulation
177: */
178: void M68000_Start(void)
179: {
180: m68k_go(true);
181: }
182:
183:
184: /*-----------------------------------------------------------------------*/
185: /**
1.1.1.2 root 186: * Check whether CPU settings have been changed.
1.1 root 187: */
1.1.1.2 root 188: void M68000_CheckCpuSettings(void)
1.1 root 189: {
1.1.1.4 root 190: if (ConfigureParams.System.nCpuFreq < 20)
191: {
192: ConfigureParams.System.nCpuFreq = 16;
193: }
194: else if (ConfigureParams.System.nCpuFreq < 24)
195: {
196: ConfigureParams.System.nCpuFreq = 20;
197: }
198: else if (ConfigureParams.System.nCpuFreq < 32)
199: {
200: ConfigureParams.System.nCpuFreq = 25;
201: }
202: else if (ConfigureParams.System.nCpuFreq < 40)
203: {
204: ConfigureParams.System.nCpuFreq = 33;
205: } else {
206: if (ConfigureParams.System.bTurbo) {
207: ConfigureParams.System.nCpuFreq = 40;
208: } else {
209: ConfigureParams.System.nCpuFreq = 33;
210: }
211: }
1.1 root 212: changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel;
213: changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
1.1.1.2 root 214:
215: switch (changed_prefs.cpu_level) {
216: case 0 : changed_prefs.cpu_model = 68000; break;
217: case 1 : changed_prefs.cpu_model = 68010; break;
218: case 2 : changed_prefs.cpu_model = 68020; break;
219: case 3 : changed_prefs.cpu_model = 68030; break;
220: case 4 : changed_prefs.cpu_model = 68040; break;
221: case 5 : changed_prefs.cpu_model = 68060; break;
222: default: fprintf (stderr, "Init680x0() : Error, cpu_level unknown\n");
223: }
224:
1.1.1.4 root 225: changed_prefs.fpu_model = ConfigureParams.System.n_FPUType;
226: switch (changed_prefs.fpu_model) {
227: case 68881: changed_prefs.fpu_revision = 0x1f; break;
228: case 68882: changed_prefs.fpu_revision = 0x20; break;
229: case 68040:
230: if (ConfigureParams.System.bTurbo)
231: changed_prefs.fpu_revision = 0x41;
232: else
233: changed_prefs.fpu_revision = 0x40;
234: break;
235: default: fprintf (stderr, "Init680x0() : Error, fpu_model unknown\n");
236: }
237:
1.1.1.2 root 238: changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU;
1.1.1.4 root 239: changed_prefs.mmu_model = ConfigureParams.System.bMMU?changed_prefs.cpu_model:0;
240:
1.1 root 241: if (table68k)
242: check_prefs_changed_cpu();
243: }
244:
245: /*-----------------------------------------------------------------------*/
246: /**
247: * BUSERROR - Access outside valid memory range.
1.1.1.2 root 248: * Use bRead = 0 for write errors and bRead = 1 for read errors!
1.1 root 249: */
1.1.1.2 root 250: void M68000_BusError(Uint32 addr, bool bRead)
1.1 root 251: {
1.1.1.4 root 252: exception2 (addr, bRead, 0, regs.s ? 5 : 1); /* assumes data access,
253: size not set */
254: }
255: #if 0
256: void M68000_BusError(Uint32 addr, bool bRead)
257: {
1.1 root 258: /* FIXME: In prefetch mode, m68k_getpc() seems already to point to the next instruction */
259: // BusErrorPC = M68000_GetPC(); /* [NP] We set BusErrorPC in m68k_run_1 */
260:
1.1.1.2 root 261:
1.1 root 262: if ((regs.spcflags & SPCFLAG_BUSERROR) == 0) /* [NP] Check that the opcode has not already generated a read bus error */
263: {
1.1.1.3 root 264: regs.mmu_fault_addr = addr;
1.1 root 265: BusErrorAddress = addr; /* Store for exception frame */
1.1.1.2 root 266: bBusErrorReadWrite = bRead;
1.1.1.4 root 267:
1.1.1.3 root 268: if (currprefs.mmu_model) {
1.1.1.4 root 269: /* This is a hack for the special status word, this needs to be corrected later */
270: if (ConfigureParams.System.nCpuLevel==3) { /* CPU 68030 */
271: int fc = 5; /* hack */
272: regs.mmu_ssw = (fc&1) ? MMU030_SSW_DF : (MMU030_SSW_FB|MMU030_SSW_RB);
273: regs.mmu_ssw |= bRead ? MMU030_SSW_RW : 0;
274: regs.mmu_ssw |= fc&MMU030_SSW_FC_MASK;
275: /*switch (size) {
276: case 4: regs.mmu_ssw |= MMU030_SSW_SIZE_L; break;
277: case 2: regs.mmu_ssw |= MMU030_SSW_SIZE_W; break;
278: case 1: regs.mmu_ssw |= MMU030_SSW_SIZE_B; break;
279: default: break;
280: }*/
281: printf("Bus Error: Warning! Using hacked SSW (%04X)!\n", regs.mmu_ssw);
282: }
1.1.1.3 root 283: THROW(2);
284: return;
285: }
1.1.1.4 root 286:
1.1 root 287: M68000_SetSpecial(SPCFLAG_BUSERROR); /* The exception will be done in newcpu.c */
288: }
289: }
1.1.1.4 root 290: #endif
1.1 root 291:
292: /*-----------------------------------------------------------------------*/
293: /**
294: * Exception handler
295: */
296: void M68000_Exception(Uint32 ExceptionVector , int ExceptionSource)
297: {
298: int exceptionNr = ExceptionVector/4;
299:
300: if ((ExceptionSource == M68000_EXC_SRC_AUTOVEC)
301: && (exceptionNr>24 && exceptionNr<32)) /* 68k autovector interrupt? */
302: {
303: /* Handle autovector interrupts the UAE's way
304: * (see intlev() and do_specialties() in UAE CPU core) */
305: int intnr = exceptionNr - 24;
306: pendingInterrupts |= (1 << intnr);
307: M68000_SetSpecial(SPCFLAG_INT);
308: }
309:
1.1.1.5 ! root 310: else /* direct CPU exceptions */
1.1 root 311: {
312: Uint16 SR;
313:
314: /* Was the CPU stopped, i.e. by a STOP instruction? */
315: if (regs.spcflags & SPCFLAG_STOP)
316: {
317: regs.stopped = 0;
318: M68000_UnsetSpecial(SPCFLAG_STOP); /* All is go,go,go! */
319: }
320:
321: /* 68k exceptions are handled by Exception() of the UAE CPU core */
1.1.1.4 root 322: Exception(exceptionNr/*, m68k_getpc(), ExceptionSource*/);
323:
1.1 root 324: SR = M68000_GetSR();
325:
326: /* Set Status Register so interrupt can ONLY be stopped by another interrupt
327: * of higher priority! */
1.1.1.2 root 328:
1.1 root 329: SR = (SR&SR_CLEAR_IPL)|0x0600; /* DSP, level 6 */
1.1.1.2 root 330:
331: M68000_SetSR(SR);
1.1 root 332: }
1.1.1.5 ! root 333: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.