Import Upstream version 1.23
[debian-dgen.git] / musa / m68kcpu.c
blob33047d0e0ffa1148a19cb2b47c859c811aaaa271
1 /* ======================================================================== */
2 /* ========================= LICENSING & COPYRIGHT ======================== */
3 /* ======================================================================== */
5 static const char* copyright_notice =
6 "MUSASHI\n"
7 "Version 2.0a (1999-02-21)\n"
8 "A portable Motorola M680x0 processor emulation engine.\n"
9 "Copyright 1999 Karl Stenerud. All rights reserved.\n"
10 "\n"
11 "This code may be freely used for non-commercial purpooses as long as this\n"
12 "copyright notice remains unaltered in the source code and any binary files\n"
13 "containing this code in compiled form.\n"
14 "\n"
15 "Any commercial ventures wishing to use this code must contact the author\n"
16 "(Karl Stenerud) to negotiate commercial licensing terms.\n"
17 "\n"
18 "The latest version of this code can be obtained at:\n"
19 "http://milliways.scas.bcit.bc.ca/~karl/musashi\n"
23 /* ======================================================================== */
24 /* ================================= NOTES ================================ */
25 /* ======================================================================== */
29 /* ======================================================================== */
30 /* ================================ INCLUDES ============================== */
31 /* ======================================================================== */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "m68kcpu.h"
37 #include "m68kops.h"
39 /* ======================================================================== */
40 /* =============================== PROTOTYPES ============================= */
41 /* ======================================================================== */
43 /* Build the opcode handler table */
44 void m68ki_build_opcode_table(void);
48 /* ======================================================================== */
49 /* ================================= DATA ================================= */
50 /* ======================================================================== */
52 static uint m68k_emulation_initialized = 0; /* flag if emulation has been initialized */
53 void (*m68k_instruction_jump_table[0x10000])(void); /* opcode handler jump table */
54 int m68k_clks_left = 0; /* Number of clocks remaining */
55 uint m68k_tracing = 0;
57 #ifdef M68K_LOG
58 uint m68k_pc_offset = 2;
59 char* m68k_cpu_names[5] =
61 "Invalid CPU",
62 "M68000",
63 "M68010",
64 "Invalid CPU",
65 "M68020"
67 #endif /* M68K_LOG */
69 /* Mask which bits of the SR ar eimplemented */
70 uint m68k_sr_implemented_bits[5] =
72 0x0000, /* invalid */
73 0xa71f, /* 68000: T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
74 0xa71f, /* 68010: T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
75 0x0000, /* invalid */
76 0xf71f, /* 68020: T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
79 /* The CPU core */
80 m68k_cpu_core m68k_cpu = {0};
82 /* Pointers to speed up address register indirect with index calculation */
83 uint* m68k_cpu_dar[2] = {CPU_D, CPU_A};
85 /* Pointers to speed up movem instructions */
86 uint* m68k_movem_pi_table[16] =
88 CPU_D, CPU_D+1, CPU_D+2, CPU_D+3, CPU_D+4, CPU_D+5, CPU_D+6, CPU_D+7,
89 CPU_A, CPU_A+1, CPU_A+2, CPU_A+3, CPU_A+4, CPU_A+5, CPU_A+6, CPU_A+7
91 uint* m68k_movem_pd_table[16] =
93 CPU_A+7, CPU_A+6, CPU_A+5, CPU_A+4, CPU_A+3, CPU_A+2, CPU_A+1, CPU_A,
94 CPU_D+7, CPU_D+6, CPU_D+5, CPU_D+4, CPU_D+3, CPU_D+2, CPU_D+1, CPU_D,
98 /* Used when checking for pending interrupts */
99 uint8 m68k_int_masks[] = {0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x80};
101 /* Used by shift & rotate instructions */
102 uint8 m68k_shift_8_table[65] =
104 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
105 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
109 uint16 m68k_shift_16_table[65] =
111 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0,
112 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
113 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
114 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
115 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
116 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
118 uint m68k_shift_32_table[65] =
120 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
121 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
122 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
123 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe,
124 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
125 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
126 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
127 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 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 uint8 m68k_exception_cycle_table[256] =
136 40, /* 0: Reset - should never be called */
137 40, /* 1: Reset - should never be called */
138 50, /* 2: Bus Error (unused in emulation) */
139 50, /* 3: Address Error (unused in emulation) */
140 34, /* 4: Illegal Instruction */
141 38, /* 5: Divide by Zero -- ASG: changed from 42 */
142 40, /* 6: CHK -- ASG: chanaged from 44 */
143 34, /* 7: TRAPV */
144 34, /* 8: Privilege Violation */
145 34, /* 9: Trace */
146 4, /* 10: 1010 */
147 4, /* 11: 1111 */
148 4, /* 12: RESERVED */
149 4, /* 13: Coprocessor Protocol Violation (unused in emulation) */
150 4, /* 14: Format Error (unused in emulation) */
151 44, /* 15: Uninitialized Interrupt */
152 4, /* 16: RESERVED */
153 4, /* 17: RESERVED */
154 4, /* 18: RESERVED */
155 4, /* 19: RESERVED */
156 4, /* 20: RESERVED */
157 4, /* 21: RESERVED */
158 4, /* 22: RESERVED */
159 4, /* 23: RESERVED */
160 44, /* 24: Spurious Interrupt */
161 44, /* 25: Level 1 Interrupt Autovector */
162 44, /* 26: Level 2 Interrupt Autovector */
163 44, /* 27: Level 3 Interrupt Autovector */
164 44, /* 28: Level 4 Interrupt Autovector */
165 44, /* 29: Level 5 Interrupt Autovector */
166 44, /* 30: Level 6 Interrupt Autovector */
167 44, /* 31: Level 7 Interrupt Autovector */
168 34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
169 34, /* 33: TRAP #1 */
170 34, /* 34: TRAP #2 */
171 34, /* 35: TRAP #3 */
172 34, /* 36: TRAP #4 */
173 34, /* 37: TRAP #5 */
174 34, /* 38: TRAP #6 */
175 34, /* 39: TRAP #7 */
176 34, /* 40: TRAP #8 */
177 34, /* 41: TRAP #9 */
178 34, /* 42: TRAP #10 */
179 34, /* 43: TRAP #11 */
180 34, /* 44: TRAP #12 */
181 34, /* 45: TRAP #13 */
182 34, /* 46: TRAP #14 */
183 34, /* 47: TRAP #15 */
184 4, /* 48: FP Branch or Set on Unknown Condition (unused in emulation) */
185 4, /* 49: FP Inexact Result (unused in emulation) */
186 4, /* 50: FP Divide by Zero (unused in emulation) */
187 4, /* 51: FP Underflow (unused in emulation) */
188 4, /* 52: FP Operand Error (unused in emulation) */
189 4, /* 53: FP Overflow (unused in emulation) */
190 4, /* 54: FP Signaling NAN (unused in emulation) */
191 4, /* 55: FP Unimplemented Data Type (unused in emulation) */
192 4, /* 56: MMU Configuration Error (unused in emulation) */
193 4, /* 57: MMU Illegal Operation Error (unused in emulation) */
194 4, /* 58: MMU Access Level Violation Error (unused in emulation) */
195 4, /* 59: RESERVED */
196 4, /* 60: RESERVED */
197 4, /* 61: RESERVED */
198 4, /* 62: RESERVED */
199 4, /* 63: RESERVED */
200 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 64- 79: User Defined */
201 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 80- 95: User Defined */
202 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 96-111: User Defined */
203 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 112-127: User Defined */
204 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 128-143: User Defined */
205 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 144-159: User Defined */
206 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 160-175: User Defined */
207 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 176-191: User Defined */
208 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 192-207: User Defined */
209 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 208-223: User Defined */
210 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 224-239: User Defined */
211 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, /* 240-255: User Defined */
216 /* ======================================================================== */
217 /* =============================== CALLBACKS ============================== */
218 /* ======================================================================== */
220 /* Default callbacks used if the callback hasn't been set yet, or if the
221 * callback is set to NULL
224 /* Interrupt acknowledge */
225 static int default_int_ack_callback_data;
226 static int default_int_ack_callback(int int_level)
228 default_int_ack_callback_data = int_level;
229 return M68K_INT_ACK_AUTOVECTOR;
232 /* Breakpoint acknowledge */
233 static int default_bkpt_ack_callback_data;
234 static void default_bkpt_ack_callback(int data)
236 default_bkpt_ack_callback_data = data;
239 /* Called when a reset instruction is executed */
240 static void default_reset_instr_callback(void)
244 /* Called when the program counter changed by a large value */
245 static int default_pc_changed_callback_data;
246 static void default_pc_changed_callback(int new_pc)
248 default_pc_changed_callback_data = new_pc;
251 /* Called every time there's bus activity (read/write to/from memory */
252 static int default_set_fc_callback_data;
253 static void default_set_fc_callback(int new_fc)
255 default_set_fc_callback_data = new_fc;
258 /* Called every instruction cycle prior to execution */
259 static void default_instr_hook_callback(void)
265 /* ======================================================================== */
266 /* ================================= API ================================== */
267 /* ======================================================================== */
269 /* Peek at the internals of the M68K */
270 int m68k_peek_dr(int reg_num) { return (reg_num < 8) ? CPU_D[reg_num] : 0; }
271 int m68k_peek_ar(int reg_num) { return (reg_num < 8) ? CPU_A[reg_num] : 0; }
272 unsigned int m68k_peek_pc(void) { return ADDRESS_68K(CPU_PC); }
273 unsigned int m68k_peek_ppc(void) { return ADDRESS_68K(CPU_PPC); }
274 int m68k_peek_sr(void) { return m68ki_get_sr(); }
275 int m68k_peek_ir(void) { return CPU_IR; }
276 int m68k_peek_t1_flag(void) { return CPU_T1 != 0; }
277 int m68k_peek_t0_flag(void) { return CPU_T0 != 0; }
278 int m68k_peek_s_flag(void) { return CPU_S != 0; }
279 int m68k_peek_m_flag(void) { return CPU_M != 0; }
280 int m68k_peek_int_mask(void) { return CPU_INT_MASK; }
281 int m68k_peek_x_flag(void) { return CPU_X != 0; }
282 int m68k_peek_n_flag(void) { return CPU_N != 0; }
283 int m68k_peek_z_flag(void) { return CPU_NOT_Z == 0; }
284 int m68k_peek_v_flag(void) { return CPU_V != 0; }
285 int m68k_peek_c_flag(void) { return CPU_C != 0; }
286 int m68k_peek_usp(void) { return CPU_S ? CPU_USP : CPU_A[7]; }
287 int m68k_peek_isp(void) { return CPU_S && !CPU_M ? CPU_A[7] : CPU_ISP; }
288 int m68k_peek_msp(void) { return CPU_S && CPU_M ? CPU_A[7] : CPU_MSP; }
290 /* Poke data into the M68K */
291 void m68k_poke_dr(int reg_num, int value) { if(reg_num < 8) CPU_D[reg_num] = MASK_OUT_ABOVE_32(value); }
292 void m68k_poke_ar(int reg_num, int value) { if(reg_num < 8) CPU_A[reg_num] = MASK_OUT_ABOVE_32(value); }
293 void m68k_poke_pc(unsigned int value) { m68ki_set_pc(ADDRESS_68K(value)); }
294 void m68k_poke_sr(int value) { m68ki_set_sr(MASK_OUT_ABOVE_16(value)); }
295 void m68k_poke_ir(int value) { CPU_IR = MASK_OUT_ABOVE_16(value); }
296 void m68k_poke_t1_flag(int value) { CPU_T1 = (value != 0); }
297 void m68k_poke_t0_flag(int value) { if(CPU_MODE & CPU_MODE_020_PLUS) CPU_T0 = (value != 0); }
298 void m68k_poke_s_flag(int value) { m68ki_set_s_flag(value); }
299 void m68k_poke_m_flag(int value) { if(CPU_MODE & CPU_MODE_020_PLUS) m68ki_set_m_flag(value); }
300 void m68k_poke_int_mask(int value) { CPU_INT_MASK = value & 7; }
301 void m68k_poke_x_flag(int value) { CPU_X = (value != 0); }
302 void m68k_poke_n_flag(int value) { CPU_N = (value != 0); }
303 void m68k_poke_z_flag(int value) { CPU_NOT_Z = (value == 0); }
304 void m68k_poke_v_flag(int value) { CPU_V = (value != 0); }
305 void m68k_poke_c_flag(int value) { CPU_C = (value != 0); }
306 void m68k_poke_usp(int value)
308 if(CPU_S)
309 CPU_USP = MASK_OUT_ABOVE_32(value);
310 else
311 CPU_A[7] = MASK_OUT_ABOVE_32(value);
313 void m68k_poke_isp(int value)
315 if(CPU_S && !CPU_M)
316 CPU_A[7] = MASK_OUT_ABOVE_32(value);
317 else
318 CPU_ISP = MASK_OUT_ABOVE_32(value);
320 void m68k_poke_msp(int value)
322 if(CPU_MODE & CPU_MODE_020_PLUS)
324 if(CPU_S && CPU_M)
325 CPU_A[7] = MASK_OUT_ABOVE_32(value);
326 else
327 CPU_MSP = MASK_OUT_ABOVE_32(value);
331 /* Set the callbacks */
332 void m68k_set_int_ack_callback(int (*callback)(int int_level))
334 CPU_INT_ACK_CALLBACK = callback ? callback : default_int_ack_callback;
337 void m68k_set_bkpt_ack_callback(void (*callback)(int data))
339 CPU_BKPT_ACK_CALLBACK = callback ? callback : default_bkpt_ack_callback;
342 void m68k_set_reset_instr_callback(void (*callback)(void))
344 CPU_RESET_INSTR_CALLBACK = callback ? callback : default_reset_instr_callback;
347 void m68k_set_pc_changed_callback(void (*callback)(int new_pc))
349 CPU_PC_CHANGED_CALLBACK = callback ? callback : default_pc_changed_callback;
352 void m68k_set_fc_callback(void (*callback)(int new_fc))
354 CPU_SET_FC_CALLBACK = callback ? callback : default_set_fc_callback;
357 void m68k_set_instr_hook_callback(void (*callback)(void))
359 CPU_INSTR_HOOK_CALLBACK = callback ? callback : default_instr_hook_callback;
363 void m68k_set_cpu_mode(int cpu_mode)
365 switch(cpu_mode)
367 case M68K_CPU_MODE_68000:
368 case M68K_CPU_MODE_68010:
369 case M68K_CPU_MODE_68020:
370 CPU_MODE = cpu_mode;
371 return;
372 default:
373 CPU_MODE = M68K_DEFAULT_CPU_MODE;
378 /* Execute some instructions until we use up num_clks clock cycles */
379 /* ASG: removed per-instruction interrupt checks */
380 int m68k_execute(int num_clks)
382 #if M68K_HALT
383 if(!CPU_HALTED)
385 #endif /* M68K_HALT */
386 /* Make sure we're not stopped */
387 if(!CPU_STOPPED)
389 /* Set our pool of clock cycles available */
390 m68k_clks_left = num_clks;
392 /* ASG: update cycles */
393 m68k_clks_left -= CPU_INT_CYCLES;
394 CPU_INT_CYCLES = 0;
396 /* Main loop. Keep going until we run out of clock cycles */
399 /* Set tracing accodring to T1. (T0 is done inside instruction) */
400 m68ki_set_trace(); /* auto-disable (see m68kcpu.h) */
402 /* Call external hook to peek at CPU */
403 m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
405 /* MAME */
407 CPU_PPC = CPU_PC;
408 CALL_MAME_DEBUG;
409 #if A68000_COREDEBUG
410 Asgard68000MiniTrace(&CPU_D[0], &CPU_A[0], m68k_peek_pc(), m68k_peek_sr(), m68k_clks_left);
411 #endif
413 /* MAME */
415 /* Read an instruction and call its handler */
416 CPU_IR = m68ki_read_instruction();
417 m68k_instruction_jump_table[CPU_IR]();
419 /* Trace m68k_exception, if necessary */
420 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
421 continue;
422 } while(m68k_clks_left > 0);
424 /* set previous PC to current PC for the next entry into the loop */
425 CPU_PPC = CPU_PC;
427 /* ASG: update cycles */
428 m68k_clks_left -= CPU_INT_CYCLES;
429 CPU_INT_CYCLES = 0;
431 #if A68000_COREDEBUG
432 Asgard68000MiniTrace(&CPU_D[0], &CPU_A[0], m68k_peek_pc(), m68k_peek_sr(), m68k_clks_left);
433 #endif
435 /* return how many clocks we used */
436 return num_clks - m68k_clks_left;
438 #if M68K_HALT
440 #endif /* M68K_HALT */
442 /* We get here if the CPU is stopped */
443 m68k_clks_left = 0;
445 #if A68000_COREDEBUG
446 Asgard68000MiniTrace(&CPU_D[0], &CPU_A[0], m68k_peek_pc(), m68k_peek_sr(), m68k_clks_left);
447 #endif
449 return num_clks;
453 /* ASG: rewrote so that the int_line is a mask of the IPL0/IPL1/IPL2 bits */
454 void m68k_assert_irq(int int_line)
456 /* OR in the bits of the interrupt */
457 int old_state = CPU_INT_STATE;
458 CPU_INT_STATE = 0; /* ASG: remove me to do proper mask setting */
459 CPU_INT_STATE |= int_line & 7;
461 /* if it's NMI, we're edge triggered */
462 if (CPU_INT_STATE == 7)
464 if (old_state != 7)
465 m68ki_service_interrupt(1 << 7);
468 /* other interrupts just reflect the current state */
469 else
470 m68ki_check_interrupts();
473 /* ASG: rewrote so that the int_line is a mask of the IPL0/IPL1/IPL2 bits */
474 void m68k_clear_irq(int int_line)
476 /* AND in the bits of the interrupt */
477 CPU_INT_STATE &= ~int_line & 7;
478 CPU_INT_STATE = 0; /* ASG: remove me to do proper mask setting */
480 /* check for interrupts again */
481 m68ki_check_interrupts();
485 /* Reset the M68K */
486 void m68k_pulse_reset(void *param)
488 CPU_HALTED = 0;
489 CPU_STOPPED = 0;
490 CPU_INT_STATE = 0; /* ASG: changed from CPU_INTS_PENDING */
491 CPU_T1 = CPU_T0 = 0;
492 m68ki_clear_trace();
493 CPU_S = 1;
494 CPU_M = 0;
495 CPU_INT_MASK = 7;
496 /* ASG: removed a bunch of this initialization....
497 CPU_X = CPU_N = CPU_V = CPU_C = 0;
498 CPU_NOT_Z = 1;
499 CPU_USP = 0;
500 CPU_MSP = 0;
501 CPU_IR = 0;
502 CPU_D[0] = CPU_D[1] = CPU_D[2] = CPU_D[3] =
503 CPU_D[4] = CPU_D[5] = CPU_D[6] = CPU_D[7] =
504 CPU_A[0] = CPU_A[1] = CPU_A[2] = CPU_A[3] =
505 CPU_A[4] = CPU_A[5] = CPU_A[6] = CPU_A[7] = 0;*/
506 CPU_VBR = 0;
507 /* CPU_SFC = 0;
508 CPU_DFC = 0;*/
509 CPU_A[7] = /*CPU_ISP =*/ m68ki_read_32(0);
510 m68ki_set_pc(m68ki_read_32(4));
511 m68k_clks_left = 0;
513 if (CPU_MODE == 0) CPU_MODE = M68K_DEFAULT_CPU_MODE; /* KW 990319 */
514 /* The first call to this function initializes the opcode handler jump table */
515 if(m68k_emulation_initialized)
516 return;
517 else
519 m68ki_build_opcode_table();
520 /* if(CPU_MODE == 0)
521 CPU_MODE = M68K_DEFAULT_CPU_MODE;*/
522 m68k_set_int_ack_callback(NULL);
523 m68k_set_bkpt_ack_callback(NULL);
524 m68k_set_reset_instr_callback(NULL);
525 m68k_set_pc_changed_callback(NULL);
526 m68k_set_fc_callback(NULL);
527 m68k_set_instr_hook_callback(NULL);
529 m68k_emulation_initialized = 1;
534 /* Halt the CPU */
535 void m68k_pulse_halt(void)
537 CPU_HALTED = 1;
541 /* Get and set the current CPU context */
542 /* This is to allow for multiple CPUs */
543 unsigned m68k_get_context(void* dst)
545 if( dst )
547 m68k_cpu_context *cpu = dst;
549 cpu->mode = CPU_MODE;
550 cpu->sr = m68ki_get_sr();
551 cpu->pc = CPU_PC;
552 memcpy(cpu->d, CPU_D, sizeof(CPU_D));
553 memcpy(cpu->a, CPU_A, sizeof(CPU_A));
554 cpu->usp = CPU_USP;
555 cpu->isp = CPU_ISP;
556 cpu->msp = CPU_MSP;
557 cpu->vbr = CPU_VBR;
558 cpu->sfc = CPU_SFC;
559 cpu->dfc = CPU_DFC;
560 cpu->stopped = CPU_STOPPED;
561 cpu->halted = CPU_HALTED;
562 cpu->int_state = CPU_INT_STATE; /* ASG: changed from CPU_INTS_PENDING */
563 cpu->int_cycles = CPU_INT_CYCLES; /* ASG */
564 cpu->int_ack_callback = CPU_INT_ACK_CALLBACK;
565 cpu->bkpt_ack_callback = CPU_BKPT_ACK_CALLBACK;
566 cpu->reset_instr_callback = CPU_RESET_INSTR_CALLBACK;
567 cpu->pc_changed_callback = CPU_PC_CHANGED_CALLBACK;
568 cpu->set_fc_callback = CPU_SET_FC_CALLBACK;
569 cpu->instr_hook_callback = CPU_INSTR_HOOK_CALLBACK;
571 return sizeof(m68k_cpu_context);
574 void m68k_set_context(void* src)
576 if( src )
578 m68k_cpu_context *cpu = src;
580 CPU_MODE = cpu->mode;
581 m68ki_set_sr_no_int(cpu->sr); /* This stays on top to prevent side-effects */
582 m68ki_set_pc(cpu->pc);
583 memcpy(CPU_D, cpu->d, sizeof(CPU_D));
584 memcpy(CPU_A, cpu->a, sizeof(CPU_D));
585 CPU_USP = cpu->usp;
586 CPU_ISP = cpu->isp;
587 CPU_MSP = cpu->msp;
588 CPU_VBR = cpu->vbr;
589 CPU_SFC = cpu->sfc;
590 CPU_DFC = cpu->dfc;
591 CPU_STOPPED = cpu->stopped;
592 CPU_HALTED = cpu->halted;
593 CPU_INT_STATE = cpu->int_state; /* ASG: changed from CPU_INTS_PENDING */
594 CPU_INT_CYCLES = cpu->int_cycles; /* ASG */
595 CPU_INT_ACK_CALLBACK = cpu->int_ack_callback;
596 CPU_BKPT_ACK_CALLBACK = cpu->bkpt_ack_callback;
597 CPU_RESET_INSTR_CALLBACK = cpu->reset_instr_callback;
598 CPU_PC_CHANGED_CALLBACK = cpu->pc_changed_callback;
599 CPU_SET_FC_CALLBACK = cpu->set_fc_callback;
600 CPU_INSTR_HOOK_CALLBACK = cpu->instr_hook_callback;
602 /* ASG: check for interrupts */
603 m68ki_check_interrupts();
608 /* Check if the instruction is a valid one */
609 int m68k_is_valid_instruction(int instruction, int cpu_mode)
611 if(m68k_instruction_jump_table[MASK_OUT_ABOVE_16(instruction)] == m68000_illegal)
612 return 0;
613 if(!(cpu_mode & CPU_MODE_010_PLUS))
615 if((instruction & 0xfff8) == 0x4848) /* bkpt */
616 return 0;
617 if((instruction & 0xffc0) == 0x42c0) /* move from ccr */
618 return 0;
619 if((instruction & 0xfffe) == 0x4e7a) /* movec */
620 return 0;
621 if((instruction & 0xff00) == 0x0e00) /* moves */
622 return 0;
623 if((instruction & 0xffff) == 0x4e74) /* rtd */
624 return 0;
626 if(!(cpu_mode & CPU_MODE_020_PLUS))
628 if((instruction & 0xf0ff) == 0x60ff) /* bcc.l */
629 return 0;
630 if((instruction & 0xf8c0) == 0xe8c0) /* bfxxx */
631 return 0;
632 if((instruction & 0xffc0) == 0x06c0) /* callm */
633 return 0;
634 if((instruction & 0xf9c0) == 0x08c0) /* cas */
635 return 0;
636 if((instruction & 0xf9ff) == 0x08fc) /* cas2 */
637 return 0;
638 if((instruction & 0xf1c0) == 0x4100) /* chk.l */
639 return 0;
640 if((instruction & 0xf9c0) == 0x00c0) /* chk2, cmp2 */
641 return 0;
642 if((instruction & 0xff3f) == 0x0c3a) /* cmpi (pcdi) */
643 return 0;
644 if((instruction & 0xff3f) == 0x0c3b) /* cmpi (pcix) */
645 return 0;
646 if((instruction & 0xffc0) == 0x4c40) /* divl */
647 return 0;
648 if((instruction & 0xfff8) == 0x49c0) /* extb */
649 return 0;
650 if((instruction & 0xfff8) == 0x4808) /* link.l */
651 return 0;
652 if((instruction & 0xffc0) == 0x4c00) /* mull */
653 return 0;
654 if((instruction & 0xf1f0) == 0x8140) /* pack */
655 return 0;
656 if((instruction & 0xfff0) == 0x06c0) /* rtm */
657 return 0;
658 if((instruction & 0xf0f8) == 0x50f8) /* trapcc */
659 return 0;
660 if((instruction & 0xff38) == 0x4a08) /* tst (a) */
661 return 0;
662 if((instruction & 0xff3f) == 0x4a3a) /* tst (pcdi) */
663 return 0;
664 if((instruction & 0xff3f) == 0x4a3b) /* tst (pcix) */
665 return 0;
666 if((instruction & 0xff3f) == 0x4a3c) /* tst (imm) */
667 return 0;
668 if((instruction & 0xf1f0) == 0x8180) /* unpk */
669 return 0;
671 return 1;
676 /* ======================================================================== */
677 /* ============================== END OF FILE ============================= */
678 /* ======================================================================== */