cc68a136 |
1 | /* ======================================================================== */\r |
2 | /* ========================= LICENSING & COPYRIGHT ======================== */\r |
3 | /* ======================================================================== */\r |
4 | \r |
5 | #if 0\r |
6 | static 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 |
672ad671 |
42 | // int m68ki_initial_cycles; // moved to m68k_execute() stack\r |
43 | // int m68ki_remaining_cycles = 0; /* Number of clocks remaining */\r |
cc68a136 |
44 | uint m68ki_tracing = 0;\r |
45 | uint m68ki_address_space;\r |
46 | \r |
47 | #ifdef M68K_LOG_ENABLE\r |
48 | const 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 |
72 | m68ki_cpu_core *m68ki_cpu_p = NULL;\r |
73 | \r |
74 | \r |
75 | #if M68K_EMULATE_ADDRESS_ERROR\r |
76 | jmp_buf m68ki_aerr_trap;\r |
77 | #endif /* M68K_EMULATE_ADDRESS_ERROR */\r |
78 | \r |
79 | uint m68ki_aerr_address;\r |
80 | uint m68ki_aerr_write_mode;\r |
81 | uint m68ki_aerr_fc;\r |
82 | \r |
83 | /* Used by shift & rotate instructions */\r |
84 | uint8 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 |
93 | uint16 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 |
104 | uint 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 |
123 | uint8 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 |
419 | uint8 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 |
450 | static int default_int_ack_callback_data;\r |
451 | static 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 |
459 | static unsigned int default_bkpt_ack_callback_data;\r |
460 | static 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 |
466 | static 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 |
471 | static 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 |
476 | static 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 |
481 | static unsigned int default_pc_changed_callback_data;\r |
482 | static 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 |
488 | static unsigned int default_set_fc_callback_data;\r |
489 | static 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 |
495 | static 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 |
511 | unsigned 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 |
573 | void 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 |
625 | void 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 |
630 | void 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 |
635 | void 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 |
640 | void 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 |
645 | void 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 |
650 | void 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 |
655 | void 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 |
660 | void 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 |
667 | void 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 |
772 | int m68k_execute(int num_cycles)\r |
773 | {\r |
672ad671 |
774 | int m68ki_initial_cycles;\r |
775 | \r |
cc68a136 |
776 | /* Make sure we're not stopped */\r |
777 | if(!CPU_STOPPED)\r |
778 | {\r |
779 | /* Set our pool of clock cycles available */\r |
780 | SET_CYCLES(num_cycles);\r |
781 | m68ki_initial_cycles = num_cycles;\r |
782 | \r |
783 | /* ASG: update cycles */\r |
784 | USE_CYCLES(CPU_INT_CYCLES);\r |
785 | CPU_INT_CYCLES = 0;\r |
786 | \r |
787 | /* Return point if we had an address error */\r |
788 | m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */\r |
789 | \r |
790 | /* Main loop. Keep going until we run out of clock cycles */\r |
791 | while(GET_CYCLES() > 0)\r |
792 | {\r |
793 | /* Set tracing accodring to T1. (T0 is done inside instruction) */\r |
794 | m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */\r |
795 | \r |
796 | /* Set the address space for reads */\r |
797 | m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */\r |
798 | \r |
799 | /* Call external hook to peek at CPU */\r |
800 | m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */\r |
801 | \r |
802 | /* Record previous program counter */\r |
803 | REG_PPC = REG_PC;\r |
804 | \r |
805 | /* Read an instruction and call its handler */\r |
806 | REG_IR = m68ki_read_imm_16();\r |
807 | m68ki_instruction_jump_table[REG_IR]();\r |
808 | USE_CYCLES(CYC_INSTRUCTION[REG_IR]);\r |
809 | \r |
810 | /* Trace m68k_exception, if necessary */\r |
811 | m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */\r |
812 | }\r |
813 | \r |
814 | /* set previous PC to current PC for the next entry into the loop */\r |
815 | REG_PPC = REG_PC;\r |
816 | \r |
817 | /* ASG: update cycles */\r |
818 | USE_CYCLES(CPU_INT_CYCLES);\r |
819 | CPU_INT_CYCLES = 0;\r |
820 | \r |
821 | /* return how many clocks we used */\r |
822 | return m68ki_initial_cycles - GET_CYCLES();\r |
823 | }\r |
824 | \r |
825 | /* We get here if the CPU is stopped or halted */\r |
826 | SET_CYCLES(0);\r |
827 | CPU_INT_CYCLES = 0;\r |
828 | \r |
829 | return num_cycles;\r |
830 | }\r |
831 | \r |
672ad671 |
832 | #if 0\r |
cc68a136 |
833 | int m68k_cycles_run(void)\r |
834 | {\r |
835 | return m68ki_initial_cycles - GET_CYCLES();\r |
836 | }\r |
672ad671 |
837 | #endif\r |
cc68a136 |
838 | \r |
839 | int m68k_cycles_remaining(void)\r |
840 | {\r |
841 | return GET_CYCLES();\r |
842 | }\r |
843 | \r |
672ad671 |
844 | #if 0\r |
cc68a136 |
845 | /* Change the timeslice */\r |
846 | void m68k_modify_timeslice(int cycles)\r |
847 | {\r |
848 | m68ki_initial_cycles += cycles;\r |
849 | ADD_CYCLES(cycles);\r |
850 | }\r |
851 | \r |
852 | \r |
853 | void m68k_end_timeslice(void)\r |
854 | {\r |
855 | m68ki_initial_cycles = GET_CYCLES();\r |
856 | SET_CYCLES(0);\r |
857 | }\r |
672ad671 |
858 | #endif\r |
cc68a136 |
859 | \r |
860 | /* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */\r |
861 | /* KS: Modified so that IPL* bits match with mask positions in the SR\r |
862 | * and cleaned out remenants of the interrupt controller.\r |
863 | */\r |
864 | void m68k_set_irq(unsigned int int_level)\r |
865 | {\r |
866 | uint old_level = CPU_INT_LEVEL;\r |
867 | CPU_INT_LEVEL = int_level << 8;\r |
868 | \r |
869 | /* A transition from < 7 to 7 always interrupts (NMI) */\r |
870 | /* Note: Level 7 can also level trigger like a normal IRQ */\r |
871 | if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)\r |
872 | m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */\r |
873 | else\r |
874 | m68ki_check_interrupts(); /* Level triggered (IRQ) */\r |
875 | }\r |
876 | \r |
877 | void m68k_init(void)\r |
878 | {\r |
879 | static uint emulation_initialized = 0;\r |
880 | \r |
881 | /* The first call to this function initializes the opcode handler jump table */\r |
882 | if(!emulation_initialized)\r |
883 | {\r |
884 | m68ki_build_opcode_table();\r |
885 | emulation_initialized = 1;\r |
886 | }\r |
887 | \r |
888 | m68k_set_int_ack_callback(NULL);\r |
889 | m68k_set_bkpt_ack_callback(NULL);\r |
890 | m68k_set_reset_instr_callback(NULL);\r |
891 | m68k_set_cmpild_instr_callback(NULL);\r |
892 | m68k_set_rte_instr_callback(NULL);\r |
893 | m68k_set_pc_changed_callback(NULL);\r |
894 | m68k_set_fc_callback(NULL);\r |
895 | m68k_set_instr_hook_callback(NULL);\r |
896 | }\r |
897 | \r |
898 | /* Pulse the RESET line on the CPU */\r |
899 | void m68k_pulse_reset(void)\r |
900 | {\r |
901 | /* Clear all stop levels and eat up all remaining cycles */\r |
902 | CPU_STOPPED = 0;\r |
903 | SET_CYCLES(0);\r |
904 | \r |
905 | CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;\r |
906 | \r |
907 | /* Turn off tracing */\r |
908 | FLAG_T1 = FLAG_T0 = 0;\r |
909 | m68ki_clear_trace();\r |
910 | /* Interrupt mask to level 7 */\r |
911 | FLAG_INT_MASK = 0x0700;\r |
912 | /* Reset VBR */\r |
913 | REG_VBR = 0;\r |
914 | /* Go to supervisor mode */\r |
915 | m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);\r |
916 | \r |
917 | /* Invalidate the prefetch queue */\r |
918 | #if M68K_EMULATE_PREFETCH\r |
919 | /* Set to arbitrary number since our first fetch is from 0 */\r |
920 | CPU_PREF_ADDR = 0x1000;\r |
921 | #endif /* M68K_EMULATE_PREFETCH */\r |
922 | \r |
923 | /* Read the initial stack pointer and program counter */\r |
924 | m68ki_jump(0);\r |
925 | REG_SP = m68ki_read_imm_32();\r |
926 | REG_PC = m68ki_read_imm_32();\r |
927 | m68ki_jump(REG_PC);\r |
928 | \r |
929 | CPU_RUN_MODE = RUN_MODE_NORMAL;\r |
930 | }\r |
931 | \r |
932 | /* Pulse the HALT line on the CPU */\r |
933 | void m68k_pulse_halt(void)\r |
934 | {\r |
935 | CPU_STOPPED |= STOP_LEVEL_HALT;\r |
936 | }\r |
937 | \r |
938 | \r |
939 | /* Get and set the current CPU context */\r |
940 | /* This is to allow for multiple CPUs */\r |
941 | unsigned int m68k_context_size()\r |
942 | {\r |
943 | return sizeof(m68ki_cpu_core);\r |
944 | }\r |
945 | \r |
946 | /*\r |
947 | unsigned int m68k_get_context(void* dst)\r |
948 | {\r |
949 | if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;\r |
950 | return sizeof(m68ki_cpu_core);\r |
951 | }\r |
952 | */\r |
953 | \r |
954 | void m68k_set_context(void* src)\r |
955 | {\r |
956 | if(src) m68ki_cpu_p = src;\r |
957 | }\r |
958 | \r |
959 | \r |
960 | \r |
961 | /* ======================================================================== */\r |
962 | /* ============================== MAME STUFF ============================== */\r |
963 | /* ======================================================================== */\r |
964 | \r |
965 | #if M68K_COMPILE_FOR_MAME == OPT_ON\r |
966 | \r |
967 | #include "state.h"\r |
968 | \r |
969 | static struct {\r |
970 | UINT16 sr;\r |
971 | UINT8 stopped;\r |
972 | UINT8 halted;\r |
973 | } m68k_substate;\r |
974 | \r |
975 | static void m68k_prepare_substate(void)\r |
976 | {\r |
977 | m68k_substate.sr = m68ki_get_sr();\r |
978 | m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;\r |
979 | m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;\r |
980 | }\r |
981 | \r |
982 | static void m68k_post_load(void)\r |
983 | {\r |
984 | m68ki_set_sr_noint_nosp(m68k_substate.sr);\r |
985 | CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0\r |
986 | | m68k_substate.halted ? STOP_LEVEL_HALT : 0;\r |
987 | m68ki_jump(REG_PC);\r |
988 | }\r |
989 | \r |
990 | void m68k_state_register(const char *type, int index)\r |
991 | {\r |
992 | state_save_register_item_array(type, index, REG_D);\r |
993 | state_save_register_item_array(type, index, REG_A);\r |
994 | state_save_register_item(type, index, REG_PPC);\r |
995 | state_save_register_item(type, index, REG_PC);\r |
996 | state_save_register_item(type, index, REG_USP);\r |
997 | state_save_register_item(type, index, REG_ISP);\r |
998 | state_save_register_item(type, index, REG_MSP);\r |
999 | state_save_register_item(type, index, REG_VBR);\r |
1000 | state_save_register_item(type, index, REG_SFC);\r |
1001 | state_save_register_item(type, index, REG_DFC);\r |
1002 | state_save_register_item(type, index, REG_CACR);\r |
1003 | state_save_register_item(type, index, REG_CAAR);\r |
1004 | state_save_register_item(type, index, m68k_substate.sr);\r |
1005 | state_save_register_item(type, index, CPU_INT_LEVEL);\r |
1006 | state_save_register_item(type, index, CPU_INT_CYCLES);\r |
1007 | state_save_register_item(type, index, m68k_substate.stopped);\r |
1008 | state_save_register_item(type, index, m68k_substate.halted);\r |
1009 | state_save_register_item(type, index, CPU_PREF_ADDR);\r |
1010 | state_save_register_item(type, index, CPU_PREF_DATA);\r |
1011 | state_save_register_func_presave(m68k_prepare_substate);\r |
1012 | state_save_register_func_postload(m68k_post_load);\r |
1013 | }\r |
1014 | \r |
1015 | #endif /* M68K_COMPILE_FOR_MAME */\r |
1016 | \r |
1017 | /* ======================================================================== */\r |
1018 | /* ============================== END OF FILE ============================= */\r |
1019 | /* ======================================================================== */\r |