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