1 /* ======================================================================== */
2 /* ========================= LICENSING & COPYRIGHT ======================== */
3 /* ======================================================================== */
4
5 #if 1
6 static const char copyright_notice[] =
7 "MUSASHI\n"
8 "Version 3.32 (2007-12-15)\n"
9 "A portable Motorola M680x0 processor emulation engine.\n"
10 "Copyright Karl Stenerud. All rights reserved.\n"
11 "\n"
12 "This code may be freely used for non-commercial purpooses as long as this\n"
13 "copyright notice remains unaltered in the source code and any binary files\n"
14 "containing this code in compiled form.\n"
15 "\n"
16 "All other licensing terms must be negotiated with the author\n"
17 "(Karl Stenerud).\n"
18 "\n"
19 "The latest version of this code can be obtained at:\n"
20 "http://kstenerud.cjb.net\n"
21 ;
22 #endif
23
24
25 /* ======================================================================== */
26 /* ================================= NOTES ================================ */
27 /* ======================================================================== */
28
29
30
31 /* ======================================================================== */
32 /* ================================ INCLUDES ============================== */
33 /* ======================================================================== */
34
35 #include <stdint.h>
36 #include <stddef.h>
37
38 extern void m68040_fpu_op0(void);
39 extern void m68040_fpu_op1(void);
40
41 #include "m68kops.h"
42 #include "m68kcpu.h"
43 #include "m68kfpu.c"
44
45 /* ======================================================================== */
46 /* ================================= DATA ================================= */
47 /* ======================================================================== */
48 int m68k_ICount = 0;
49
50 int m68ki_initial_cycles = 0;
51 uint m68ki_tracing = 0;
52 uint m68ki_address_space;
53
54 int megadrive_sr_checkint_mode = 0;
55
56 #ifdef M68K_LOG_ENABLE
57 const char *const m68ki_cpu_names[] =
58 {
59 "Invalid CPU",
60 "M68000",
61 "M68008",
62 "Invalid CPU",
63 "M68010",
64 "Invalid CPU",
65 "Invalid CPU",
66 "Invalid CPU",
67 "M68EC020",
68 "Invalid CPU",
69 "Invalid CPU",
70 "Invalid CPU",
71 "Invalid CPU",
72 "Invalid CPU",
73 "Invalid CPU",
74 "Invalid CPU",
75 "M68020"
76 };
77 #endif /* M68K_LOG_ENABLE */
78
79 /* The CPU core */
80 m68ki_cpu_core m68ki_cpu = {0};
81
82 #if M68K_EMULATE_ADDRESS_ERROR
83 jmp_buf m68ki_aerr_trap;
84 #endif /* M68K_EMULATE_ADDRESS_ERROR */
85
86 uint m68ki_aerr_address;
87 uint m68ki_aerr_write_mode;
88 uint m68ki_aerr_fc;
89
90 /* Used by shift & rotate instructions */
91 const uint8 m68ki_shift_8_table[65] =
92 {
93 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
96 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
97 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
98 0xff, 0xff, 0xff, 0xff, 0xff
99 };
100 const uint16 m68ki_shift_16_table[65] =
101 {
102 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
103 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
104 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
105 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
106 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
107 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
108 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
109 0xffff, 0xffff
110 };
111 const uint m68ki_shift_32_table[65] =
112 {
113 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
114 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
115 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
116 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
117 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
118 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
119 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
120 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
121 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
122 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
123 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
124 };
125
126
127 /* Number of clock cycles to use for exception processing.
128 * I used 4 for any vectors that are undocumented for processing times.
129 */
130 const uint8 m68ki_exception_cycle_table[4][256] =
131 {
132 { /* 000 */
133 4, /* 0: Reset - Initial Stack Pointer */
134 4, /* 1: Reset - Initial Program Counter */
135 50, /* 2: Bus Error (unemulated) */
136 50, /* 3: Address Error (unemulated) */
137 34, /* 4: Illegal Instruction */
138 38, /* 5: Divide by Zero -- ASG: changed from 42 */
139 40, /* 6: CHK -- ASG: chanaged from 44 */
140 34, /* 7: TRAPV */
141 34, /* 8: Privilege Violation */
142 34, /* 9: Trace */
143 4, /* 10: 1010 */
144 4, /* 11: 1111 */
145 4, /* 12: RESERVED */
146 4, /* 13: Coprocessor Protocol Violation (unemulated) */
147 4, /* 14: Format Error */
148 44, /* 15: Uninitialized Interrupt */
149 4, /* 16: RESERVED */
150 4, /* 17: RESERVED */
151 4, /* 18: RESERVED */
152 4, /* 19: RESERVED */
153 4, /* 20: RESERVED */
154 4, /* 21: RESERVED */
155 4, /* 22: RESERVED */
156 4, /* 23: RESERVED */
157 44, /* 24: Spurious Interrupt */
158 44, /* 25: Level 1 Interrupt Autovector */
159 44, /* 26: Level 2 Interrupt Autovector */
160 44, /* 27: Level 3 Interrupt Autovector */
161 44, /* 28: Level 4 Interrupt Autovector */
162 44, /* 29: Level 5 Interrupt Autovector */
163 44, /* 30: Level 6 Interrupt Autovector */
164 44, /* 31: Level 7 Interrupt Autovector */
165 34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
166 34, /* 33: TRAP #1 */
167 34, /* 34: TRAP #2 */
168 34, /* 35: TRAP #3 */
169 34, /* 36: TRAP #4 */
170 34, /* 37: TRAP #5 */
171 34, /* 38: TRAP #6 */
172 34, /* 39: TRAP #7 */
173 34, /* 40: TRAP #8 */
174 34, /* 41: TRAP #9 */
175 34, /* 42: TRAP #10 */
176 34, /* 43: TRAP #11 */
177 34, /* 44: TRAP #12 */
178 34, /* 45: TRAP #13 */
179 34, /* 46: TRAP #14 */
180 34, /* 47: TRAP #15 */
181 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
182 4, /* 49: FP Inexact Result (unemulated) */
183 4, /* 50: FP Divide by Zero (unemulated) */
184 4, /* 51: FP Underflow (unemulated) */
185 4, /* 52: FP Operand Error (unemulated) */
186 4, /* 53: FP Overflow (unemulated) */
187 4, /* 54: FP Signaling NAN (unemulated) */
188 4, /* 55: FP Unimplemented Data Type (unemulated) */
189 4, /* 56: MMU Configuration Error (unemulated) */
190 4, /* 57: MMU Illegal Operation Error (unemulated) */
191 4, /* 58: MMU Access Level Violation Error (unemulated) */
192 4, /* 59: RESERVED */
193 4, /* 60: RESERVED */
194 4, /* 61: RESERVED */
195 4, /* 62: RESERVED */
196 4, /* 63: RESERVED */
197 /* 64-255: User Defined */
198 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
199 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
200 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
201 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
202 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
203 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
204 },
205 { /* 010 */
206 4, /* 0: Reset - Initial Stack Pointer */
207 4, /* 1: Reset - Initial Program Counter */
208 126, /* 2: Bus Error (unemulated) */
209 126, /* 3: Address Error (unemulated) */
210 38, /* 4: Illegal Instruction */
211 44, /* 5: Divide by Zero */
212 44, /* 6: CHK */
213 34, /* 7: TRAPV */
214 38, /* 8: Privilege Violation */
215 38, /* 9: Trace */
216 4, /* 10: 1010 */
217 4, /* 11: 1111 */
218 4, /* 12: RESERVED */
219 4, /* 13: Coprocessor Protocol Violation (unemulated) */
220 4, /* 14: Format Error */
221 44, /* 15: Uninitialized Interrupt */
222 4, /* 16: RESERVED */
223 4, /* 17: RESERVED */
224 4, /* 18: RESERVED */
225 4, /* 19: RESERVED */
226 4, /* 20: RESERVED */
227 4, /* 21: RESERVED */
228 4, /* 22: RESERVED */
229 4, /* 23: RESERVED */
230 46, /* 24: Spurious Interrupt */
231 46, /* 25: Level 1 Interrupt Autovector */
232 46, /* 26: Level 2 Interrupt Autovector */
233 46, /* 27: Level 3 Interrupt Autovector */
234 46, /* 28: Level 4 Interrupt Autovector */
235 46, /* 29: Level 5 Interrupt Autovector */
236 46, /* 30: Level 6 Interrupt Autovector */
237 46, /* 31: Level 7 Interrupt Autovector */
238 38, /* 32: TRAP #0 */
239 38, /* 33: TRAP #1 */
240 38, /* 34: TRAP #2 */
241 38, /* 35: TRAP #3 */
242 38, /* 36: TRAP #4 */
243 38, /* 37: TRAP #5 */
244 38, /* 38: TRAP #6 */
245 38, /* 39: TRAP #7 */
246 38, /* 40: TRAP #8 */
247 38, /* 41: TRAP #9 */
248 38, /* 42: TRAP #10 */
249 38, /* 43: TRAP #11 */
250 38, /* 44: TRAP #12 */
251 38, /* 45: TRAP #13 */
252 38, /* 46: TRAP #14 */
253 38, /* 47: TRAP #15 */
254 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
255 4, /* 49: FP Inexact Result (unemulated) */
256 4, /* 50: FP Divide by Zero (unemulated) */
257 4, /* 51: FP Underflow (unemulated) */
258 4, /* 52: FP Operand Error (unemulated) */
259 4, /* 53: FP Overflow (unemulated) */
260 4, /* 54: FP Signaling NAN (unemulated) */
261 4, /* 55: FP Unimplemented Data Type (unemulated) */
262 4, /* 56: MMU Configuration Error (unemulated) */
263 4, /* 57: MMU Illegal Operation Error (unemulated) */
264 4, /* 58: MMU Access Level Violation Error (unemulated) */
265 4, /* 59: RESERVED */
266 4, /* 60: RESERVED */
267 4, /* 61: RESERVED */
268 4, /* 62: RESERVED */
269 4, /* 63: RESERVED */
270 /* 64-255: User Defined */
271 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
272 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
273 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
274 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
275 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
276 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
277 },
278 { /* 020 */
279 4, /* 0: Reset - Initial Stack Pointer */
280 4, /* 1: Reset - Initial Program Counter */
281 50, /* 2: Bus Error (unemulated) */
282 50, /* 3: Address Error (unemulated) */
283 20, /* 4: Illegal Instruction */
284 38, /* 5: Divide by Zero */
285 40, /* 6: CHK */
286 20, /* 7: TRAPV */
287 34, /* 8: Privilege Violation */
288 25, /* 9: Trace */
289 20, /* 10: 1010 */
290 20, /* 11: 1111 */
291 4, /* 12: RESERVED */
292 4, /* 13: Coprocessor Protocol Violation (unemulated) */
293 4, /* 14: Format Error */
294 30, /* 15: Uninitialized Interrupt */
295 4, /* 16: RESERVED */
296 4, /* 17: RESERVED */
297 4, /* 18: RESERVED */
298 4, /* 19: RESERVED */
299 4, /* 20: RESERVED */
300 4, /* 21: RESERVED */
301 4, /* 22: RESERVED */
302 4, /* 23: RESERVED */
303 30, /* 24: Spurious Interrupt */
304 30, /* 25: Level 1 Interrupt Autovector */
305 30, /* 26: Level 2 Interrupt Autovector */
306 30, /* 27: Level 3 Interrupt Autovector */
307 30, /* 28: Level 4 Interrupt Autovector */
308 30, /* 29: Level 5 Interrupt Autovector */
309 30, /* 30: Level 6 Interrupt Autovector */
310 30, /* 31: Level 7 Interrupt Autovector */
311 20, /* 32: TRAP #0 */
312 20, /* 33: TRAP #1 */
313 20, /* 34: TRAP #2 */
314 20, /* 35: TRAP #3 */
315 20, /* 36: TRAP #4 */
316 20, /* 37: TRAP #5 */
317 20, /* 38: TRAP #6 */
318 20, /* 39: TRAP #7 */
319 20, /* 40: TRAP #8 */
320 20, /* 41: TRAP #9 */
321 20, /* 42: TRAP #10 */
322 20, /* 43: TRAP #11 */
323 20, /* 44: TRAP #12 */
324 20, /* 45: TRAP #13 */
325 20, /* 46: TRAP #14 */
326 20, /* 47: TRAP #15 */
327 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
328 4, /* 49: FP Inexact Result (unemulated) */
329 4, /* 50: FP Divide by Zero (unemulated) */
330 4, /* 51: FP Underflow (unemulated) */
331 4, /* 52: FP Operand Error (unemulated) */
332 4, /* 53: FP Overflow (unemulated) */
333 4, /* 54: FP Signaling NAN (unemulated) */
334 4, /* 55: FP Unimplemented Data Type (unemulated) */
335 4, /* 56: MMU Configuration Error (unemulated) */
336 4, /* 57: MMU Illegal Operation Error (unemulated) */
337 4, /* 58: MMU Access Level Violation Error (unemulated) */
338 4, /* 59: RESERVED */
339 4, /* 60: RESERVED */
340 4, /* 61: RESERVED */
341 4, /* 62: RESERVED */
342 4, /* 63: RESERVED */
343 /* 64-255: User Defined */
344 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
345 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
346 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
347 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
348 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
349 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
350 },
351 { /* 040 */ // TODO: these values are not correct
352 4, /* 0: Reset - Initial Stack Pointer */
353 4, /* 1: Reset - Initial Program Counter */
354 50, /* 2: Bus Error (unemulated) */
355 50, /* 3: Address Error (unemulated) */
356 20, /* 4: Illegal Instruction */
357 38, /* 5: Divide by Zero */
358 40, /* 6: CHK */
359 20, /* 7: TRAPV */
360 34, /* 8: Privilege Violation */
361 25, /* 9: Trace */
362 20, /* 10: 1010 */
363 20, /* 11: 1111 */
364 4, /* 12: RESERVED */
365 4, /* 13: Coprocessor Protocol Violation (unemulated) */
366 4, /* 14: Format Error */
367 30, /* 15: Uninitialized Interrupt */
368 4, /* 16: RESERVED */
369 4, /* 17: RESERVED */
370 4, /* 18: RESERVED */
371 4, /* 19: RESERVED */
372 4, /* 20: RESERVED */
373 4, /* 21: RESERVED */
374 4, /* 22: RESERVED */
375 4, /* 23: RESERVED */
376 30, /* 24: Spurious Interrupt */
377 30, /* 25: Level 1 Interrupt Autovector */
378 30, /* 26: Level 2 Interrupt Autovector */
379 30, /* 27: Level 3 Interrupt Autovector */
380 30, /* 28: Level 4 Interrupt Autovector */
381 30, /* 29: Level 5 Interrupt Autovector */
382 30, /* 30: Level 6 Interrupt Autovector */
383 30, /* 31: Level 7 Interrupt Autovector */
384 20, /* 32: TRAP #0 */
385 20, /* 33: TRAP #1 */
386 20, /* 34: TRAP #2 */
387 20, /* 35: TRAP #3 */
388 20, /* 36: TRAP #4 */
389 20, /* 37: TRAP #5 */
390 20, /* 38: TRAP #6 */
391 20, /* 39: TRAP #7 */
392 20, /* 40: TRAP #8 */
393 20, /* 41: TRAP #9 */
394 20, /* 42: TRAP #10 */
395 20, /* 43: TRAP #11 */
396 20, /* 44: TRAP #12 */
397 20, /* 45: TRAP #13 */
398 20, /* 46: TRAP #14 */
399 20, /* 47: TRAP #15 */
400 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
401 4, /* 49: FP Inexact Result (unemulated) */
402 4, /* 50: FP Divide by Zero (unemulated) */
403 4, /* 51: FP Underflow (unemulated) */
404 4, /* 52: FP Operand Error (unemulated) */
405 4, /* 53: FP Overflow (unemulated) */
406 4, /* 54: FP Signaling NAN (unemulated) */
407 4, /* 55: FP Unimplemented Data Type (unemulated) */
408 4, /* 56: MMU Configuration Error (unemulated) */
409 4, /* 57: MMU Illegal Operation Error (unemulated) */
410 4, /* 58: MMU Access Level Violation Error (unemulated) */
411 4, /* 59: RESERVED */
412 4, /* 60: RESERVED */
413 4, /* 61: RESERVED */
414 4, /* 62: RESERVED */
415 4, /* 63: RESERVED */
416 /* 64-255: User Defined */
417 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
418 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
419 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
420 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
421 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
422 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
423 }
424 };
425
426 const uint8 m68ki_ea_idx_cycle_table[64] =
427 {
428 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
429 0, /* ..01.000 no memory indirect, base NULL */
430 5, /* ..01..01 memory indirect, base NULL, outer NULL */
431 7, /* ..01..10 memory indirect, base NULL, outer 16 */
432 7, /* ..01..11 memory indirect, base NULL, outer 32 */
433 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
434 2, /* ..10.000 no memory indirect, base 16 */
435 7, /* ..10..01 memory indirect, base 16, outer NULL */
436 9, /* ..10..10 memory indirect, base 16, outer 16 */
437 9, /* ..10..11 memory indirect, base 16, outer 32 */
438 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
439 6, /* ..11.000 no memory indirect, base 32 */
440 11, /* ..11..01 memory indirect, base 32, outer NULL */
441 13, /* ..11..10 memory indirect, base 32, outer 16 */
442 13, /* ..11..11 memory indirect, base 32, outer 32 */
443 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
444 };
445
446
447
448 /* ======================================================================== */
449 /* =============================== CALLBACKS ============================== */
450 /* ======================================================================== */
451
452 /* Default callbacks used if the callback hasn't been set yet, or if the
453 * callback is set to NULL
454 */
455
456 /* Interrupt acknowledge */
457 static int default_int_ack_callback_data;
default_int_ack_callback(int int_level)458 static int default_int_ack_callback(int int_level)
459 {
460 default_int_ack_callback_data = int_level;
461 CPU_INT_LEVEL = 0;
462 return M68K_INT_ACK_AUTOVECTOR;
463 }
464
465 /* Breakpoint acknowledge */
466 static unsigned int default_bkpt_ack_callback_data;
default_bkpt_ack_callback(unsigned int data)467 static void default_bkpt_ack_callback(unsigned int data)
468 {
469 default_bkpt_ack_callback_data = data;
470 }
471
472 /* Called when a reset instruction is executed */
default_reset_instr_callback(void)473 static void default_reset_instr_callback(void)
474 {
475 }
476
477 /* Called when a cmpi.l #v, dn instruction is executed */
default_cmpild_instr_callback(unsigned int val,int reg)478 static void default_cmpild_instr_callback(unsigned int val, int reg)
479 {
480 }
481
482 /* Called when a rte instruction is executed */
default_rte_instr_callback(void)483 static void default_rte_instr_callback(void)
484 {
485 }
486
487 /* Called when a tas instruction is executed */
default_tas_instr_callback(void)488 static int default_tas_instr_callback(void)
489 {
490 return 1; // allow writeback
491 }
492
493 /* Called when the program counter changed by a large value */
494 static unsigned int default_pc_changed_callback_data;
default_pc_changed_callback(unsigned int new_pc)495 static void default_pc_changed_callback(unsigned int new_pc)
496 {
497 default_pc_changed_callback_data = new_pc;
498 }
499
500 /* Called every time there's bus activity (read/write to/from memory */
501 static unsigned int default_set_fc_callback_data;
default_set_fc_callback(unsigned int new_fc)502 static void default_set_fc_callback(unsigned int new_fc)
503 {
504 default_set_fc_callback_data = new_fc;
505 }
506
507 /* Called every instruction cycle prior to execution */
default_instr_hook_callback(unsigned int pc)508 static void default_instr_hook_callback(unsigned int pc)
509 {
510 }
511
512
513 #if M68K_EMULATE_ADDRESS_ERROR
514 #include <setjmp.h>
515 jmp_buf m68ki_aerr_trap;
516 #endif /* M68K_EMULATE_ADDRESS_ERROR */
517
518
519 /* ======================================================================== */
520 /* ================================= API ================================== */
521 /* ======================================================================== */
522
523 /* Access the internals of the CPU */
m68k_get_reg(void * context,m68k_register_t regnum)524 unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
525 {
526 m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
527
528 switch(regnum)
529 {
530 case M68K_REG_D0: return cpu->dar[0];
531 case M68K_REG_D1: return cpu->dar[1];
532 case M68K_REG_D2: return cpu->dar[2];
533 case M68K_REG_D3: return cpu->dar[3];
534 case M68K_REG_D4: return cpu->dar[4];
535 case M68K_REG_D5: return cpu->dar[5];
536 case M68K_REG_D6: return cpu->dar[6];
537 case M68K_REG_D7: return cpu->dar[7];
538 case M68K_REG_A0: return cpu->dar[8];
539 case M68K_REG_A1: return cpu->dar[9];
540 case M68K_REG_A2: return cpu->dar[10];
541 case M68K_REG_A3: return cpu->dar[11];
542 case M68K_REG_A4: return cpu->dar[12];
543 case M68K_REG_A5: return cpu->dar[13];
544 case M68K_REG_A6: return cpu->dar[14];
545 case M68K_REG_A7: return cpu->dar[15];
546 case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
547 case M68K_REG_SR: return cpu->t1_flag |
548 cpu->t0_flag |
549 (cpu->s_flag << 11) |
550 (cpu->m_flag << 11) |
551 cpu->int_mask |
552 ((cpu->x_flag & XFLAG_SET) >> 4) |
553 ((cpu->n_flag & NFLAG_SET) >> 4) |
554 ((!cpu->not_z_flag) << 2) |
555 ((cpu->v_flag & VFLAG_SET) >> 6) |
556 ((cpu->c_flag & CFLAG_SET) >> 8);
557 case M68K_REG_SP: return cpu->dar[15];
558 case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
559 case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
560 case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
561 case M68K_REG_SFC: return cpu->sfc;
562 case M68K_REG_DFC: return cpu->dfc;
563 case M68K_REG_VBR: return cpu->vbr;
564 case M68K_REG_CACR: return cpu->cacr;
565 case M68K_REG_CAAR: return cpu->caar;
566 case M68K_REG_PREF_ADDR: return cpu->pref_addr;
567 case M68K_REG_PREF_DATA: return cpu->pref_data;
568 case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
569 case M68K_REG_IR: return cpu->ir;
570 case M68K_REG_CPU_TYPE:
571 switch(cpu->cpu_type)
572 {
573 case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
574 case CPU_TYPE_008: return (unsigned int)M68K_CPU_TYPE_68008;
575 case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
576 case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
577 case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
578 case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040;
579 }
580 return M68K_CPU_TYPE_INVALID;
581 default: return 0;
582 }
583 }
584
m68k_set_reg(m68k_register_t regnum,unsigned int value)585 void m68k_set_reg(m68k_register_t regnum, unsigned int value)
586 {
587 switch(regnum)
588 {
589 case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
590 case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
591 case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
592 case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
593 case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
594 case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
595 case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
596 case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
597 case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
598 case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
599 case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
600 case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
601 case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
602 case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
603 case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
604 case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
605 case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
606 case M68K_REG_SR: m68ki_set_sr(value); return;
607 case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
608 case M68K_REG_USP: if(FLAG_S)
609 REG_USP = MASK_OUT_ABOVE_32(value);
610 else
611 REG_SP = MASK_OUT_ABOVE_32(value);
612 return;
613 case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
614 REG_SP = MASK_OUT_ABOVE_32(value);
615 else
616 REG_ISP = MASK_OUT_ABOVE_32(value);
617 return;
618 case M68K_REG_MSP: if(FLAG_S && FLAG_M)
619 REG_SP = MASK_OUT_ABOVE_32(value);
620 else
621 REG_MSP = MASK_OUT_ABOVE_32(value);
622 return;
623 case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
624 case M68K_REG_SFC: REG_SFC = value & 7; return;
625 case M68K_REG_DFC: REG_DFC = value & 7; return;
626 case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
627 case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
628 case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
629 case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
630 case M68K_REG_PREF_ADDR: CPU_PREF_ADDR = MASK_OUT_ABOVE_32(value); return;
631 case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
632 default: return;
633 }
634 }
635
636 /* Set the callbacks */
m68k_set_int_ack_callback(int (* callback)(int int_level))637 void m68k_set_int_ack_callback(int (*callback)(int int_level))
638 {
639 CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
640 }
641
m68k_set_bkpt_ack_callback(void (* callback)(unsigned int data))642 void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
643 {
644 CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
645 }
646
m68k_set_reset_instr_callback(void (* callback)(void))647 void m68k_set_reset_instr_callback(void (*callback)(void))
648 {
649 CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
650 }
651
m68k_set_cmpild_instr_callback(void (* callback)(unsigned int,int))652 void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int))
653 {
654 CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback;
655 }
656
m68k_set_rte_instr_callback(void (* callback)(void))657 void m68k_set_rte_instr_callback(void (*callback)(void))
658 {
659 CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback;
660 }
661
m68k_set_tas_instr_callback(int (* callback)(void))662 void m68k_set_tas_instr_callback(int (*callback)(void))
663 {
664 CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback;
665 }
666
m68k_set_pc_changed_callback(void (* callback)(unsigned int new_pc))667 void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
668 {
669 CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
670 }
671
m68k_set_fc_callback(void (* callback)(unsigned int new_fc))672 void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
673 {
674 CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
675 }
676
m68k_set_instr_hook_callback(void (* callback)(unsigned int pc))677 void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc))
678 {
679 CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
680 }
681
682 #include <stdio.h>
683 /* Set the CPU type. */
m68k_set_cpu_type(unsigned int cpu_type)684 void m68k_set_cpu_type(unsigned int cpu_type)
685 {
686 switch(cpu_type)
687 {
688 case M68K_CPU_TYPE_68000:
689 CPU_TYPE = CPU_TYPE_000;
690 CPU_ADDRESS_MASK = 0x00ffffff;
691 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
692 CYC_INSTRUCTION = m68ki_cycles[0];
693 CYC_EXCEPTION = m68ki_exception_cycle_table[0];
694 CYC_BCC_NOTAKE_B = -2;
695 CYC_BCC_NOTAKE_W = 2;
696 CYC_DBCC_F_NOEXP = -2;
697 CYC_DBCC_F_EXP = 2;
698 CYC_SCC_R_TRUE = 2;
699 CYC_MOVEM_W = 2;
700 CYC_MOVEM_L = 3;
701 CYC_SHIFT = 1;
702 CYC_RESET = 132;
703 return;
704 case M68K_CPU_TYPE_68008:
705 CPU_TYPE = CPU_TYPE_008;
706 CPU_ADDRESS_MASK = 0x003fffff;
707 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
708 CYC_INSTRUCTION = m68ki_cycles[0];
709 CYC_EXCEPTION = m68ki_exception_cycle_table[0];
710 CYC_BCC_NOTAKE_B = -2;
711 CYC_BCC_NOTAKE_W = 2;
712 CYC_DBCC_F_NOEXP = -2;
713 CYC_DBCC_F_EXP = 2;
714 CYC_SCC_R_TRUE = 2;
715 CYC_MOVEM_W = 2;
716 CYC_MOVEM_L = 3;
717 CYC_SHIFT = 1;
718 CYC_RESET = 132;
719 return;
720 case M68K_CPU_TYPE_68010:
721 CPU_TYPE = CPU_TYPE_010;
722 CPU_ADDRESS_MASK = 0x00ffffff;
723 CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
724 CYC_INSTRUCTION = m68ki_cycles[1];
725 CYC_EXCEPTION = m68ki_exception_cycle_table[1];
726 CYC_BCC_NOTAKE_B = -4;
727 CYC_BCC_NOTAKE_W = 0;
728 CYC_DBCC_F_NOEXP = 0;
729 CYC_DBCC_F_EXP = 6;
730 CYC_SCC_R_TRUE = 0;
731 CYC_MOVEM_W = 2;
732 CYC_MOVEM_L = 3;
733 CYC_SHIFT = 1;
734 CYC_RESET = 130;
735 return;
736 case M68K_CPU_TYPE_68EC020:
737 CPU_TYPE = CPU_TYPE_EC020;
738 CPU_ADDRESS_MASK = 0x00ffffff;
739 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
740 CYC_INSTRUCTION = m68ki_cycles[2];
741 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
742 CYC_BCC_NOTAKE_B = -2;
743 CYC_BCC_NOTAKE_W = 0;
744 CYC_DBCC_F_NOEXP = 0;
745 CYC_DBCC_F_EXP = 4;
746 CYC_SCC_R_TRUE = 0;
747 CYC_MOVEM_W = 2;
748 CYC_MOVEM_L = 2;
749 CYC_SHIFT = 0;
750 CYC_RESET = 518;
751 return;
752 case M68K_CPU_TYPE_68020:
753 CPU_TYPE = CPU_TYPE_020;
754 CPU_ADDRESS_MASK = 0xffffffff;
755 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
756 CYC_INSTRUCTION = m68ki_cycles[2];
757 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
758 CYC_BCC_NOTAKE_B = -2;
759 CYC_BCC_NOTAKE_W = 0;
760 CYC_DBCC_F_NOEXP = 0;
761 CYC_DBCC_F_EXP = 4;
762 CYC_SCC_R_TRUE = 0;
763 CYC_MOVEM_W = 2;
764 CYC_MOVEM_L = 2;
765 CYC_SHIFT = 0;
766 CYC_RESET = 518;
767 return;
768 case M68K_CPU_TYPE_68040: // TODO: these values are not correct
769 CPU_TYPE = CPU_TYPE_040;
770 CPU_ADDRESS_MASK = 0xffffffff;
771 CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
772 CYC_INSTRUCTION = m68ki_cycles[2];
773 CYC_EXCEPTION = m68ki_exception_cycle_table[2];
774 CYC_BCC_NOTAKE_B = -2;
775 CYC_BCC_NOTAKE_W = 0;
776 CYC_DBCC_F_NOEXP = 0;
777 CYC_DBCC_F_EXP = 4;
778 CYC_SCC_R_TRUE = 0;
779 CYC_MOVEM_W = 2;
780 CYC_MOVEM_L = 2;
781 CYC_SHIFT = 0;
782 CYC_RESET = 518;
783 return;
784 }
785 }
786
m68k_check_shouldinterrupt(void)787 int m68k_check_shouldinterrupt(void)
788 {
789 return (CPU_INT_LEVEL > FLAG_INT_MASK);
790 }
791
792 /* Execute some instructions until we use up num_cycles clock cycles */
793 /* ASG: removed per-instruction interrupt checks */
m68k_execute(int num_cycles)794 int m68k_execute(int num_cycles)
795 {
796 if (m68ki_cpu.sleepuntilint) {
797 return num_cycles;
798 }
799
800 /* Set our pool of clock cycles available */
801 SET_CYCLES(num_cycles);
802 m68ki_initial_cycles = num_cycles;
803
804 /* See if interrupts came in */
805 m68ki_check_interrupts();
806
807 /* Make sure we're not stopped */
808 if(!CPU_STOPPED)
809 {
810 /* Return point if we had an address error */
811 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
812
813 /* Main loop. Keep going until we run out of clock cycles */
814 do
815 {
816 /* Set tracing accodring to T1. (T0 is done inside instruction) */
817 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
818
819 /* Set the address space for reads */
820 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
821
822 /* Call external hook to peek at CPU */
823 m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
824
825 /* Record previous program counter */
826 REG_PPC = REG_PC;
827
828 /* Read an instruction and call its handler */
829 REG_IR = m68ki_read_imm_16();
830 m68ki_instruction_jump_table[REG_IR]();
831 USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
832
833 /* Trace m68k_exception, if necessary */
834 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
835 } while(GET_CYCLES() > 0);
836
837 /* set previous PC to current PC for the next entry into the loop */
838 REG_PPC = REG_PC;
839 }
840 else
841 SET_CYCLES(0);
842
843 /* return how many clocks we used */
844 return m68ki_initial_cycles - GET_CYCLES();
845 }
846
m68k_megadrive_sr_checkint_mode(int onoff)847 void m68k_megadrive_sr_checkint_mode(int onoff)
848 {
849 megadrive_sr_checkint_mode = onoff;
850 }
851
m68k_executeMD(int num_cycles)852 int m68k_executeMD(int num_cycles)
853 {
854 if (m68ki_cpu.sleepuntilint) {
855 return num_cycles;
856 }
857
858 /* Set our pool of clock cycles available */
859 SET_CYCLES(num_cycles);
860 m68ki_initial_cycles = num_cycles;
861
862 /* See if interrupts came in */
863 m68ki_check_interrupts();
864
865 /* Make sure we're not stopped */
866 if(!CPU_STOPPED)
867 {
868 /* Return point if we had an address error */
869 m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
870
871 /* Set tracing accodring to T1. (T0 is done inside instruction) */
872 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
873
874 /* Main loop. Keep going until we run out of clock cycles */
875 while (GET_CYCLES() >= 0)
876 {
877 /* Set the address space for reads */
878 m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
879
880 /* Call external hook to peek at CPU */
881 m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
882
883 /* Record previous program counter */
884 REG_PPC = REG_PC;
885
886 /* Read an instruction and call its handler */
887 REG_IR = m68ki_read_imm_16();
888 m68ki_instruction_jump_table[REG_IR]();
889 USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
890
891 /* Trace m68k_exception, if necessary */
892 m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
893
894 /* Set tracing accodring to T1. (T0 is done inside instruction) */
895 m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
896 }// while(GET_CYCLES() > 0);
897
898 /* set previous PC to current PC for the next entry into the loop */
899 REG_PPC = REG_PC;
900 }
901 else
902 SET_CYCLES(0);
903
904 /* return how many clocks we used */
905 return m68ki_initial_cycles - GET_CYCLES();
906 }
907
908
m68k_cycles_run(void)909 int m68k_cycles_run(void)
910 {
911 return m68ki_initial_cycles - GET_CYCLES();
912 }
913
m68k_cycles_remaining(void)914 int m68k_cycles_remaining(void)
915 {
916 return GET_CYCLES();
917 }
918
m68k_cycles_remaining_set(int cycles)919 void m68k_cycles_remaining_set(int cycles)
920 {
921 SET_CYCLES(cycles);
922 }
923
924 /* Change the timeslice */
m68k_modify_timeslice(int cycles)925 void m68k_modify_timeslice(int cycles)
926 {
927 m68ki_initial_cycles += cycles;
928 ADD_CYCLES(cycles);
929 }
930
931
m68k_end_timeslice(void)932 void m68k_end_timeslice(void)
933 {
934 m68ki_initial_cycles = GET_CYCLES();
935 SET_CYCLES(0);
936 }
937
m68k_burn_until_irq(int enabled)938 void m68k_burn_until_irq(int enabled)
939 {
940 m68ki_cpu.sleepuntilint = enabled;
941 }
942
943 /* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
944 /* KS: Modified so that IPL* bits match with mask positions in the SR
945 * and cleaned out remenants of the interrupt controller.
946 */
m68k_set_irq(unsigned int int_level)947 void m68k_set_irq(unsigned int int_level)
948 {
949 uint old_level = CPU_INT_LEVEL;
950 CPU_INT_LEVEL = int_level << 8;
951
952 /* A transition from < 7 to 7 always interrupts (NMI) */
953 /* Note: Level 7 can also level trigger like a normal IRQ */
954 if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
955 m68ki_cpu.nmi_pending = TRUE;
956
957 m68ki_cpu.sleepuntilint = 0;
958 }
959
m68k_set_virq(unsigned int level,unsigned int active)960 void m68k_set_virq(unsigned int level, unsigned int active)
961 {
962 uint state = m68ki_cpu.virq_state;
963 uint blevel;
964
965 if(active)
966 state |= 1 << level;
967 else
968 state &= ~(1 << level);
969 m68ki_cpu.virq_state = state;
970
971 for(blevel = 7; blevel > 0; blevel--)
972 if(state & (1 << blevel))
973 break;
974 m68k_set_irq(blevel);
975 }
976
m68k_get_virq(unsigned int level)977 unsigned int m68k_get_virq(unsigned int level)
978 {
979 return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0;
980 }
981
m68k_init(void)982 void m68k_init(void)
983 {
984 static uint emulation_initialized = 0;
985
986 /* The first call to this function initializes the opcode handler jump table */
987 if(!emulation_initialized)
988 {
989 m68ki_build_opcode_table();
990 emulation_initialized = 1;
991 }
992
993 m68k_set_int_ack_callback(NULL);
994 m68k_set_bkpt_ack_callback(NULL);
995 m68k_set_reset_instr_callback(NULL);
996 m68k_set_cmpild_instr_callback(NULL);
997 m68k_set_rte_instr_callback(NULL);
998 m68k_set_tas_instr_callback(NULL);
999 m68k_set_pc_changed_callback(NULL);
1000 m68k_set_fc_callback(NULL);
1001 m68k_set_instr_hook_callback(NULL);
1002
1003 megadrive_sr_checkint_mode = 0;
1004 }
1005
1006 /* Pulse the RESET line on the CPU */
m68k_pulse_reset(void)1007 void m68k_pulse_reset(void)
1008 {
1009 /* Clear all stop levels and eat up all remaining cycles */
1010 CPU_STOPPED = 0;
1011 SET_CYCLES(0);
1012
1013 CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
1014
1015 /* Turn off tracing */
1016 FLAG_T1 = FLAG_T0 = 0;
1017 m68ki_clear_trace();
1018 /* Interrupt mask to level 7 */
1019 FLAG_INT_MASK = 0x0700;
1020 CPU_INT_LEVEL = 0;
1021 m68ki_cpu.virq_state = 0;
1022 /* Reset VBR */
1023 REG_VBR = 0;
1024 /* Go to supervisor mode */
1025 m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
1026
1027 /* Invalidate the prefetch queue */
1028 #if M68K_EMULATE_PREFETCH
1029 /* Set to arbitrary number since our first fetch is from 0 */
1030 CPU_PREF_ADDR = 0x1000;
1031 #endif /* M68K_EMULATE_PREFETCH */
1032
1033 /* Read the initial stack pointer and program counter */
1034 m68ki_jump(0);
1035 REG_SP = m68ki_read_imm_32();
1036 REG_PC = m68ki_read_imm_32();
1037 m68ki_jump(REG_PC);
1038
1039 CPU_RUN_MODE = RUN_MODE_NORMAL;
1040 }
1041
1042 /* Pulse the HALT line on the CPU */
m68k_pulse_halt(void)1043 void m68k_pulse_halt(void)
1044 {
1045 CPU_STOPPED |= STOP_LEVEL_HALT;
1046 }
1047
1048
1049 /* Get and set the current CPU context */
1050 /* This is to allow for multiple CPUs */
m68k_context_size()1051 unsigned int m68k_context_size()
1052 {
1053 return sizeof(m68ki_cpu_core);
1054 }
1055
1056 /* Used to calculate the context size minus the system-specific pointers, for savestates */
m68k_context_size_no_pointers()1057 unsigned int m68k_context_size_no_pointers()
1058 {
1059 return STRUCT_SIZE_HELPER(struct _m68ki_cpu_core, sleepuntilint);
1060 }
1061
m68k_get_context(void * dst)1062 unsigned int m68k_get_context(void* dst)
1063 {
1064 if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
1065 return sizeof(m68ki_cpu_core);
1066 }
1067
m68k_set_context(void * src)1068 void m68k_set_context(void* src)
1069 {
1070 if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
1071 }
1072
1073
1074
1075 /* ======================================================================== */
1076 /* ============================== MAME STUFF ============================== */
1077 /* ======================================================================== */
1078
1079 #if M68K_COMPILE_FOR_MAME == OPT_ON
1080
1081 #include "deprecat.h"
1082
1083 static struct {
1084 UINT16 sr;
1085 UINT8 stopped;
1086 UINT8 halted;
1087 } m68k_substate;
1088
m68k_prepare_substate(running_machine * machine,void * param)1089 static void m68k_prepare_substate(running_machine *machine, void *param)
1090 {
1091 m68k_substate.sr = m68ki_get_sr();
1092 m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
1093 m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
1094 }
1095
m68k_post_load(running_machine * machine,void * param)1096 static void m68k_post_load(running_machine *machine, void *param)
1097 {
1098 m68ki_set_sr_noint_nosp(m68k_substate.sr);
1099 CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
1100 | m68k_substate.halted ? STOP_LEVEL_HALT : 0;
1101 m68ki_jump(REG_PC);
1102 }
1103
m68k_state_register(const char * type,int index)1104 void m68k_state_register(const char *type, int index)
1105 {
1106 /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */
1107 state_save_register_item_array(type, index, REG_D);
1108 state_save_register_item(type, index, REG_PPC);
1109 state_save_register_item(type, index, REG_PC);
1110 state_save_register_item(type, index, REG_USP);
1111 state_save_register_item(type, index, REG_ISP);
1112 state_save_register_item(type, index, REG_MSP);
1113 state_save_register_item(type, index, REG_VBR);
1114 state_save_register_item(type, index, REG_SFC);
1115 state_save_register_item(type, index, REG_DFC);
1116 state_save_register_item(type, index, REG_CACR);
1117 state_save_register_item(type, index, REG_CAAR);
1118 state_save_register_item(type, index, m68k_substate.sr);
1119 state_save_register_item(type, index, CPU_INT_LEVEL);
1120 state_save_register_item(type, index, m68k_substate.stopped);
1121 state_save_register_item(type, index, m68k_substate.halted);
1122 state_save_register_item(type, index, CPU_PREF_ADDR);
1123 state_save_register_item(type, index, CPU_PREF_DATA);
1124 state_save_register_presave(Machine, m68k_prepare_substate, NULL);
1125 state_save_register_postload(Machine, m68k_post_load, NULL);
1126 }
1127
1128 #endif /* M68K_COMPILE_FOR_MAME */
1129
1130 /* ======================================================================== */
1131 /* ============================== END OF FILE ============================= */
1132 /* ======================================================================== */
1133