1 /* ======================================================================== */
2 /* ========================= LICENSING & COPYRIGHT ======================== */
3 /* ======================================================================== */
8 * A portable Motorola M680x0 processor emulation engine.
9 * Copyright 1998-2001 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 /* ======================================================================== */
44 /* ======================================================================== */
45 /* ================================= DATA ================================= */
46 /* ======================================================================== */
48 int m68ki_initial_cycles;
49 int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
50 uint m68ki_tracing = 0;
51 uint m68ki_address_space;
53 #ifdef M68K_LOG_ENABLE
54 char* m68ki_cpu_names[9] =
66 #endif /* M68K_LOG_ENABLE */
69 m68ki_cpu_core m68ki_cpu = {0};
71 #if M68K_EMULATE_ADDRESS_ERROR
72 jmp_buf m68ki_aerr_trap;
73 #endif /* M68K_EMULATE_ADDRESS_ERROR */
75 uint m68ki_aerr_address;
76 uint m68ki_aerr_write_mode;
79 /* Used by shift & rotate instructions */
80 uint8 m68ki_shift_8_table[65] =
82 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
83 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
84 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
85 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
86 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
87 0xff, 0xff, 0xff, 0xff, 0xff
89 uint16 m68ki_shift_16_table[65] =
91 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
92 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
93 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
94 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
95 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
96 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
97 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
100 uint m68ki_shift_32_table[65] =
102 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
103 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
104 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
105 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
106 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
107 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
108 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
109 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
110 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
111 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
112 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
116 /* Number of clock cycles to use for exception processing.
117 * I used 4 for any vectors that are undocumented for processing times.
119 uint8 m68ki_exception_cycle_table[3][256] =
122 4, /* 0: Reset - Initial Stack Pointer */
123 4, /* 1: Reset - Initial Program Counter */
124 50, /* 2: Bus Error (unemulated) */
125 50, /* 3: Address Error (unemulated) */
126 34, /* 4: Illegal Instruction */
127 38, /* 5: Divide by Zero -- ASG: changed from 42 */
128 40, /* 6: CHK -- ASG: chanaged from 44 */
130 34, /* 8: Privilege Violation */
134 4, /* 12: RESERVED */
135 4, /* 13: Coprocessor Protocol Violation (unemulated) */
136 4, /* 14: Format Error */
137 44, /* 15: Uninitialized Interrupt */
138 4, /* 16: RESERVED */
139 4, /* 17: RESERVED */
140 4, /* 18: RESERVED */
141 4, /* 19: RESERVED */
142 4, /* 20: RESERVED */
143 4, /* 21: RESERVED */
144 4, /* 22: RESERVED */
145 4, /* 23: RESERVED */
146 44, /* 24: Spurious Interrupt */
147 44, /* 25: Level 1 Interrupt Autovector */
148 44, /* 26: Level 2 Interrupt Autovector */
149 44, /* 27: Level 3 Interrupt Autovector */
150 44, /* 28: Level 4 Interrupt Autovector */
151 44, /* 29: Level 5 Interrupt Autovector */
152 44, /* 30: Level 6 Interrupt Autovector */
153 44, /* 31: Level 7 Interrupt Autovector */
154 34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
155 34, /* 33: TRAP #1 */
156 34, /* 34: TRAP #2 */
157 34, /* 35: TRAP #3 */
158 34, /* 36: TRAP #4 */
159 34, /* 37: TRAP #5 */
160 34, /* 38: TRAP #6 */
161 34, /* 39: TRAP #7 */
162 34, /* 40: TRAP #8 */
163 34, /* 41: TRAP #9 */
164 34, /* 42: TRAP #10 */
165 34, /* 43: TRAP #11 */
166 34, /* 44: TRAP #12 */
167 34, /* 45: TRAP #13 */
168 34, /* 46: TRAP #14 */
169 34, /* 47: TRAP #15 */
170 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
171 4, /* 49: FP Inexact Result (unemulated) */
172 4, /* 50: FP Divide by Zero (unemulated) */
173 4, /* 51: FP Underflow (unemulated) */
174 4, /* 52: FP Operand Error (unemulated) */
175 4, /* 53: FP Overflow (unemulated) */
176 4, /* 54: FP Signaling NAN (unemulated) */
177 4, /* 55: FP Unimplemented Data Type (unemulated) */
178 4, /* 56: MMU Configuration Error (unemulated) */
179 4, /* 57: MMU Illegal Operation Error (unemulated) */
180 4, /* 58: MMU Access Level Violation Error (unemulated) */
181 4, /* 59: RESERVED */
182 4, /* 60: RESERVED */
183 4, /* 61: RESERVED */
184 4, /* 62: RESERVED */
185 4, /* 63: RESERVED */
186 /* 64-255: User Defined */
187 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
188 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
189 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
190 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
191 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
192 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
195 4, /* 0: Reset - Initial Stack Pointer */
196 4, /* 1: Reset - Initial Program Counter */
197 126, /* 2: Bus Error (unemulated) */
198 126, /* 3: Address Error (unemulated) */
199 38, /* 4: Illegal Instruction */
200 44, /* 5: Divide by Zero */
203 38, /* 8: Privilege Violation */
207 4, /* 12: RESERVED */
208 4, /* 13: Coprocessor Protocol Violation (unemulated) */
209 4, /* 14: Format Error */
210 44, /* 15: Uninitialized Interrupt */
211 4, /* 16: RESERVED */
212 4, /* 17: RESERVED */
213 4, /* 18: RESERVED */
214 4, /* 19: RESERVED */
215 4, /* 20: RESERVED */
216 4, /* 21: RESERVED */
217 4, /* 22: RESERVED */
218 4, /* 23: RESERVED */
219 46, /* 24: Spurious Interrupt */
220 46, /* 25: Level 1 Interrupt Autovector */
221 46, /* 26: Level 2 Interrupt Autovector */
222 46, /* 27: Level 3 Interrupt Autovector */
223 46, /* 28: Level 4 Interrupt Autovector */
224 46, /* 29: Level 5 Interrupt Autovector */
225 46, /* 30: Level 6 Interrupt Autovector */
226 46, /* 31: Level 7 Interrupt Autovector */
227 38, /* 32: TRAP #0 */
228 38, /* 33: TRAP #1 */
229 38, /* 34: TRAP #2 */
230 38, /* 35: TRAP #3 */
231 38, /* 36: TRAP #4 */
232 38, /* 37: TRAP #5 */
233 38, /* 38: TRAP #6 */
234 38, /* 39: TRAP #7 */
235 38, /* 40: TRAP #8 */
236 38, /* 41: TRAP #9 */
237 38, /* 42: TRAP #10 */
238 38, /* 43: TRAP #11 */
239 38, /* 44: TRAP #12 */
240 38, /* 45: TRAP #13 */
241 38, /* 46: TRAP #14 */
242 38, /* 47: TRAP #15 */
243 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
244 4, /* 49: FP Inexact Result (unemulated) */
245 4, /* 50: FP Divide by Zero (unemulated) */
246 4, /* 51: FP Underflow (unemulated) */
247 4, /* 52: FP Operand Error (unemulated) */
248 4, /* 53: FP Overflow (unemulated) */
249 4, /* 54: FP Signaling NAN (unemulated) */
250 4, /* 55: FP Unimplemented Data Type (unemulated) */
251 4, /* 56: MMU Configuration Error (unemulated) */
252 4, /* 57: MMU Illegal Operation Error (unemulated) */
253 4, /* 58: MMU Access Level Violation Error (unemulated) */
254 4, /* 59: RESERVED */
255 4, /* 60: RESERVED */
256 4, /* 61: RESERVED */
257 4, /* 62: RESERVED */
258 4, /* 63: RESERVED */
259 /* 64-255: User Defined */
260 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
261 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
262 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
263 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
264 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
265 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
268 4, /* 0: Reset - Initial Stack Pointer */
269 4, /* 1: Reset - Initial Program Counter */
270 50, /* 2: Bus Error (unemulated) */
271 50, /* 3: Address Error (unemulated) */
272 20, /* 4: Illegal Instruction */
273 38, /* 5: Divide by Zero */
276 34, /* 8: Privilege Violation */
280 4, /* 12: RESERVED */
281 4, /* 13: Coprocessor Protocol Violation (unemulated) */
282 4, /* 14: Format Error */
283 30, /* 15: Uninitialized Interrupt */
284 4, /* 16: RESERVED */
285 4, /* 17: RESERVED */
286 4, /* 18: RESERVED */
287 4, /* 19: RESERVED */
288 4, /* 20: RESERVED */
289 4, /* 21: RESERVED */
290 4, /* 22: RESERVED */
291 4, /* 23: RESERVED */
292 30, /* 24: Spurious Interrupt */
293 30, /* 25: Level 1 Interrupt Autovector */
294 30, /* 26: Level 2 Interrupt Autovector */
295 30, /* 27: Level 3 Interrupt Autovector */
296 30, /* 28: Level 4 Interrupt Autovector */
297 30, /* 29: Level 5 Interrupt Autovector */
298 30, /* 30: Level 6 Interrupt Autovector */
299 30, /* 31: Level 7 Interrupt Autovector */
300 20, /* 32: TRAP #0 */
301 20, /* 33: TRAP #1 */
302 20, /* 34: TRAP #2 */
303 20, /* 35: TRAP #3 */
304 20, /* 36: TRAP #4 */
305 20, /* 37: TRAP #5 */
306 20, /* 38: TRAP #6 */
307 20, /* 39: TRAP #7 */
308 20, /* 40: TRAP #8 */
309 20, /* 41: TRAP #9 */
310 20, /* 42: TRAP #10 */
311 20, /* 43: TRAP #11 */
312 20, /* 44: TRAP #12 */
313 20, /* 45: TRAP #13 */
314 20, /* 46: TRAP #14 */
315 20, /* 47: TRAP #15 */
316 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
317 4, /* 49: FP Inexact Result (unemulated) */
318 4, /* 50: FP Divide by Zero (unemulated) */
319 4, /* 51: FP Underflow (unemulated) */
320 4, /* 52: FP Operand Error (unemulated) */
321 4, /* 53: FP Overflow (unemulated) */
322 4, /* 54: FP Signaling NAN (unemulated) */
323 4, /* 55: FP Unimplemented Data Type (unemulated) */
324 4, /* 56: MMU Configuration Error (unemulated) */
325 4, /* 57: MMU Illegal Operation Error (unemulated) */
326 4, /* 58: MMU Access Level Violation Error (unemulated) */
327 4, /* 59: RESERVED */
328 4, /* 60: RESERVED */
329 4, /* 61: RESERVED */
330 4, /* 62: RESERVED */
331 4, /* 63: RESERVED */
332 /* 64-255: User Defined */
333 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
334 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
335 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
336 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
337 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
338 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
342 uint8 m68ki_ea_idx_cycle_table[64] =
344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
345 0, /* ..01.000 no memory indirect, base NULL */
346 5, /* ..01..01 memory indirect, base NULL, outer NULL */
347 7, /* ..01..10 memory indirect, base NULL, outer 16 */
348 7, /* ..01..11 memory indirect, base NULL, outer 32 */
349 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
350 2, /* ..10.000 no memory indirect, base 16 */
351 7, /* ..10..01 memory indirect, base 16, outer NULL */
352 9, /* ..10..10 memory indirect, base 16, outer 16 */
353 9, /* ..10..11 memory indirect, base 16, outer 32 */
354 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
355 6, /* ..11.000 no memory indirect, base 32 */
356 11, /* ..11..01 memory indirect, base 32, outer NULL */
357 13, /* ..11..10 memory indirect, base 32, outer 16 */
358 13, /* ..11..11 memory indirect, base 32, outer 32 */
359 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
364 /* ======================================================================== */
365 /* =============================== CALLBACKS ============================== */
366 /* ======================================================================== */
368 /* Default callbacks used if the callback hasn't been set yet, or if the
369 * callback is set to NULL
372 /* Interrupt acknowledge */
373 static int default_int_ack_callback_data;
374 static int default_int_ack_callback(int int_level)
376 default_int_ack_callback_data = int_level;
378 return M68K_INT_ACK_AUTOVECTOR;
381 /* Breakpoint acknowledge */
382 static unsigned int default_bkpt_ack_callback_data;
383 static void default_bkpt_ack_callback(unsigned int data)
385 default_bkpt_ack_callback_data = data;
388 /* Called when a reset instruction is executed */
389 static void default_reset_instr_callback(void)
393 /* Called when the program counter changed by a large value */
394 static unsigned int default_pc_changed_callback_data;
395 static void default_pc_changed_callback(unsigned int new_pc)
397 default_pc_changed_callback_data = new_pc;
400 /* Called every time there's bus activity (read/write to/from memory */
401 static unsigned int default_set_fc_callback_data;
402 static void default_set_fc_callback(unsigned int new_fc)
404 default_set_fc_callback_data = new_fc;
407 /* Called every instruction cycle prior to execution */
408 static void default_instr_hook_callback(void)
413 #if M68K_EMULATE_ADDRESS_ERROR
415 jmp_buf m68ki_aerr_trap;
416 #endif /* M68K_EMULATE_ADDRESS_ERROR */
419 /* ======================================================================== */
420 /* ================================= API ================================== */
421 /* ======================================================================== */
423 /* Access the internals of the CPU */
424 unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
426 m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
430 case M68K_REG_D0: return cpu->dar[0];
431 case M68K_REG_D1: return cpu->dar[1];
432 case M68K_REG_D2: return cpu->dar[2];
433 case M68K_REG_D3: return cpu->dar[3];
434 case M68K_REG_D4: return cpu->dar[4];
435 case M68K_REG_D5: return cpu->dar[5];
436 case M68K_REG_D6: return cpu->dar[6];
437 case M68K_REG_D7: return cpu->dar[7];
438 case M68K_REG_A0: return cpu->dar[8];
439 case M68K_REG_A1: return cpu->dar[9];
440 case M68K_REG_A2: return cpu->dar[10];
441 case M68K_REG_A3: return cpu->dar[11];
442 case M68K_REG_A4: return cpu->dar[12];
443 case M68K_REG_A5: return cpu->dar[13];
444 case M68K_REG_A6: return cpu->dar[14];
445 case M68K_REG_A7: return cpu->dar[15];
446 case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
447 case M68K_REG_SR: return cpu->t1_flag |
449 (cpu->s_flag << 11) |
450 (cpu->m_flag << 11) |
452 ((cpu->x_flag & XFLAG_SET) >> 4) |
453 ((cpu->n_flag & NFLAG_SET) >> 4) |
454 ((!cpu->not_z_flag) << 2) |
455 ((cpu->v_flag & VFLAG_SET) >> 6) |
456 ((cpu->c_flag & CFLAG_SET) >> 8);
457 case M68K_REG_SP: return cpu->dar[15];
458 case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
459 case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
460 case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
461 case M68K_REG_SFC: return cpu->sfc;
462 case M68K_REG_DFC: return cpu->dfc;
463 case M68K_REG_VBR: return cpu->vbr;
464 case M68K_REG_CACR: return cpu->cacr;
465 case M68K_REG_CAAR: return cpu->caar;
466 case M68K_REG_PREF_ADDR: return cpu->pref_addr;
467 case M68K_REG_PREF_DATA: return cpu->pref_data;
468 case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
469 case M68K_REG_IR: return cpu->ir;
470 case M68K_REG_CPU_TYPE:
471 switch(cpu->cpu_type)
473 case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
474 case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
475 case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
476 case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
478 return M68K_CPU_TYPE_INVALID;
484 void m68k_set_reg(m68k_register_t regnum, unsigned int value)
488 case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
489 case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
490 case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
491 case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
492 case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
493 case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
494 case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
495 case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
496 case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
497 case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
498 case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
499 case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
500 case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
501 case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
502 case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
503 case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
504 case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
505 case M68K_REG_SR: m68ki_set_sr(value); return;
506 case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
507 case M68K_REG_USP: if(FLAG_S)
508 REG_USP = MASK_OUT_ABOVE_32(value);
510 REG_SP = MASK_OUT_ABOVE_32(value);
512 case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
513 REG_SP = MASK_OUT_ABOVE_32(value);
515 REG_ISP = MASK_OUT_ABOVE_32(value);
517 case M68K_REG_MSP: if(FLAG_S && FLAG_M)
518 REG_SP = MASK_OUT_ABOVE_32(value);
520 REG_MSP = MASK_OUT_ABOVE_32(value);
522 case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
523 case M68K_REG_SFC: REG_SFC = value & 7; return;
524 case M68K_REG_DFC: REG_DFC = value & 7; return;
525 case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
526 case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
527 case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
528 case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
529 case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
534 /* Set the callbacks */
535 void m68k_set_int_ack_callback(int (*callback)(int int_level))
537 CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
540 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
542 CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
545 void m68k_set_reset_instr_callback(void (*callback)(void))
547 CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
550 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
552 CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
555 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
557 CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
560 void m68k_set_instr_hook_callback(void (*callback)(void))
562 CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
566 /* Set the CPU type. */
567 void m68k_set_cpu_type(unsigned int cpu_type)
571 case M68K_CPU_TYPE_68000:
572 CPU_TYPE = CPU_TYPE_000;
573 CPU_ADDRESS_MASK = 0x00ffffff;
574 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
575 CYC_INSTRUCTION = m68ki_cycles[0];
576 CYC_EXCEPTION = m68ki_exception_cycle_table[0];
577 CYC_BCC_NOTAKE_B = -2;
578 CYC_BCC_NOTAKE_W = 2;
579 CYC_DBCC_F_NOEXP = -2;
587 case M68K_CPU_TYPE_68010:
588 CPU_TYPE = CPU_TYPE_010;
589 CPU_ADDRESS_MASK = 0x00ffffff;
590 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
591 CYC_INSTRUCTION = m68ki_cycles[1];
592 CYC_EXCEPTION = m68ki_exception_cycle_table[1];
593 CYC_BCC_NOTAKE_B = -4;
594 CYC_BCC_NOTAKE_W = 0;
595 CYC_DBCC_F_NOEXP = 0;
603 case M68K_CPU_TYPE_68EC020:
604 CPU_TYPE = CPU_TYPE_EC020;
605 CPU_ADDRESS_MASK = 0x00ffffff;
606 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
607 CYC_INSTRUCTION = m68ki_cycles[2];
608 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
609 CYC_BCC_NOTAKE_B = -2;
610 CYC_BCC_NOTAKE_W = 0;
611 CYC_DBCC_F_NOEXP = 0;
619 case M68K_CPU_TYPE_68020:
620 CPU_TYPE = CPU_TYPE_020;
621 CPU_ADDRESS_MASK = 0xffffffff;
622 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
623 CYC_INSTRUCTION = m68ki_cycles[2];
624 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
625 CYC_BCC_NOTAKE_B = -2;
626 CYC_BCC_NOTAKE_W = 0;
627 CYC_DBCC_F_NOEXP = 0;
638 /* Execute some instructions until we use up num_cycles clock cycles */
639 /* ASG: removed per-instruction interrupt checks */
640 int m68k_execute(int num_cycles)
642 /* Make sure we're not stopped */
645 /* Set our pool of clock cycles available */
646 SET_CYCLES(num_cycles);
647 m68ki_initial_cycles = num_cycles;
649 /* ASG: update cycles */
650 USE_CYCLES(CPU_INT_CYCLES);
653 /* Return point if we had an address error */
654 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
656 /* Main loop. Keep going until we run out of clock cycles */
659 /* Set tracing accodring to T1. (T0 is done inside instruction) */
660 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
662 /* Set the address space for reads */
663 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
665 /* Call external hook to peek at CPU */
666 m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
668 /* Record previous program counter */
671 /* Read an instruction and call its handler */
672 REG_IR = m68ki_read_imm_16();
673 m68ki_instruction_jump_table[REG_IR]();
674 USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
676 /* Trace m68k_exception, if necessary */
677 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
678 } while(GET_CYCLES() > 0);
680 /* set previous PC to current PC for the next entry into the loop */
683 /* ASG: update cycles */
684 USE_CYCLES(CPU_INT_CYCLES);
687 /* return how many clocks we used */
688 return m68ki_initial_cycles - GET_CYCLES();
691 /* We get here if the CPU is stopped or halted */
699 int m68k_cycles_run(void)
701 return m68ki_initial_cycles - GET_CYCLES();
704 int m68k_cycles_remaining(void)
709 /* Change the timeslice */
710 void m68k_modify_timeslice(int cycles)
712 m68ki_initial_cycles += cycles;
717 void m68k_end_timeslice(void)
719 m68ki_initial_cycles = GET_CYCLES();
724 /* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
725 /* KS: Modified so that IPL* bits match with mask positions in the SR
726 * and cleaned out remenants of the interrupt controller.
728 void m68k_set_irq(unsigned int int_level)
730 uint old_level = CPU_INT_LEVEL;
731 CPU_INT_LEVEL = int_level << 8;
733 /* A transition from < 7 to 7 always interrupts (NMI) */
734 /* Note: Level 7 can also level trigger like a normal IRQ */
735 if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
736 m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
738 m68ki_check_interrupts(); /* Level triggered (IRQ) */
743 static uint emulation_initialized = 0;
745 /* The first call to this function initializes the opcode handler jump table */
746 if(!emulation_initialized)
748 m68ki_build_opcode_table();
749 emulation_initialized = 1;
752 m68k_set_int_ack_callback(NULL);
753 m68k_set_bkpt_ack_callback(NULL);
754 m68k_set_reset_instr_callback(NULL);
755 m68k_set_pc_changed_callback(NULL);
756 m68k_set_fc_callback(NULL);
757 m68k_set_instr_hook_callback(NULL);
760 /* Pulse the RESET line on the CPU */
761 void m68k_pulse_reset(void)
763 /* Clear all stop levels and eat up all remaining cycles */
767 CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
768 CPU_INSTR_MODE = INSTRUCTION_YES;
770 /* Turn off tracing */
771 FLAG_T1 = FLAG_T0 = 0;
773 /* Interrupt mask to level 7 */
774 FLAG_INT_MASK = 0x0700;
777 /* Go to supervisor mode */
778 m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
780 /* Invalidate the prefetch queue */
781 #if M68K_EMULATE_PREFETCH
782 /* Set to arbitrary number since our first fetch is from 0 */
783 CPU_PREF_ADDR = 0x1000;
784 #endif /* M68K_EMULATE_PREFETCH */
786 /* Read the initial stack pointer and program counter */
788 REG_SP = m68ki_read_imm_32();
789 REG_PC = m68ki_read_imm_32();
792 CPU_RUN_MODE = RUN_MODE_NORMAL;
795 /* Pulse the HALT line on the CPU */
796 void m68k_pulse_halt(void)
798 CPU_STOPPED |= STOP_LEVEL_HALT;
802 /* Get and set the current CPU context */
803 /* This is to allow for multiple CPUs */
804 unsigned int m68k_context_size()
806 return sizeof(m68ki_cpu_core);
809 unsigned int m68k_get_context(void* dst)
811 if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
812 return sizeof(m68ki_cpu_core);
815 void m68k_set_context(void* src)
817 if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
822 /* ======================================================================== */
823 /* ============================== MAME STUFF ============================== */
824 /* ======================================================================== */
826 #if M68K_COMPILE_FOR_MAME == OPT_ON
836 static void m68k_prepare_substate(void)
838 m68k_substate.sr = m68ki_get_sr();
839 m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
840 m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
843 static void m68k_post_load(void)
845 m68ki_set_sr_noint_nosp(m68k_substate.sr);
846 CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
847 | m68k_substate.halted ? STOP_LEVEL_HALT : 0;
851 void m68k_state_register(const char *type)
853 int cpu = cpu_getactivecpu();
855 state_save_register_UINT32(type, cpu, "D" , REG_D, 8);
856 state_save_register_UINT32(type, cpu, "A" , REG_A, 8);
857 state_save_register_UINT32(type, cpu, "PPC" , ®_PPC, 1);
858 state_save_register_UINT32(type, cpu, "PC" , ®_PC, 1);
859 state_save_register_UINT32(type, cpu, "USP" , ®_USP, 1);
860 state_save_register_UINT32(type, cpu, "ISP" , ®_ISP, 1);
861 state_save_register_UINT32(type, cpu, "MSP" , ®_MSP, 1);
862 state_save_register_UINT32(type, cpu, "VBR" , ®_VBR, 1);
863 state_save_register_UINT32(type, cpu, "SFC" , ®_SFC, 1);
864 state_save_register_UINT32(type, cpu, "DFC" , ®_DFC, 1);
865 state_save_register_UINT32(type, cpu, "CACR" , ®_CACR, 1);
866 state_save_register_UINT32(type, cpu, "CAAR" , ®_CAAR, 1);
867 state_save_register_UINT16(type, cpu, "SR" , &m68k_substate.sr, 1);
868 state_save_register_UINT32(type, cpu, "INT_LEVEL" , &CPU_INT_LEVEL, 1);
869 state_save_register_UINT32(type, cpu, "INT_CYCLES", &CPU_INT_CYCLES, 1);
870 state_save_register_int (type, cpu, "STOPPED" , &m68k_substate.stopped);
871 state_save_register_int (type, cpu, "HALTED" , &m68k_substate.halted);
872 state_save_register_UINT32(type, cpu, "PREF_ADDR" , &CPU_PREF_ADDR, 1);
873 state_save_register_UINT32(type, cpu, "PREF_DATA" , &CPU_PREF_DATA, 1);
874 state_save_register_func_presave(m68k_prepare_substate);
875 state_save_register_func_postload(m68k_post_load);
878 #endif /* M68K_COMPILE_FOR_MAME */
880 /* ======================================================================== */
881 /* ============================== END OF FILE ============================= */
882 /* ======================================================================== */