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