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 |
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 |
35 | extern void m68040_fpu_op0(void);\r |
36 | extern 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 |
46 | int m68ki_initial_cycles;\r |
47 | //int m68ki_remaining_cycles = 0; /* Number of clocks remaining */\r |
cc68a136 |
48 | uint m68ki_tracing = 0;\r |
49 | uint m68ki_address_space;\r |
50 | \r |
51 | #ifdef M68K_LOG_ENABLE\r |
52 | const 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 |
76 | m68ki_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 |
81 | jmp_buf m68ki_aerr_trap;\r |
82 | #endif /* M68K_EMULATE_ADDRESS_ERROR */\r |
83 | \r |
84 | uint m68ki_aerr_address;\r |
85 | uint m68ki_aerr_write_mode;\r |
86 | uint m68ki_aerr_fc;\r |
87 | \r |
88 | /* Used by shift & rotate instructions */\r |
89 | uint8 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 |
98 | uint16 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 |
109 | uint 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 |
128 | uint8 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 |
424 | uint8 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 |
455 | static int default_int_ack_callback_data;\r |
456 | static 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 |
464 | static unsigned int default_bkpt_ack_callback_data;\r |
465 | static 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 |
471 | static 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 |
476 | static 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 |
481 | static void default_rte_instr_callback(void)\r |
482 | {\r |
483 | }\r |
484 | \r |
c6a4c892 |
485 | /* Called when a tas instruction is executed */\r |
486 | static 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 |
492 | static unsigned int default_pc_changed_callback_data;\r |
493 | static 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 |
499 | static unsigned int default_set_fc_callback_data;\r |
500 | static 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 |
506 | static 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 |
522 | unsigned 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 |
584 | void 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 |
636 | void 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 |
641 | void 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 |
646 | void 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 |
651 | void 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 |
656 | void 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 |
661 | void 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 |
666 | void 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 |
671 | void 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 |
676 | void 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 |
683 | void 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 |
788 | int 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 |
858 | int m68k_cycles_run(void)\r |
859 | {\r |
860 | return m68ki_initial_cycles - GET_CYCLES();\r |
861 | }\r |
862 | \r |
863 | int m68k_cycles_remaining(void)\r |
864 | {\r |
865 | return GET_CYCLES();\r |
866 | }\r |
867 | \r |
868 | /* Change the timeslice */\r |
869 | void 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 |
876 | void 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 |
887 | void 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 |
900 | void 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 |
923 | void 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 |
957 | void 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 |
965 | unsigned int m68k_context_size()\r |
966 | {\r |
967 | return sizeof(m68ki_cpu_core);\r |
968 | }\r |
969 | \r |
cc68a136 |
970 | unsigned 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 |
976 | void 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 |
991 | static struct {\r |
992 | UINT16 sr;\r |
993 | UINT8 stopped;\r |
994 | UINT8 halted;\r |
995 | } m68k_substate;\r |
996 | \r |
997 | static 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 |
1004 | static 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 |
1012 | void 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 |