source: buchla-emu/cpu/m68kcpu.c@ 4f967e8

Last change on this file since 4f967e8 was 93280c2, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Added Musashi CPU emulator.

  • Property mode set to 100755
File size: 36.1 KB
Line 
1/* ======================================================================== */
2/* ========================= LICENSING & COPYRIGHT ======================== */
3/* ======================================================================== */
4/*
5 * MUSASHI
6 * Version 3.4
7 *
8 * A portable Motorola M680x0 processor emulation engine.
9 * Copyright 1998-2001 Karl Stenerud. All rights reserved.
10 *
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:
17 *
18 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20
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
27 * THE SOFTWARE.
28 */
29
30
31/* ======================================================================== */
32/* ================================= NOTES ================================ */
33/* ======================================================================== */
34
35
36
37/* ======================================================================== */
38/* ================================ INCLUDES ============================== */
39/* ======================================================================== */
40
41#include "m68kops.h"
42#include "m68kcpu.h"
43
44/* ======================================================================== */
45/* ================================= DATA ================================= */
46/* ======================================================================== */
47
48int m68ki_initial_cycles;
49int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
50uint m68ki_tracing = 0;
51uint m68ki_address_space;
52
53#ifdef M68K_LOG_ENABLE
54char* m68ki_cpu_names[9] =
55{
56 "Invalid CPU",
57 "M68000",
58 "M68010",
59 "Invalid CPU",
60 "M68EC020"
61 "Invalid CPU",
62 "Invalid CPU",
63 "Invalid CPU",
64 "M68020"
65};
66#endif /* M68K_LOG_ENABLE */
67
68/* The CPU core */
69m68ki_cpu_core m68ki_cpu = {0};
70
71#if M68K_EMULATE_ADDRESS_ERROR
72jmp_buf m68ki_aerr_trap;
73#endif /* M68K_EMULATE_ADDRESS_ERROR */
74
75uint m68ki_aerr_address;
76uint m68ki_aerr_write_mode;
77uint m68ki_aerr_fc;
78
79/* Used by shift & rotate instructions */
80uint8 m68ki_shift_8_table[65] =
81{
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
88};
89uint16 m68ki_shift_16_table[65] =
90{
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,
98 0xffff, 0xffff
99};
100uint m68ki_shift_32_table[65] =
101{
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
113};
114
115
116/* Number of clock cycles to use for exception processing.
117 * I used 4 for any vectors that are undocumented for processing times.
118 */
119uint8 m68ki_exception_cycle_table[3][256] =
120{
121 { /* 000 */
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 */
129 34, /* 7: TRAPV */
130 34, /* 8: Privilege Violation */
131 34, /* 9: Trace */
132 34, /* 10: 1010 */
133 34, /* 11: 1111 */
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
193 },
194 { /* 010 */
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 */
201 44, /* 6: CHK */
202 34, /* 7: TRAPV */
203 38, /* 8: Privilege Violation */
204 38, /* 9: Trace */
205 4, /* 10: 1010 */
206 4, /* 11: 1111 */
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
266 },
267 { /* 020 */
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 */
274 40, /* 6: CHK */
275 20, /* 7: TRAPV */
276 34, /* 8: Privilege Violation */
277 25, /* 9: Trace */
278 20, /* 10: 1010 */
279 20, /* 11: 1111 */
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
339 }
340};
341
342uint8 m68ki_ea_idx_cycle_table[64] =
343{
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
360};
361
362
363
364/* ======================================================================== */
365/* =============================== CALLBACKS ============================== */
366/* ======================================================================== */
367
368/* Default callbacks used if the callback hasn't been set yet, or if the
369 * callback is set to NULL
370 */
371
372/* Interrupt acknowledge */
373static int default_int_ack_callback_data;
374static int default_int_ack_callback(int int_level)
375{
376 default_int_ack_callback_data = int_level;
377 CPU_INT_LEVEL = 0;
378 return M68K_INT_ACK_AUTOVECTOR;
379}
380
381/* Breakpoint acknowledge */
382static unsigned int default_bkpt_ack_callback_data;
383static void default_bkpt_ack_callback(unsigned int data)
384{
385 default_bkpt_ack_callback_data = data;
386}
387
388/* Called when a reset instruction is executed */
389static void default_reset_instr_callback(void)
390{
391}
392
393/* Called when the program counter changed by a large value */
394static unsigned int default_pc_changed_callback_data;
395static void default_pc_changed_callback(unsigned int new_pc)
396{
397 default_pc_changed_callback_data = new_pc;
398}
399
400/* Called every time there's bus activity (read/write to/from memory */
401static unsigned int default_set_fc_callback_data;
402static void default_set_fc_callback(unsigned int new_fc)
403{
404 default_set_fc_callback_data = new_fc;
405}
406
407/* Called every instruction cycle prior to execution */
408static void default_instr_hook_callback(void)
409{
410}
411
412
413#if M68K_EMULATE_ADDRESS_ERROR
414 #include <setjmp.h>
415 jmp_buf m68ki_aerr_trap;
416#endif /* M68K_EMULATE_ADDRESS_ERROR */
417
418
419/* ======================================================================== */
420/* ================================= API ================================== */
421/* ======================================================================== */
422
423/* Access the internals of the CPU */
424unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
425{
426 m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
427
428 switch(regnum)
429 {
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 |
448 cpu->t0_flag |
449 (cpu->s_flag << 11) |
450 (cpu->m_flag << 11) |
451 cpu->int_mask |
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)
472 {
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;
477 }
478 return M68K_CPU_TYPE_INVALID;
479 default: return 0;
480 }
481 return 0;
482}
483
484void m68k_set_reg(m68k_register_t regnum, unsigned int value)
485{
486 switch(regnum)
487 {
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);
509 else
510 REG_SP = MASK_OUT_ABOVE_32(value);
511 return;
512 case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
513 REG_SP = MASK_OUT_ABOVE_32(value);
514 else
515 REG_ISP = MASK_OUT_ABOVE_32(value);
516 return;
517 case M68K_REG_MSP: if(FLAG_S && FLAG_M)
518 REG_SP = MASK_OUT_ABOVE_32(value);
519 else
520 REG_MSP = MASK_OUT_ABOVE_32(value);
521 return;
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;
530 default: return;
531 }
532}
533
534/* Set the callbacks */
535void m68k_set_int_ack_callback(int (*callback)(int int_level))
536{
537 CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
538}
539
540void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
541{
542 CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
543}
544
545void m68k_set_reset_instr_callback(void (*callback)(void))
546{
547 CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
548}
549
550void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
551{
552 CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
553}
554
555void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
556{
557 CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
558}
559
560void m68k_set_instr_hook_callback(void (*callback)(void))
561{
562 CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
563}
564
565#include <stdio.h>
566/* Set the CPU type. */
567void m68k_set_cpu_type(unsigned int cpu_type)
568{
569 switch(cpu_type)
570 {
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;
580 CYC_DBCC_F_EXP = 2;
581 CYC_SCC_R_TRUE = 2;
582 CYC_MOVEM_W = 2;
583 CYC_MOVEM_L = 3;
584 CYC_SHIFT = 1;
585 CYC_RESET = 132;
586 return;
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;
596 CYC_DBCC_F_EXP = 6;
597 CYC_SCC_R_TRUE = 0;
598 CYC_MOVEM_W = 2;
599 CYC_MOVEM_L = 3;
600 CYC_SHIFT = 1;
601 CYC_RESET = 130;
602 return;
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;
612 CYC_DBCC_F_EXP = 4;
613 CYC_SCC_R_TRUE = 0;
614 CYC_MOVEM_W = 2;
615 CYC_MOVEM_L = 2;
616 CYC_SHIFT = 0;
617 CYC_RESET = 518;
618 return;
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;
628 CYC_DBCC_F_EXP = 4;
629 CYC_SCC_R_TRUE = 0;
630 CYC_MOVEM_W = 2;
631 CYC_MOVEM_L = 2;
632 CYC_SHIFT = 0;
633 CYC_RESET = 518;
634 return;
635 }
636}
637
638/* Execute some instructions until we use up num_cycles clock cycles */
639/* ASG: removed per-instruction interrupt checks */
640int m68k_execute(int num_cycles)
641{
642 /* Make sure we're not stopped */
643 if(!CPU_STOPPED)
644 {
645 /* Set our pool of clock cycles available */
646 SET_CYCLES(num_cycles);
647 m68ki_initial_cycles = num_cycles;
648
649 /* ASG: update cycles */
650 USE_CYCLES(CPU_INT_CYCLES);
651 CPU_INT_CYCLES = 0;
652
653 /* Return point if we had an address error */
654 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
655
656 /* Main loop. Keep going until we run out of clock cycles */
657 do
658 {
659 /* Set tracing accodring to T1. (T0 is done inside instruction) */
660 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
661
662 /* Set the address space for reads */
663 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
664
665 /* Call external hook to peek at CPU */
666 m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
667
668 /* Record previous program counter */
669 REG_PPC = REG_PC;
670
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]);
675
676 /* Trace m68k_exception, if necessary */
677 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
678 } while(GET_CYCLES() > 0);
679
680 /* set previous PC to current PC for the next entry into the loop */
681 REG_PPC = REG_PC;
682
683 /* ASG: update cycles */
684 USE_CYCLES(CPU_INT_CYCLES);
685 CPU_INT_CYCLES = 0;
686
687 /* return how many clocks we used */
688 return m68ki_initial_cycles - GET_CYCLES();
689 }
690
691 /* We get here if the CPU is stopped or halted */
692 SET_CYCLES(0);
693 CPU_INT_CYCLES = 0;
694
695 return num_cycles;
696}
697
698
699int m68k_cycles_run(void)
700{
701 return m68ki_initial_cycles - GET_CYCLES();
702}
703
704int m68k_cycles_remaining(void)
705{
706 return GET_CYCLES();
707}
708
709/* Change the timeslice */
710void m68k_modify_timeslice(int cycles)
711{
712 m68ki_initial_cycles += cycles;
713 ADD_CYCLES(cycles);
714}
715
716
717void m68k_end_timeslice(void)
718{
719 m68ki_initial_cycles = GET_CYCLES();
720 SET_CYCLES(0);
721}
722
723
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.
727 */
728void m68k_set_irq(unsigned int int_level)
729{
730 uint old_level = CPU_INT_LEVEL;
731 CPU_INT_LEVEL = int_level << 8;
732
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) */
737 else
738 m68ki_check_interrupts(); /* Level triggered (IRQ) */
739}
740
741void m68k_init(void)
742{
743 static uint emulation_initialized = 0;
744
745 /* The first call to this function initializes the opcode handler jump table */
746 if(!emulation_initialized)
747 {
748 m68ki_build_opcode_table();
749 emulation_initialized = 1;
750 }
751
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);
758}
759
760/* Pulse the RESET line on the CPU */
761void m68k_pulse_reset(void)
762{
763 /* Clear all stop levels and eat up all remaining cycles */
764 CPU_STOPPED = 0;
765 SET_CYCLES(0);
766
767 CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
768 CPU_INSTR_MODE = INSTRUCTION_YES;
769
770 /* Turn off tracing */
771 FLAG_T1 = FLAG_T0 = 0;
772 m68ki_clear_trace();
773 /* Interrupt mask to level 7 */
774 FLAG_INT_MASK = 0x0700;
775 /* Reset VBR */
776 REG_VBR = 0;
777 /* Go to supervisor mode */
778 m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
779
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 */
785
786 /* Read the initial stack pointer and program counter */
787 m68ki_jump(0);
788 REG_SP = m68ki_read_imm_32();
789 REG_PC = m68ki_read_imm_32();
790 m68ki_jump(REG_PC);
791
792 CPU_RUN_MODE = RUN_MODE_NORMAL;
793}
794
795/* Pulse the HALT line on the CPU */
796void m68k_pulse_halt(void)
797{
798 CPU_STOPPED |= STOP_LEVEL_HALT;
799}
800
801
802/* Get and set the current CPU context */
803/* This is to allow for multiple CPUs */
804unsigned int m68k_context_size()
805{
806 return sizeof(m68ki_cpu_core);
807}
808
809unsigned int m68k_get_context(void* dst)
810{
811 if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
812 return sizeof(m68ki_cpu_core);
813}
814
815void m68k_set_context(void* src)
816{
817 if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
818}
819
820
821
822/* ======================================================================== */
823/* ============================== MAME STUFF ============================== */
824/* ======================================================================== */
825
826#if M68K_COMPILE_FOR_MAME == OPT_ON
827
828#include "state.h"
829
830static struct {
831 UINT16 sr;
832 int stopped;
833 int halted;
834} m68k_substate;
835
836static void m68k_prepare_substate(void)
837{
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;
841}
842
843static void m68k_post_load(void)
844{
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;
848 m68ki_jump(REG_PC);
849}
850
851void m68k_state_register(const char *type)
852{
853 int cpu = cpu_getactivecpu();
854
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" , &REG_PPC, 1);
858 state_save_register_UINT32(type, cpu, "PC" , &REG_PC, 1);
859 state_save_register_UINT32(type, cpu, "USP" , &REG_USP, 1);
860 state_save_register_UINT32(type, cpu, "ISP" , &REG_ISP, 1);
861 state_save_register_UINT32(type, cpu, "MSP" , &REG_MSP, 1);
862 state_save_register_UINT32(type, cpu, "VBR" , &REG_VBR, 1);
863 state_save_register_UINT32(type, cpu, "SFC" , &REG_SFC, 1);
864 state_save_register_UINT32(type, cpu, "DFC" , &REG_DFC, 1);
865 state_save_register_UINT32(type, cpu, "CACR" , &REG_CACR, 1);
866 state_save_register_UINT32(type, cpu, "CAAR" , &REG_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);
876}
877
878#endif /* M68K_COMPILE_FOR_MAME */
879
880/* ======================================================================== */
881/* ============================== END OF FILE ============================= */
882/* ======================================================================== */
Note: See TracBrowser for help on using the repository browser.