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