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