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