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 /* ======================================================================== */
41 extern void m68040_fpu_op0(void);
42 extern void m68040_fpu_op1(void);
43 extern void m68881_mmu_ops();
44 extern unsigned char m68ki_cycles[][0x10000];
45 extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */
46 extern void m68ki_build_opcode_table(void);
52 #include "m68kmmu.h" // uses some functions from m68kfpu.c which are static !
54 /* ======================================================================== */
55 /* ================================= DATA ================================= */
56 /* ======================================================================== */
58 int m68ki_initial_cycles;
59 int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
60 uint m68ki_tracing = 0;
61 uint m68ki_address_space;
63 #ifdef M68K_LOG_ENABLE
64 const char *const m68ki_cpu_names[] =
76 #endif /* M68K_LOG_ENABLE */
79 m68ki_cpu_core m68ki_cpu = {0};
81 #if M68K_EMULATE_ADDRESS_ERROR
83 sigjmp_buf m68ki_aerr_trap;
85 jmp_buf m68ki_aerr_trap;
87 #endif /* M68K_EMULATE_ADDRESS_ERROR */
89 uint m68ki_aerr_address;
90 uint m68ki_aerr_write_mode;
93 jmp_buf m68ki_bus_error_jmp_buf;
95 /* Used by shift & rotate instructions */
96 const uint8 m68ki_shift_8_table[65] =
98 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
103 0xff, 0xff, 0xff, 0xff, 0xff
105 const uint16 m68ki_shift_16_table[65] =
107 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
108 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 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,
113 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
116 const uint m68ki_shift_32_table[65] =
118 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
119 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
120 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
121 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
122 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
123 0xfffffffc, 0xfffffffe, 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, 0xffffffff,
128 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
132 /* Number of clock cycles to use for exception processing.
133 * I used 4 for any vectors that are undocumented for processing times.
135 const uint8 m68ki_exception_cycle_table[5][256] =
138 40, /* 0: Reset - Initial Stack Pointer */
139 4, /* 1: Reset - Initial Program Counter */
140 50, /* 2: Bus Error (unemulated) */
141 50, /* 3: Address Error (unemulated) */
142 34, /* 4: Illegal Instruction */
143 38, /* 5: Divide by Zero */
146 34, /* 8: Privilege Violation */
150 4, /* 12: RESERVED */
151 4, /* 13: Coprocessor Protocol Violation (unemulated) */
152 4, /* 14: Format Error */
153 44, /* 15: Uninitialized Interrupt */
154 4, /* 16: RESERVED */
155 4, /* 17: RESERVED */
156 4, /* 18: RESERVED */
157 4, /* 19: RESERVED */
158 4, /* 20: RESERVED */
159 4, /* 21: RESERVED */
160 4, /* 22: RESERVED */
161 4, /* 23: RESERVED */
162 44, /* 24: Spurious Interrupt */
163 44, /* 25: Level 1 Interrupt Autovector */
164 44, /* 26: Level 2 Interrupt Autovector */
165 44, /* 27: Level 3 Interrupt Autovector */
166 44, /* 28: Level 4 Interrupt Autovector */
167 44, /* 29: Level 5 Interrupt Autovector */
168 44, /* 30: Level 6 Interrupt Autovector */
169 44, /* 31: Level 7 Interrupt Autovector */
170 34, /* 32: TRAP #0 */
171 34, /* 33: TRAP #1 */
172 34, /* 34: TRAP #2 */
173 34, /* 35: TRAP #3 */
174 34, /* 36: TRAP #4 */
175 34, /* 37: TRAP #5 */
176 34, /* 38: TRAP #6 */
177 34, /* 39: TRAP #7 */
178 34, /* 40: TRAP #8 */
179 34, /* 41: TRAP #9 */
180 34, /* 42: TRAP #10 */
181 34, /* 43: TRAP #11 */
182 34, /* 44: TRAP #12 */
183 34, /* 45: TRAP #13 */
184 34, /* 46: TRAP #14 */
185 34, /* 47: TRAP #15 */
186 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
187 4, /* 49: FP Inexact Result (unemulated) */
188 4, /* 50: FP Divide by Zero (unemulated) */
189 4, /* 51: FP Underflow (unemulated) */
190 4, /* 52: FP Operand Error (unemulated) */
191 4, /* 53: FP Overflow (unemulated) */
192 4, /* 54: FP Signaling NAN (unemulated) */
193 4, /* 55: FP Unimplemented Data Type (unemulated) */
194 4, /* 56: MMU Configuration Error (unemulated) */
195 4, /* 57: MMU Illegal Operation Error (unemulated) */
196 4, /* 58: MMU Access Level Violation Error (unemulated) */
197 4, /* 59: RESERVED */
198 4, /* 60: RESERVED */
199 4, /* 61: RESERVED */
200 4, /* 62: RESERVED */
201 4, /* 63: RESERVED */
202 /* 64-255: User Defined */
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,
208 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
211 40, /* 0: Reset - Initial Stack Pointer */
212 4, /* 1: Reset - Initial Program Counter */
213 126, /* 2: Bus Error (unemulated) */
214 126, /* 3: Address Error (unemulated) */
215 38, /* 4: Illegal Instruction */
216 44, /* 5: Divide by Zero */
219 38, /* 8: Privilege Violation */
223 4, /* 12: RESERVED */
224 4, /* 13: Coprocessor Protocol Violation (unemulated) */
225 4, /* 14: Format Error */
226 44, /* 15: Uninitialized Interrupt */
227 4, /* 16: RESERVED */
228 4, /* 17: RESERVED */
229 4, /* 18: RESERVED */
230 4, /* 19: RESERVED */
231 4, /* 20: RESERVED */
232 4, /* 21: RESERVED */
233 4, /* 22: RESERVED */
234 4, /* 23: RESERVED */
235 46, /* 24: Spurious Interrupt */
236 46, /* 25: Level 1 Interrupt Autovector */
237 46, /* 26: Level 2 Interrupt Autovector */
238 46, /* 27: Level 3 Interrupt Autovector */
239 46, /* 28: Level 4 Interrupt Autovector */
240 46, /* 29: Level 5 Interrupt Autovector */
241 46, /* 30: Level 6 Interrupt Autovector */
242 46, /* 31: Level 7 Interrupt Autovector */
243 38, /* 32: TRAP #0 */
244 38, /* 33: TRAP #1 */
245 38, /* 34: TRAP #2 */
246 38, /* 35: TRAP #3 */
247 38, /* 36: TRAP #4 */
248 38, /* 37: TRAP #5 */
249 38, /* 38: TRAP #6 */
250 38, /* 39: TRAP #7 */
251 38, /* 40: TRAP #8 */
252 38, /* 41: TRAP #9 */
253 38, /* 42: TRAP #10 */
254 38, /* 43: TRAP #11 */
255 38, /* 44: TRAP #12 */
256 38, /* 45: TRAP #13 */
257 38, /* 46: TRAP #14 */
258 38, /* 47: TRAP #15 */
259 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
260 4, /* 49: FP Inexact Result (unemulated) */
261 4, /* 50: FP Divide by Zero (unemulated) */
262 4, /* 51: FP Underflow (unemulated) */
263 4, /* 52: FP Operand Error (unemulated) */
264 4, /* 53: FP Overflow (unemulated) */
265 4, /* 54: FP Signaling NAN (unemulated) */
266 4, /* 55: FP Unimplemented Data Type (unemulated) */
267 4, /* 56: MMU Configuration Error (unemulated) */
268 4, /* 57: MMU Illegal Operation Error (unemulated) */
269 4, /* 58: MMU Access Level Violation Error (unemulated) */
270 4, /* 59: RESERVED */
271 4, /* 60: RESERVED */
272 4, /* 61: RESERVED */
273 4, /* 62: RESERVED */
274 4, /* 63: RESERVED */
275 /* 64-255: User Defined */
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,
281 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
284 4, /* 0: Reset - Initial Stack Pointer */
285 4, /* 1: Reset - Initial Program Counter */
286 50, /* 2: Bus Error (unemulated) */
287 50, /* 3: Address Error (unemulated) */
288 20, /* 4: Illegal Instruction */
289 38, /* 5: Divide by Zero */
292 34, /* 8: Privilege Violation */
296 4, /* 12: RESERVED */
297 4, /* 13: Coprocessor Protocol Violation (unemulated) */
298 4, /* 14: Format Error */
299 30, /* 15: Uninitialized Interrupt */
300 4, /* 16: RESERVED */
301 4, /* 17: RESERVED */
302 4, /* 18: RESERVED */
303 4, /* 19: RESERVED */
304 4, /* 20: RESERVED */
305 4, /* 21: RESERVED */
306 4, /* 22: RESERVED */
307 4, /* 23: RESERVED */
308 30, /* 24: Spurious Interrupt */
309 30, /* 25: Level 1 Interrupt Autovector */
310 30, /* 26: Level 2 Interrupt Autovector */
311 30, /* 27: Level 3 Interrupt Autovector */
312 30, /* 28: Level 4 Interrupt Autovector */
313 30, /* 29: Level 5 Interrupt Autovector */
314 30, /* 30: Level 6 Interrupt Autovector */
315 30, /* 31: Level 7 Interrupt Autovector */
316 20, /* 32: TRAP #0 */
317 20, /* 33: TRAP #1 */
318 20, /* 34: TRAP #2 */
319 20, /* 35: TRAP #3 */
320 20, /* 36: TRAP #4 */
321 20, /* 37: TRAP #5 */
322 20, /* 38: TRAP #6 */
323 20, /* 39: TRAP #7 */
324 20, /* 40: TRAP #8 */
325 20, /* 41: TRAP #9 */
326 20, /* 42: TRAP #10 */
327 20, /* 43: TRAP #11 */
328 20, /* 44: TRAP #12 */
329 20, /* 45: TRAP #13 */
330 20, /* 46: TRAP #14 */
331 20, /* 47: TRAP #15 */
332 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
333 4, /* 49: FP Inexact Result (unemulated) */
334 4, /* 50: FP Divide by Zero (unemulated) */
335 4, /* 51: FP Underflow (unemulated) */
336 4, /* 52: FP Operand Error (unemulated) */
337 4, /* 53: FP Overflow (unemulated) */
338 4, /* 54: FP Signaling NAN (unemulated) */
339 4, /* 55: FP Unimplemented Data Type (unemulated) */
340 4, /* 56: MMU Configuration Error (unemulated) */
341 4, /* 57: MMU Illegal Operation Error (unemulated) */
342 4, /* 58: MMU Access Level Violation Error (unemulated) */
343 4, /* 59: RESERVED */
344 4, /* 60: RESERVED */
345 4, /* 61: RESERVED */
346 4, /* 62: RESERVED */
347 4, /* 63: RESERVED */
348 /* 64-255: User Defined */
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,
354 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
356 { /* 030 - not correct */
357 4, /* 0: Reset - Initial Stack Pointer */
358 4, /* 1: Reset - Initial Program Counter */
359 50, /* 2: Bus Error (unemulated) */
360 50, /* 3: Address Error (unemulated) */
361 20, /* 4: Illegal Instruction */
362 38, /* 5: Divide by Zero */
365 34, /* 8: Privilege Violation */
369 4, /* 12: RESERVED */
370 4, /* 13: Coprocessor Protocol Violation (unemulated) */
371 4, /* 14: Format Error */
372 30, /* 15: Uninitialized Interrupt */
373 4, /* 16: RESERVED */
374 4, /* 17: RESERVED */
375 4, /* 18: RESERVED */
376 4, /* 19: RESERVED */
377 4, /* 20: RESERVED */
378 4, /* 21: RESERVED */
379 4, /* 22: RESERVED */
380 4, /* 23: RESERVED */
381 30, /* 24: Spurious Interrupt */
382 30, /* 25: Level 1 Interrupt Autovector */
383 30, /* 26: Level 2 Interrupt Autovector */
384 30, /* 27: Level 3 Interrupt Autovector */
385 30, /* 28: Level 4 Interrupt Autovector */
386 30, /* 29: Level 5 Interrupt Autovector */
387 30, /* 30: Level 6 Interrupt Autovector */
388 30, /* 31: Level 7 Interrupt Autovector */
389 20, /* 32: TRAP #0 */
390 20, /* 33: TRAP #1 */
391 20, /* 34: TRAP #2 */
392 20, /* 35: TRAP #3 */
393 20, /* 36: TRAP #4 */
394 20, /* 37: TRAP #5 */
395 20, /* 38: TRAP #6 */
396 20, /* 39: TRAP #7 */
397 20, /* 40: TRAP #8 */
398 20, /* 41: TRAP #9 */
399 20, /* 42: TRAP #10 */
400 20, /* 43: TRAP #11 */
401 20, /* 44: TRAP #12 */
402 20, /* 45: TRAP #13 */
403 20, /* 46: TRAP #14 */
404 20, /* 47: TRAP #15 */
405 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
406 4, /* 49: FP Inexact Result (unemulated) */
407 4, /* 50: FP Divide by Zero (unemulated) */
408 4, /* 51: FP Underflow (unemulated) */
409 4, /* 52: FP Operand Error (unemulated) */
410 4, /* 53: FP Overflow (unemulated) */
411 4, /* 54: FP Signaling NAN (unemulated) */
412 4, /* 55: FP Unimplemented Data Type (unemulated) */
413 4, /* 56: MMU Configuration Error (unemulated) */
414 4, /* 57: MMU Illegal Operation Error (unemulated) */
415 4, /* 58: MMU Access Level Violation Error (unemulated) */
416 4, /* 59: RESERVED */
417 4, /* 60: RESERVED */
418 4, /* 61: RESERVED */
419 4, /* 62: RESERVED */
420 4, /* 63: RESERVED */
421 /* 64-255: User Defined */
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,
427 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
429 { /* 040 */ // TODO: these values are not correct
430 4, /* 0: Reset - Initial Stack Pointer */
431 4, /* 1: Reset - Initial Program Counter */
432 50, /* 2: Bus Error (unemulated) */
433 50, /* 3: Address Error (unemulated) */
434 20, /* 4: Illegal Instruction */
435 38, /* 5: Divide by Zero */
438 34, /* 8: Privilege Violation */
442 4, /* 12: RESERVED */
443 4, /* 13: Coprocessor Protocol Violation (unemulated) */
444 4, /* 14: Format Error */
445 30, /* 15: Uninitialized Interrupt */
446 4, /* 16: RESERVED */
447 4, /* 17: RESERVED */
448 4, /* 18: RESERVED */
449 4, /* 19: RESERVED */
450 4, /* 20: RESERVED */
451 4, /* 21: RESERVED */
452 4, /* 22: RESERVED */
453 4, /* 23: RESERVED */
454 30, /* 24: Spurious Interrupt */
455 30, /* 25: Level 1 Interrupt Autovector */
456 30, /* 26: Level 2 Interrupt Autovector */
457 30, /* 27: Level 3 Interrupt Autovector */
458 30, /* 28: Level 4 Interrupt Autovector */
459 30, /* 29: Level 5 Interrupt Autovector */
460 30, /* 30: Level 6 Interrupt Autovector */
461 30, /* 31: Level 7 Interrupt Autovector */
462 20, /* 32: TRAP #0 */
463 20, /* 33: TRAP #1 */
464 20, /* 34: TRAP #2 */
465 20, /* 35: TRAP #3 */
466 20, /* 36: TRAP #4 */
467 20, /* 37: TRAP #5 */
468 20, /* 38: TRAP #6 */
469 20, /* 39: TRAP #7 */
470 20, /* 40: TRAP #8 */
471 20, /* 41: TRAP #9 */
472 20, /* 42: TRAP #10 */
473 20, /* 43: TRAP #11 */
474 20, /* 44: TRAP #12 */
475 20, /* 45: TRAP #13 */
476 20, /* 46: TRAP #14 */
477 20, /* 47: TRAP #15 */
478 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
479 4, /* 49: FP Inexact Result (unemulated) */
480 4, /* 50: FP Divide by Zero (unemulated) */
481 4, /* 51: FP Underflow (unemulated) */
482 4, /* 52: FP Operand Error (unemulated) */
483 4, /* 53: FP Overflow (unemulated) */
484 4, /* 54: FP Signaling NAN (unemulated) */
485 4, /* 55: FP Unimplemented Data Type (unemulated) */
486 4, /* 56: MMU Configuration Error (unemulated) */
487 4, /* 57: MMU Illegal Operation Error (unemulated) */
488 4, /* 58: MMU Access Level Violation Error (unemulated) */
489 4, /* 59: RESERVED */
490 4, /* 60: RESERVED */
491 4, /* 61: RESERVED */
492 4, /* 62: RESERVED */
493 4, /* 63: RESERVED */
494 /* 64-255: User Defined */
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,
500 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
504 const uint8 m68ki_ea_idx_cycle_table[64] =
506 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
507 0, /* ..01.000 no memory indirect, base NULL */
508 5, /* ..01..01 memory indirect, base NULL, outer NULL */
509 7, /* ..01..10 memory indirect, base NULL, outer 16 */
510 7, /* ..01..11 memory indirect, base NULL, outer 32 */
511 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
512 2, /* ..10.000 no memory indirect, base 16 */
513 7, /* ..10..01 memory indirect, base 16, outer NULL */
514 9, /* ..10..10 memory indirect, base 16, outer 16 */
515 9, /* ..10..11 memory indirect, base 16, outer 32 */
516 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
517 6, /* ..11.000 no memory indirect, base 32 */
518 11, /* ..11..01 memory indirect, base 32, outer NULL */
519 13, /* ..11..10 memory indirect, base 32, outer 16 */
520 13, /* ..11..11 memory indirect, base 32, outer 32 */
521 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
526 /* ======================================================================== */
527 /* =============================== CALLBACKS ============================== */
528 /* ======================================================================== */
530 /* Default callbacks used if the callback hasn't been set yet, or if the
531 * callback is set to NULL
534 /* Interrupt acknowledge */
535 static int default_int_ack_callback_data;
536 static int default_int_ack_callback(int int_level)
538 default_int_ack_callback_data = int_level;
540 return M68K_INT_ACK_AUTOVECTOR;
543 /* Breakpoint acknowledge */
544 static unsigned int default_bkpt_ack_callback_data;
545 static void default_bkpt_ack_callback(unsigned int data)
547 default_bkpt_ack_callback_data = data;
550 /* Called when a reset instruction is executed */
551 static void default_reset_instr_callback(void)
555 /* Called when a cmpi.l #v, dn instruction is executed */
556 static void default_cmpild_instr_callback(unsigned int val, int reg)
562 /* Called when a rte instruction is executed */
563 static void default_rte_instr_callback(void)
567 /* Called when a tas instruction is executed */
568 static int default_tas_instr_callback(void)
570 return 1; // allow writeback
573 /* Called when an illegal instruction is encountered */
574 static int default_illg_instr_callback(int opcode)
577 return 0; // not handled : exception will occur
580 /* Called when the program counter changed by a large value */
581 static unsigned int default_pc_changed_callback_data;
582 static void default_pc_changed_callback(unsigned int new_pc)
584 default_pc_changed_callback_data = new_pc;
587 /* Called every time there's bus activity (read/write to/from memory */
588 static unsigned int default_set_fc_callback_data;
589 static void default_set_fc_callback(unsigned int new_fc)
591 default_set_fc_callback_data = new_fc;
594 /* Called every instruction cycle prior to execution */
595 static void default_instr_hook_callback(unsigned int pc)
601 #if M68K_EMULATE_ADDRESS_ERROR
604 sigjmp_buf m68ki_aerr_trap;
606 jmp_buf m68ki_aerr_trap;
608 #endif /* M68K_EMULATE_ADDRESS_ERROR */
610 /* ======================================================================== */
611 /* ================================= API ================================== */
612 /* ======================================================================== */
614 /* Access the internals of the CPU */
615 unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
617 m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
621 case M68K_REG_D0: return cpu->dar[0];
622 case M68K_REG_D1: return cpu->dar[1];
623 case M68K_REG_D2: return cpu->dar[2];
624 case M68K_REG_D3: return cpu->dar[3];
625 case M68K_REG_D4: return cpu->dar[4];
626 case M68K_REG_D5: return cpu->dar[5];
627 case M68K_REG_D6: return cpu->dar[6];
628 case M68K_REG_D7: return cpu->dar[7];
629 case M68K_REG_A0: return cpu->dar[8];
630 case M68K_REG_A1: return cpu->dar[9];
631 case M68K_REG_A2: return cpu->dar[10];
632 case M68K_REG_A3: return cpu->dar[11];
633 case M68K_REG_A4: return cpu->dar[12];
634 case M68K_REG_A5: return cpu->dar[13];
635 case M68K_REG_A6: return cpu->dar[14];
636 case M68K_REG_A7: return cpu->dar[15];
637 case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
638 case M68K_REG_SR: return cpu->t1_flag |
640 (cpu->s_flag << 11) |
641 (cpu->m_flag << 11) |
643 ((cpu->x_flag & XFLAG_SET) >> 4) |
644 ((cpu->n_flag & NFLAG_SET) >> 4) |
645 ((!cpu->not_z_flag) << 2) |
646 ((cpu->v_flag & VFLAG_SET) >> 6) |
647 ((cpu->c_flag & CFLAG_SET) >> 8);
648 case M68K_REG_SP: return cpu->dar[15];
649 case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
650 case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
651 case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
652 case M68K_REG_SFC: return cpu->sfc;
653 case M68K_REG_DFC: return cpu->dfc;
654 case M68K_REG_VBR: return cpu->vbr;
655 case M68K_REG_CACR: return cpu->cacr;
656 case M68K_REG_CAAR: return cpu->caar;
657 case M68K_REG_PREF_ADDR: return cpu->pref_addr;
658 case M68K_REG_PREF_DATA: return cpu->pref_data;
659 case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
660 case M68K_REG_IR: return cpu->ir;
661 case M68K_REG_CPU_TYPE:
662 switch(cpu->cpu_type)
664 case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
665 case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
666 case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
667 case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
668 case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040;
670 return M68K_CPU_TYPE_INVALID;
676 void m68k_set_reg(m68k_register_t regnum, unsigned int value)
680 case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
681 case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
682 case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
683 case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
684 case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
685 case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
686 case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
687 case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
688 case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
689 case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
690 case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
691 case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
692 case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
693 case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
694 case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
695 case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
696 case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
697 case M68K_REG_SR: m68ki_set_sr_noint_nosp(value); return;
698 case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
699 case M68K_REG_USP: if(FLAG_S)
700 REG_USP = MASK_OUT_ABOVE_32(value);
702 REG_SP = MASK_OUT_ABOVE_32(value);
704 case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
705 REG_SP = MASK_OUT_ABOVE_32(value);
707 REG_ISP = MASK_OUT_ABOVE_32(value);
709 case M68K_REG_MSP: if(FLAG_S && FLAG_M)
710 REG_SP = MASK_OUT_ABOVE_32(value);
712 REG_MSP = MASK_OUT_ABOVE_32(value);
714 case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
715 case M68K_REG_SFC: REG_SFC = value & 7; return;
716 case M68K_REG_DFC: REG_DFC = value & 7; return;
717 case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
718 case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
719 case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
720 case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
721 case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
726 /* Set the callbacks */
727 void m68k_set_int_ack_callback(int (*callback)(int int_level))
729 CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
732 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
734 CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
737 void m68k_set_reset_instr_callback(void (*callback)(void))
739 CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
742 void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int))
744 CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback;
747 void m68k_set_rte_instr_callback(void (*callback)(void))
749 CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback;
752 void m68k_set_tas_instr_callback(int (*callback)(void))
754 CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
757 void m68k_set_illg_instr_callback(int (*callback)(int))
759 CALLBACK_ILLG_INSTR = callback ? callback : default_illg_instr_callback;
762 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
764 CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
767 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
769 CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
772 void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc))
774 CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
777 /* Set the CPU type. */
778 void m68k_set_cpu_type(unsigned int cpu_type)
782 case M68K_CPU_TYPE_68000:
783 CPU_TYPE = CPU_TYPE_000;
784 CPU_ADDRESS_MASK = 0x00ffffff;
785 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
786 CYC_INSTRUCTION = m68ki_cycles[0];
787 CYC_EXCEPTION = m68ki_exception_cycle_table[0];
788 CYC_BCC_NOTAKE_B = -2;
789 CYC_BCC_NOTAKE_W = 2;
790 CYC_DBCC_F_NOEXP = -2;
800 case M68K_CPU_TYPE_SCC68070:
801 m68k_set_cpu_type(M68K_CPU_TYPE_68010);
802 CPU_ADDRESS_MASK = 0xffffffff;
803 CPU_TYPE = CPU_TYPE_SCC070;
805 case M68K_CPU_TYPE_68010:
806 CPU_TYPE = CPU_TYPE_010;
807 CPU_ADDRESS_MASK = 0x00ffffff;
808 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
809 CYC_INSTRUCTION = m68ki_cycles[1];
810 CYC_EXCEPTION = m68ki_exception_cycle_table[1];
811 CYC_BCC_NOTAKE_B = -4;
812 CYC_BCC_NOTAKE_W = 0;
813 CYC_DBCC_F_NOEXP = 0;
823 case M68K_CPU_TYPE_68EC020:
824 CPU_TYPE = CPU_TYPE_EC020;
825 CPU_ADDRESS_MASK = 0x00ffffff;
826 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
827 CYC_INSTRUCTION = m68ki_cycles[2];
828 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
829 CYC_BCC_NOTAKE_B = -2;
830 CYC_BCC_NOTAKE_W = 0;
831 CYC_DBCC_F_NOEXP = 0;
841 case M68K_CPU_TYPE_68020:
842 CPU_TYPE = CPU_TYPE_020;
843 CPU_ADDRESS_MASK = 0xffffffff;
844 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
845 CYC_INSTRUCTION = m68ki_cycles[2];
846 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
847 CYC_BCC_NOTAKE_B = -2;
848 CYC_BCC_NOTAKE_W = 0;
849 CYC_DBCC_F_NOEXP = 0;
859 case M68K_CPU_TYPE_68030:
860 CPU_TYPE = CPU_TYPE_030;
861 CPU_ADDRESS_MASK = 0xffffffff;
862 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
863 CYC_INSTRUCTION = m68ki_cycles[3];
864 CYC_EXCEPTION = m68ki_exception_cycle_table[3];
865 CYC_BCC_NOTAKE_B = -2;
866 CYC_BCC_NOTAKE_W = 0;
867 CYC_DBCC_F_NOEXP = 0;
877 case M68K_CPU_TYPE_68EC030:
878 CPU_TYPE = CPU_TYPE_EC030;
879 CPU_ADDRESS_MASK = 0xffffffff;
880 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
881 CYC_INSTRUCTION = m68ki_cycles[3];
882 CYC_EXCEPTION = m68ki_exception_cycle_table[3];
883 CYC_BCC_NOTAKE_B = -2;
884 CYC_BCC_NOTAKE_W = 0;
885 CYC_DBCC_F_NOEXP = 0;
892 HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */
895 case M68K_CPU_TYPE_68040: // TODO: these values are not correct
896 CPU_TYPE = CPU_TYPE_040;
897 CPU_ADDRESS_MASK = 0xffffffff;
898 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
899 CYC_INSTRUCTION = m68ki_cycles[4];
900 CYC_EXCEPTION = m68ki_exception_cycle_table[4];
901 CYC_BCC_NOTAKE_B = -2;
902 CYC_BCC_NOTAKE_W = 0;
903 CYC_DBCC_F_NOEXP = 0;
913 case M68K_CPU_TYPE_68EC040: // Just a 68040 without pmmu apparently...
914 CPU_TYPE = CPU_TYPE_EC040;
915 CPU_ADDRESS_MASK = 0xffffffff;
916 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
917 CYC_INSTRUCTION = m68ki_cycles[4];
918 CYC_EXCEPTION = m68ki_exception_cycle_table[4];
919 CYC_BCC_NOTAKE_B = -2;
920 CYC_BCC_NOTAKE_W = 0;
921 CYC_DBCC_F_NOEXP = 0;
931 case M68K_CPU_TYPE_68LC040:
932 CPU_TYPE = CPU_TYPE_LC040;
933 CPU_ADDRESS_MASK = 0xffffffff;
934 m68ki_cpu.sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
935 m68ki_cpu.cyc_instruction = m68ki_cycles[4];
936 m68ki_cpu.cyc_exception = m68ki_exception_cycle_table[4];
937 m68ki_cpu.cyc_bcc_notake_b = -2;
938 m68ki_cpu.cyc_bcc_notake_w = 0;
939 m68ki_cpu.cyc_dbcc_f_noexp = 0;
940 m68ki_cpu.cyc_dbcc_f_exp = 4;
941 m68ki_cpu.cyc_scc_r_true = 0;
942 m68ki_cpu.cyc_movem_w = 2;
943 m68ki_cpu.cyc_movem_l = 2;
944 m68ki_cpu.cyc_shift = 0;
945 m68ki_cpu.cyc_reset = 518;
952 uint m68k_get_address_mask() {
953 return m68ki_cpu.address_mask;
956 /* Execute some instructions until we use up num_cycles clock cycles */
957 /* ASG: removed per-instruction interrupt checks */
958 int m68k_execute(int num_cycles)
960 /* eat up any reset cycles */
962 int rc = RESET_CYCLES;
969 /* Set our pool of clock cycles available */
970 SET_CYCLES(num_cycles);
971 m68ki_initial_cycles = num_cycles;
973 /* See if interrupts came in */
974 m68ki_check_interrupts();
976 /* Make sure we're not stopped */
979 /* Return point if we had an address error */
980 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
982 #ifdef M68K_BUSERR_THING
983 m68ki_check_bus_error_trap();
986 /* Main loop. Keep going until we run out of clock cycles */
989 #ifdef M68K_BUSERR_THING
992 /* Set tracing accodring to T1. (T0 is done inside instruction) */
993 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
995 /* Set the address space for reads */
996 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
998 /* Call external hook to peek at CPU */
999 m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
1001 /* Record previous program counter */
1004 /* Record previous D/A register state (in case of bus error) */
1005 #ifdef M68K_BUSERR_THING
1006 for (i = 15; i >= 0; i--){
1007 REG_DA_SAVE[i] = REG_DA[i];
1011 /* Read an instruction and call its handler */
1012 REG_IR = m68ki_read_imm_16();
1013 m68ki_instruction_jump_table[REG_IR]();
1014 USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
1016 /* Trace m68k_exception, if necessary */
1017 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
1018 } while(GET_CYCLES() > 0);
1020 /* set previous PC to current PC for the next entry into the loop */
1026 /* return how many clocks we used */
1027 return m68ki_initial_cycles - GET_CYCLES();
1031 int m68k_cycles_run(void)
1033 return m68ki_initial_cycles - GET_CYCLES();
1036 int m68k_cycles_remaining(void)
1038 return GET_CYCLES();
1041 /* Change the timeslice */
1042 void m68k_modify_timeslice(int cycles)
1044 m68ki_initial_cycles += cycles;
1049 void m68k_end_timeslice(void)
1051 m68ki_initial_cycles = GET_CYCLES();
1056 /* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
1057 /* KS: Modified so that IPL* bits match with mask positions in the SR
1058 * and cleaned out remenants of the interrupt controller.
1060 void m68k_set_irq(unsigned int int_level)
1062 uint old_level = CPU_INT_LEVEL;
1063 CPU_INT_LEVEL = int_level << 8;
1065 /* A transition from < 7 to 7 always interrupts (NMI) */
1066 /* Note: Level 7 can also level trigger like a normal IRQ */
1067 if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
1068 m68ki_cpu.nmi_pending = TRUE;
1071 void m68k_set_virq(unsigned int level, unsigned int active)
1073 uint state = m68ki_cpu.virq_state;
1077 state |= 1 << level;
1079 state &= ~(1 << level);
1080 m68ki_cpu.virq_state = state;
1082 for(blevel = 7; blevel > 0; blevel--)
1083 if(state & (1 << blevel))
1085 m68k_set_irq(blevel);
1088 unsigned int m68k_get_virq(unsigned int level)
1090 return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0;
1093 void m68k_init(void)
1095 static uint emulation_initialized = 0;
1097 /* The first call to this function initializes the opcode handler jump table */
1098 if(!emulation_initialized)
1100 m68ki_build_opcode_table();
1101 emulation_initialized = 1;
1104 m68k_set_int_ack_callback(NULL);
1105 m68k_set_bkpt_ack_callback(NULL);
1106 m68k_set_reset_instr_callback(NULL);
1107 m68k_set_cmpild_instr_callback(NULL);
1108 m68k_set_rte_instr_callback(NULL);
1109 m68k_set_tas_instr_callback(NULL);
1110 m68k_set_illg_instr_callback(NULL);
1111 m68k_set_pc_changed_callback(NULL);
1112 m68k_set_fc_callback(NULL);
1113 m68k_set_instr_hook_callback(NULL);
1116 /* Trigger a Bus Error exception */
1117 void m68k_pulse_bus_error(void)
1119 m68ki_exception_bus_error();
1122 /* Pulse the RESET line on the CPU */
1123 void m68k_pulse_reset(void)
1125 /* Disable the PMMU on reset */
1126 m68ki_cpu.pmmu_enabled = 0;
1128 /* Clear all stop levels and eat up all remaining cycles */
1132 CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
1133 CPU_INSTR_MODE = INSTRUCTION_YES;
1135 /* Turn off tracing */
1136 FLAG_T1 = FLAG_T0 = 0;
1137 m68ki_clear_trace();
1138 /* Interrupt mask to level 7 */
1139 FLAG_INT_MASK = 0x0700;
1141 m68ki_cpu.virq_state = 0;
1144 /* Go to supervisor mode */
1145 m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
1147 /* Invalidate the prefetch queue */
1148 #if M68K_EMULATE_PREFETCH
1149 /* Set to arbitrary number since our first fetch is from 0 */
1150 CPU_PREF_ADDR = 0x1000;
1151 #endif /* M68K_EMULATE_PREFETCH */
1153 /* Read the initial stack pointer and program counter */
1155 REG_SP = m68ki_read_imm_32();
1156 REG_PC = m68ki_read_imm_32();
1159 CPU_RUN_MODE = RUN_MODE_NORMAL;
1161 RESET_CYCLES = CYC_EXCEPTION[EXCEPTION_RESET];
1164 /* Pulse the HALT line on the CPU */
1165 void m68k_pulse_halt(void)
1167 CPU_STOPPED |= STOP_LEVEL_HALT;
1170 /* Get and set the current CPU context */
1171 /* This is to allow for multiple CPUs */
1172 unsigned int m68k_context_size()
1174 return sizeof(m68ki_cpu_core);
1177 unsigned int m68k_get_context(void* dst)
1179 if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
1180 return sizeof(m68ki_cpu_core);
1183 void m68k_set_context(void* src)
1185 if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
1188 #if M68K_SEPARATE_READS
1189 /* Read data immediately following the PC */
1190 inline unsigned int m68k_read_immediate_16(unsigned int address) {
1191 #if M68K_EMULATE_PREFETCH == OPT_ON
1192 for (int i = 0; i < read_ranges; i++) {
1193 if(address >= read_addr[i] && address < read_upper[i]) {
1194 return be16toh(((unsigned short *)(read_data[i] + (address - read_addr[i])))[0]);
1199 return m68k_read_memory_16(address);
1201 inline unsigned int m68k_read_immediate_32(unsigned int address) {
1202 #if M68K_EMULATE_PREFETCH == OPT_ON
1203 for (int i = 0; i < read_ranges; i++) {
1204 if(address >= read_addr[i] && address < read_upper[i]) {
1205 return be32toh(((unsigned int *)(read_data[i] + (address - read_addr[i])))[0]);
1210 return m68k_read_memory_32(address);
1213 /* Read data relative to the PC */
1214 inline unsigned int m68k_read_pcrelative_8(unsigned int address) {
1215 for (int i = 0; i < read_ranges; i++) {
1216 if(address >= read_addr[i] && address < read_upper[i]) {
1217 return read_data[i][address - read_addr[i]];
1221 return m68k_read_memory_8(address);
1223 inline unsigned int m68k_read_pcrelative_16(unsigned int address) {
1224 for (int i = 0; i < read_ranges; i++) {
1225 if(address >= read_addr[i] && address < read_upper[i]) {
1226 return be16toh(((unsigned short *)(read_data[i] + (address - read_addr[i])))[0]);
1230 return m68k_read_memory_16(address);
1232 inline unsigned int m68k_read_pcrelative_32(unsigned int address) {
1233 for (int i = 0; i < read_ranges; i++) {
1234 if(address >= read_addr[i] && address < read_upper[i]) {
1235 return be32toh(((unsigned int *)(read_data[i] + (address - read_addr[i])))[0]);
1239 return m68k_read_memory_32(address);
1243 void m68k_add_ram_range(uint32_t addr, uint32_t upper, unsigned char *ptr)
1245 if ((addr == 0 && upper == 0) || upper < addr)
1248 for (int i = 0; i < write_ranges; i++) {
1249 if (write_addr[i] == addr) {
1250 uint8_t changed = 0;
1251 if (write_upper[i] != upper) {
1252 write_upper[i] = upper;
1255 if (write_data[i] != ptr) {
1256 write_data[i] = ptr;
1260 printf("[MUSASHI] Adjusted mapped write range %d: %.8X-%.8X (%p)\n", write_ranges, addr, upper, ptr);
1266 if (read_ranges + 1 < 8) {
1267 read_addr[read_ranges] = addr;
1268 read_upper[read_ranges] = upper;
1269 read_data[read_ranges] = ptr;
1271 printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr);
1274 printf("Can't Musashi map more than eight RAM/ROM read ranges.\n");
1276 if (write_ranges + 1 < 8) {
1277 write_addr[write_ranges] = addr;
1278 write_upper[write_ranges] = upper;
1279 write_data[write_ranges] = ptr;
1281 printf("[MUSASHI] Mapped write range %d: %.8X-%.8X (%p)\n", write_ranges, addr, upper, ptr);
1284 printf("Can't Musashi map more than eight RAM write ranges.\n");
1288 void m68k_add_rom_range(uint32_t addr, uint32_t upper, unsigned char *ptr)
1290 if ((addr == 0 && upper == 0) || upper < addr)
1293 for (int i = 0; i < read_ranges; i++) {
1294 if (read_addr[i] == addr) {
1295 uint8_t changed = 0;
1296 if (read_upper[i] != upper) {
1297 read_upper[i] = upper;
1300 if (read_data[i] != ptr) {
1305 printf("[MUSASHI] Adjusted mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr);
1311 if (read_ranges + 1 < 8) {
1312 read_addr[read_ranges] = addr;
1313 read_upper[read_ranges] = upper;
1314 read_data[read_ranges] = ptr;
1316 printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr);
1319 printf("Can't Musashi map more than eight RAM/ROM read ranges.\n");
1323 /* ======================================================================== */
1324 /* ============================== MAME STUFF ============================== */
1325 /* ======================================================================== */
1327 #if M68K_COMPILE_FOR_MAME == OPT_ON
1335 static void m68k_prepare_substate(void)
1337 m68k_substate.sr = m68ki_get_sr();
1338 m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
1339 m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
1342 static void m68k_post_load(void)
1344 m68ki_set_sr_noint_nosp(m68k_substate.sr);
1345 CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
1346 | m68k_substate.halted ? STOP_LEVEL_HALT : 0;
1350 void m68k_state_register(const char *type, int index)
1352 /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */
1353 state_save_register_item_array(type, index, REG_D);
1354 state_save_register_item(type, index, REG_PPC);
1355 state_save_register_item(type, index, REG_PC);
1356 state_save_register_item(type, index, REG_USP);
1357 state_save_register_item(type, index, REG_ISP);
1358 state_save_register_item(type, index, REG_MSP);
1359 state_save_register_item(type, index, REG_VBR);
1360 state_save_register_item(type, index, REG_SFC);
1361 state_save_register_item(type, index, REG_DFC);
1362 state_save_register_item(type, index, REG_CACR);
1363 state_save_register_item(type, index, REG_CAAR);
1364 state_save_register_item(type, index, m68k_substate.sr);
1365 state_save_register_item(type, index, CPU_INT_LEVEL);
1366 state_save_register_item(type, index, m68k_substate.stopped);
1367 state_save_register_item(type, index, m68k_substate.halted);
1368 state_save_register_item(type, index, CPU_PREF_ADDR);
1369 state_save_register_item(type, index, CPU_PREF_DATA);
1370 state_save_register_func_presave(m68k_prepare_substate);
1371 state_save_register_func_postload(m68k_post_load);
1374 #endif /* M68K_COMPILE_FOR_MAME */
1376 /* ======================================================================== */
1377 /* ============================== END OF FILE ============================= */
1378 /* ======================================================================== */