1 /* ======================================================================== */
2 /* ========================= LICENSING & COPYRIGHT ======================== */
3 /* ======================================================================== */
8 * A portable Motorola M680x0 processor emulation engine.
9 * Copyright Karl Stenerud. All rights reserved.
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31 /* ======================================================================== */
32 /* ================================= NOTES ================================ */
33 /* ======================================================================== */
37 /* ======================================================================== */
38 /* ================================ INCLUDES ============================== */
39 /* ======================================================================== */
40 struct m68ki_cpu_core;
41 extern void m68040_fpu_op0(struct m68ki_cpu_core *state);
42 extern void m68040_fpu_op1(struct m68ki_cpu_core *state);
43 extern void m68851_mmu_ops(struct m68ki_cpu_core *state);
44 extern unsigned char m68ki_cycles[][0x10000];
45 extern void m68ki_build_opcode_table(void);
51 #include "m68kmmu.h" // uses some functions from m68kfpu.c which are static !
53 /* ======================================================================== */
54 /* ================================= DATA ================================= */
55 /* ======================================================================== */
57 int m68ki_initial_cycles;
58 int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
59 uint m68ki_tracing = 0;
60 uint m68ki_address_space;
62 #ifdef M68K_LOG_ENABLE
63 const char *const m68ki_cpu_names[] =
75 #endif /* M68K_LOG_ENABLE */
78 m68ki_cpu_core m68ki_cpu = {0};
80 #if M68K_EMULATE_ADDRESS_ERROR
82 sigjmp_buf m68ki_aerr_trap;
84 jmp_buf m68ki_aerr_trap;
86 #endif /* M68K_EMULATE_ADDRESS_ERROR */
88 uint m68ki_aerr_address;
89 uint m68ki_aerr_write_mode;
92 jmp_buf m68ki_bus_error_jmp_buf;
94 /* Used by shift & rotate instructions */
95 const uint8 m68ki_shift_8_table[65] =
97 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
98 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
99 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
102 0xff, 0xff, 0xff, 0xff, 0xff
104 const uint16 m68ki_shift_16_table[65] =
106 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
107 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
108 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
109 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
110 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
111 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
112 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
115 const uint m68ki_shift_32_table[65] =
117 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
118 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
119 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
120 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
121 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
122 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
123 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
124 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
125 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
126 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
127 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
131 /* Number of clock cycles to use for exception processing.
132 * I used 4 for any vectors that are undocumented for processing times.
134 const uint8 m68ki_exception_cycle_table[5][256] =
137 40, /* 0: Reset - Initial Stack Pointer */
138 4, /* 1: Reset - Initial Program Counter */
139 50, /* 2: Bus Error (unemulated) */
140 50, /* 3: Address Error (unemulated) */
141 34, /* 4: Illegal Instruction */
142 38, /* 5: Divide by Zero */
145 34, /* 8: Privilege Violation */
149 4, /* 12: RESERVED */
150 4, /* 13: Coprocessor Protocol Violation (unemulated) */
151 4, /* 14: Format Error */
152 44, /* 15: Uninitialized Interrupt */
153 4, /* 16: RESERVED */
154 4, /* 17: RESERVED */
155 4, /* 18: RESERVED */
156 4, /* 19: RESERVED */
157 4, /* 20: RESERVED */
158 4, /* 21: RESERVED */
159 4, /* 22: RESERVED */
160 4, /* 23: RESERVED */
161 44, /* 24: Spurious Interrupt */
162 44, /* 25: Level 1 Interrupt Autovector */
163 44, /* 26: Level 2 Interrupt Autovector */
164 44, /* 27: Level 3 Interrupt Autovector */
165 44, /* 28: Level 4 Interrupt Autovector */
166 44, /* 29: Level 5 Interrupt Autovector */
167 44, /* 30: Level 6 Interrupt Autovector */
168 44, /* 31: Level 7 Interrupt Autovector */
169 34, /* 32: TRAP #0 */
170 34, /* 33: TRAP #1 */
171 34, /* 34: TRAP #2 */
172 34, /* 35: TRAP #3 */
173 34, /* 36: TRAP #4 */
174 34, /* 37: TRAP #5 */
175 34, /* 38: TRAP #6 */
176 34, /* 39: TRAP #7 */
177 34, /* 40: TRAP #8 */
178 34, /* 41: TRAP #9 */
179 34, /* 42: TRAP #10 */
180 34, /* 43: TRAP #11 */
181 34, /* 44: TRAP #12 */
182 34, /* 45: TRAP #13 */
183 34, /* 46: TRAP #14 */
184 34, /* 47: TRAP #15 */
185 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
186 4, /* 49: FP Inexact Result (unemulated) */
187 4, /* 50: FP Divide by Zero (unemulated) */
188 4, /* 51: FP Underflow (unemulated) */
189 4, /* 52: FP Operand Error (unemulated) */
190 4, /* 53: FP Overflow (unemulated) */
191 4, /* 54: FP Signaling NAN (unemulated) */
192 4, /* 55: FP Unimplemented Data Type (unemulated) */
193 4, /* 56: MMU Configuration Error (unemulated) */
194 4, /* 57: MMU Illegal Operation Error (unemulated) */
195 4, /* 58: MMU Access Level Violation Error (unemulated) */
196 4, /* 59: RESERVED */
197 4, /* 60: RESERVED */
198 4, /* 61: RESERVED */
199 4, /* 62: RESERVED */
200 4, /* 63: RESERVED */
201 /* 64-255: User Defined */
202 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
203 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
204 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
205 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
206 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
207 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
210 40, /* 0: Reset - Initial Stack Pointer */
211 4, /* 1: Reset - Initial Program Counter */
212 126, /* 2: Bus Error (unemulated) */
213 126, /* 3: Address Error (unemulated) */
214 38, /* 4: Illegal Instruction */
215 44, /* 5: Divide by Zero */
218 38, /* 8: Privilege Violation */
222 4, /* 12: RESERVED */
223 4, /* 13: Coprocessor Protocol Violation (unemulated) */
224 4, /* 14: Format Error */
225 44, /* 15: Uninitialized Interrupt */
226 4, /* 16: RESERVED */
227 4, /* 17: RESERVED */
228 4, /* 18: RESERVED */
229 4, /* 19: RESERVED */
230 4, /* 20: RESERVED */
231 4, /* 21: RESERVED */
232 4, /* 22: RESERVED */
233 4, /* 23: RESERVED */
234 46, /* 24: Spurious Interrupt */
235 46, /* 25: Level 1 Interrupt Autovector */
236 46, /* 26: Level 2 Interrupt Autovector */
237 46, /* 27: Level 3 Interrupt Autovector */
238 46, /* 28: Level 4 Interrupt Autovector */
239 46, /* 29: Level 5 Interrupt Autovector */
240 46, /* 30: Level 6 Interrupt Autovector */
241 46, /* 31: Level 7 Interrupt Autovector */
242 38, /* 32: TRAP #0 */
243 38, /* 33: TRAP #1 */
244 38, /* 34: TRAP #2 */
245 38, /* 35: TRAP #3 */
246 38, /* 36: TRAP #4 */
247 38, /* 37: TRAP #5 */
248 38, /* 38: TRAP #6 */
249 38, /* 39: TRAP #7 */
250 38, /* 40: TRAP #8 */
251 38, /* 41: TRAP #9 */
252 38, /* 42: TRAP #10 */
253 38, /* 43: TRAP #11 */
254 38, /* 44: TRAP #12 */
255 38, /* 45: TRAP #13 */
256 38, /* 46: TRAP #14 */
257 38, /* 47: TRAP #15 */
258 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
259 4, /* 49: FP Inexact Result (unemulated) */
260 4, /* 50: FP Divide by Zero (unemulated) */
261 4, /* 51: FP Underflow (unemulated) */
262 4, /* 52: FP Operand Error (unemulated) */
263 4, /* 53: FP Overflow (unemulated) */
264 4, /* 54: FP Signaling NAN (unemulated) */
265 4, /* 55: FP Unimplemented Data Type (unemulated) */
266 4, /* 56: MMU Configuration Error (unemulated) */
267 4, /* 57: MMU Illegal Operation Error (unemulated) */
268 4, /* 58: MMU Access Level Violation Error (unemulated) */
269 4, /* 59: RESERVED */
270 4, /* 60: RESERVED */
271 4, /* 61: RESERVED */
272 4, /* 62: RESERVED */
273 4, /* 63: RESERVED */
274 /* 64-255: User Defined */
275 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
276 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
277 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
278 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
279 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
280 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
283 4, /* 0: Reset - Initial Stack Pointer */
284 4, /* 1: Reset - Initial Program Counter */
285 50, /* 2: Bus Error (unemulated) */
286 50, /* 3: Address Error (unemulated) */
287 20, /* 4: Illegal Instruction */
288 38, /* 5: Divide by Zero */
291 34, /* 8: Privilege Violation */
295 4, /* 12: RESERVED */
296 4, /* 13: Coprocessor Protocol Violation (unemulated) */
297 4, /* 14: Format Error */
298 30, /* 15: Uninitialized Interrupt */
299 4, /* 16: RESERVED */
300 4, /* 17: RESERVED */
301 4, /* 18: RESERVED */
302 4, /* 19: RESERVED */
303 4, /* 20: RESERVED */
304 4, /* 21: RESERVED */
305 4, /* 22: RESERVED */
306 4, /* 23: RESERVED */
307 30, /* 24: Spurious Interrupt */
308 30, /* 25: Level 1 Interrupt Autovector */
309 30, /* 26: Level 2 Interrupt Autovector */
310 30, /* 27: Level 3 Interrupt Autovector */
311 30, /* 28: Level 4 Interrupt Autovector */
312 30, /* 29: Level 5 Interrupt Autovector */
313 30, /* 30: Level 6 Interrupt Autovector */
314 30, /* 31: Level 7 Interrupt Autovector */
315 20, /* 32: TRAP #0 */
316 20, /* 33: TRAP #1 */
317 20, /* 34: TRAP #2 */
318 20, /* 35: TRAP #3 */
319 20, /* 36: TRAP #4 */
320 20, /* 37: TRAP #5 */
321 20, /* 38: TRAP #6 */
322 20, /* 39: TRAP #7 */
323 20, /* 40: TRAP #8 */
324 20, /* 41: TRAP #9 */
325 20, /* 42: TRAP #10 */
326 20, /* 43: TRAP #11 */
327 20, /* 44: TRAP #12 */
328 20, /* 45: TRAP #13 */
329 20, /* 46: TRAP #14 */
330 20, /* 47: TRAP #15 */
331 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
332 4, /* 49: FP Inexact Result (unemulated) */
333 4, /* 50: FP Divide by Zero (unemulated) */
334 4, /* 51: FP Underflow (unemulated) */
335 4, /* 52: FP Operand Error (unemulated) */
336 4, /* 53: FP Overflow (unemulated) */
337 4, /* 54: FP Signaling NAN (unemulated) */
338 4, /* 55: FP Unimplemented Data Type (unemulated) */
339 4, /* 56: MMU Configuration Error (unemulated) */
340 4, /* 57: MMU Illegal Operation Error (unemulated) */
341 4, /* 58: MMU Access Level Violation Error (unemulated) */
342 4, /* 59: RESERVED */
343 4, /* 60: RESERVED */
344 4, /* 61: RESERVED */
345 4, /* 62: RESERVED */
346 4, /* 63: RESERVED */
347 /* 64-255: User Defined */
348 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
349 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
350 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
351 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
352 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
353 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
355 { /* 030 - not correct */
356 4, /* 0: Reset - Initial Stack Pointer */
357 4, /* 1: Reset - Initial Program Counter */
358 50, /* 2: Bus Error (unemulated) */
359 50, /* 3: Address Error (unemulated) */
360 20, /* 4: Illegal Instruction */
361 38, /* 5: Divide by Zero */
364 34, /* 8: Privilege Violation */
368 4, /* 12: RESERVED */
369 4, /* 13: Coprocessor Protocol Violation (unemulated) */
370 4, /* 14: Format Error */
371 30, /* 15: Uninitialized Interrupt */
372 4, /* 16: RESERVED */
373 4, /* 17: RESERVED */
374 4, /* 18: RESERVED */
375 4, /* 19: RESERVED */
376 4, /* 20: RESERVED */
377 4, /* 21: RESERVED */
378 4, /* 22: RESERVED */
379 4, /* 23: RESERVED */
380 30, /* 24: Spurious Interrupt */
381 30, /* 25: Level 1 Interrupt Autovector */
382 30, /* 26: Level 2 Interrupt Autovector */
383 30, /* 27: Level 3 Interrupt Autovector */
384 30, /* 28: Level 4 Interrupt Autovector */
385 30, /* 29: Level 5 Interrupt Autovector */
386 30, /* 30: Level 6 Interrupt Autovector */
387 30, /* 31: Level 7 Interrupt Autovector */
388 20, /* 32: TRAP #0 */
389 20, /* 33: TRAP #1 */
390 20, /* 34: TRAP #2 */
391 20, /* 35: TRAP #3 */
392 20, /* 36: TRAP #4 */
393 20, /* 37: TRAP #5 */
394 20, /* 38: TRAP #6 */
395 20, /* 39: TRAP #7 */
396 20, /* 40: TRAP #8 */
397 20, /* 41: TRAP #9 */
398 20, /* 42: TRAP #10 */
399 20, /* 43: TRAP #11 */
400 20, /* 44: TRAP #12 */
401 20, /* 45: TRAP #13 */
402 20, /* 46: TRAP #14 */
403 20, /* 47: TRAP #15 */
404 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
405 4, /* 49: FP Inexact Result (unemulated) */
406 4, /* 50: FP Divide by Zero (unemulated) */
407 4, /* 51: FP Underflow (unemulated) */
408 4, /* 52: FP Operand Error (unemulated) */
409 4, /* 53: FP Overflow (unemulated) */
410 4, /* 54: FP Signaling NAN (unemulated) */
411 4, /* 55: FP Unimplemented Data Type (unemulated) */
412 4, /* 56: MMU Configuration Error (unemulated) */
413 4, /* 57: MMU Illegal Operation Error (unemulated) */
414 4, /* 58: MMU Access Level Violation Error (unemulated) */
415 4, /* 59: RESERVED */
416 4, /* 60: RESERVED */
417 4, /* 61: RESERVED */
418 4, /* 62: RESERVED */
419 4, /* 63: RESERVED */
420 /* 64-255: User Defined */
421 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
422 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
423 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
424 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
425 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
426 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
428 { /* 040 */ // TODO: these values are not correct
429 4, /* 0: Reset - Initial Stack Pointer */
430 4, /* 1: Reset - Initial Program Counter */
431 50, /* 2: Bus Error (unemulated) */
432 50, /* 3: Address Error (unemulated) */
433 20, /* 4: Illegal Instruction */
434 38, /* 5: Divide by Zero */
437 34, /* 8: Privilege Violation */
441 4, /* 12: RESERVED */
442 4, /* 13: Coprocessor Protocol Violation (unemulated) */
443 4, /* 14: Format Error */
444 30, /* 15: Uninitialized Interrupt */
445 4, /* 16: RESERVED */
446 4, /* 17: RESERVED */
447 4, /* 18: RESERVED */
448 4, /* 19: RESERVED */
449 4, /* 20: RESERVED */
450 4, /* 21: RESERVED */
451 4, /* 22: RESERVED */
452 4, /* 23: RESERVED */
453 30, /* 24: Spurious Interrupt */
454 30, /* 25: Level 1 Interrupt Autovector */
455 30, /* 26: Level 2 Interrupt Autovector */
456 30, /* 27: Level 3 Interrupt Autovector */
457 30, /* 28: Level 4 Interrupt Autovector */
458 30, /* 29: Level 5 Interrupt Autovector */
459 30, /* 30: Level 6 Interrupt Autovector */
460 30, /* 31: Level 7 Interrupt Autovector */
461 20, /* 32: TRAP #0 */
462 20, /* 33: TRAP #1 */
463 20, /* 34: TRAP #2 */
464 20, /* 35: TRAP #3 */
465 20, /* 36: TRAP #4 */
466 20, /* 37: TRAP #5 */
467 20, /* 38: TRAP #6 */
468 20, /* 39: TRAP #7 */
469 20, /* 40: TRAP #8 */
470 20, /* 41: TRAP #9 */
471 20, /* 42: TRAP #10 */
472 20, /* 43: TRAP #11 */
473 20, /* 44: TRAP #12 */
474 20, /* 45: TRAP #13 */
475 20, /* 46: TRAP #14 */
476 20, /* 47: TRAP #15 */
477 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
478 4, /* 49: FP Inexact Result (unemulated) */
479 4, /* 50: FP Divide by Zero (unemulated) */
480 4, /* 51: FP Underflow (unemulated) */
481 4, /* 52: FP Operand Error (unemulated) */
482 4, /* 53: FP Overflow (unemulated) */
483 4, /* 54: FP Signaling NAN (unemulated) */
484 4, /* 55: FP Unimplemented Data Type (unemulated) */
485 4, /* 56: MMU Configuration Error (unemulated) */
486 4, /* 57: MMU Illegal Operation Error (unemulated) */
487 4, /* 58: MMU Access Level Violation Error (unemulated) */
488 4, /* 59: RESERVED */
489 4, /* 60: RESERVED */
490 4, /* 61: RESERVED */
491 4, /* 62: RESERVED */
492 4, /* 63: RESERVED */
493 /* 64-255: User Defined */
494 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
495 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
496 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
497 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
498 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
499 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
503 const uint8 m68ki_ea_idx_cycle_table[64] =
505 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
506 0, /* ..01.000 no memory indirect, base NULL */
507 5, /* ..01..01 memory indirect, base NULL, outer NULL */
508 7, /* ..01..10 memory indirect, base NULL, outer 16 */
509 7, /* ..01..11 memory indirect, base NULL, outer 32 */
510 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
511 2, /* ..10.000 no memory indirect, base 16 */
512 7, /* ..10..01 memory indirect, base 16, outer NULL */
513 9, /* ..10..10 memory indirect, base 16, outer 16 */
514 9, /* ..10..11 memory indirect, base 16, outer 32 */
515 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
516 6, /* ..11.000 no memory indirect, base 32 */
517 11, /* ..11..01 memory indirect, base 32, outer NULL */
518 13, /* ..11..10 memory indirect, base 32, outer 16 */
519 13, /* ..11..11 memory indirect, base 32, outer 32 */
520 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
525 /* ======================================================================== */
526 /* =============================== CALLBACKS ============================== */
527 /* ======================================================================== */
529 /* Default callbacks used if the callback hasn't been set yet, or if the
530 * callback is set to NULL
533 /* Interrupt acknowledge */
534 static int default_int_ack_callback_data;
535 static int default_int_ack_callback(int int_level)
537 default_int_ack_callback_data = int_level;
539 return M68K_INT_ACK_AUTOVECTOR;
542 /* Breakpoint acknowledge */
543 static unsigned int default_bkpt_ack_callback_data;
544 static void default_bkpt_ack_callback(unsigned int data)
546 default_bkpt_ack_callback_data = data;
549 /* Called when a reset instruction is executed */
550 static void default_reset_instr_callback(void)
554 /* Called when a cmpi.l #v, dn instruction is executed */
555 static void default_cmpild_instr_callback(unsigned int val, int reg)
561 /* Called when a rte instruction is executed */
562 static void default_rte_instr_callback(void)
566 /* Called when a tas instruction is executed */
567 static int default_tas_instr_callback(void)
569 return 1; // allow writeback
572 /* Called when an illegal instruction is encountered */
573 static int default_illg_instr_callback(int opcode)
576 return 0; // not handled : exception will occur
579 /* Called when the program counter changed by a large value */
580 static unsigned int default_pc_changed_callback_data;
581 static void default_pc_changed_callback(unsigned int new_pc)
583 default_pc_changed_callback_data = new_pc;
586 /* Called every time there's bus activity (read/write to/from memory */
587 static unsigned int default_set_fc_callback_data;
588 static void default_set_fc_callback(unsigned int new_fc)
590 default_set_fc_callback_data = new_fc;
593 /* Called every instruction cycle prior to execution */
594 static void default_instr_hook_callback(unsigned int pc)
600 #if M68K_EMULATE_ADDRESS_ERROR
603 sigjmp_buf m68ki_aerr_trap;
605 jmp_buf m68ki_aerr_trap;
607 #endif /* M68K_EMULATE_ADDRESS_ERROR */
609 /* ======================================================================== */
610 /* ================================= API ================================== */
611 /* ======================================================================== */
613 /* Access the internals of the CPU */
614 unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
616 m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
620 case M68K_REG_D0: return cpu->dar[0];
621 case M68K_REG_D1: return cpu->dar[1];
622 case M68K_REG_D2: return cpu->dar[2];
623 case M68K_REG_D3: return cpu->dar[3];
624 case M68K_REG_D4: return cpu->dar[4];
625 case M68K_REG_D5: return cpu->dar[5];
626 case M68K_REG_D6: return cpu->dar[6];
627 case M68K_REG_D7: return cpu->dar[7];
628 case M68K_REG_A0: return cpu->dar[8];
629 case M68K_REG_A1: return cpu->dar[9];
630 case M68K_REG_A2: return cpu->dar[10];
631 case M68K_REG_A3: return cpu->dar[11];
632 case M68K_REG_A4: return cpu->dar[12];
633 case M68K_REG_A5: return cpu->dar[13];
634 case M68K_REG_A6: return cpu->dar[14];
635 case M68K_REG_A7: return cpu->dar[15];
636 case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
637 case M68K_REG_SR: return cpu->t1_flag |
639 (cpu->s_flag << 11) |
640 (cpu->m_flag << 11) |
642 ((cpu->x_flag & XFLAG_SET) >> 4) |
643 ((cpu->n_flag & NFLAG_SET) >> 4) |
644 ((!cpu->not_z_flag) << 2) |
645 ((cpu->v_flag & VFLAG_SET) >> 6) |
646 ((cpu->c_flag & CFLAG_SET) >> 8);
647 case M68K_REG_SP: return cpu->dar[15];
648 case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
649 case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
650 case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
651 case M68K_REG_SFC: return cpu->sfc;
652 case M68K_REG_DFC: return cpu->dfc;
653 case M68K_REG_VBR: return cpu->vbr;
654 case M68K_REG_CACR: return cpu->cacr;
655 case M68K_REG_CAAR: return cpu->caar;
656 case M68K_REG_PREF_ADDR: return cpu->pref_addr;
657 case M68K_REG_PREF_DATA: return cpu->pref_data;
658 case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
659 case M68K_REG_IR: return cpu->ir;
660 case M68K_REG_CPU_TYPE:
661 switch(cpu->cpu_type)
663 case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
664 case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
665 case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
666 case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
667 case CPU_TYPE_EC030: return (unsigned int)M68K_CPU_TYPE_68EC030;
668 case CPU_TYPE_030: return (unsigned int)M68K_CPU_TYPE_68030;
669 case CPU_TYPE_EC040: return (unsigned int)M68K_CPU_TYPE_68EC040;
670 case CPU_TYPE_LC040: return (unsigned int)M68K_CPU_TYPE_68LC040;
671 case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040;
673 return M68K_CPU_TYPE_INVALID;
679 void m68k_set_reg(void *context, m68k_register_t regnum, unsigned int value)
681 m68ki_cpu_core* state = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
684 case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
685 case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
686 case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
687 case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
688 case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
689 case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
690 case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
691 case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
692 case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
693 case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
694 case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
695 case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
696 case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
697 case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
698 case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
699 case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
701 m68ki_jump(state, MASK_OUT_ABOVE_32(value)); return;
703 m68ki_set_sr_noint_nosp(state, value); return;
704 case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
705 case M68K_REG_USP: if(FLAG_S)
706 REG_USP = MASK_OUT_ABOVE_32(value);
708 REG_SP = MASK_OUT_ABOVE_32(value);
710 case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
711 REG_SP = MASK_OUT_ABOVE_32(value);
713 REG_ISP = MASK_OUT_ABOVE_32(value);
715 case M68K_REG_MSP: if(FLAG_S && FLAG_M)
716 REG_SP = MASK_OUT_ABOVE_32(value);
718 REG_MSP = MASK_OUT_ABOVE_32(value);
720 case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
721 case M68K_REG_SFC: REG_SFC = value & 7; return;
722 case M68K_REG_DFC: REG_DFC = value & 7; return;
723 case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
724 case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
725 case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
726 case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
727 case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
732 /* Set the callbacks */
733 void m68k_set_int_ack_callback(int (*callback)(int int_level))
735 CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
738 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
740 CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
743 void m68k_set_reset_instr_callback(void (*callback)(void))
745 CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
748 void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int))
750 CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback;
753 void m68k_set_rte_instr_callback(void (*callback)(void))
755 CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback;
758 void m68k_set_tas_instr_callback(int (*callback)(void))
760 CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
763 void m68k_set_illg_instr_callback(int (*callback)(int))
765 CALLBACK_ILLG_INSTR = callback ? callback : default_illg_instr_callback;
768 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
770 CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
773 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
775 CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
778 void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc))
780 CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
783 /* Set the CPU type. */
784 void m68k_set_cpu_type(unsigned int cpu_type)
788 case M68K_CPU_TYPE_68000:
789 CPU_TYPE = CPU_TYPE_000;
790 CPU_ADDRESS_MASK = 0x00ffffff;
791 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
792 CYC_INSTRUCTION = m68ki_cycles[0];
793 CYC_EXCEPTION = m68ki_exception_cycle_table[0];
794 CYC_BCC_NOTAKE_B = -2;
795 CYC_BCC_NOTAKE_W = 2;
796 CYC_DBCC_F_NOEXP = -2;
806 case M68K_CPU_TYPE_SCC68070:
807 m68k_set_cpu_type(M68K_CPU_TYPE_68010);
808 CPU_ADDRESS_MASK = 0xffffffff;
809 CPU_TYPE = CPU_TYPE_SCC070;
811 case M68K_CPU_TYPE_68010:
812 CPU_TYPE = CPU_TYPE_010;
813 CPU_ADDRESS_MASK = 0x00ffffff;
814 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
815 CYC_INSTRUCTION = m68ki_cycles[1];
816 CYC_EXCEPTION = m68ki_exception_cycle_table[1];
817 CYC_BCC_NOTAKE_B = -4;
818 CYC_BCC_NOTAKE_W = 0;
819 CYC_DBCC_F_NOEXP = 0;
829 case M68K_CPU_TYPE_68EC020:
830 CPU_TYPE = CPU_TYPE_EC020;
831 CPU_ADDRESS_MASK = 0x00ffffff;
832 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
833 CYC_INSTRUCTION = m68ki_cycles[2];
834 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
835 CYC_BCC_NOTAKE_B = -2;
836 CYC_BCC_NOTAKE_W = 0;
837 CYC_DBCC_F_NOEXP = 0;
847 case M68K_CPU_TYPE_68020:
848 CPU_TYPE = CPU_TYPE_020;
849 CPU_ADDRESS_MASK = 0xffffffff;
850 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
851 CYC_INSTRUCTION = m68ki_cycles[2];
852 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
853 CYC_BCC_NOTAKE_B = -2;
854 CYC_BCC_NOTAKE_W = 0;
855 CYC_DBCC_F_NOEXP = 0;
865 case M68K_CPU_TYPE_68030:
866 CPU_TYPE = CPU_TYPE_030;
867 CPU_ADDRESS_MASK = 0xffffffff;
868 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
869 CYC_INSTRUCTION = m68ki_cycles[3];
870 CYC_EXCEPTION = m68ki_exception_cycle_table[3];
871 CYC_BCC_NOTAKE_B = -2;
872 CYC_BCC_NOTAKE_W = 0;
873 CYC_DBCC_F_NOEXP = 0;
883 case M68K_CPU_TYPE_68EC030:
884 CPU_TYPE = CPU_TYPE_EC030;
885 CPU_ADDRESS_MASK = 0xffffffff;
886 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
887 CYC_INSTRUCTION = m68ki_cycles[3];
888 CYC_EXCEPTION = m68ki_exception_cycle_table[3];
889 CYC_BCC_NOTAKE_B = -2;
890 CYC_BCC_NOTAKE_W = 0;
891 CYC_DBCC_F_NOEXP = 0;
898 HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */
901 case M68K_CPU_TYPE_68040: // TODO: these values are not correct
902 CPU_TYPE = CPU_TYPE_040;
903 CPU_ADDRESS_MASK = 0xffffffff;
904 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
905 CYC_INSTRUCTION = m68ki_cycles[4];
906 CYC_EXCEPTION = m68ki_exception_cycle_table[4];
907 CYC_BCC_NOTAKE_B = -2;
908 CYC_BCC_NOTAKE_W = 0;
909 CYC_DBCC_F_NOEXP = 0;
919 case M68K_CPU_TYPE_68EC040: // Just a 68040 without pmmu apparently...
920 CPU_TYPE = CPU_TYPE_EC040;
921 CPU_ADDRESS_MASK = 0xffffffff;
922 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
923 CYC_INSTRUCTION = m68ki_cycles[4];
924 CYC_EXCEPTION = m68ki_exception_cycle_table[4];
925 CYC_BCC_NOTAKE_B = -2;
926 CYC_BCC_NOTAKE_W = 0;
927 CYC_DBCC_F_NOEXP = 0;
937 case M68K_CPU_TYPE_68LC040:
938 CPU_TYPE = CPU_TYPE_LC040;
939 CPU_ADDRESS_MASK = 0xffffffff;
940 m68ki_cpu.sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
941 m68ki_cpu.cyc_instruction = m68ki_cycles[4];
942 m68ki_cpu.cyc_exception = m68ki_exception_cycle_table[4];
943 m68ki_cpu.cyc_bcc_notake_b = -2;
944 m68ki_cpu.cyc_bcc_notake_w = 0;
945 m68ki_cpu.cyc_dbcc_f_noexp = 0;
946 m68ki_cpu.cyc_dbcc_f_exp = 4;
947 m68ki_cpu.cyc_scc_r_true = 0;
948 m68ki_cpu.cyc_movem_w = 2;
949 m68ki_cpu.cyc_movem_l = 2;
950 m68ki_cpu.cyc_shift = 0;
951 m68ki_cpu.cyc_reset = 518;
958 uint m68k_get_address_mask() {
959 return m68ki_cpu.address_mask;
962 /* Execute some instructions until we use up num_cycles clock cycles */
963 /* ASG: removed per-instruction interrupt checks */
964 int m68k_execute(m68ki_cpu_core *state, int num_cycles)
966 /* eat up any reset cycles */
968 int rc = RESET_CYCLES;
975 /* Set our pool of clock cycles available */
976 SET_CYCLES(num_cycles);
977 m68ki_initial_cycles = num_cycles;
979 /* See if interrupts came in */
980 m68ki_check_interrupts(state);
982 /* Make sure we're not stopped */
985 /* Return point if we had an address error */
986 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
988 #ifdef M68K_BUSERR_THING
989 m68ki_check_bus_error_trap();
992 /* Main loop. Keep going until we run out of clock cycles */
995 /* Set tracing according to T1. (T0 is done inside instruction) */
996 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
998 /* Set the address space for reads */
999 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
1001 /* Call external hook to peek at CPU */
1002 m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
1004 /* Record previous program counter */
1007 /* Record previous D/A register state (in case of bus error) */
1008 //#define M68K_BUSERR_THING
1009 #ifdef M68K_BUSERR_THING
1010 for (int i = 15; i >= 0; i--){
1011 REG_DA_SAVE[i] = REG_DA[i];
1015 /* Read an instruction and call its handler */
1016 REG_IR = m68ki_read_imm_16(state);
1017 m68ki_instruction_jump_table[REG_IR](state);
1018 USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
1020 /* Trace m68k_exception, if necessary */
1021 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
1022 } while(GET_CYCLES() > 0);
1024 /* set previous PC to current PC for the next entry into the loop */
1030 /* return how many clocks we used */
1031 return m68ki_initial_cycles - GET_CYCLES();
1035 int m68k_cycles_run(void)
1037 return m68ki_initial_cycles - GET_CYCLES();
1040 int m68k_cycles_remaining(void)
1042 return GET_CYCLES();
1045 /* Change the timeslice */
1046 void m68k_modify_timeslice(int cycles)
1048 m68ki_initial_cycles += cycles;
1053 void m68k_end_timeslice(void)
1055 m68ki_initial_cycles = GET_CYCLES();
1060 /* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
1061 /* KS: Modified so that IPL* bits match with mask positions in the SR
1062 * and cleaned out remenants of the interrupt controller.
1064 void m68k_set_irq(unsigned int int_level)
1066 uint old_level = CPU_INT_LEVEL;
1067 CPU_INT_LEVEL = int_level << 8;
1069 /* A transition from < 7 to 7 always interrupts (NMI) */
1070 /* Note: Level 7 can also level trigger like a normal IRQ */
1071 if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
1072 m68ki_cpu.nmi_pending = TRUE;
1075 void m68k_set_virq(unsigned int level, unsigned int active)
1077 uint state = m68ki_cpu.virq_state;
1081 state |= 1 << level;
1083 state &= ~(1 << level);
1084 m68ki_cpu.virq_state = state;
1086 for(blevel = 7; blevel > 0; blevel--)
1087 if(state & (1 << blevel))
1089 m68k_set_irq(blevel);
1092 unsigned int m68k_get_virq(unsigned int level)
1094 return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0;
1097 void m68k_init(void)
1099 static uint emulation_initialized = 0;
1101 /* The first call to this function initializes the opcode handler jump table */
1102 if(!emulation_initialized)
1104 m68ki_build_opcode_table();
1105 emulation_initialized = 1;
1108 m68k_set_int_ack_callback(NULL);
1109 m68k_set_bkpt_ack_callback(NULL);
1110 m68k_set_reset_instr_callback(NULL);
1111 m68k_set_cmpild_instr_callback(NULL);
1112 m68k_set_rte_instr_callback(NULL);
1113 m68k_set_tas_instr_callback(NULL);
1114 m68k_set_illg_instr_callback(NULL);
1115 m68k_set_pc_changed_callback(NULL);
1116 m68k_set_fc_callback(NULL);
1117 m68k_set_instr_hook_callback(NULL);
1120 /* Trigger a Bus Error exception */
1121 void m68k_pulse_bus_error(m68ki_cpu_core *state)
1123 m68ki_exception_bus_error(state);
1126 /* Pulse the RESET line on the CPU */
1127 void m68k_pulse_reset(m68ki_cpu_core *state)
1129 /* Disable the PMMU/HMMU on reset, if any */
1130 m68ki_cpu.pmmu_enabled = 0;
1131 // m68ki_cpu.hmmu_enabled = 0;
1133 m68ki_cpu.mmu_tc = 0;
1134 m68ki_cpu.mmu_tt0 = 0;
1135 m68ki_cpu.mmu_tt1 = 0;
1137 /* Clear all stop levels and eat up all remaining cycles */
1141 CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
1142 CPU_INSTR_MODE = INSTRUCTION_YES;
1144 /* Turn off tracing */
1145 FLAG_T1 = FLAG_T0 = 0;
1146 m68ki_clear_trace();
1147 /* Interrupt mask to level 7 */
1148 FLAG_INT_MASK = 0x0700;
1150 m68ki_cpu.virq_state = 0;
1153 /* Go to supervisor mode */
1154 m68ki_set_sm_flag(state, SFLAG_SET | MFLAG_CLEAR);
1156 /* Invalidate the prefetch queue */
1157 #if M68K_EMULATE_PREFETCH
1158 /* Set to arbitrary number since our first fetch is from 0 */
1159 CPU_PREF_ADDR = 0x1000;
1160 #endif /* M68K_EMULATE_PREFETCH */
1162 /* Read the initial stack pointer and program counter */
1163 m68ki_jump(state, 0);
1164 REG_SP = m68ki_read_imm_32(state);
1165 REG_PC = m68ki_read_imm_32(state);
1166 m68ki_jump(state, REG_PC);
1168 CPU_RUN_MODE = RUN_MODE_NORMAL;
1170 RESET_CYCLES = CYC_EXCEPTION[EXCEPTION_RESET];
1172 /* flush the MMU's cache */
1173 pmmu_atc_flush(state);
1175 if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))
1177 // clear instruction cache
1178 m68ki_ic_clear(state);
1182 /* Pulse the HALT line on the CPU */
1183 void m68k_pulse_halt(void)
1185 CPU_STOPPED |= STOP_LEVEL_HALT;
1188 /* Get and set the current CPU context */
1189 /* This is to allow for multiple CPUs */
1190 unsigned int m68k_context_size()
1192 return sizeof(m68ki_cpu_core);
1195 unsigned int m68k_get_context(void* dst)
1197 if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
1198 return sizeof(m68ki_cpu_core);
1201 void m68k_set_context(void* src)
1203 if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
1206 #if M68K_SEPARATE_READS
1207 /* Read data immediately following the PC */
1208 inline unsigned int m68k_read_immediate_16(m68ki_cpu_core *state, unsigned int address) {
1209 #if M68K_EMULATE_PREFETCH == OPT_ON
1210 for (int i = 0; i < m68ki_cpu.read_ranges; i++) {
1211 if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) {
1212 return be16toh(((unsigned short *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]);
1217 return m68k_read_memory_16(address);
1219 inline unsigned int m68k_read_immediate_32(m68ki_cpu_core *state, unsigned int address) {
1220 #if M68K_EMULATE_PREFETCH == OPT_ON
1221 for (int i = 0; i < m68ki_cpu.read_ranges; i++) {
1222 if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) {
1223 return be32toh(((unsigned int *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]);
1228 return m68k_read_memory_32(address);
1231 /* Read data relative to the PC */
1232 inline unsigned int m68k_read_pcrelative_8(m68ki_cpu_core *state, unsigned int address) {
1233 for (int i = 0; i < m68ki_cpu.read_ranges; i++) {
1234 if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) {
1235 return m68ki_cpu.read_data[i][address - m68ki_cpu.read_addr[i]];
1239 return m68k_read_memory_8(address);
1241 inline unsigned int m68k_read_pcrelative_16(m68ki_cpu_core *state, unsigned int address) {
1242 for (int i = 0; i < m68ki_cpu.read_ranges; i++) {
1243 if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) {
1244 return be16toh(((unsigned short *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]);
1248 return m68k_read_memory_16(address);
1250 inline unsigned int m68k_read_pcrelative_32(m68ki_cpu_core *state, unsigned int address) {
1251 for (int i = 0; i < m68ki_cpu.read_ranges; i++) {
1252 if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) {
1253 return be32toh(((unsigned int *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]);
1257 return m68k_read_memory_32(address);
1262 uint m68ki_read_imm16_addr_slowpath(m68ki_cpu_core *state, uint32_t pc, address_translation_cache *cache)
1264 uint32_t address = ADDRESS_68K(pc);
1265 uint32_t pc_address_diff = pc - address;
1266 for (int i = 0; i < m68ki_cpu.read_ranges; i++) {
1267 if(address >= m68ki_cpu.read_addr[i] && address < m68ki_cpu.read_upper[i]) {
1268 cache->lower = m68ki_cpu.read_addr[i] + pc_address_diff;
1269 cache->upper = m68ki_cpu.read_upper[i] + pc_address_diff;
1270 cache->offset = m68ki_cpu.read_data[i] - cache->lower;
1272 return be16toh(((unsigned short *)(m68ki_cpu.read_data[i] + (address - m68ki_cpu.read_addr[i])))[0]);
1276 m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
1277 m68ki_cpu.mmu_tmp_fc = FLAG_S | FUNCTION_CODE_USER_PROGRAM;
1278 m68ki_cpu.mmu_tmp_rw = 1;
1279 m68ki_cpu.mmu_tmp_sz = M68K_SZ_WORD;
1280 m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
1282 #if M68K_EMULATE_PREFETCH
1285 if(REG_PC != CPU_PREF_ADDR)
1287 CPU_PREF_DATA = m68ki_ic_readimm16(state, REG_PC);
1288 CPU_PREF_ADDR = m68ki_cpu.mmu_tmp_buserror_occurred ? ((uint32)~0) : REG_PC;
1290 result = MASK_OUT_ABOVE_16(CPU_PREF_DATA);
1292 if (!m68ki_cpu.mmu_tmp_buserror_occurred) {
1293 // prefetch only if no bus error occurred in opcode fetch
1294 CPU_PREF_DATA = m68ki_ic_readimm16(state, REG_PC);
1295 CPU_PREF_ADDR = m68ki_cpu.mmu_tmp_buserror_occurred ? ((uint32)~0) : REG_PC;
1296 // ignore bus error on prefetch
1297 m68ki_cpu.mmu_tmp_buserror_occurred = 0;
1304 return m68k_read_immediate_16(address);
1305 #endif /* M68K_EMULATE_PREFETCH */
1310 void m68k_add_ram_range(uint32_t addr, uint32_t upper, unsigned char *ptr)
1312 m68ki_cpu.code_translation_cache.lower = 0;
1313 m68ki_cpu.code_translation_cache.upper = 0;
1314 if ((addr == 0 && upper == 0) || upper < addr)
1317 for (int i = 0; i < m68ki_cpu.write_ranges; i++) {
1318 if (m68ki_cpu.write_addr[i] == addr) {
1319 uint8_t changed = 0;
1320 if (m68ki_cpu.write_upper[i] != upper) {
1321 m68ki_cpu.write_upper[i] = upper;
1324 if (m68ki_cpu.write_data[i] != ptr) {
1325 m68ki_cpu.write_data[i] = ptr;
1329 printf("[MUSASHI] Adjusted mapped write range %d: %.8X-%.8X (%p)\n", m68ki_cpu.write_ranges, addr, upper, ptr);
1335 if (m68ki_cpu.read_ranges + 1 < 8) {
1336 m68ki_cpu.read_addr[m68ki_cpu.read_ranges] = addr;
1337 m68ki_cpu.read_upper[m68ki_cpu.read_ranges] = upper;
1338 m68ki_cpu.read_data[m68ki_cpu.read_ranges] = ptr;
1339 m68ki_cpu.read_ranges++;
1340 printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", m68ki_cpu.read_ranges, addr, upper, ptr);
1343 printf("Can't Musashi map more than eight RAM/ROM read ranges.\n");
1345 if (m68ki_cpu.write_ranges + 1 < 8) {
1346 m68ki_cpu.write_addr[m68ki_cpu.write_ranges] = addr;
1347 m68ki_cpu.write_upper[m68ki_cpu.write_ranges] = upper;
1348 m68ki_cpu.write_data[m68ki_cpu.write_ranges] = ptr;
1349 m68ki_cpu.write_ranges++;
1350 printf("[MUSASHI] Mapped write range %d: %.8X-%.8X (%p)\n", m68ki_cpu.write_ranges, addr, upper, ptr);
1353 printf("Can't Musashi map more than eight RAM write ranges.\n");
1357 void m68k_add_rom_range(uint32_t addr, uint32_t upper, unsigned char *ptr)
1359 m68ki_cpu.code_translation_cache.lower = 0;
1360 m68ki_cpu.code_translation_cache.upper = 0;
1361 if ((addr == 0 && upper == 0) || upper < addr)
1364 for (int i = 0; i < m68ki_cpu.read_ranges; i++) {
1365 if (m68ki_cpu.read_addr[i] == addr) {
1366 uint8_t changed = 0;
1367 if (m68ki_cpu.read_upper[i] != upper) {
1368 m68ki_cpu.read_upper[i] = upper;
1371 if (m68ki_cpu.read_data[i] != ptr) {
1372 m68ki_cpu.read_data[i] = ptr;
1376 printf("[MUSASHI] Adjusted mapped read range %d: %.8X-%.8X (%p)\n", m68ki_cpu.read_ranges, addr, upper, ptr);
1382 if (m68ki_cpu.read_ranges + 1 < 8) {
1383 m68ki_cpu.read_addr[m68ki_cpu.read_ranges] = addr;
1384 m68ki_cpu.read_upper[m68ki_cpu.read_ranges] = upper;
1385 m68ki_cpu.read_data[m68ki_cpu.read_ranges] = ptr;
1386 m68ki_cpu.read_ranges++;
1387 printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", m68ki_cpu.read_ranges, addr, upper, ptr);
1390 printf("Can't Musashi map more than eight RAM/ROM read ranges.\n");
1394 void m68k_clear_ranges()
1396 printf("[MUSASHI] Clearing all reads/write memory ranges.\n");
1397 for (int i = 0; i < 8; i++) {
1398 m68ki_cpu.read_upper[i] = 0;
1399 m68ki_cpu.read_addr[i] = 0;
1400 m68ki_cpu.read_data[i] = NULL;
1401 m68ki_cpu.write_upper[i] = 0;
1402 m68ki_cpu.write_addr[i] = 0;
1403 m68ki_cpu.write_data[i] = NULL;
1405 m68ki_cpu.write_ranges = 0;
1406 m68ki_cpu.read_ranges = 0;
1407 m68ki_cpu.code_translation_cache.lower = 0;
1408 m68ki_cpu.code_translation_cache.upper = 0;
1411 /* ======================================================================== */
1412 /* ============================== MAME STUFF ============================== */
1413 /* ======================================================================== */
1415 #if M68K_COMPILE_FOR_MAME == OPT_ON
1423 static void m68k_prepare_substate(void)
1425 m68k_substate.sr = m68ki_get_sr();
1426 m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
1427 m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
1430 static void m68k_post_load(void)
1432 m68ki_set_sr_noint_nosp(m68k_substate.sr);
1433 CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
1434 | m68k_substate.halted ? STOP_LEVEL_HALT : 0;
1438 void m68k_state_register(const char *type, int index)
1440 /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */
1441 state_save_register_item_array(type, index, REG_D);
1442 state_save_register_item(type, index, REG_PPC);
1443 state_save_register_item(type, index, REG_PC);
1444 state_save_register_item(type, index, REG_USP);
1445 state_save_register_item(type, index, REG_ISP);
1446 state_save_register_item(type, index, REG_MSP);
1447 state_save_register_item(type, index, REG_VBR);
1448 state_save_register_item(type, index, REG_SFC);
1449 state_save_register_item(type, index, REG_DFC);
1450 state_save_register_item(type, index, REG_CACR);
1451 state_save_register_item(type, index, REG_CAAR);
1452 state_save_register_item(type, index, m68k_substate.sr);
1453 state_save_register_item(type, index, CPU_INT_LEVEL);
1454 state_save_register_item(type, index, m68k_substate.stopped);
1455 state_save_register_item(type, index, m68k_substate.halted);
1456 state_save_register_item(type, index, CPU_PREF_ADDR);
1457 state_save_register_item(type, index, CPU_PREF_DATA);
1458 state_save_register_func_presave(m68k_prepare_substate);
1459 state_save_register_func_postload(m68k_post_load);
1462 #endif /* M68K_COMPILE_FOR_MAME */
1464 /* ======================================================================== */
1465 /* ============================== END OF FILE ============================= */
1466 /* ======================================================================== */