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);
48 static unsigned char read_ranges;
49 static unsigned int read_addr[8];
50 static unsigned int read_upper[8];
51 static unsigned char *read_data[8];
52 static unsigned char write_ranges;
53 static unsigned int write_addr[8];
54 static unsigned int write_upper[8];
55 static unsigned char *write_data[8];
61 #include "m68kmmu.h" // uses some functions from m68kfpu.c which are static !
63 /* ======================================================================== */
64 /* ================================= DATA ================================= */
65 /* ======================================================================== */
67 int m68ki_initial_cycles;
68 int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
69 uint m68ki_tracing = 0;
70 uint m68ki_address_space;
72 #ifdef M68K_LOG_ENABLE
73 const char *const m68ki_cpu_names[] =
85 #endif /* M68K_LOG_ENABLE */
88 m68ki_cpu_core m68ki_cpu = {0};
90 #if M68K_EMULATE_ADDRESS_ERROR
92 sigjmp_buf m68ki_aerr_trap;
94 jmp_buf m68ki_aerr_trap;
96 #endif /* M68K_EMULATE_ADDRESS_ERROR */
98 uint m68ki_aerr_address;
99 uint m68ki_aerr_write_mode;
102 jmp_buf m68ki_bus_error_jmp_buf;
104 /* Used by shift & rotate instructions */
105 const uint8 m68ki_shift_8_table[65] =
107 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
110 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
111 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
112 0xff, 0xff, 0xff, 0xff, 0xff
114 const uint16 m68ki_shift_16_table[65] =
116 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
117 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
118 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
119 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
120 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
121 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
122 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
125 const uint m68ki_shift_32_table[65] =
127 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
128 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
129 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
130 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
131 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
132 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
133 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
134 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
135 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
136 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
137 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
141 /* Number of clock cycles to use for exception processing.
142 * I used 4 for any vectors that are undocumented for processing times.
144 const uint8 m68ki_exception_cycle_table[5][256] =
147 40, /* 0: Reset - Initial Stack Pointer */
148 4, /* 1: Reset - Initial Program Counter */
149 50, /* 2: Bus Error (unemulated) */
150 50, /* 3: Address Error (unemulated) */
151 34, /* 4: Illegal Instruction */
152 38, /* 5: Divide by Zero */
155 34, /* 8: Privilege Violation */
159 4, /* 12: RESERVED */
160 4, /* 13: Coprocessor Protocol Violation (unemulated) */
161 4, /* 14: Format Error */
162 44, /* 15: Uninitialized Interrupt */
163 4, /* 16: RESERVED */
164 4, /* 17: RESERVED */
165 4, /* 18: RESERVED */
166 4, /* 19: RESERVED */
167 4, /* 20: RESERVED */
168 4, /* 21: RESERVED */
169 4, /* 22: RESERVED */
170 4, /* 23: RESERVED */
171 44, /* 24: Spurious Interrupt */
172 44, /* 25: Level 1 Interrupt Autovector */
173 44, /* 26: Level 2 Interrupt Autovector */
174 44, /* 27: Level 3 Interrupt Autovector */
175 44, /* 28: Level 4 Interrupt Autovector */
176 44, /* 29: Level 5 Interrupt Autovector */
177 44, /* 30: Level 6 Interrupt Autovector */
178 44, /* 31: Level 7 Interrupt Autovector */
179 34, /* 32: TRAP #0 */
180 34, /* 33: TRAP #1 */
181 34, /* 34: TRAP #2 */
182 34, /* 35: TRAP #3 */
183 34, /* 36: TRAP #4 */
184 34, /* 37: TRAP #5 */
185 34, /* 38: TRAP #6 */
186 34, /* 39: TRAP #7 */
187 34, /* 40: TRAP #8 */
188 34, /* 41: TRAP #9 */
189 34, /* 42: TRAP #10 */
190 34, /* 43: TRAP #11 */
191 34, /* 44: TRAP #12 */
192 34, /* 45: TRAP #13 */
193 34, /* 46: TRAP #14 */
194 34, /* 47: TRAP #15 */
195 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
196 4, /* 49: FP Inexact Result (unemulated) */
197 4, /* 50: FP Divide by Zero (unemulated) */
198 4, /* 51: FP Underflow (unemulated) */
199 4, /* 52: FP Operand Error (unemulated) */
200 4, /* 53: FP Overflow (unemulated) */
201 4, /* 54: FP Signaling NAN (unemulated) */
202 4, /* 55: FP Unimplemented Data Type (unemulated) */
203 4, /* 56: MMU Configuration Error (unemulated) */
204 4, /* 57: MMU Illegal Operation Error (unemulated) */
205 4, /* 58: MMU Access Level Violation Error (unemulated) */
206 4, /* 59: RESERVED */
207 4, /* 60: RESERVED */
208 4, /* 61: RESERVED */
209 4, /* 62: RESERVED */
210 4, /* 63: RESERVED */
211 /* 64-255: User Defined */
212 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
213 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
214 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
215 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
216 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
217 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
220 40, /* 0: Reset - Initial Stack Pointer */
221 4, /* 1: Reset - Initial Program Counter */
222 126, /* 2: Bus Error (unemulated) */
223 126, /* 3: Address Error (unemulated) */
224 38, /* 4: Illegal Instruction */
225 44, /* 5: Divide by Zero */
228 38, /* 8: Privilege Violation */
232 4, /* 12: RESERVED */
233 4, /* 13: Coprocessor Protocol Violation (unemulated) */
234 4, /* 14: Format Error */
235 44, /* 15: Uninitialized Interrupt */
236 4, /* 16: RESERVED */
237 4, /* 17: RESERVED */
238 4, /* 18: RESERVED */
239 4, /* 19: RESERVED */
240 4, /* 20: RESERVED */
241 4, /* 21: RESERVED */
242 4, /* 22: RESERVED */
243 4, /* 23: RESERVED */
244 46, /* 24: Spurious Interrupt */
245 46, /* 25: Level 1 Interrupt Autovector */
246 46, /* 26: Level 2 Interrupt Autovector */
247 46, /* 27: Level 3 Interrupt Autovector */
248 46, /* 28: Level 4 Interrupt Autovector */
249 46, /* 29: Level 5 Interrupt Autovector */
250 46, /* 30: Level 6 Interrupt Autovector */
251 46, /* 31: Level 7 Interrupt Autovector */
252 38, /* 32: TRAP #0 */
253 38, /* 33: TRAP #1 */
254 38, /* 34: TRAP #2 */
255 38, /* 35: TRAP #3 */
256 38, /* 36: TRAP #4 */
257 38, /* 37: TRAP #5 */
258 38, /* 38: TRAP #6 */
259 38, /* 39: TRAP #7 */
260 38, /* 40: TRAP #8 */
261 38, /* 41: TRAP #9 */
262 38, /* 42: TRAP #10 */
263 38, /* 43: TRAP #11 */
264 38, /* 44: TRAP #12 */
265 38, /* 45: TRAP #13 */
266 38, /* 46: TRAP #14 */
267 38, /* 47: TRAP #15 */
268 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
269 4, /* 49: FP Inexact Result (unemulated) */
270 4, /* 50: FP Divide by Zero (unemulated) */
271 4, /* 51: FP Underflow (unemulated) */
272 4, /* 52: FP Operand Error (unemulated) */
273 4, /* 53: FP Overflow (unemulated) */
274 4, /* 54: FP Signaling NAN (unemulated) */
275 4, /* 55: FP Unimplemented Data Type (unemulated) */
276 4, /* 56: MMU Configuration Error (unemulated) */
277 4, /* 57: MMU Illegal Operation Error (unemulated) */
278 4, /* 58: MMU Access Level Violation Error (unemulated) */
279 4, /* 59: RESERVED */
280 4, /* 60: RESERVED */
281 4, /* 61: RESERVED */
282 4, /* 62: RESERVED */
283 4, /* 63: RESERVED */
284 /* 64-255: User Defined */
285 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
286 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
287 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
288 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
289 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
290 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
293 4, /* 0: Reset - Initial Stack Pointer */
294 4, /* 1: Reset - Initial Program Counter */
295 50, /* 2: Bus Error (unemulated) */
296 50, /* 3: Address Error (unemulated) */
297 20, /* 4: Illegal Instruction */
298 38, /* 5: Divide by Zero */
301 34, /* 8: Privilege Violation */
305 4, /* 12: RESERVED */
306 4, /* 13: Coprocessor Protocol Violation (unemulated) */
307 4, /* 14: Format Error */
308 30, /* 15: Uninitialized Interrupt */
309 4, /* 16: RESERVED */
310 4, /* 17: RESERVED */
311 4, /* 18: RESERVED */
312 4, /* 19: RESERVED */
313 4, /* 20: RESERVED */
314 4, /* 21: RESERVED */
315 4, /* 22: RESERVED */
316 4, /* 23: RESERVED */
317 30, /* 24: Spurious Interrupt */
318 30, /* 25: Level 1 Interrupt Autovector */
319 30, /* 26: Level 2 Interrupt Autovector */
320 30, /* 27: Level 3 Interrupt Autovector */
321 30, /* 28: Level 4 Interrupt Autovector */
322 30, /* 29: Level 5 Interrupt Autovector */
323 30, /* 30: Level 6 Interrupt Autovector */
324 30, /* 31: Level 7 Interrupt Autovector */
325 20, /* 32: TRAP #0 */
326 20, /* 33: TRAP #1 */
327 20, /* 34: TRAP #2 */
328 20, /* 35: TRAP #3 */
329 20, /* 36: TRAP #4 */
330 20, /* 37: TRAP #5 */
331 20, /* 38: TRAP #6 */
332 20, /* 39: TRAP #7 */
333 20, /* 40: TRAP #8 */
334 20, /* 41: TRAP #9 */
335 20, /* 42: TRAP #10 */
336 20, /* 43: TRAP #11 */
337 20, /* 44: TRAP #12 */
338 20, /* 45: TRAP #13 */
339 20, /* 46: TRAP #14 */
340 20, /* 47: TRAP #15 */
341 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
342 4, /* 49: FP Inexact Result (unemulated) */
343 4, /* 50: FP Divide by Zero (unemulated) */
344 4, /* 51: FP Underflow (unemulated) */
345 4, /* 52: FP Operand Error (unemulated) */
346 4, /* 53: FP Overflow (unemulated) */
347 4, /* 54: FP Signaling NAN (unemulated) */
348 4, /* 55: FP Unimplemented Data Type (unemulated) */
349 4, /* 56: MMU Configuration Error (unemulated) */
350 4, /* 57: MMU Illegal Operation Error (unemulated) */
351 4, /* 58: MMU Access Level Violation Error (unemulated) */
352 4, /* 59: RESERVED */
353 4, /* 60: RESERVED */
354 4, /* 61: RESERVED */
355 4, /* 62: RESERVED */
356 4, /* 63: RESERVED */
357 /* 64-255: User Defined */
358 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
359 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
360 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
361 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
362 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
363 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
365 { /* 030 - not correct */
366 4, /* 0: Reset - Initial Stack Pointer */
367 4, /* 1: Reset - Initial Program Counter */
368 50, /* 2: Bus Error (unemulated) */
369 50, /* 3: Address Error (unemulated) */
370 20, /* 4: Illegal Instruction */
371 38, /* 5: Divide by Zero */
374 34, /* 8: Privilege Violation */
378 4, /* 12: RESERVED */
379 4, /* 13: Coprocessor Protocol Violation (unemulated) */
380 4, /* 14: Format Error */
381 30, /* 15: Uninitialized Interrupt */
382 4, /* 16: RESERVED */
383 4, /* 17: RESERVED */
384 4, /* 18: RESERVED */
385 4, /* 19: RESERVED */
386 4, /* 20: RESERVED */
387 4, /* 21: RESERVED */
388 4, /* 22: RESERVED */
389 4, /* 23: RESERVED */
390 30, /* 24: Spurious Interrupt */
391 30, /* 25: Level 1 Interrupt Autovector */
392 30, /* 26: Level 2 Interrupt Autovector */
393 30, /* 27: Level 3 Interrupt Autovector */
394 30, /* 28: Level 4 Interrupt Autovector */
395 30, /* 29: Level 5 Interrupt Autovector */
396 30, /* 30: Level 6 Interrupt Autovector */
397 30, /* 31: Level 7 Interrupt Autovector */
398 20, /* 32: TRAP #0 */
399 20, /* 33: TRAP #1 */
400 20, /* 34: TRAP #2 */
401 20, /* 35: TRAP #3 */
402 20, /* 36: TRAP #4 */
403 20, /* 37: TRAP #5 */
404 20, /* 38: TRAP #6 */
405 20, /* 39: TRAP #7 */
406 20, /* 40: TRAP #8 */
407 20, /* 41: TRAP #9 */
408 20, /* 42: TRAP #10 */
409 20, /* 43: TRAP #11 */
410 20, /* 44: TRAP #12 */
411 20, /* 45: TRAP #13 */
412 20, /* 46: TRAP #14 */
413 20, /* 47: TRAP #15 */
414 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
415 4, /* 49: FP Inexact Result (unemulated) */
416 4, /* 50: FP Divide by Zero (unemulated) */
417 4, /* 51: FP Underflow (unemulated) */
418 4, /* 52: FP Operand Error (unemulated) */
419 4, /* 53: FP Overflow (unemulated) */
420 4, /* 54: FP Signaling NAN (unemulated) */
421 4, /* 55: FP Unimplemented Data Type (unemulated) */
422 4, /* 56: MMU Configuration Error (unemulated) */
423 4, /* 57: MMU Illegal Operation Error (unemulated) */
424 4, /* 58: MMU Access Level Violation Error (unemulated) */
425 4, /* 59: RESERVED */
426 4, /* 60: RESERVED */
427 4, /* 61: RESERVED */
428 4, /* 62: RESERVED */
429 4, /* 63: RESERVED */
430 /* 64-255: User Defined */
431 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
432 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
433 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
434 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
435 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
436 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
438 { /* 040 */ // TODO: these values are not correct
439 4, /* 0: Reset - Initial Stack Pointer */
440 4, /* 1: Reset - Initial Program Counter */
441 50, /* 2: Bus Error (unemulated) */
442 50, /* 3: Address Error (unemulated) */
443 20, /* 4: Illegal Instruction */
444 38, /* 5: Divide by Zero */
447 34, /* 8: Privilege Violation */
451 4, /* 12: RESERVED */
452 4, /* 13: Coprocessor Protocol Violation (unemulated) */
453 4, /* 14: Format Error */
454 30, /* 15: Uninitialized Interrupt */
455 4, /* 16: RESERVED */
456 4, /* 17: RESERVED */
457 4, /* 18: RESERVED */
458 4, /* 19: RESERVED */
459 4, /* 20: RESERVED */
460 4, /* 21: RESERVED */
461 4, /* 22: RESERVED */
462 4, /* 23: RESERVED */
463 30, /* 24: Spurious Interrupt */
464 30, /* 25: Level 1 Interrupt Autovector */
465 30, /* 26: Level 2 Interrupt Autovector */
466 30, /* 27: Level 3 Interrupt Autovector */
467 30, /* 28: Level 4 Interrupt Autovector */
468 30, /* 29: Level 5 Interrupt Autovector */
469 30, /* 30: Level 6 Interrupt Autovector */
470 30, /* 31: Level 7 Interrupt Autovector */
471 20, /* 32: TRAP #0 */
472 20, /* 33: TRAP #1 */
473 20, /* 34: TRAP #2 */
474 20, /* 35: TRAP #3 */
475 20, /* 36: TRAP #4 */
476 20, /* 37: TRAP #5 */
477 20, /* 38: TRAP #6 */
478 20, /* 39: TRAP #7 */
479 20, /* 40: TRAP #8 */
480 20, /* 41: TRAP #9 */
481 20, /* 42: TRAP #10 */
482 20, /* 43: TRAP #11 */
483 20, /* 44: TRAP #12 */
484 20, /* 45: TRAP #13 */
485 20, /* 46: TRAP #14 */
486 20, /* 47: TRAP #15 */
487 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
488 4, /* 49: FP Inexact Result (unemulated) */
489 4, /* 50: FP Divide by Zero (unemulated) */
490 4, /* 51: FP Underflow (unemulated) */
491 4, /* 52: FP Operand Error (unemulated) */
492 4, /* 53: FP Overflow (unemulated) */
493 4, /* 54: FP Signaling NAN (unemulated) */
494 4, /* 55: FP Unimplemented Data Type (unemulated) */
495 4, /* 56: MMU Configuration Error (unemulated) */
496 4, /* 57: MMU Illegal Operation Error (unemulated) */
497 4, /* 58: MMU Access Level Violation Error (unemulated) */
498 4, /* 59: RESERVED */
499 4, /* 60: RESERVED */
500 4, /* 61: RESERVED */
501 4, /* 62: RESERVED */
502 4, /* 63: RESERVED */
503 /* 64-255: User Defined */
504 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
505 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
506 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
507 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
508 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
509 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
513 const uint8 m68ki_ea_idx_cycle_table[64] =
515 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
516 0, /* ..01.000 no memory indirect, base NULL */
517 5, /* ..01..01 memory indirect, base NULL, outer NULL */
518 7, /* ..01..10 memory indirect, base NULL, outer 16 */
519 7, /* ..01..11 memory indirect, base NULL, outer 32 */
520 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
521 2, /* ..10.000 no memory indirect, base 16 */
522 7, /* ..10..01 memory indirect, base 16, outer NULL */
523 9, /* ..10..10 memory indirect, base 16, outer 16 */
524 9, /* ..10..11 memory indirect, base 16, outer 32 */
525 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
526 6, /* ..11.000 no memory indirect, base 32 */
527 11, /* ..11..01 memory indirect, base 32, outer NULL */
528 13, /* ..11..10 memory indirect, base 32, outer 16 */
529 13, /* ..11..11 memory indirect, base 32, outer 32 */
530 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
535 /* ======================================================================== */
536 /* =============================== CALLBACKS ============================== */
537 /* ======================================================================== */
539 /* Default callbacks used if the callback hasn't been set yet, or if the
540 * callback is set to NULL
543 /* Interrupt acknowledge */
544 static int default_int_ack_callback_data;
545 static int default_int_ack_callback(int int_level)
547 default_int_ack_callback_data = int_level;
549 return M68K_INT_ACK_AUTOVECTOR;
552 /* Breakpoint acknowledge */
553 static unsigned int default_bkpt_ack_callback_data;
554 static void default_bkpt_ack_callback(unsigned int data)
556 default_bkpt_ack_callback_data = data;
559 /* Called when a reset instruction is executed */
560 static void default_reset_instr_callback(void)
564 /* Called when a cmpi.l #v, dn instruction is executed */
565 static void default_cmpild_instr_callback(unsigned int val, int reg)
571 /* Called when a rte instruction is executed */
572 static void default_rte_instr_callback(void)
576 /* Called when a tas instruction is executed */
577 static int default_tas_instr_callback(void)
579 return 1; // allow writeback
582 /* Called when an illegal instruction is encountered */
583 static int default_illg_instr_callback(int opcode)
586 return 0; // not handled : exception will occur
589 /* Called when the program counter changed by a large value */
590 static unsigned int default_pc_changed_callback_data;
591 static void default_pc_changed_callback(unsigned int new_pc)
593 default_pc_changed_callback_data = new_pc;
596 /* Called every time there's bus activity (read/write to/from memory */
597 static unsigned int default_set_fc_callback_data;
598 static void default_set_fc_callback(unsigned int new_fc)
600 default_set_fc_callback_data = new_fc;
603 /* Called every instruction cycle prior to execution */
604 static void default_instr_hook_callback(unsigned int pc)
610 #if M68K_EMULATE_ADDRESS_ERROR
613 sigjmp_buf m68ki_aerr_trap;
615 jmp_buf m68ki_aerr_trap;
617 #endif /* M68K_EMULATE_ADDRESS_ERROR */
619 /* ======================================================================== */
620 /* ================================= API ================================== */
621 /* ======================================================================== */
623 /* Access the internals of the CPU */
624 unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
626 m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
630 case M68K_REG_D0: return cpu->dar[0];
631 case M68K_REG_D1: return cpu->dar[1];
632 case M68K_REG_D2: return cpu->dar[2];
633 case M68K_REG_D3: return cpu->dar[3];
634 case M68K_REG_D4: return cpu->dar[4];
635 case M68K_REG_D5: return cpu->dar[5];
636 case M68K_REG_D6: return cpu->dar[6];
637 case M68K_REG_D7: return cpu->dar[7];
638 case M68K_REG_A0: return cpu->dar[8];
639 case M68K_REG_A1: return cpu->dar[9];
640 case M68K_REG_A2: return cpu->dar[10];
641 case M68K_REG_A3: return cpu->dar[11];
642 case M68K_REG_A4: return cpu->dar[12];
643 case M68K_REG_A5: return cpu->dar[13];
644 case M68K_REG_A6: return cpu->dar[14];
645 case M68K_REG_A7: return cpu->dar[15];
646 case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
647 case M68K_REG_SR: return cpu->t1_flag |
649 (cpu->s_flag << 11) |
650 (cpu->m_flag << 11) |
652 ((cpu->x_flag & XFLAG_SET) >> 4) |
653 ((cpu->n_flag & NFLAG_SET) >> 4) |
654 ((!cpu->not_z_flag) << 2) |
655 ((cpu->v_flag & VFLAG_SET) >> 6) |
656 ((cpu->c_flag & CFLAG_SET) >> 8);
657 case M68K_REG_SP: return cpu->dar[15];
658 case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
659 case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
660 case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
661 case M68K_REG_SFC: return cpu->sfc;
662 case M68K_REG_DFC: return cpu->dfc;
663 case M68K_REG_VBR: return cpu->vbr;
664 case M68K_REG_CACR: return cpu->cacr;
665 case M68K_REG_CAAR: return cpu->caar;
666 case M68K_REG_PREF_ADDR: return cpu->pref_addr;
667 case M68K_REG_PREF_DATA: return cpu->pref_data;
668 case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
669 case M68K_REG_IR: return cpu->ir;
670 case M68K_REG_CPU_TYPE:
671 switch(cpu->cpu_type)
673 case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
674 case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
675 case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
676 case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
677 case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040;
679 return M68K_CPU_TYPE_INVALID;
685 void m68k_set_reg(m68k_register_t regnum, unsigned int value)
689 case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
690 case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
691 case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
692 case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
693 case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
694 case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
695 case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
696 case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
697 case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
698 case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
699 case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
700 case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
701 case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
702 case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
703 case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
704 case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
705 case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
706 case M68K_REG_SR: m68ki_set_sr_noint_nosp(value); return;
707 case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
708 case M68K_REG_USP: if(FLAG_S)
709 REG_USP = MASK_OUT_ABOVE_32(value);
711 REG_SP = MASK_OUT_ABOVE_32(value);
713 case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
714 REG_SP = MASK_OUT_ABOVE_32(value);
716 REG_ISP = MASK_OUT_ABOVE_32(value);
718 case M68K_REG_MSP: if(FLAG_S && FLAG_M)
719 REG_SP = MASK_OUT_ABOVE_32(value);
721 REG_MSP = MASK_OUT_ABOVE_32(value);
723 case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
724 case M68K_REG_SFC: REG_SFC = value & 7; return;
725 case M68K_REG_DFC: REG_DFC = value & 7; return;
726 case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
727 case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
728 case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
729 case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
730 case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
735 /* Set the callbacks */
736 void m68k_set_int_ack_callback(int (*callback)(int int_level))
738 CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
741 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
743 CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
746 void m68k_set_reset_instr_callback(void (*callback)(void))
748 CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
751 void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int))
753 CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback;
756 void m68k_set_rte_instr_callback(void (*callback)(void))
758 CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback;
761 void m68k_set_tas_instr_callback(int (*callback)(void))
763 CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
766 void m68k_set_illg_instr_callback(int (*callback)(int))
768 CALLBACK_ILLG_INSTR = callback ? callback : default_illg_instr_callback;
771 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
773 CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
776 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
778 CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
781 void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc))
783 CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
786 /* Set the CPU type. */
787 void m68k_set_cpu_type(unsigned int cpu_type)
791 case M68K_CPU_TYPE_68000:
792 CPU_TYPE = CPU_TYPE_000;
793 CPU_ADDRESS_MASK = 0x00ffffff;
794 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
795 CYC_INSTRUCTION = m68ki_cycles[0];
796 CYC_EXCEPTION = m68ki_exception_cycle_table[0];
797 CYC_BCC_NOTAKE_B = -2;
798 CYC_BCC_NOTAKE_W = 2;
799 CYC_DBCC_F_NOEXP = -2;
808 case M68K_CPU_TYPE_SCC68070:
809 m68k_set_cpu_type(M68K_CPU_TYPE_68010);
810 CPU_ADDRESS_MASK = 0xffffffff;
811 CPU_TYPE = CPU_TYPE_SCC070;
813 case M68K_CPU_TYPE_68010:
814 CPU_TYPE = CPU_TYPE_010;
815 CPU_ADDRESS_MASK = 0x00ffffff;
816 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
817 CYC_INSTRUCTION = m68ki_cycles[1];
818 CYC_EXCEPTION = m68ki_exception_cycle_table[1];
819 CYC_BCC_NOTAKE_B = -4;
820 CYC_BCC_NOTAKE_W = 0;
821 CYC_DBCC_F_NOEXP = 0;
830 case M68K_CPU_TYPE_68EC020:
831 CPU_TYPE = CPU_TYPE_EC020;
832 CPU_ADDRESS_MASK = 0x00ffffff;
833 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
834 CYC_INSTRUCTION = m68ki_cycles[2];
835 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
836 CYC_BCC_NOTAKE_B = -2;
837 CYC_BCC_NOTAKE_W = 0;
838 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;
864 case M68K_CPU_TYPE_68030:
865 CPU_TYPE = CPU_TYPE_030;
866 CPU_ADDRESS_MASK = 0xffffffff;
867 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
868 CYC_INSTRUCTION = m68ki_cycles[3];
869 CYC_EXCEPTION = m68ki_exception_cycle_table[3];
870 CYC_BCC_NOTAKE_B = -2;
871 CYC_BCC_NOTAKE_W = 0;
872 CYC_DBCC_F_NOEXP = 0;
881 case M68K_CPU_TYPE_68EC030:
882 CPU_TYPE = CPU_TYPE_EC030;
883 CPU_ADDRESS_MASK = 0xffffffff;
884 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
885 CYC_INSTRUCTION = m68ki_cycles[3];
886 CYC_EXCEPTION = m68ki_exception_cycle_table[3];
887 CYC_BCC_NOTAKE_B = -2;
888 CYC_BCC_NOTAKE_W = 0;
889 CYC_DBCC_F_NOEXP = 0;
896 HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */
898 case M68K_CPU_TYPE_68040: // TODO: these values are not correct
899 CPU_TYPE = CPU_TYPE_040;
900 CPU_ADDRESS_MASK = 0xffffffff;
901 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
902 CYC_INSTRUCTION = m68ki_cycles[4];
903 CYC_EXCEPTION = m68ki_exception_cycle_table[4];
904 CYC_BCC_NOTAKE_B = -2;
905 CYC_BCC_NOTAKE_W = 0;
906 CYC_DBCC_F_NOEXP = 0;
915 case M68K_CPU_TYPE_68EC040: // Just a 68040 without pmmu apparently...
916 CPU_TYPE = CPU_TYPE_EC040;
917 CPU_ADDRESS_MASK = 0xffffffff;
918 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
919 CYC_INSTRUCTION = m68ki_cycles[4];
920 CYC_EXCEPTION = m68ki_exception_cycle_table[4];
921 CYC_BCC_NOTAKE_B = -2;
922 CYC_BCC_NOTAKE_W = 0;
923 CYC_DBCC_F_NOEXP = 0;
932 case M68K_CPU_TYPE_68LC040:
933 CPU_TYPE = CPU_TYPE_LC040;
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;
951 /* Execute some instructions until we use up num_cycles clock cycles */
952 /* ASG: removed per-instruction interrupt checks */
953 int m68k_execute(int num_cycles)
955 /* eat up any reset cycles */
957 int rc = RESET_CYCLES;
964 /* Set our pool of clock cycles available */
965 SET_CYCLES(num_cycles);
966 m68ki_initial_cycles = num_cycles;
968 /* See if interrupts came in */
969 m68ki_check_interrupts();
971 /* Make sure we're not stopped */
974 /* Return point if we had an address error */
975 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
977 m68ki_check_bus_error_trap();
979 /* Main loop. Keep going until we run out of clock cycles */
983 /* Set tracing accodring to T1. (T0 is done inside instruction) */
984 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
986 /* Set the address space for reads */
987 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
989 /* Call external hook to peek at CPU */
990 m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
992 /* Record previous program counter */
995 /* Record previous D/A register state (in case of bus error) */
996 for (i = 15; i >= 0; i--){
997 REG_DA_SAVE[i] = REG_DA[i];
1000 /* Read an instruction and call its handler */
1001 REG_IR = m68ki_read_imm_16();
1002 m68ki_instruction_jump_table[REG_IR]();
1003 USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
1005 /* Trace m68k_exception, if necessary */
1006 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
1007 } while(GET_CYCLES() > 0);
1009 /* set previous PC to current PC for the next entry into the loop */
1015 /* return how many clocks we used */
1016 return m68ki_initial_cycles - GET_CYCLES();
1020 int m68k_cycles_run(void)
1022 return m68ki_initial_cycles - GET_CYCLES();
1025 int m68k_cycles_remaining(void)
1027 return GET_CYCLES();
1030 /* Change the timeslice */
1031 void m68k_modify_timeslice(int cycles)
1033 m68ki_initial_cycles += cycles;
1038 void m68k_end_timeslice(void)
1040 m68ki_initial_cycles = GET_CYCLES();
1045 /* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
1046 /* KS: Modified so that IPL* bits match with mask positions in the SR
1047 * and cleaned out remenants of the interrupt controller.
1049 void m68k_set_irq(unsigned int int_level)
1051 uint old_level = CPU_INT_LEVEL;
1052 CPU_INT_LEVEL = int_level << 8;
1054 /* A transition from < 7 to 7 always interrupts (NMI) */
1055 /* Note: Level 7 can also level trigger like a normal IRQ */
1056 if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
1057 m68ki_cpu.nmi_pending = TRUE;
1060 void m68k_set_virq(unsigned int level, unsigned int active)
1062 uint state = m68ki_cpu.virq_state;
1066 state |= 1 << level;
1068 state &= ~(1 << level);
1069 m68ki_cpu.virq_state = state;
1071 for(blevel = 7; blevel > 0; blevel--)
1072 if(state & (1 << blevel))
1074 m68k_set_irq(blevel);
1077 unsigned int m68k_get_virq(unsigned int level)
1079 return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0;
1082 void m68k_init(void)
1084 static uint emulation_initialized = 0;
1086 /* The first call to this function initializes the opcode handler jump table */
1087 if(!emulation_initialized)
1089 m68ki_build_opcode_table();
1090 emulation_initialized = 1;
1093 m68k_set_int_ack_callback(NULL);
1094 m68k_set_bkpt_ack_callback(NULL);
1095 m68k_set_reset_instr_callback(NULL);
1096 m68k_set_cmpild_instr_callback(NULL);
1097 m68k_set_rte_instr_callback(NULL);
1098 m68k_set_tas_instr_callback(NULL);
1099 m68k_set_illg_instr_callback(NULL);
1100 m68k_set_pc_changed_callback(NULL);
1101 m68k_set_fc_callback(NULL);
1102 m68k_set_instr_hook_callback(NULL);
1105 /* Trigger a Bus Error exception */
1106 void m68k_pulse_bus_error(void)
1108 m68ki_exception_bus_error();
1111 /* Pulse the RESET line on the CPU */
1112 void m68k_pulse_reset(void)
1114 /* Disable the PMMU on reset */
1115 m68ki_cpu.pmmu_enabled = 0;
1117 /* Clear all stop levels and eat up all remaining cycles */
1121 CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
1122 CPU_INSTR_MODE = INSTRUCTION_YES;
1124 /* Turn off tracing */
1125 FLAG_T1 = FLAG_T0 = 0;
1126 m68ki_clear_trace();
1127 /* Interrupt mask to level 7 */
1128 FLAG_INT_MASK = 0x0700;
1130 m68ki_cpu.virq_state = 0;
1133 /* Go to supervisor mode */
1134 m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
1136 /* Invalidate the prefetch queue */
1137 #if M68K_EMULATE_PREFETCH
1138 /* Set to arbitrary number since our first fetch is from 0 */
1139 CPU_PREF_ADDR = 0x1000;
1140 #endif /* M68K_EMULATE_PREFETCH */
1142 /* Read the initial stack pointer and program counter */
1144 REG_SP = m68ki_read_imm_32();
1145 REG_PC = m68ki_read_imm_32();
1148 CPU_RUN_MODE = RUN_MODE_NORMAL;
1150 RESET_CYCLES = CYC_EXCEPTION[EXCEPTION_RESET];
1153 /* Pulse the HALT line on the CPU */
1154 void m68k_pulse_halt(void)
1156 CPU_STOPPED |= STOP_LEVEL_HALT;
1159 /* Get and set the current CPU context */
1160 /* This is to allow for multiple CPUs */
1161 unsigned int m68k_context_size()
1163 return sizeof(m68ki_cpu_core);
1166 unsigned int m68k_get_context(void* dst)
1168 if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
1169 return sizeof(m68ki_cpu_core);
1172 void m68k_set_context(void* src)
1174 if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
1177 void m68k_add_ram_range(uint32_t addr, uint32_t upper, unsigned char *ptr)
1179 if (read_ranges + 1 < 8) {
1180 read_addr[read_ranges] = addr;
1181 read_upper[read_ranges] = upper;
1182 read_data[read_ranges] = ptr;
1184 printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr);
1187 printf("Can't Musashi map more than eight RAM/ROM read ranges.\n");
1189 if (write_ranges + 1 < 8) {
1190 write_addr[write_ranges] = addr;
1191 write_upper[write_ranges] = upper;
1192 write_data[write_ranges] = ptr;
1194 printf("[MUSASHI] Mapped write range %d: %.8X-%.8X (%p)\n", write_ranges, addr, upper, ptr);
1197 printf("Can't Musashi map more than eight RAM write ranges.\n");
1201 void m68k_add_rom_range(uint32_t addr, uint32_t upper, unsigned char *ptr)
1203 if (read_ranges + 1 < 8) {
1204 read_addr[read_ranges] = addr;
1205 read_upper[read_ranges] = upper;
1206 read_data[read_ranges] = ptr;
1208 printf("[MUSASHI] Mapped read range %d: %.8X-%.8X (%p)\n", read_ranges, addr, upper, ptr);
1211 printf("Can't Musashi map more than eight RAM/ROM read ranges.\n");
1215 /* ======================================================================== */
1216 /* ============================== MAME STUFF ============================== */
1217 /* ======================================================================== */
1219 #if M68K_COMPILE_FOR_MAME == OPT_ON
1227 static void m68k_prepare_substate(void)
1229 m68k_substate.sr = m68ki_get_sr();
1230 m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
1231 m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
1234 static void m68k_post_load(void)
1236 m68ki_set_sr_noint_nosp(m68k_substate.sr);
1237 CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
1238 | m68k_substate.halted ? STOP_LEVEL_HALT : 0;
1242 void m68k_state_register(const char *type, int index)
1244 /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */
1245 state_save_register_item_array(type, index, REG_D);
1246 state_save_register_item(type, index, REG_PPC);
1247 state_save_register_item(type, index, REG_PC);
1248 state_save_register_item(type, index, REG_USP);
1249 state_save_register_item(type, index, REG_ISP);
1250 state_save_register_item(type, index, REG_MSP);
1251 state_save_register_item(type, index, REG_VBR);
1252 state_save_register_item(type, index, REG_SFC);
1253 state_save_register_item(type, index, REG_DFC);
1254 state_save_register_item(type, index, REG_CACR);
1255 state_save_register_item(type, index, REG_CAAR);
1256 state_save_register_item(type, index, m68k_substate.sr);
1257 state_save_register_item(type, index, CPU_INT_LEVEL);
1258 state_save_register_item(type, index, m68k_substate.stopped);
1259 state_save_register_item(type, index, m68k_substate.halted);
1260 state_save_register_item(type, index, CPU_PREF_ADDR);
1261 state_save_register_item(type, index, CPU_PREF_DATA);
1262 state_save_register_func_presave(m68k_prepare_substate);
1263 state_save_register_func_postload(m68k_post_load);
1266 #endif /* M68K_COMPILE_FOR_MAME */
1268 /* ======================================================================== */
1269 /* ============================== END OF FILE ============================= */
1270 /* ======================================================================== */