1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * MC68000 emulation
5 *
6 * (c) 1995 Bernd Schmidt
7 */
8
9 #define MOVEC_DEBUG 0
10 #define MMUOP_DEBUG 2
11 #define DEBUG_CD32CDTVIO 0
12 #define EXCEPTION3_DEBUGGER 0
13 #define CPUTRACE_DEBUG 0
14 #undef OPCODE_DEBUG
15
16 #include "sysconfig.h"
17 #include "sysdeps.h"
18
19 #include "options.h"
20 #include "events.h"
21 #include "uae.h"
22 #include "memory_uae.h"
23 #include "custom.h"
24 #include "newcpu.h"
25 #include "cpummu.h"
26 #include "cpummu030.h"
27 #include "cpu_prefetch.h"
28 #include "autoconf.h"
29 #include "traps.h"
30 #include "debug.h"
31 #include "gui.h"
32 #include "savestate.h"
33 #include "blitter.h"
34 #include "ar.h"
35 #include "gayle.h"
36 #include "cia.h"
37 #include "inputrecord.h"
38 #include "inputdevice.h"
39 #include "misc.h"
40
41 #define f_out write_log
42 #define console_out write_log
43 #define console_out_f write_log
44 #ifdef JIT
45 #include "compemu.h"
46 #include <signal.h>
47 #else
48 /* Need to have these somewhere */
build_comp(void)49 STATIC_INLINE void build_comp (void) {}
check_prefs_changed_comp(void)50 STATIC_INLINE bool check_prefs_changed_comp (void) { return false; }
51 #endif
52 /* For faster JIT cycles handling */
53 signed long pissoff = 0;
54
55 /* Opcode of faulting instruction */
56 static uae_u16 last_op_for_exception_3;
57 /* PC at fault time */
58 static uaecptr last_addr_for_exception_3;
59 /* Address that generated the exception */
60 static uaecptr last_fault_for_exception_3;
61 /* read (0) or write (1) access */
62 static int last_writeaccess_for_exception_3;
63 /* instruction (1) or data (0) access */
64 static int last_instructionaccess_for_exception_3;
65 int mmu_enabled, mmu_triggered;
66 int cpu_cycles;
67 static int baseclock;
68
69 int cpucycleunit;
70 int cpu_tracer;
71
72 const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
73 const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
74
75 int movem_index1[256];
76 int movem_index2[256];
77 int movem_next[256];
78
79 cpuop_func *cpufunctbl[65536];
80
81 struct mmufixup mmufixup[2];
82
83 extern uae_u32 get_fpsr (void);
84
85 #define COUNT_INSTRS 0
86 #define MC68060_PCR 0x04300000
87 #define MC68EC060_PCR 0x04310000
88
89 static uae_u64 fake_srp_030, fake_crp_030;
90 static uae_u32 fake_tt0_030, fake_tt1_030, fake_tc_030;
91 static uae_u16 fake_mmusr_030;
92
93 static struct cache020 caches020[CACHELINES020];
94 static struct cache030 icaches030[CACHELINES030];
95 static struct cache030 dcaches030[CACHELINES030];
96 static struct cache040 caches040[CACHESETS040];
97
98 #if COUNT_INSTRS
99 static unsigned long int instrcount[65536];
100 static uae_u16 opcodenums[65536];
101
compfn(const void * el1,const void * el2)102 static int compfn (const void *el1, const void *el2)
103 {
104 return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
105 }
106
icountfilename(void)107 static TCHAR *icountfilename (void)
108 {
109 TCHAR *name = getenv ("INSNCOUNT");
110 if (name)
111 return name;
112 return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
113 }
114
dump_counts(void)115 void dump_counts (void)
116 {
117 FILE *f = fopen (icountfilename (), "w");
118 unsigned long int total;
119 int i;
120
121 write_log (_T("Writing instruction count file...\n"));
122 for (i = 0; i < 65536; i++) {
123 opcodenums[i] = i;
124 total += instrcount[i];
125 }
126 qsort (opcodenums, 65536, sizeof (uae_u16), compfn);
127
128 fprintf (f, "Total: %lu\n", total);
129 for (i=0; i < 65536; i++) {
130 unsigned long int cnt = instrcount[opcodenums[i]];
131 struct instr *dp;
132 struct mnemolookup *lookup;
133 if (!cnt)
134 break;
135 dp = table68k + opcodenums[i];
136 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
137 ;
138 fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
139 }
140 fclose (f);
141 }
142 #else
dump_counts(void)143 void dump_counts (void)
144 {
145 }
146 #endif
147
148 /*
149
150 ok, all this to "record" current instruction state
151 for later 100% cycle-exact restoring
152
153 */
154
155 static uae_u32 (*x2_prefetch)(int);
156 static uae_u32 (*x2_prefetch_long)(int);
157 static uae_u32 (*x2_next_iword)(void);
158 static uae_u32 (*x2_next_ilong)(void);
159 static uae_u32 (*x2_get_ilong)(int);
160 static uae_u32 (*x2_get_iword)(int);
161 static uae_u32 (*x2_get_ibyte)(int);
162 static uae_u32 (*x2_get_long)(uaecptr);
163 static uae_u32 (*x2_get_word)(uaecptr);
164 static uae_u32 (*x2_get_byte)(uaecptr);
165 static void (*x2_put_long)(uaecptr,uae_u32);
166 static void (*x2_put_word)(uaecptr,uae_u32);
167 static void (*x2_put_byte)(uaecptr,uae_u32);
168 static void (*x2_do_cycles)(unsigned long);
169 static void (*x2_do_cycles_pre)(unsigned long);
170 static void (*x2_do_cycles_post)(unsigned long, uae_u32);
171
172 uae_u32 (*x_prefetch)(int);
173 uae_u32 (*x_prefetch_long)(int);
174 uae_u32 (*x_next_iword)(void);
175 uae_u32 (*x_next_ilong)(void);
176 uae_u32 (*x_get_ilong)(int);
177 uae_u32 (*x_get_iword)(int);
178 uae_u32 (*x_get_ibyte)(int);
179 uae_u32 (*x_get_long)(uaecptr);
180 uae_u32 (*x_get_word)(uaecptr);
181 uae_u32 (*x_get_byte)(uaecptr);
182 void (*x_put_long)(uaecptr,uae_u32);
183 void (*x_put_word)(uaecptr,uae_u32);
184 void (*x_put_byte)(uaecptr,uae_u32);
185
186 uae_u32 (*x_cp_next_iword)(void);
187 uae_u32 (*x_cp_next_ilong)(void);
188 uae_u32 (*x_cp_get_long)(uaecptr);
189 uae_u32 (*x_cp_get_word)(uaecptr);
190 uae_u32 (*x_cp_get_byte)(uaecptr);
191 void (*x_cp_put_long)(uaecptr,uae_u32);
192 void (*x_cp_put_word)(uaecptr,uae_u32);
193 void (*x_cp_put_byte)(uaecptr,uae_u32);
194 uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
195
196 void (*x_do_cycles)(unsigned long);
197 void (*x_do_cycles_pre)(unsigned long);
198 void (*x_do_cycles_post)(unsigned long, uae_u32);
199
200 static struct cputracestruct cputrace;
201
202 #if CPUTRACE_DEBUG
validate_trace(void)203 static void validate_trace (void)
204 {
205 for (int i = 0; i < cputrace.memoryoffset; i++) {
206 struct cputracememory *ctm = &cputrace.ctm[i];
207 if (ctm->data == 0xdeadf00d) {
208 write_log (_T("unfinished write operation %d %08x\n"), i, ctm->addr);
209 }
210 }
211 }
212 #endif
213
debug_trace(void)214 static void debug_trace (void)
215 {
216 if (cputrace.writecounter > 10000 || cputrace.readcounter > 10000)
217 write_log (_T("cputrace.readcounter=%d cputrace.writecounter=%d\n"), cputrace.readcounter, cputrace.writecounter);
218 }
219
clear_trace(void)220 STATIC_INLINE void clear_trace (void)
221 {
222 #if CPUTRACE_DEBUG
223 validate_trace ();
224 #endif
225 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
226 ctm->mode = 0;
227 cputrace.cyclecounter = 0;
228 cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
229 }
set_trace(uaecptr addr,int accessmode,int size)230 static void set_trace (uaecptr addr, int accessmode, int size)
231 {
232 #if CPUTRACE_DEBUG
233 validate_trace ();
234 #endif
235 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
236 ctm->addr = addr;
237 ctm->data = 0xdeadf00d;
238 ctm->mode = accessmode | (size << 4);
239 cputrace.cyclecounter_pre = -1;
240 if (accessmode == 1)
241 cputrace.writecounter++;
242 else
243 cputrace.readcounter++;
244 debug_trace ();
245 }
add_trace(uaecptr addr,uae_u32 val,int accessmode,int size)246 static void add_trace (uaecptr addr, uae_u32 val, int accessmode, int size)
247 {
248 if (cputrace.memoryoffset < 1) {
249 #if CPUTRACE_DEBUG
250 write_log (_T("add_trace memoryoffset=%d!\n"), cputrace.memoryoffset);
251 #endif
252 return;
253 }
254 int mode = accessmode | (size << 4);
255 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
256 ctm->addr = addr;
257 ctm->data = val;
258 if (!ctm->mode) {
259 ctm->mode = mode;
260 if (accessmode == 1)
261 cputrace.writecounter++;
262 else
263 cputrace.readcounter++;
264 }
265 debug_trace ();
266 cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
267 }
268
269
check_trace2(void)270 static void check_trace2 (void)
271 {
272 if (cputrace.readcounter || cputrace.writecounter ||
273 cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
274 write_log (_T("CPU tracer invalid state during playback!\n"));
275 }
276
check_trace(void)277 static bool check_trace (void)
278 {
279 if (!cpu_tracer)
280 return true;
281 if (!cputrace.readcounter && !cputrace.writecounter && !cputrace.cyclecounter) {
282 if (cpu_tracer != -2) {
283 write_log (_T("CPU trace: dma_cycle() enabled. %08x %08x NOW=%08X\n"),
284 cputrace.cyclecounter_pre, cputrace.cyclecounter_post, get_cycles ());
285 cpu_tracer = -2; // dma_cycle() allowed to work now
286 }
287 }
288 if (cputrace.readcounter || cputrace.writecounter ||
289 cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
290 return false;
291 x_prefetch = x2_prefetch;
292 x_prefetch_long = x2_prefetch_long;
293 x_get_ilong = x2_get_ilong;
294 x_get_iword = x2_get_iword;
295 x_get_ibyte = x2_get_ibyte;
296 x_next_iword = x2_next_iword;
297 x_next_ilong = x2_next_ilong;
298 x_put_long = x2_put_long;
299 x_put_word = x2_put_word;
300 x_put_byte = x2_put_byte;
301 x_get_long = x2_get_long;
302 x_get_word = x2_get_word;
303 x_get_byte = x2_get_byte;
304 x_do_cycles = x2_do_cycles;
305 x_do_cycles_pre = x2_do_cycles_pre;
306 x_do_cycles_post = x2_do_cycles_post;
307 write_log (_T("CPU tracer playback complete. STARTCYCLES=%08x NOWCYCLES=%08x\n"), cputrace.startcycles, get_cycles ());
308 cputrace.needendcycles = 1;
309 cpu_tracer = 0;
310 return true;
311 }
312
get_trace(uaecptr addr,int accessmode,int size,uae_u32 * data)313 static bool get_trace (uaecptr addr, int accessmode, int size, uae_u32 *data)
314 {
315 int mode = accessmode | (size << 4);
316 for (int i = 0; i < cputrace.memoryoffset; i++) {
317 struct cputracememory *ctm = &cputrace.ctm[i];
318 if (ctm->addr == addr && ctm->mode == mode) {
319 ctm->mode = 0;
320 write_log (_T("CPU trace: GET %d: PC=%08x %08x=%08x %d %d %08x/%08x/%08x %d/%d (%08X)\n"),
321 i, cputrace.pc, addr, ctm->data, accessmode, size,
322 cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
323 cputrace.readcounter, cputrace.writecounter, get_cycles ());
324 if (accessmode == 1)
325 cputrace.writecounter--;
326 else
327 cputrace.readcounter--;
328 if (cputrace.writecounter == 0 && cputrace.readcounter == 0) {
329 if (cputrace.cyclecounter_post) {
330 int c = cputrace.cyclecounter_post;
331 cputrace.cyclecounter_post = 0;
332 x_do_cycles (c);
333 } else if (cputrace.cyclecounter_pre) {
334 check_trace ();
335 *data = ctm->data;
336 return true; // argh, need to rerun the memory access..
337 }
338 }
339 check_trace ();
340 *data = ctm->data;
341 return false;
342 }
343 }
344 if (cputrace.cyclecounter_post) {
345 int c = cputrace.cyclecounter_post;
346 cputrace.cyclecounter_post = 0;
347 check_trace ();
348 check_trace2 ();
349 x_do_cycles (c);
350 return false;
351 }
352 gui_message (_T("CPU trace: GET %08x %d %d NOT FOUND!\n"), addr, accessmode, size);
353 check_trace ();
354 *data = 0;
355 return false;
356 }
357
cputracefunc_x_prefetch(int o)358 static uae_u32 cputracefunc_x_prefetch (int o)
359 {
360 uae_u32 pc = m68k_getpc ();
361 set_trace (pc + o, 2, 2);
362 uae_u32 v = x2_prefetch (o);
363 add_trace (pc + o, v, 2, 2);
364 return v;
365 }
cputracefunc2_x_prefetch(int o)366 static uae_u32 cputracefunc2_x_prefetch (int o)
367 {
368 uae_u32 v;
369 if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
370 v = x2_prefetch (o);
371 check_trace2 ();
372 }
373 return v;
374 }
cputracefunc_x_prefetch_long(int o)375 static uae_u32 cputracefunc_x_prefetch_long (int o)
376 {
377 uae_u32 pc = m68k_getpc ();
378 set_trace (pc + o, 2, 4);
379 uae_u32 v = x2_prefetch_long (o);
380 add_trace (pc + o, v, 2, 4);
381 return v;
382 }
cputracefunc2_x_prefetch_long(int o)383 static uae_u32 cputracefunc2_x_prefetch_long (int o)
384 {
385 uae_u32 v;
386 if (get_trace (m68k_getpc () + o, 2, 4, &v)) {
387 v = x2_prefetch_long (o);
388 check_trace2 ();
389 }
390 return v;
391 }
392
cputracefunc_x_next_iword(void)393 static uae_u32 cputracefunc_x_next_iword (void)
394 {
395 uae_u32 pc = m68k_getpc ();
396 set_trace (pc, 2, 2);
397 uae_u32 v = x2_next_iword ();
398 add_trace (pc, v, 2, 2);
399 return v;
400 }
cputracefunc_x_next_ilong(void)401 static uae_u32 cputracefunc_x_next_ilong (void)
402 {
403 uae_u32 pc = m68k_getpc ();
404 set_trace (pc, 2, 4);
405 uae_u32 v = x2_next_ilong ();
406 add_trace (pc, v, 2, 4);
407 return v;
408 }
cputracefunc2_x_next_iword(void)409 static uae_u32 cputracefunc2_x_next_iword (void)
410 {
411 uae_u32 v;
412 if (get_trace (m68k_getpc (), 2, 2, &v)) {
413 v = x2_next_iword ();
414 check_trace2 ();
415 }
416 return v;
417 }
cputracefunc2_x_next_ilong(void)418 static uae_u32 cputracefunc2_x_next_ilong (void)
419 {
420 uae_u32 v;
421 if (get_trace (m68k_getpc (), 2, 4, &v)) {
422 v = x2_next_ilong ();
423 check_trace2 ();
424 }
425 return v;
426 }
427
cputracefunc_x_get_ilong(int o)428 static uae_u32 cputracefunc_x_get_ilong (int o)
429 {
430 uae_u32 pc = m68k_getpc ();
431 set_trace (pc + o, 2, 4);
432 uae_u32 v = x2_get_ilong (o);
433 add_trace (pc + o, v, 2, 4);
434 return v;
435 }
cputracefunc_x_get_iword(int o)436 static uae_u32 cputracefunc_x_get_iword (int o)
437 {
438 uae_u32 pc = m68k_getpc ();
439 set_trace (pc + o, 2, 2);
440 uae_u32 v = x2_get_iword (o);
441 add_trace (pc + o, v, 2, 2);
442 return v;
443 }
cputracefunc_x_get_ibyte(int o)444 static uae_u32 cputracefunc_x_get_ibyte (int o)
445 {
446 uae_u32 pc = m68k_getpc ();
447 set_trace (pc + o, 2, 1);
448 uae_u32 v = x2_get_ibyte (o);
449 add_trace (pc + o, v, 2, 1);
450 return v;
451 }
cputracefunc2_x_get_ilong(int o)452 static uae_u32 cputracefunc2_x_get_ilong (int o)
453 {
454 uae_u32 v;
455 if (get_trace (m68k_getpc () + o, 2, 4, &v)) {
456 v = x2_get_ilong (o);
457 check_trace2 ();
458 }
459 return v;
460 }
cputracefunc2_x_get_iword(int o)461 static uae_u32 cputracefunc2_x_get_iword (int o)
462 {
463 uae_u32 v;
464 if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
465 v = x2_get_iword (o);
466 check_trace2 ();
467 }
468 return v;
469 }
cputracefunc2_x_get_ibyte(int o)470 static uae_u32 cputracefunc2_x_get_ibyte (int o)
471 {
472 uae_u32 v;
473 if (get_trace (m68k_getpc () + o, 2, 1, &v)) {
474 v = x2_get_ibyte (o);
475 check_trace2 ();
476 }
477 return v;
478 }
479
cputracefunc_x_get_long(uaecptr o)480 static uae_u32 cputracefunc_x_get_long (uaecptr o)
481 {
482 set_trace (o, 0, 4);
483 uae_u32 v = x2_get_long (o);
484 add_trace (o, v, 0, 4);
485 return v;
486 }
cputracefunc_x_get_word(uaecptr o)487 static uae_u32 cputracefunc_x_get_word (uaecptr o)
488 {
489 set_trace (o, 0, 2);
490 uae_u32 v = x2_get_word (o);
491 add_trace (o, v, 0, 2);
492 return v;
493 }
cputracefunc_x_get_byte(uaecptr o)494 static uae_u32 cputracefunc_x_get_byte (uaecptr o)
495 {
496 set_trace (o, 0, 1);
497 uae_u32 v = x2_get_byte (o);
498 add_trace (o, v, 0, 1);
499 return v;
500 }
cputracefunc2_x_get_long(uaecptr o)501 static uae_u32 cputracefunc2_x_get_long (uaecptr o)
502 {
503 uae_u32 v;
504 if (get_trace (o, 0, 4, &v)) {
505 v = x2_get_long (o);
506 check_trace2 ();
507 }
508 return v;
509 }
cputracefunc2_x_get_word(uaecptr o)510 static uae_u32 cputracefunc2_x_get_word (uaecptr o)
511 {
512 uae_u32 v;
513 if (get_trace (o, 0, 2, &v)) {
514 v = x2_get_word (o);
515 check_trace2 ();
516 }
517 return v;
518 }
cputracefunc2_x_get_byte(uaecptr o)519 static uae_u32 cputracefunc2_x_get_byte (uaecptr o)
520 {
521 uae_u32 v;
522 if (get_trace (o, 0, 1, &v)) {
523 v = x2_get_byte (o);
524 check_trace2 ();
525 }
526 return v;
527 }
528
cputracefunc_x_put_long(uaecptr o,uae_u32 val)529 static void cputracefunc_x_put_long (uaecptr o, uae_u32 val)
530 {
531 clear_trace ();
532 add_trace (o, val, 1, 4);
533 x2_put_long (o, val);
534 }
cputracefunc_x_put_word(uaecptr o,uae_u32 val)535 static void cputracefunc_x_put_word (uaecptr o, uae_u32 val)
536 {
537 clear_trace ();
538 add_trace (o, val, 1, 2);
539 x2_put_word (o, val);
540 }
cputracefunc_x_put_byte(uaecptr o,uae_u32 val)541 static void cputracefunc_x_put_byte (uaecptr o, uae_u32 val)
542 {
543 clear_trace ();
544 add_trace (o, val, 1, 1);
545 x2_put_byte (o, val);
546 }
cputracefunc2_x_put_long(uaecptr o,uae_u32 val)547 static void cputracefunc2_x_put_long (uaecptr o, uae_u32 val)
548 {
549 uae_u32 v;
550 if (get_trace (o, 1, 4, &v)) {
551 x2_put_long (o, val);
552 check_trace2 ();
553 }
554 if (v != val)
555 write_log (_T("cputracefunc2_x_put_long %d <> %d\n"), v, val);
556 }
cputracefunc2_x_put_word(uaecptr o,uae_u32 val)557 static void cputracefunc2_x_put_word (uaecptr o, uae_u32 val)
558 {
559 uae_u32 v;
560 if (get_trace (o, 1, 2, &v)) {
561 x2_put_word (o, val);
562 check_trace2 ();
563 }
564 if (v != val)
565 write_log (_T("cputracefunc2_x_put_word %d <> %d\n"), v, val);
566 }
cputracefunc2_x_put_byte(uaecptr o,uae_u32 val)567 static void cputracefunc2_x_put_byte (uaecptr o, uae_u32 val)
568 {
569 uae_u32 v;
570 if (get_trace (o, 1, 1, &v)) {
571 x2_put_byte (o, val);
572 check_trace2 ();
573 }
574 if (v != val)
575 write_log (_T("cputracefunc2_x_put_byte %d <> %d\n"), v, val);
576 }
577
cputracefunc_x_do_cycles(unsigned long cycles)578 static void cputracefunc_x_do_cycles (unsigned long cycles)
579 {
580 while (cycles >= CYCLE_UNIT) {
581 cputrace.cyclecounter += CYCLE_UNIT;
582 cycles -= CYCLE_UNIT;
583 x2_do_cycles (CYCLE_UNIT);
584 }
585 if (cycles > 0) {
586 cputrace.cyclecounter += cycles;
587 x2_do_cycles (cycles);
588 }
589 }
590
cputracefunc2_x_do_cycles(unsigned long cycles)591 static void cputracefunc2_x_do_cycles (unsigned long cycles)
592 {
593 if (cputrace.cyclecounter > cycles) {
594 cputrace.cyclecounter -= cycles;
595 return;
596 }
597 cycles -= cputrace.cyclecounter;
598 cputrace.cyclecounter = 0;
599 check_trace ();
600 x_do_cycles = x2_do_cycles;
601 if (cycles > 0)
602 x_do_cycles (cycles);
603 }
604
cputracefunc_x_do_cycles_pre(unsigned long cycles)605 static void cputracefunc_x_do_cycles_pre (unsigned long cycles)
606 {
607 cputrace.cyclecounter_post = 0;
608 cputrace.cyclecounter_pre = 0;
609 while (cycles >= CYCLE_UNIT) {
610 cycles -= CYCLE_UNIT;
611 cputrace.cyclecounter_pre += CYCLE_UNIT;
612 x2_do_cycles (CYCLE_UNIT);
613 }
614 if (cycles > 0) {
615 x2_do_cycles (cycles);
616 cputrace.cyclecounter_pre += cycles;
617 }
618 cputrace.cyclecounter_pre = 0;
619 }
620 // cyclecounter_pre = how many cycles we need to SWALLOW
621 // -1 = rerun whole access
cputracefunc2_x_do_cycles_pre(unsigned long cycles)622 static void cputracefunc2_x_do_cycles_pre (unsigned long cycles)
623 {
624 if (cputrace.cyclecounter_pre == (unsigned long)-1) {
625 cputrace.cyclecounter_pre = 0;
626 check_trace ();
627 check_trace2 ();
628 x_do_cycles (cycles);
629 return;
630 }
631 if (cputrace.cyclecounter_pre > cycles) {
632 cputrace.cyclecounter_pre -= cycles;
633 return;
634 }
635 cycles -= cputrace.cyclecounter_pre;
636 cputrace.cyclecounter_pre = 0;
637 check_trace ();
638 if (cycles > 0)
639 x_do_cycles (cycles);
640 }
641
cputracefunc_x_do_cycles_post(unsigned long cycles,uae_u32 v)642 static void cputracefunc_x_do_cycles_post (unsigned long cycles, uae_u32 v)
643 {
644 if (cputrace.memoryoffset < 1) {
645 #if CPUTRACE_DEBUG
646 write_log (_T("cputracefunc_x_do_cycles_post memoryoffset=%d!\n"), cputrace.memoryoffset);
647 #endif
648 return;
649 }
650 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
651 ctm->data = v;
652 cputrace.cyclecounter_post = cycles;
653 cputrace.cyclecounter_pre = 0;
654 while (cycles >= CYCLE_UNIT) {
655 cycles -= CYCLE_UNIT;
656 cputrace.cyclecounter_post -= CYCLE_UNIT;
657 x2_do_cycles (CYCLE_UNIT);
658 }
659 if (cycles > 0) {
660 cputrace.cyclecounter_post -= cycles;
661 x2_do_cycles (cycles);
662 }
663 cputrace.cyclecounter_post = 0;
664 }
665 // cyclecounter_post = how many cycles we need to WAIT
cputracefunc2_x_do_cycles_post(unsigned long cycles,uae_u32 v)666 static void cputracefunc2_x_do_cycles_post (unsigned long cycles, uae_u32 v)
667 {
668 uae_u32 c;
669 if (cputrace.cyclecounter_post) {
670 c = cputrace.cyclecounter_post;
671 cputrace.cyclecounter_post = 0;
672 } else {
673 c = cycles;
674 }
675 check_trace ();
676 if (c > 0)
677 x_do_cycles (c);
678 }
679
do_cycles_post(unsigned long cycles,uae_u32 v)680 static void do_cycles_post (unsigned long cycles, uae_u32 v)
681 {
682 do_cycles (cycles);
683 }
do_cycles_ce_post(unsigned long cycles,uae_u32 v)684 static void do_cycles_ce_post (unsigned long cycles, uae_u32 v)
685 {
686 do_cycles_ce (cycles);
687 }
688
689 // indirect memory access functions
set_x_funcs(void)690 static void set_x_funcs (void)
691 {
692 if (currprefs.mmu_model) {
693 if (currprefs.cpu_model == 68060) {
694 x_prefetch = get_iword_mmu060;
695 x_prefetch_long = get_ilong_mmu060;
696 x_get_ilong = get_ilong_mmu060;
697 x_get_iword = get_iword_mmu060;
698 x_get_ibyte = get_ibyte_mmu060;
699 x_next_iword = next_iword_mmu060;
700 x_next_ilong = next_ilong_mmu060;
701 x_put_long = put_long_mmu060;
702 x_put_word = put_word_mmu060;
703 x_put_byte = put_byte_mmu060;
704 x_get_long = get_long_mmu060;
705 x_get_word = get_word_mmu060;
706 x_get_byte = get_byte_mmu060;
707 } else if (currprefs.cpu_model == 68040) {
708 x_prefetch = get_iword_mmu040;
709 x_prefetch_long = get_ilong_mmu040;
710 x_get_ilong = get_ilong_mmu040;
711 x_get_iword = get_iword_mmu040;
712 x_get_ibyte = get_ibyte_mmu040;
713 x_next_iword = next_iword_mmu040;
714 x_next_ilong = next_ilong_mmu040;
715 x_put_long = put_long_mmu040;
716 x_put_word = put_word_mmu040;
717 x_put_byte = put_byte_mmu040;
718 x_get_long = get_long_mmu040;
719 x_get_word = get_word_mmu040;
720 x_get_byte = get_byte_mmu040;
721 } else {
722 x_prefetch = get_iword_mmu030;
723 x_prefetch_long = get_ilong_mmu030;
724 x_get_ilong = get_ilong_mmu030;
725 x_get_iword = get_iword_mmu030;
726 x_get_ibyte = get_ibyte_mmu030;
727 x_next_iword = next_iword_mmu030;
728 x_next_ilong = next_ilong_mmu030;
729 x_put_long = put_long_mmu030;
730 x_put_word = put_word_mmu030;
731 x_put_byte = put_byte_mmu030;
732 x_get_long = get_long_mmu030;
733 x_get_word = get_word_mmu030;
734 x_get_byte = get_byte_mmu030;
735 }
736 x_do_cycles = do_cycles;
737 x_do_cycles_pre = do_cycles;
738 x_do_cycles_post = do_cycles_post;
739 } else if (currprefs.cpu_model < 68020) {
740 if (currprefs.cpu_cycle_exact) {
741 x_prefetch = get_word_ce000_prefetch;
742 x_prefetch_long = NULL;
743 x_get_ilong = NULL;
744 x_get_iword = get_wordi_ce000;
745 x_get_ibyte = NULL;
746 x_next_iword = NULL;
747 x_next_ilong = NULL;
748 x_put_long = put_long_ce000;
749 x_put_word = put_word_ce000;
750 x_put_byte = put_byte_ce000;
751 x_get_long = get_long_ce000;
752 x_get_word = get_word_ce000;
753 x_get_byte = get_byte_ce000;
754 x_do_cycles = do_cycles_ce;
755 x_do_cycles_pre = do_cycles_ce;
756 x_do_cycles_post = do_cycles_ce_post;
757 } else if (currprefs.cpu_compatible) {
758 x_prefetch = get_word_prefetch;
759 x_prefetch_long = get_long_prefetch;
760 x_get_ilong = NULL;
761 x_get_iword = get_iword;
762 x_get_ibyte = get_ibyte;
763 x_next_iword = NULL;
764 x_next_ilong = NULL;
765 x_put_long = put_long;
766 x_put_word = put_word;
767 x_put_byte = put_byte;
768 x_get_long = get_long;
769 x_get_word = get_word;
770 x_get_byte = get_byte;
771 x_do_cycles = do_cycles;
772 x_do_cycles_pre = do_cycles;
773 x_do_cycles_post = do_cycles_post;
774 } else {
775 x_prefetch = NULL;
776 x_prefetch_long = NULL;
777 x_get_ilong = get_ilong;
778 x_get_iword = get_iword;
779 x_get_ibyte = get_ibyte;
780 x_next_iword = next_iword;
781 x_next_ilong = next_ilong;
782 x_put_long = put_long;
783 x_put_word = put_word;
784 x_put_byte = put_byte;
785 x_get_long = get_long;
786 x_get_word = get_word;
787 x_get_byte = get_byte;
788 x_do_cycles = do_cycles;
789 x_do_cycles_pre = do_cycles;
790 x_do_cycles_post = do_cycles_post;
791 }
792 } else if (!currprefs.cpu_cycle_exact) {
793 x_prefetch = NULL;
794 x_prefetch_long = NULL;
795 x_get_ilong = get_ilong;
796 x_get_iword = get_iword;
797 x_get_ibyte = get_ibyte;
798 x_next_iword = next_iword;
799 x_next_ilong = next_ilong;
800 x_put_long = put_long;
801 x_put_word = put_word;
802 x_put_byte = put_byte;
803 x_get_long = get_long;
804 x_get_word = get_word;
805 x_get_byte = get_byte;
806 x_do_cycles = do_cycles;
807 x_do_cycles_pre = do_cycles;
808 x_do_cycles_post = do_cycles_post;
809 } else if (currprefs.cpu_model == 68020) {
810 x_prefetch = get_word_ce020_prefetch;
811 x_prefetch_long = NULL;
812 x_get_ilong = get_long_ce020_prefetch;
813 x_get_iword = get_word_ce020_prefetch;
814 x_get_ibyte = NULL;
815 x_next_iword = next_iword_020ce;
816 x_next_ilong = next_ilong_020ce;
817 x_put_long = put_long_ce020;
818 x_put_word = put_word_ce020;
819 x_put_byte = put_byte_ce020;
820 x_get_long = get_long_ce020;
821 x_get_word = get_word_ce020;
822 x_get_byte = get_byte_ce020;
823 x_do_cycles = do_cycles_ce;
824 x_do_cycles_pre = do_cycles_ce;
825 x_do_cycles_post = do_cycles_ce_post;
826 } else {
827 x_prefetch = get_word_ce030_prefetch;
828 x_prefetch_long = NULL;
829 x_get_ilong = get_long_ce030_prefetch;
830 x_get_iword = get_word_ce030_prefetch;
831 x_get_ibyte = NULL;
832 x_next_iword = next_iword_030ce;
833 x_next_ilong = next_ilong_030ce;
834 x_put_long = put_long_ce030;
835 x_put_word = put_word_ce030;
836 x_put_byte = put_byte_ce030;
837 x_get_long = get_long_ce030;
838 x_get_word = get_word_ce030;
839 x_get_byte = get_byte_ce030;
840 x_do_cycles = do_cycles_ce;
841 x_do_cycles_pre = do_cycles_ce;
842 x_do_cycles_post = do_cycles_ce_post;
843 }
844 x2_prefetch = x_prefetch;
845 x2_prefetch_long = x_prefetch_long;
846 x2_get_ilong = x_get_ilong;
847 x2_get_iword = x_get_iword;
848 x2_get_ibyte = x_get_ibyte;
849 x2_next_iword = x_next_iword;
850 x2_next_ilong = x_next_ilong;
851 x2_put_long = x_put_long;
852 x2_put_word = x_put_word;
853 x2_put_byte = x_put_byte;
854 x2_get_long = x_get_long;
855 x2_get_word = x_get_word;
856 x2_get_byte = x_get_byte;
857 x2_do_cycles = x_do_cycles;
858 x2_do_cycles_pre = x_do_cycles_pre;
859 x2_do_cycles_post = x_do_cycles_post;
860
861 if (cpu_tracer > 0) {
862 x_prefetch = cputracefunc_x_prefetch;
863 x_prefetch_long = cputracefunc_x_prefetch_long;
864 x_get_ilong = cputracefunc_x_get_ilong;
865 x_get_iword = cputracefunc_x_get_iword;
866 x_get_ibyte = cputracefunc_x_get_ibyte;
867 x_next_iword = cputracefunc_x_next_iword;
868 x_next_ilong = cputracefunc_x_next_ilong;
869 x_put_long = cputracefunc_x_put_long;
870 x_put_word = cputracefunc_x_put_word;
871 x_put_byte = cputracefunc_x_put_byte;
872 x_get_long = cputracefunc_x_get_long;
873 x_get_word = cputracefunc_x_get_word;
874 x_get_byte = cputracefunc_x_get_byte;
875 x_do_cycles = cputracefunc_x_do_cycles;
876 x_do_cycles_pre = cputracefunc_x_do_cycles_pre;
877 x_do_cycles_post = cputracefunc_x_do_cycles_post;
878 } else if (cpu_tracer < 0) {
879 if (!check_trace ()) {
880 x_prefetch = cputracefunc2_x_prefetch;
881 x_prefetch_long = cputracefunc2_x_prefetch_long;
882 x_get_ilong = cputracefunc2_x_get_ilong;
883 x_get_iword = cputracefunc2_x_get_iword;
884 x_get_ibyte = cputracefunc2_x_get_ibyte;
885 x_next_iword = cputracefunc2_x_next_iword;
886 x_next_ilong = cputracefunc2_x_next_ilong;
887 x_put_long = cputracefunc2_x_put_long;
888 x_put_word = cputracefunc2_x_put_word;
889 x_put_byte = cputracefunc2_x_put_byte;
890 x_get_long = cputracefunc2_x_get_long;
891 x_get_word = cputracefunc2_x_get_word;
892 x_get_byte = cputracefunc2_x_get_byte;
893 x_do_cycles = cputracefunc2_x_do_cycles;
894 x_do_cycles_pre = cputracefunc2_x_do_cycles_pre;
895 x_do_cycles_post = cputracefunc2_x_do_cycles_post;
896 }
897 }
898
899 x_cp_put_long = x_put_long;
900 x_cp_put_word = x_put_word;
901 x_cp_put_byte = x_put_byte;
902 x_cp_get_long = x_get_long;
903 x_cp_get_word = x_get_word;
904 x_cp_get_byte = x_get_byte;
905 x_cp_next_iword = x_next_iword;
906 x_cp_next_ilong = x_next_ilong;
907 x_cp_get_disp_ea_020 = x_get_disp_ea_020;
908
909 if (currprefs.mmu_model == 68030) {
910 x_cp_put_long = put_long_mmu030_state;
911 x_cp_put_word = put_word_mmu030_state;
912 x_cp_put_byte = put_byte_mmu030_state;
913 x_cp_get_long = get_long_mmu030_state;
914 x_cp_get_word = get_word_mmu030_state;
915 x_cp_get_byte = get_byte_mmu030_state;
916 x_cp_next_iword = next_iword_mmu030_state;
917 x_cp_next_ilong = next_ilong_mmu030_state;
918 x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
919 }
920 }
921
can_cpu_tracer(void)922 bool can_cpu_tracer (void)
923 {
924 return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_cycle_exact;
925 }
926
is_cpu_tracer(void)927 bool is_cpu_tracer (void)
928 {
929 return cpu_tracer > 0;
930 }
set_cpu_tracer(bool state)931 bool set_cpu_tracer (bool state)
932 {
933 if (cpu_tracer < 0)
934 return false;
935 int old = cpu_tracer;
936 if (input_record)
937 state = true;
938 cpu_tracer = 0;
939 if (state && can_cpu_tracer ()) {
940 cpu_tracer = 1;
941 set_x_funcs ();
942 if (old != cpu_tracer)
943 write_log (_T("CPU tracer enabled\n"));
944 }
945 if (old > 0 && state == false) {
946 set_x_funcs ();
947 write_log (_T("CPU tracer disabled\n"));
948 }
949 return is_cpu_tracer ();
950 }
951
set_cpu_caches(void)952 static void set_cpu_caches (void)
953 {
954 int i;
955
956 regs.prefetch020addr = 0xffffffff;
957 regs.cacheholdingaddr020 = 0xffffffff;
958
959 #ifdef JIT
960 if (currprefs.cachesize) {
961 if (currprefs.cpu_model < 68040) {
962 set_cache_state (regs.cacr & 1);
963 if (regs.cacr & 0x08) {
964 flush_icache (0, 3);
965 }
966 } else {
967 set_cache_state ((regs.cacr & 0x8000) ? 1 : 0);
968 }
969 }
970 #endif
971 if (currprefs.cpu_model == 68020) {
972 if (regs.cacr & 0x08) { // clear instr cache
973 for (i = 0; i < CACHELINES020; i++)
974 caches020[i].valid = 0;
975 }
976 if (regs.cacr & 0x04) { // clear entry in instr cache
977 caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0;
978 regs.cacr &= ~0x04;
979 }
980 } else if (currprefs.cpu_model == 68030) {
981 //regs.cacr |= 0x100;
982 if (regs.cacr & 0x08) { // clear instr cache
983 for (i = 0; i < CACHELINES030; i++) {
984 icaches030[i].valid[0] = 0;
985 icaches030[i].valid[1] = 0;
986 icaches030[i].valid[2] = 0;
987 icaches030[i].valid[3] = 0;
988 }
989 }
990 if (regs.cacr & 0x04) { // clear entry in instr cache
991 icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
992 regs.cacr &= ~0x04;
993 }
994 if (regs.cacr & 0x800) { // clear data cache
995 for (i = 0; i < CACHELINES030; i++) {
996 dcaches030[i].valid[0] = 0;
997 dcaches030[i].valid[1] = 0;
998 dcaches030[i].valid[2] = 0;
999 dcaches030[i].valid[3] = 0;
1000 }
1001 regs.cacr &= ~0x800;
1002 }
1003 if (regs.cacr & 0x400) { // clear entry in data cache
1004 dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1005 regs.cacr &= ~0x400;
1006 }
1007 } else if (currprefs.cpu_model == 68040) {
1008 if (!(regs.cacr & 0x8000)) {
1009 for (i = 0; i < CACHESETS040; i++) {
1010 caches040[i].valid[0] = 0;
1011 caches040[i].valid[1] = 0;
1012 caches040[i].valid[2] = 0;
1013 caches040[i].valid[3] = 0;
1014 }
1015 }
1016 }
1017 }
1018
count_instr(unsigned int opcode)1019 STATIC_INLINE void count_instr (unsigned int opcode)
1020 {
1021 }
1022
op_illg_1(uae_u32 opcode)1023 static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
1024 {
1025 op_illg (opcode);
1026 return 4;
1027 }
op_unimpl_1(uae_u32 opcode)1028 static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
1029 {
1030 if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
1031 op_illg (opcode);
1032 else
1033 op_unimpl (opcode);
1034 return 4;
1035 }
1036
build_cpufunctbl(void)1037 static void build_cpufunctbl (void)
1038 {
1039 int i, opcnt;
1040 unsigned long opcode;
1041 const struct cputbl *tbl = 0;
1042 int lvl;
1043
1044 switch (currprefs.cpu_model)
1045 {
1046 #ifdef CPUEMU_0
1047 #ifndef CPUEMU_68000_ONLY
1048 case 68060:
1049 lvl = 5;
1050 tbl = op_smalltbl_0_ff;
1051 if (currprefs.cpu_cycle_exact)
1052 tbl = op_smalltbl_22_ff;
1053 if (currprefs.mmu_model)
1054 tbl = op_smalltbl_33_ff;
1055 break;
1056 case 68040:
1057 lvl = 4;
1058 tbl = op_smalltbl_1_ff;
1059 if (currprefs.cpu_cycle_exact)
1060 tbl = op_smalltbl_23_ff;
1061 if (currprefs.mmu_model)
1062 tbl = op_smalltbl_31_ff;
1063 break;
1064 case 68030:
1065 lvl = 3;
1066 tbl = op_smalltbl_2_ff;
1067 if (currprefs.cpu_cycle_exact)
1068 tbl = op_smalltbl_24_ff;
1069 if (currprefs.mmu_model)
1070 tbl = op_smalltbl_32_ff;
1071 break;
1072 case 68020:
1073 lvl = 2;
1074 tbl = op_smalltbl_3_ff;
1075 #ifdef CPUEMU_20
1076 if (currprefs.cpu_compatible)
1077 tbl = op_smalltbl_20_ff;
1078 #endif
1079 #ifdef CPUEMU_21
1080 if (currprefs.cpu_cycle_exact)
1081 tbl = op_smalltbl_21_ff;
1082 #endif
1083 break;
1084 case 68010:
1085 lvl = 1;
1086 tbl = op_smalltbl_4_ff;
1087 break;
1088 #endif
1089 #endif
1090 default:
1091 changed_prefs.cpu_model = currprefs.cpu_model = 68000;
1092 case 68000:
1093 lvl = 0;
1094 tbl = op_smalltbl_5_ff;
1095 #ifdef CPUEMU_11
1096 if (currprefs.cpu_compatible)
1097 tbl = op_smalltbl_11_ff; /* prefetch */
1098 #endif
1099 #ifdef CPUEMU_12
1100 if (currprefs.cpu_cycle_exact)
1101 tbl = op_smalltbl_12_ff; /* prefetch and cycle-exact */
1102 #endif
1103 break;
1104 }
1105
1106 if (tbl == 0) {
1107 write_log (_T("no CPU emulation cores available CPU=%d!"), currprefs.cpu_model);
1108 abort ();
1109 }
1110
1111 for (opcode = 0; opcode < 65536; opcode++)
1112 cpufunctbl[opcode] = op_illg_1;
1113 for (i = 0; tbl[i].handler != NULL; i++) {
1114 opcode = tbl[i].opcode;
1115 cpufunctbl[opcode] = tbl[i].handler;
1116 }
1117
1118 /* hack fpu to 68000/68010 mode */
1119 if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
1120 tbl = op_smalltbl_3_ff;
1121 for (i = 0; tbl[i].handler != NULL; i++) {
1122 if ((tbl[i].opcode & 0xfe00) == 0xf200)
1123 cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1124 }
1125 }
1126
1127 opcnt = 0;
1128 for (opcode = 0; opcode < 65536; opcode++) {
1129 cpuop_func *f;
1130 struct instr *table = &table68k[opcode];
1131
1132 if (table->mnemo == i_ILLG)
1133 continue;
1134
1135 /* unimplemented opcode? */
1136 if (table->unimpclev > 0 && lvl >= table->unimpclev) {
1137 if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
1138 cpufunctbl[opcode] = op_unimpl_1;
1139 } else {
1140 cpufunctbl[opcode] = op_illg_1;
1141 }
1142 continue;
1143 }
1144
1145 if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
1146 /* more hack fpu to 68000/68010 mode */
1147 if (table->clev > lvl && (opcode & 0xfe00) != 0xf200)
1148 continue;
1149 } else if (table->clev > lvl) {
1150 continue;
1151 }
1152
1153 if (table->handler != -1) {
1154 int idx = table->handler;
1155 f = cpufunctbl[idx];
1156 if (f == op_illg_1)
1157 abort ();
1158 cpufunctbl[opcode] = f;
1159 opcnt++;
1160 }
1161 }
1162 write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"),
1163 opcnt, lvl,
1164 currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24);
1165 write_log (_T("CPU=%d, FPU=%d, MMU=%d, JIT%s=%d.\n"),
1166 currprefs.cpu_model, currprefs.fpu_model,
1167 currprefs.mmu_model,
1168 #ifdef JIT
1169 currprefs.cachesize ? (currprefs.compfpu ? _T("=CPU/FPU") : _T("=CPU")) : _T(""),
1170 currprefs.cachesize);
1171 #else
1172 "=CPU", 0);
1173 #endif
1174 #ifdef JIT
1175 build_comp ();
1176 #endif
1177 set_cpu_caches ();
1178 }
1179
fill_prefetch(void)1180 void fill_prefetch (void)
1181 {
1182 if (currprefs.cpu_model >= 68020)
1183 return;
1184 regs.ir = x_get_word (m68k_getpc ());
1185 regs.irc = x_get_word (m68k_getpc () + 2);
1186 }
fill_prefetch_quick(void)1187 static void fill_prefetch_quick (void)
1188 {
1189 if (currprefs.cpu_model >= 68020)
1190 return;
1191 regs.ir = get_word (m68k_getpc ());
1192 regs.irc = get_word (m68k_getpc () + 2);
1193 }
1194
1195 #define CYCLES_DIV 8192
1196 static unsigned long cycles_mult;
1197
update_68k_cycles(void)1198 static void update_68k_cycles (void)
1199 {
1200 cycles_mult = 0;
1201 if (currprefs.m68k_speed >= 0 && !currprefs.cpu_cycle_exact) {
1202 if (currprefs.m68k_speed_throttle < 0) {
1203 cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
1204 } else if (currprefs.m68k_speed_throttle > 0) {
1205 cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
1206 }
1207 }
1208 if (currprefs.m68k_speed == 0 && currprefs.cpu_model >= 68020) {
1209 if (!cycles_mult)
1210 cycles_mult = CYCLES_DIV / 4;
1211 else
1212 cycles_mult /= 4;
1213 }
1214
1215 currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier;
1216 currprefs.cpu_frequency = changed_prefs.cpu_frequency;
1217
1218 baseclock = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) * 8;
1219 cpucycleunit = CYCLE_UNIT / 2;
1220 if (currprefs.cpu_clock_multiplier) {
1221 if (currprefs.cpu_clock_multiplier >= 256) {
1222 cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8);
1223 } else {
1224 cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier;
1225 }
1226 } else if (currprefs.cpu_frequency) {
1227 cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency;
1228 } else if (currprefs.cpu_cycle_exact && currprefs.cpu_clock_multiplier == 0) {
1229 if (currprefs.cpu_model >= 68030) {
1230 cpucycleunit = CYCLE_UNIT / 8;
1231 } else if (currprefs.cpu_model == 68020) {
1232 cpucycleunit = CYCLE_UNIT / 4;
1233 } else {
1234 cpucycleunit = CYCLE_UNIT / 2;
1235 }
1236 }
1237 if (cpucycleunit < 1)
1238 cpucycleunit = 1;
1239 if (currprefs.cpu_cycle_exact)
1240 write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
1241 config_changed = 1;
1242 }
1243
prefs_changed_cpu(void)1244 static void prefs_changed_cpu (void)
1245 {
1246 fixup_cpu (&changed_prefs);
1247 currprefs.cpu_model = changed_prefs.cpu_model;
1248 currprefs.fpu_model = changed_prefs.fpu_model;
1249 currprefs.mmu_model = changed_prefs.mmu_model;
1250 currprefs.cpu_compatible = changed_prefs.cpu_compatible;
1251 currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1252 currprefs.int_no_unimplemented = changed_prefs.int_no_unimplemented;
1253 currprefs.fpu_no_unimplemented = changed_prefs.fpu_no_unimplemented;
1254 currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
1255 }
1256
check_prefs_changed_cpu(void)1257 void check_prefs_changed_cpu (void)
1258 {
1259 bool changed = false;
1260
1261 if (!config_changed)
1262 return;
1263
1264 #ifdef JIT
1265 changed = check_prefs_changed_comp ();
1266 #endif
1267 if (changed
1268 || currprefs.cpu_model != changed_prefs.cpu_model
1269 || currprefs.fpu_model != changed_prefs.fpu_model
1270 #ifdef MMUEMU
1271 || currprefs.mmu_model != changed_prefs.mmu_model
1272 #endif
1273 || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented
1274 || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented
1275 || currprefs.cpu_compatible != changed_prefs.cpu_compatible
1276 || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) {
1277
1278 prefs_changed_cpu ();
1279 if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible)
1280 fill_prefetch_quick ();
1281 build_cpufunctbl ();
1282 changed = true;
1283 }
1284 if (changed
1285 || currprefs.m68k_speed != changed_prefs.m68k_speed
1286 || currprefs.m68k_speed_throttle != changed_prefs.m68k_speed_throttle
1287 || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier
1288 || currprefs.cpu_frequency != changed_prefs.cpu_frequency) {
1289 currprefs.m68k_speed = changed_prefs.m68k_speed;
1290 currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle;
1291 update_68k_cycles ();
1292 changed = true;
1293 }
1294
1295 if (currprefs.cpu_idle != changed_prefs.cpu_idle) {
1296 currprefs.cpu_idle = changed_prefs.cpu_idle;
1297 }
1298 if (changed) {
1299 set_special (SPCFLAG_BRK);
1300 reset_frame_rate_hack ();
1301 }
1302
1303 }
1304
init_m68k(void)1305 void init_m68k (void)
1306 {
1307 int i;
1308
1309 prefs_changed_cpu ();
1310 update_68k_cycles ();
1311
1312 for (i = 0 ; i < 256 ; i++) {
1313 int j;
1314 for (j = 0 ; j < 8 ; j++) {
1315 if (i & (1 << j)) break;
1316 }
1317 movem_index1[i] = j;
1318 movem_index2[i] = 7-j;
1319 movem_next[i] = i & (~(1 << j));
1320 }
1321
1322 #if COUNT_INSTRS
1323 {
1324 FILE *f = fopen (icountfilename (), "r");
1325 memset (instrcount, 0, sizeof instrcount);
1326 if (f) {
1327 uae_u32 opcode, count, total;
1328 TCHAR name[20];
1329 write_log (_T("Reading instruction count file...\n"));
1330 fscanf (f, "Total: %lu\n", &total);
1331 while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
1332 instrcount[opcode] = count;
1333 }
1334 fclose (f);
1335 }
1336 }
1337 #endif
1338 write_log (_T("Building CPU table for configuration: %d"), currprefs.cpu_model);
1339 regs.address_space_mask = 0xffffffff;
1340 if (currprefs.cpu_compatible) {
1341 if (currprefs.address_space_24 && currprefs.cpu_model >= 68030)
1342 currprefs.address_space_24 = false;
1343 }
1344 if (currprefs.fpu_model > 0)
1345 write_log (_T("/%d"), currprefs.fpu_model);
1346 if (currprefs.cpu_cycle_exact) {
1347 if (currprefs.cpu_model == 68000)
1348 write_log (_T(" prefetch and cycle-exact"));
1349 else
1350 write_log (_T(" ~cycle-exact"));
1351 } else if (currprefs.cpu_compatible) {
1352 if (currprefs.cpu_model <= 68020) {
1353 write_log (_T(" prefetch"));
1354 } else {
1355 write_log (_T(" fake prefetch"));
1356 }
1357 }
1358 if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
1359 write_log (_T(" no unimplemented integer instructions"));
1360 }
1361 if (currprefs.fpu_no_unimplemented && currprefs.fpu_model) {
1362 write_log (_T(" no unimplemented floating point instructions"));
1363 }
1364 if (currprefs.address_space_24) {
1365 regs.address_space_mask = 0x00ffffff;
1366 write_log (_T(" 24-bit"));
1367 }
1368 write_log (_T("\n"));
1369
1370 read_table68k ();
1371 do_merges ();
1372
1373 write_log (_T("%d CPU functions\n"), nr_cpuop_funcs);
1374
1375 build_cpufunctbl ();
1376 set_x_funcs ();
1377
1378 #ifdef JIT
1379 /* We need to check whether NATMEM settings have changed
1380 * before starting the CPU */
1381 check_prefs_changed_comp ();
1382 #endif
1383 }
1384
1385 struct regstruct regs, mmu_backup_regs;
1386 struct flag_struct regflags;
1387 static long int m68kpc_offset;
1388
1389 #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
1390 #define get_iword_1(o) get_word (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1391 #define get_ilong_1(o) get_long (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1392
ShowEA(void * f,uaecptr pc,uae_u16 opcode,int reg,amodes mode,wordsizes size,TCHAR * buf,uae_u32 * eaddr,int safemode)1393 static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
1394 {
1395 uae_u16 dp;
1396 uae_s8 disp8;
1397 uae_s16 disp16;
1398 int r;
1399 uae_u32 dispreg;
1400 uaecptr addr = pc;
1401 uae_s32 offset = 0;
1402 TCHAR buffer[80];
1403
1404 switch (mode){
1405 case Dreg:
1406 _stprintf (buffer, _T("D%d"), reg);
1407 break;
1408 case Areg:
1409 _stprintf (buffer, _T("A%d"), reg);
1410 break;
1411 case Aind:
1412 _stprintf (buffer, _T("(A%d)"), reg);
1413 addr = regs.regs[reg + 8];
1414 break;
1415 case Aipi:
1416 _stprintf (buffer, _T("(A%d)+"), reg);
1417 addr = regs.regs[reg + 8];
1418 break;
1419 case Apdi:
1420 _stprintf (buffer, _T("-(A%d)"), reg);
1421 addr = regs.regs[reg + 8];
1422 break;
1423 case Ad16:
1424 {
1425 TCHAR offtxt[80];
1426 disp16 = get_iword_debug (pc); pc += 2;
1427 if (disp16 < 0)
1428 _stprintf (offtxt, _T("-$%04x"), -disp16);
1429 else
1430 _stprintf (offtxt, _T("$%04x"), disp16);
1431 addr = m68k_areg (regs, reg) + disp16;
1432 _stprintf (buffer, _T("(A%d, %s) == $%08lx"), reg, offtxt, (unsigned long)addr);
1433 }
1434 break;
1435 case Ad8r:
1436 dp = get_iword_debug (pc); pc += 2;
1437 disp8 = dp & 0xFF;
1438 r = (dp & 0x7000) >> 12;
1439 dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1440 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1441 dispreg <<= (dp >> 9) & 3;
1442
1443 if (dp & 0x100) {
1444 uae_s32 outer = 0, disp = 0;
1445 uae_s32 base = m68k_areg (regs, reg);
1446 TCHAR name[10];
1447 _stprintf (name, _T("A%d, "), reg);
1448 if (dp & 0x80) { base = 0; name[0] = 0; }
1449 if (dp & 0x40) dispreg = 0;
1450 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1451 if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1452 base += disp;
1453
1454 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1455 if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1456
1457 if (!(dp & 4)) base += dispreg;
1458 if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1459 if (dp & 4) base += dispreg;
1460
1461 addr = base + outer;
1462 _stprintf (buffer, _T("(%s%c%d.%c*%d+%ld)+%ld == $%08lx"), name,
1463 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1464 1 << ((dp >> 9) & 3),
1465 disp, outer,
1466 (unsigned long)addr);
1467 } else {
1468 addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
1469 _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08lx"), reg,
1470 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1471 1 << ((dp >> 9) & 3), disp8,
1472 (unsigned long)addr);
1473 }
1474 break;
1475 case PC16:
1476 disp16 = get_iword_debug (pc); pc += 2;
1477 addr += (uae_s16)disp16;
1478 _stprintf (buffer, _T("(PC,$%04x) == $%08lx"), disp16 & 0xffff, (unsigned long)addr);
1479 break;
1480 case PC8r:
1481 dp = get_iword_debug (pc); pc += 2;
1482 disp8 = dp & 0xFF;
1483 r = (dp & 0x7000) >> 12;
1484 dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1485 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1486 dispreg <<= (dp >> 9) & 3;
1487
1488 if (dp & 0x100) {
1489 uae_s32 outer = 0, disp = 0;
1490 uae_s32 base = addr;
1491 TCHAR name[10];
1492 _stprintf (name, _T("PC, "));
1493 if (dp & 0x80) { base = 0; name[0] = 0; }
1494 if (dp & 0x40) dispreg = 0;
1495 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1496 if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1497 base += disp;
1498
1499 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1500 if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1501
1502 if (!(dp & 4)) base += dispreg;
1503 if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1504 if (dp & 4) base += dispreg;
1505
1506 addr = base + outer;
1507 _stprintf (buffer, _T("(%s%c%d.%c*%d+%ld)+%ld == $%08lx"), name,
1508 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1509 1 << ((dp >> 9) & 3),
1510 disp, outer,
1511 (unsigned long)addr);
1512 } else {
1513 addr += (uae_s32)((uae_s8)disp8) + dispreg;
1514 _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08lx"), dp & 0x8000 ? 'A' : 'D',
1515 (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
1516 disp8, (unsigned long)addr);
1517 }
1518 break;
1519 case absw:
1520 addr = (uae_s32)(uae_s16)get_iword_debug (pc);
1521 _stprintf (buffer, _T("$%08lx"), (unsigned long)addr);
1522 pc += 2;
1523 break;
1524 case absl:
1525 addr = get_ilong_debug (pc);
1526 _stprintf (buffer, _T("$%08lx"), (unsigned long)addr);
1527 pc += 4;
1528 break;
1529 case imm:
1530 switch (size){
1531 case sz_byte:
1532 _stprintf (buffer, _T("#$%02x"), (unsigned int)(get_iword_debug (pc) & 0xff));
1533 pc += 2;
1534 break;
1535 case sz_word:
1536 _stprintf (buffer, _T("#$%04x"), (unsigned int)(get_iword_debug (pc) & 0xffff));
1537 pc += 2;
1538 break;
1539 case sz_long:
1540 _stprintf (buffer, _T("#$%08lx"), (unsigned long)(get_ilong_debug (pc)));
1541 pc += 4;
1542 break;
1543 default:
1544 break;
1545 }
1546 break;
1547 case imm0:
1548 offset = (uae_s32)(uae_s8)get_iword_debug (pc);
1549 _stprintf (buffer, _T("#$%02x"), (unsigned int)(offset & 0xff));
1550 addr = pc + 2 + offset;
1551 pc += 2;
1552 break;
1553 case imm1:
1554 offset = (uae_s32)(uae_s16)get_iword_debug (pc);
1555 buffer[0] = 0;
1556 _stprintf (buffer, _T("#$%04x"), (unsigned int)(offset & 0xffff));
1557 addr = pc + offset;
1558 pc += 2;
1559 break;
1560 case imm2:
1561 offset = (uae_s32)get_ilong_debug (pc);
1562 _stprintf (buffer, _T("#$%08lx"), (unsigned long)offset);
1563 addr = pc + offset;
1564 pc += 4;
1565 break;
1566 case immi:
1567 offset = (uae_s32)(uae_s8)(reg & 0xff);
1568 _stprintf (buffer, _T("#$%08lx"), (unsigned long)offset);
1569 addr = pc + offset;
1570 break;
1571 default:
1572 break;
1573 }
1574 if (buf == 0)
1575 f_out (f, _T("%s"), buffer);
1576 else
1577 _tcscat (buf, buffer);
1578 if (eaddr)
1579 *eaddr = addr;
1580 return pc;
1581 }
1582
1583 #if 0
1584 /* The plan is that this will take over the job of exception 3 handling -
1585 * the CPU emulation functions will just do a longjmp to m68k_go whenever
1586 * they hit an odd address. */
1587 static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
1588 {
1589 uae_u16 dp;
1590 uae_s8 disp8;
1591 uae_s16 disp16;
1592 int r;
1593 uae_u32 dispreg;
1594 uaecptr addr;
1595 uae_s32 offset = 0;
1596
1597 switch (mode){
1598 case Dreg:
1599 *val = m68k_dreg (regs, reg);
1600 return 1;
1601 case Areg:
1602 *val = m68k_areg (regs, reg);
1603 return 1;
1604
1605 case Aind:
1606 case Aipi:
1607 addr = m68k_areg (regs, reg);
1608 break;
1609 case Apdi:
1610 addr = m68k_areg (regs, reg);
1611 break;
1612 case Ad16:
1613 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1614 addr = m68k_areg (regs, reg) + (uae_s16)disp16;
1615 break;
1616 case Ad8r:
1617 addr = m68k_areg (regs, reg);
1618 d8r_common:
1619 dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1620 disp8 = dp & 0xFF;
1621 r = (dp & 0x7000) >> 12;
1622 dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1623 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1624 dispreg <<= (dp >> 9) & 3;
1625
1626 if (dp & 0x100) {
1627 uae_s32 outer = 0, disp = 0;
1628 uae_s32 base = addr;
1629 if (dp & 0x80) base = 0;
1630 if (dp & 0x40) dispreg = 0;
1631 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
1632 if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1633 base += disp;
1634
1635 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
1636 if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1637
1638 if (!(dp & 4)) base += dispreg;
1639 if (dp & 3) base = get_long (base);
1640 if (dp & 4) base += dispreg;
1641
1642 addr = base + outer;
1643 } else {
1644 addr += (uae_s32)((uae_s8)disp8) + dispreg;
1645 }
1646 break;
1647 case PC16:
1648 addr = m68k_getpc () + m68kpc_offset;
1649 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1650 addr += (uae_s16)disp16;
1651 break;
1652 case PC8r:
1653 addr = m68k_getpc () + m68kpc_offset;
1654 goto d8r_common;
1655 case absw:
1656 addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
1657 m68kpc_offset += 2;
1658 break;
1659 case absl:
1660 addr = get_ilong_1 (m68kpc_offset);
1661 m68kpc_offset += 4;
1662 break;
1663 case imm:
1664 switch (size){
1665 case sz_byte:
1666 *val = get_iword_1 (m68kpc_offset) & 0xff;
1667 m68kpc_offset += 2;
1668 break;
1669 case sz_word:
1670 *val = get_iword_1 (m68kpc_offset) & 0xffff;
1671 m68kpc_offset += 2;
1672 break;
1673 case sz_long:
1674 *val = get_ilong_1 (m68kpc_offset);
1675 m68kpc_offset += 4;
1676 break;
1677 default:
1678 break;
1679 }
1680 return 1;
1681 case imm0:
1682 *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
1683 m68kpc_offset += 2;
1684 return 1;
1685 case imm1:
1686 *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
1687 m68kpc_offset += 2;
1688 return 1;
1689 case imm2:
1690 *val = get_ilong_1 (m68kpc_offset);
1691 m68kpc_offset += 4;
1692 return 1;
1693 case immi:
1694 *val = (uae_s32)(uae_s8)(reg & 0xff);
1695 return 1;
1696 default:
1697 addr = 0;
1698 break;
1699 }
1700 if ((addr & 1) == 0)
1701 return 1;
1702
1703 last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
1704 last_fault_for_exception_3 = addr;
1705 last_writeaccess_for_exception_3 = 0;
1706 last_instructionaccess_for_exception_3 = 0;
1707 return 0;
1708 }
1709 #endif
1710
get_cpu_model(void)1711 int get_cpu_model (void)
1712 {
1713 return currprefs.cpu_model;
1714 }
1715
1716 /*
1717 * extract bitfield data from memory and return it in the MSBs
1718 * bdata caches the unmodified data for put_bitfield()
1719 */
get_bitfield(uae_u32 src,uae_u32 bdata[2],uae_s32 offset,int width)1720 uae_u32 REGPARAM2 get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
1721 {
1722 uae_u32 tmp, res, mask;
1723
1724 offset &= 7;
1725 mask = 0xffffffffu << (32 - width);
1726 switch ((offset + width + 7) >> 3) {
1727 case 1:
1728 tmp = get_byte (src);
1729 res = tmp << (24 + offset);
1730 bdata[0] = tmp & ~(mask >> (24 + offset));
1731 break;
1732 case 2:
1733 tmp = get_word (src);
1734 res = tmp << (16 + offset);
1735 bdata[0] = tmp & ~(mask >> (16 + offset));
1736 break;
1737 case 3:
1738 tmp = get_word (src);
1739 res = tmp << (16 + offset);
1740 bdata[0] = tmp & ~(mask >> (16 + offset));
1741 tmp = get_byte (src + 2);
1742 res |= tmp << (8 + offset);
1743 bdata[1] = tmp & ~(mask >> (8 + offset));
1744 break;
1745 case 4:
1746 tmp = get_long (src);
1747 res = tmp << offset;
1748 bdata[0] = tmp & ~(mask >> offset);
1749 break;
1750 case 5:
1751 tmp = get_long (src);
1752 res = tmp << offset;
1753 bdata[0] = tmp & ~(mask >> offset);
1754 tmp = get_byte (src + 4);
1755 res |= tmp >> (8 - offset);
1756 bdata[1] = tmp & ~(mask << (8 - offset));
1757 break;
1758 default:
1759 /* Panic? */
1760 write_log (_T("get_bitfield() can't happen %d\n"), (offset + width + 7) >> 3);
1761 res = 0;
1762 break;
1763 }
1764 return res;
1765 }
1766 /*
1767 * write bitfield data (in the LSBs) back to memory, upper bits
1768 * must be cleared already.
1769 */
put_bitfield(uae_u32 dst,uae_u32 bdata[2],uae_u32 val,uae_s32 offset,int width)1770 void REGPARAM2 put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
1771 {
1772 offset = (offset & 7) + width;
1773 switch ((offset + 7) >> 3) {
1774 case 1:
1775 put_byte (dst, bdata[0] | (val << (8 - offset)));
1776 break;
1777 case 2:
1778 put_word (dst, bdata[0] | (val << (16 - offset)));
1779 break;
1780 case 3:
1781 put_word (dst, bdata[0] | (val >> (offset - 16)));
1782 put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
1783 break;
1784 case 4:
1785 put_long (dst, bdata[0] | (val << (32 - offset)));
1786 break;
1787 case 5:
1788 put_long (dst, bdata[0] | (val >> (offset - 32)));
1789 put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
1790 break;
1791 default:
1792 write_log (_T("put_bitfield() can't happen %d\n"), (offset + 7) >> 3);
1793 break;
1794 }
1795 }
1796
x_get_bitfield(uae_u32 src,uae_u32 bdata[2],uae_s32 offset,int width)1797 uae_u32 REGPARAM2 x_get_bitfield (uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
1798 {
1799 uae_u32 tmp1, tmp2, res, mask;
1800
1801 offset &= 7;
1802 mask = 0xffffffffu << (32 - width);
1803 switch ((offset + width + 7) >> 3) {
1804 case 1:
1805 tmp1 = x_cp_get_byte (src);
1806 res = tmp1 << (24 + offset);
1807 bdata[0] = tmp1 & ~(mask >> (24 + offset));
1808 break;
1809 case 2:
1810 tmp1 = x_cp_get_word (src);
1811 res = tmp1 << (16 + offset);
1812 bdata[0] = tmp1 & ~(mask >> (16 + offset));
1813 break;
1814 case 3:
1815 tmp1 = x_cp_get_word (src);
1816 tmp2 = x_cp_get_byte (src + 2);
1817 res = tmp1 << (16 + offset);
1818 bdata[0] = tmp1 & ~(mask >> (16 + offset));
1819 res |= tmp2 << (8 + offset);
1820 bdata[1] = tmp2 & ~(mask >> (8 + offset));
1821 break;
1822 case 4:
1823 tmp1 = x_cp_get_long (src);
1824 res = tmp1 << offset;
1825 bdata[0] = tmp1 & ~(mask >> offset);
1826 break;
1827 case 5:
1828 tmp1 = x_cp_get_long (src);
1829 tmp2 = x_cp_get_byte (src + 4);
1830 res = tmp1 << offset;
1831 bdata[0] = tmp1 & ~(mask >> offset);
1832 res |= tmp2 >> (8 - offset);
1833 bdata[1] = tmp2 & ~(mask << (8 - offset));
1834 break;
1835 default:
1836 /* Panic? */
1837 write_log (_T("x_get_bitfield() can't happen %d\n"), (offset + width + 7) >> 3);
1838 res = 0;
1839 break;
1840 }
1841 return res;
1842 }
1843
x_put_bitfield(uae_u32 dst,uae_u32 bdata[2],uae_u32 val,uae_s32 offset,int width)1844 void REGPARAM2 x_put_bitfield (uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
1845 {
1846 offset = (offset & 7) + width;
1847 switch ((offset + 7) >> 3) {
1848 case 1:
1849 x_cp_put_byte (dst, bdata[0] | (val << (8 - offset)));
1850 break;
1851 case 2:
1852 x_cp_put_word (dst, bdata[0] | (val << (16 - offset)));
1853 break;
1854 case 3:
1855 x_cp_put_word (dst, bdata[0] | (val >> (offset - 16)));
1856 x_cp_put_byte (dst + 2, bdata[1] | (val << (24 - offset)));
1857 break;
1858 case 4:
1859 x_cp_put_long (dst, bdata[0] | (val << (32 - offset)));
1860 break;
1861 case 5:
1862 x_cp_put_long (dst, bdata[0] | (val >> (offset - 32)));
1863 x_cp_put_byte (dst + 4, bdata[1] | (val << (40 - offset)));
1864 break;
1865 default:
1866 write_log (_T("x_put_bitfield() can't happen %d\n"), (offset + 7) >> 3);
1867 break;
1868 }
1869 }
1870
get_disp_ea_020(uae_u32 base,int idx)1871 uae_u32 REGPARAM2 get_disp_ea_020 (uae_u32 base, int idx)
1872 {
1873 uae_u16 dp = next_iword ();
1874 int reg = (dp >> 12) & 15;
1875 uae_s32 regd = regs.regs[reg];
1876 if ((dp & 0x800) == 0)
1877 regd = (uae_s32)(uae_s16)regd;
1878 regd <<= (dp >> 9) & 3;
1879 if (dp & 0x100) {
1880 uae_s32 outer = 0;
1881 if (dp & 0x80) base = 0;
1882 if (dp & 0x40) regd = 0;
1883
1884 if ((dp & 0x30) == 0x20)
1885 base += (uae_s32)(uae_s16) next_iword ();
1886 if ((dp & 0x30) == 0x30)
1887 base += next_ilong ();
1888
1889 if ((dp & 0x3) == 0x2)
1890 outer = (uae_s32)(uae_s16) next_iword ();
1891 if ((dp & 0x3) == 0x3)
1892 outer = next_ilong ();
1893
1894 if ((dp & 0x4) == 0)
1895 base += regd;
1896 if (dp & 0x3)
1897 base = get_long (base);
1898 if (dp & 0x4)
1899 base += regd;
1900
1901 return base + outer;
1902 } else {
1903 return base + (uae_s32)((uae_s8)dp) + regd;
1904 }
1905 }
1906
x_get_disp_ea_020(uae_u32 base,int idx)1907 uae_u32 REGPARAM2 x_get_disp_ea_020 (uae_u32 base, int idx)
1908 {
1909 uae_u16 dp = x_next_iword ();
1910 int reg = (dp >> 12) & 15;
1911 int cycles = 0;
1912 uae_u32 v;
1913
1914 uae_s32 regd = regs.regs[reg];
1915 if ((dp & 0x800) == 0)
1916 regd = (uae_s32)(uae_s16)regd;
1917 regd <<= (dp >> 9) & 3;
1918 if (dp & 0x100) {
1919 uae_s32 outer = 0;
1920 if (dp & 0x80)
1921 base = 0;
1922 if (dp & 0x40)
1923 regd = 0;
1924
1925 if ((dp & 0x30) == 0x20) {
1926 base += (uae_s32)(uae_s16) x_next_iword ();
1927 cycles++;
1928 }
1929 if ((dp & 0x30) == 0x30) {
1930 base += x_next_ilong ();
1931 cycles++;
1932 }
1933
1934 if ((dp & 0x3) == 0x2) {
1935 outer = (uae_s32)(uae_s16) x_next_iword ();
1936 cycles++;
1937 }
1938 if ((dp & 0x3) == 0x3) {
1939 outer = x_next_ilong ();
1940 cycles++;
1941 }
1942
1943 if ((dp & 0x4) == 0) {
1944 base += regd;
1945 cycles++;
1946 }
1947 if (dp & 0x3) {
1948 base = x_get_long (base);
1949 cycles++;
1950 }
1951 if (dp & 0x4) {
1952 base += regd;
1953 cycles++;
1954 }
1955 v = base + outer;
1956 } else {
1957 v = base + (uae_s32)((uae_s8)dp) + regd;
1958 }
1959 if (cycles && currprefs.cpu_cycle_exact)
1960 x_do_cycles (cycles * cpucycleunit);
1961 return v;
1962 }
1963
1964
x_get_disp_ea_ce020(uae_u32 base,int idx)1965 uae_u32 REGPARAM2 x_get_disp_ea_ce020 (uae_u32 base, int idx)
1966 {
1967 uae_u16 dp = next_iword_020ce ();
1968 int reg = (dp >> 12) & 15;
1969 int cycles = 0;
1970 uae_u32 v;
1971
1972 uae_s32 regd = regs.regs[reg];
1973 if ((dp & 0x800) == 0)
1974 regd = (uae_s32)(uae_s16)regd;
1975 regd <<= (dp >> 9) & 3;
1976 if (dp & 0x100) {
1977 uae_s32 outer = 0;
1978 if (dp & 0x80)
1979 base = 0;
1980 if (dp & 0x40)
1981 regd = 0;
1982
1983 if ((dp & 0x30) == 0x20) {
1984 base += (uae_s32)(uae_s16) next_iword_020ce ();
1985 cycles++;
1986 }
1987 if ((dp & 0x30) == 0x30) {
1988 base += next_ilong_020ce ();
1989 cycles++;
1990 }
1991
1992 if ((dp & 0x3) == 0x2) {
1993 outer = (uae_s32)(uae_s16) next_iword_020ce ();
1994 cycles++;
1995 }
1996 if ((dp & 0x3) == 0x3) {
1997 outer = next_ilong_020ce ();
1998 cycles++;
1999 }
2000
2001 if ((dp & 0x4) == 0) {
2002 base += regd;
2003 cycles++;
2004 }
2005 if (dp & 0x3) {
2006 base = x_get_long (base);
2007 cycles++;
2008 }
2009 if (dp & 0x4) {
2010 base += regd;
2011 cycles++;
2012 }
2013 v = base + outer;
2014 } else {
2015 v = base + (uae_s32)((uae_s8)dp) + regd;
2016 }
2017 if (cycles && currprefs.cpu_cycle_exact)
2018 x_do_cycles (cycles * cpucycleunit);
2019 return v;
2020 }
2021
in_rom(uaecptr pc)2022 STATIC_INLINE int in_rom (uaecptr pc)
2023 {
2024 return (munge24 (pc) & 0xFFF80000) == 0xF80000;
2025 }
2026
in_rtarea(uaecptr pc)2027 STATIC_INLINE int in_rtarea (uaecptr pc)
2028 {
2029 return (munge24 (pc) & 0xFFFF0000) == rtarea_base && uae_boot_rom;
2030 }
2031
MakeSR(void)2032 void REGPARAM2 MakeSR (void)
2033 {
2034 regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
2035 | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
2036 | (GET_XFLG () << 4) | (GET_NFLG () << 3)
2037 | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
2038 | GET_CFLG ());
2039 }
2040
SetSR(uae_u16 sr)2041 void SetSR (uae_u16 sr)
2042 {
2043 regs.sr &= 0xff00;
2044 regs.sr |= sr;
2045
2046 SET_XFLG ((regs.sr >> 4) & 1);
2047 SET_NFLG ((regs.sr >> 3) & 1);
2048 SET_ZFLG ((regs.sr >> 2) & 1);
2049 SET_VFLG ((regs.sr >> 1) & 1);
2050 SET_CFLG (regs.sr & 1);
2051 }
2052
MakeFromSR(void)2053 void REGPARAM2 MakeFromSR (void)
2054 {
2055 int oldm = regs.m;
2056 int olds = regs.s;
2057
2058 if (currprefs.cpu_cycle_exact && currprefs.cpu_model >= 68020) {
2059 x_do_cycles (6 * CYCLE_UNIT);
2060 regs.ce020memcycles = 0;
2061 }
2062
2063 SET_XFLG ((regs.sr >> 4) & 1);
2064 SET_NFLG ((regs.sr >> 3) & 1);
2065 SET_ZFLG ((regs.sr >> 2) & 1);
2066 SET_VFLG ((regs.sr >> 1) & 1);
2067 SET_CFLG (regs.sr & 1);
2068 if (regs.t1 == ((regs.sr >> 15) & 1) &&
2069 regs.t0 == ((regs.sr >> 14) & 1) &&
2070 regs.s == ((regs.sr >> 13) & 1) &&
2071 regs.m == ((regs.sr >> 12) & 1) &&
2072 regs.intmask == ((regs.sr >> 8) & 7))
2073 return;
2074 regs.t1 = (regs.sr >> 15) & 1;
2075 regs.t0 = (regs.sr >> 14) & 1;
2076 regs.s = (regs.sr >> 13) & 1;
2077 regs.m = (regs.sr >> 12) & 1;
2078 regs.intmask = (regs.sr >> 8) & 7;
2079 if (currprefs.cpu_model >= 68020) {
2080 /* 68060 does not have MSP but does have M-bit.. */
2081 if (currprefs.cpu_model >= 68060)
2082 regs.msp = regs.isp;
2083 if (olds != regs.s) {
2084 if (olds) {
2085 if (oldm)
2086 regs.msp = m68k_areg (regs, 7);
2087 else
2088 regs.isp = m68k_areg (regs, 7);
2089 m68k_areg (regs, 7) = regs.usp;
2090 } else {
2091 regs.usp = m68k_areg (regs, 7);
2092 m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
2093 }
2094 } else if (olds && oldm != regs.m) {
2095 if (oldm) {
2096 regs.msp = m68k_areg (regs, 7);
2097 m68k_areg (regs, 7) = regs.isp;
2098 } else {
2099 regs.isp = m68k_areg (regs, 7);
2100 m68k_areg (regs, 7) = regs.msp;
2101 }
2102 }
2103 if (currprefs.cpu_model >= 68060)
2104 regs.t0 = 0;
2105 } else {
2106 regs.t0 = regs.m = 0;
2107 if (olds != regs.s) {
2108 if (olds) {
2109 regs.isp = m68k_areg (regs, 7);
2110 m68k_areg (regs, 7) = regs.usp;
2111 } else {
2112 regs.usp = m68k_areg (regs, 7);
2113 m68k_areg (regs, 7) = regs.isp;
2114 }
2115 }
2116 }
2117 #ifdef MMUEMU
2118 if (currprefs.mmu_model)
2119 mmu_set_super (regs.s != 0);
2120 #endif
2121
2122 doint ();
2123 if (regs.t1 || regs.t0)
2124 set_special (SPCFLAG_TRACE);
2125 else
2126 /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
2127 SR-modifying instructions (including STOP). */
2128 unset_special (SPCFLAG_TRACE);
2129 }
2130
exception_trace(int nr)2131 static void exception_trace (int nr)
2132 {
2133 unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
2134 if (regs.t1 && !regs.t0) {
2135 /* trace stays pending if exception is div by zero, chk,
2136 * trapv or trap #x
2137 */
2138 if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
2139 set_special (SPCFLAG_DOTRACE);
2140 }
2141 regs.t1 = regs.t0 = regs.m = 0;
2142 }
2143
exception_debug(int nr)2144 static void exception_debug (int nr)
2145 {
2146 #ifdef DEBUGGER
2147 if (!exception_debugging)
2148 return;
2149 console_out_f (_T("Exception %d, PC=%08X\n"), nr, M68K_GETPC);
2150 #endif
2151 }
2152
2153 #ifdef CPUEMU_12
2154
2155 /* cycle-exact exception handler, 68000 only */
2156
2157 /*
2158
2159 Address/Bus Error:
2160
2161 - 6 idle cycles
2162 - write PC low word
2163 - write SR
2164 - write PC high word
2165 - write instruction word
2166 - write fault address low word
2167 - write status code
2168 - write fault address high word
2169 - 2 idle cycles
2170 - read exception address high word
2171 - read exception address low word
2172 - prefetch
2173 - 2 idle cycles
2174 - prefetch
2175
2176 Division by Zero:
2177
2178 - 6 idle cycles
2179 - write PC low word
2180 - write SR
2181 - write PC high word
2182 - read exception address high word
2183 - read exception address low word
2184 - prefetch
2185 - 2 idle cycles
2186 - prefetch
2187
2188 Traps:
2189
2190 - 2 idle cycles
2191 - write PC low word
2192 - write SR
2193 - write PC high word
2194 - read exception address high word
2195 - read exception address low word
2196 - prefetch
2197 - 2 idle cycles
2198 - prefetch
2199
2200 TrapV:
2201
2202 - write PC low word
2203 - write SR
2204 - write PC high word
2205 - read exception address high word
2206 - read exception address low word
2207 - prefetch
2208 - 2 idle cycles
2209 - prefetch
2210
2211 CHK:
2212
2213 - 6 idle cycles
2214 - write PC low word
2215 - write SR
2216 - write PC high word
2217 - read exception address high word
2218 - read exception address low word
2219 - prefetch
2220 - 2 idle cycles
2221 - prefetch
2222
2223 Illegal Instruction:
2224
2225 - 2 idle cycles
2226 - write PC low word
2227 - write SR
2228 - write PC high word
2229 - read exception address high word
2230 - read exception address low word
2231 - prefetch
2232 - 2 idle cycles
2233 - prefetch
2234
2235 Interrupt cycle diagram:
2236
2237 - 6 idle cycles
2238 - write PC low word
2239 - read exception number byte from (0xfffff1 | (interrupt number << 1))
2240 - 4 idle cycles
2241 - write SR
2242 - write PC high word
2243 - read exception address high word
2244 - read exception address low word
2245 - prefetch
2246 - 2 idle cycles
2247 - prefetch
2248
2249 */
2250
Exception_ce000(int nr)2251 static void Exception_ce000 (int nr)
2252 {
2253 uae_u32 currpc = m68k_getpc (), newpc;
2254 int sv = regs.s;
2255 int start, interrupt;
2256
2257 start = 6;
2258 if (nr == 7) // TRAPV
2259 start = 0;
2260 else if (nr >= 32 && nr < 32 + 16) // TRAP #x
2261 start = 2;
2262 else if (nr == 4 || nr == 8) // ILLG & PRIVIL VIOL
2263 start = 2;
2264 interrupt = nr >= 24 && nr < 24 + 8;
2265
2266 if (start)
2267 x_do_cycles (start * cpucycleunit);
2268
2269 exception_debug (nr);
2270 MakeSR ();
2271
2272 if (!regs.s) {
2273 regs.usp = m68k_areg (regs, 7);
2274 m68k_areg (regs, 7) = regs.isp;
2275 regs.s = 1;
2276 }
2277 if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */
2278 uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2279 mode |= last_writeaccess_for_exception_3 ? 0 : 16;
2280 m68k_areg (regs, 7) -= 14;
2281 /* fixme: bit3=I/N */
2282 x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
2283 x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
2284 x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
2285 x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
2286 x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
2287 x_put_word (m68k_areg (regs, 7) + 0, mode);
2288 x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
2289 x_do_cycles (2 * cpucycleunit);
2290 write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_addr_for_exception_3, currpc, get_long (4 * nr));
2291 goto kludge_me_do;
2292 }
2293 m68k_areg (regs, 7) -= 6;
2294 x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
2295 if (interrupt) {
2296 // fetch interrupt vector number
2297 nr = x_get_byte (0x00fffff1 | ((nr - 24) << 1));
2298 x_do_cycles (4 * cpucycleunit);
2299 }
2300 x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
2301 x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
2302 kludge_me_do:
2303 newpc = x_get_word (4 * nr) << 16; // read high address
2304 newpc |= x_get_word (4 * nr + 2); // read low address
2305 if (newpc & 1) {
2306 if (nr == 2 || nr == 3)
2307 cpu_halt (2);
2308 else
2309 exception3 (regs.ir, newpc);
2310 return;
2311 }
2312 m68k_setpc (newpc);
2313 regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
2314 x_do_cycles (2 * cpucycleunit);
2315 regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2
2316 #ifdef JIT
2317 set_special (SPCFLAG_END_COMPILE);
2318 #endif
2319 exception_trace (nr);
2320 }
2321 #endif
2322
exception_pc(int nr)2323 static uae_u32 exception_pc (int nr)
2324 {
2325 // zero divide, chk, trapcc/trapv, trace, trap#
2326 if (nr == 5 || nr == 6 || nr == 7 || nr == 9 || (nr >= 32 && nr <= 47))
2327 return m68k_getpc ();
2328 return regs.instruction_pc;
2329 }
2330
2331
Exception_build_stack_frame(uae_u32 oldpc,uae_u32 currpc,uae_u32 ssw,int nr,int format)2332 static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
2333 {
2334 int i;
2335
2336 #if 0
2337 if (nr < 24 || nr > 31) { // do not print debugging for interrupts
2338 write_log(_T("Building exception stack frame (format %X)\n"), format);
2339 }
2340 #endif
2341
2342 switch (format) {
2343 case 0x0: // four word stack frame
2344 case 0x1: // throwaway four word stack frame
2345 break;
2346 case 0x2: // six word stack frame
2347 m68k_areg (regs, 7) -= 4;
2348 x_put_long (m68k_areg (regs, 7), oldpc);
2349 break;
2350 case 0x7: // access error stack frame (68040)
2351 for (i = 0 ; i < 7 ; i++) {
2352 m68k_areg (regs, 7) -= 4;
2353 x_put_long (m68k_areg (regs, 7), 0);
2354 }
2355 m68k_areg (regs, 7) -= 4;
2356 x_put_long (m68k_areg (regs, 7), regs.wb3_data);
2357 m68k_areg (regs, 7) -= 4;
2358 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2359 m68k_areg (regs, 7) -= 4;
2360 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2361 m68k_areg (regs, 7) -= 2;
2362 x_put_word (m68k_areg (regs, 7), 0);
2363 m68k_areg (regs, 7) -= 2;
2364 x_put_word (m68k_areg (regs, 7), 0);
2365 m68k_areg (regs, 7) -= 2;
2366 x_put_word (m68k_areg (regs, 7), regs.wb3_status);
2367 regs.wb3_status = 0;
2368 m68k_areg (regs, 7) -= 2;
2369 x_put_word (m68k_areg (regs, 7), ssw);
2370 m68k_areg (regs, 7) -= 4;
2371 x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
2372 break;
2373 case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
2374 m68k_areg (regs, 7) -= 4;
2375 x_put_long (m68k_areg (regs, 7), 0);
2376 m68k_areg (regs, 7) -= 4;
2377 x_put_long (m68k_areg (regs, 7), 0);
2378 m68k_areg (regs, 7) -= 4;
2379 x_put_long (m68k_areg (regs, 7), oldpc);
2380 break;
2381 case 0x3: // floating point post-instruction stack frame (68040)
2382 case 0x8: // bus and address error stack frame (68010)
2383 write_log(_T("Exception stack frame format %X not implemented\n"), format);
2384 return;
2385 case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
2386 // or 68060 bus access fault stack frame
2387 if (currprefs.cpu_model == 68040) {
2388 // this is actually created in fpp.c
2389 write_log(_T("Exception stack frame format %X not implemented\n"), format);
2390 return;
2391 }
2392 // 68060 bus access fault
2393 m68k_areg (regs, 7) -= 4;
2394 x_put_long (m68k_areg (regs, 7), regs.mmu_fslw);
2395 m68k_areg (regs, 7) -= 4;
2396 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2397 break;
2398 case 0xB: // long bus cycle fault stack frame (68020, 68030)
2399 // We always use B frame because it is easier to emulate,
2400 // our PC always points at start of instruction but A frame assumes
2401 // it is + 2 and handling this properly is not easy.
2402 // Store state information to internal register space
2403 for (i = 0; i < mmu030_idx + 1; i++) {
2404 m68k_areg (regs, 7) -= 4;
2405 x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
2406 }
2407 while (i < 9) {
2408 m68k_areg (regs, 7) -= 4;
2409 x_put_long (m68k_areg (regs, 7), 0);
2410 i++;
2411 }
2412 // version & internal information (We store index here)
2413 m68k_areg (regs, 7) -= 2;
2414 x_put_word (m68k_areg (regs, 7), mmu030_idx);
2415 // 3* internal registers
2416 m68k_areg (regs, 7) -= 2;
2417 x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
2418 m68k_areg (regs, 7) -= 2;
2419 x_put_word (m68k_areg (regs, 7), mmu030_state[1]);
2420 m68k_areg (regs, 7) -= 2;
2421 x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
2422 // data input buffer = fault address
2423 m68k_areg (regs, 7) -= 4;
2424 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2425 // 2xinternal
2426 m68k_areg (regs, 7) -= 2;
2427 x_put_word (m68k_areg (regs, 7), 0);
2428 m68k_areg (regs, 7) -= 2;
2429 x_put_word (m68k_areg (regs, 7), 0);
2430 // stage b address
2431 m68k_areg (regs, 7) -= 4;
2432 x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
2433 // 2xinternal
2434 m68k_areg (regs, 7) -= 4;
2435 x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
2436 /* fall through */
2437 case 0xA: // short bus cycle fault stack frame (68020, 68030)
2438 m68k_areg (regs, 7) -= 4;
2439 x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
2440 m68k_areg (regs, 7) -= 4;
2441 // Data output buffer = value that was going to be written
2442 x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
2443 m68k_areg (regs, 7) -= 4;
2444 x_put_long (m68k_areg (regs, 7), mmu030_opcode); // Internal register (opcode storage)
2445 m68k_areg (regs, 7) -= 4;
2446 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
2447 m68k_areg (regs, 7) -= 2;
2448 x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage B
2449 m68k_areg (regs, 7) -= 2;
2450 x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage C
2451 m68k_areg (regs, 7) -= 2;
2452 x_put_word (m68k_areg (regs, 7), ssw);
2453 m68k_areg (regs, 7) -= 2;
2454 x_put_word (m68k_areg (regs, 7), 0); // Internal register
2455 break;
2456 default:
2457 write_log(_T("Unknown exception stack frame format: %X\n"), format);
2458 return;
2459 }
2460 m68k_areg (regs, 7) -= 2;
2461 x_put_word (m68k_areg (regs, 7), (format<<12) | (nr * 4));
2462 m68k_areg (regs, 7) -= 4;
2463 x_put_long (m68k_areg (regs, 7), currpc);
2464 m68k_areg (regs, 7) -= 2;
2465 x_put_word (m68k_areg (regs, 7), regs.sr);
2466 }
2467
2468
2469 // 68030 MMU
Exception_mmu030(int nr,uaecptr oldpc)2470 static void Exception_mmu030 (int nr, uaecptr oldpc)
2471 {
2472 uae_u32 currpc = m68k_getpc(), newpc;
2473 int sv = regs.s;
2474
2475 exception_debug(nr);
2476 MakeSR();
2477
2478 if (!regs.s) {
2479 regs.usp = m68k_areg(regs, 7);
2480 m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
2481 regs.s = 1;
2482 mmu_set_super(1);
2483 }
2484
2485 #if 0
2486 if (nr < 24 || nr > 31) { // do not print debugging for interrupts
2487 write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
2488 nr, currpc, oldpc, regs.mmu_fault_addr);
2489 }
2490 #endif
2491
2492 #if 0
2493 write_log (_T("Exception %d -> %08x\n", nr, newpc));
2494 #endif
2495
2496
2497 newpc = x_get_long (regs.vbr + 4 * nr);
2498
2499 if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
2500 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x1);
2501 } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9 || nr == 56) {
2502 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
2503 } else if (nr == 2) {
2504 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0xB);
2505 } else if (nr == 3) {
2506 regs.mmu_fault_addr = last_fault_for_exception_3;
2507 mmu030_state[0] = mmu030_state[1] = 0;
2508 mmu030_data_buffer = 0;
2509 Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr, 0xA);
2510 } else {
2511 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
2512 }
2513
2514 if (newpc & 1) {
2515 if (nr == 2 || nr == 3)
2516 cpu_halt (2);
2517 else
2518 exception3 (regs.ir, newpc);
2519 return;
2520 }
2521 m68k_setpc (newpc);
2522 #ifdef JIT
2523 set_special (SPCFLAG_END_COMPILE);
2524 #endif
2525 fill_prefetch ();
2526 exception_trace (nr);
2527 }
2528
2529 // 68040/060 MMU
Exception_mmu(int nr,uaecptr oldpc)2530 static void Exception_mmu (int nr, uaecptr oldpc)
2531 {
2532 uae_u32 currpc = m68k_getpc (), newpc;
2533 int sv = regs.s;
2534
2535 exception_debug (nr);
2536 MakeSR ();
2537
2538 if (!regs.s) {
2539 regs.usp = m68k_areg (regs, 7);
2540 if (currprefs.cpu_model == 68060) {
2541 m68k_areg (regs, 7) = regs.isp;
2542 if (nr >= 24 && nr < 32)
2543 regs.m = 0;
2544 } else if (currprefs.cpu_model >= 68020) {
2545 m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
2546 } else {
2547 m68k_areg (regs, 7) = regs.isp;
2548 }
2549 regs.s = 1;
2550 mmu_set_super (1);
2551 }
2552
2553 newpc = x_get_long (regs.vbr + 4 * nr);
2554 #if 0
2555 write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
2556 #endif
2557
2558 if (nr == 2) { // bus error
2559 //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
2560 if (currprefs.mmu_model == 68040)
2561 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
2562 else
2563 Exception_build_stack_frame(oldpc, currpc, regs.mmu_fslw, nr, 0x4);
2564 } else if (nr == 3) { // address error
2565 Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
2566 write_log (_T("Exception %d (%x) at %x -> %x! %s at %d\n"), nr, last_fault_for_exception_3, currpc, get_long (regs.vbr + 4 * nr), __FILE__, __LINE__);
2567 } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
2568 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
2569 } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
2570 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x1);
2571 } else if (nr == 61) {
2572 Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
2573 } else {
2574 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
2575 }
2576
2577 if (newpc & 1) {
2578 if (nr == 2 || nr == 3)
2579 cpu_halt (2);
2580 else
2581 exception3 (regs.ir, newpc);
2582 return;
2583 }
2584 m68k_setpc (newpc);
2585 #ifdef JIT
2586 set_special (SPCFLAG_END_COMPILE);
2587 #endif
2588 fill_prefetch ();
2589 exception_trace (nr);
2590 }
2591
2592
Exception_normal(int nr)2593 static void Exception_normal (int nr)
2594 {
2595 uae_u32 currpc, newpc;
2596 int sv = regs.s;
2597
2598 if (nr >= 24 && nr < 24 + 8 && currprefs.cpu_model <= 68010)
2599 nr = x_get_byte (0x00fffff1 | (nr << 1));
2600
2601 exception_debug (nr);
2602 MakeSR ();
2603
2604 if (!regs.s) {
2605 regs.usp = m68k_areg (regs, 7);
2606 if (currprefs.cpu_model == 68060) {
2607 m68k_areg (regs, 7) = regs.isp;
2608 if (nr >= 24 && nr < 32)
2609 regs.m = 0;
2610 } else if (currprefs.cpu_model >= 68020) {
2611 m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
2612 } else {
2613 m68k_areg (regs, 7) = regs.isp;
2614 }
2615 regs.s = 1;
2616 #ifdef MMUEMU
2617 if (currprefs.mmu_model)
2618 mmu_set_super (regs.s != 0);
2619 #endif
2620 }
2621 if (currprefs.cpu_model > 68000) {
2622 currpc = exception_pc (nr);
2623 if (nr == 2 || nr == 3) {
2624 int i;
2625 if (currprefs.cpu_model >= 68040) {
2626 if (nr == 2) {
2627 if (currprefs.mmu_model) {
2628 // 68040 mmu bus error
2629 for (i = 0 ; i < 7 ; i++) {
2630 m68k_areg (regs, 7) -= 4;
2631 x_put_long (m68k_areg (regs, 7), 0);
2632 }
2633 m68k_areg (regs, 7) -= 4;
2634 x_put_long (m68k_areg (regs, 7), regs.wb3_data);
2635 m68k_areg (regs, 7) -= 4;
2636 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2637 m68k_areg (regs, 7) -= 4;
2638 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2639 m68k_areg (regs, 7) -= 2;
2640 x_put_word (m68k_areg (regs, 7), 0);
2641 m68k_areg (regs, 7) -= 2;
2642 x_put_word (m68k_areg (regs, 7), 0);
2643 m68k_areg (regs, 7) -= 2;
2644 x_put_word (m68k_areg (regs, 7), regs.wb3_status);
2645 regs.wb3_status = 0;
2646 m68k_areg (regs, 7) -= 2;
2647 x_put_word (m68k_areg (regs, 7), regs.mmu_ssw);
2648 m68k_areg (regs, 7) -= 4;
2649 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2650
2651 m68k_areg (regs, 7) -= 2;
2652 x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4);
2653 m68k_areg (regs, 7) -= 4;
2654 x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
2655 m68k_areg (regs, 7) -= 2;
2656 x_put_word (m68k_areg (regs, 7), regs.sr);
2657 newpc = x_get_long (regs.vbr + 4 * nr);
2658 if (newpc & 1) {
2659 if (nr == 2 || nr == 3)
2660 cpu_halt (2);
2661 else
2662 exception3 (regs.ir, newpc);
2663 return;
2664 }
2665 m68k_setpc (newpc);
2666 #ifdef JIT
2667 set_special (SPCFLAG_END_COMPILE);
2668 #endif
2669 exception_trace (nr);
2670 return;
2671
2672 } else {
2673
2674 // 68040 bus error (not really, some garbage?)
2675 for (i = 0 ; i < 18 ; i++) {
2676 m68k_areg (regs, 7) -= 2;
2677 x_put_word (m68k_areg (regs, 7), 0);
2678 }
2679 m68k_areg (regs, 7) -= 4;
2680 x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2681 m68k_areg (regs, 7) -= 2;
2682 x_put_word (m68k_areg (regs, 7), 0);
2683 m68k_areg (regs, 7) -= 2;
2684 x_put_word (m68k_areg (regs, 7), 0);
2685 m68k_areg (regs, 7) -= 2;
2686 x_put_word (m68k_areg (regs, 7), 0);
2687 m68k_areg (regs, 7) -= 2;
2688 x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
2689 m68k_areg (regs, 7) -= 4;
2690 x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
2691 m68k_areg (regs, 7) -= 2;
2692 x_put_word (m68k_areg (regs, 7), 0x7000 + nr * 4);
2693 m68k_areg (regs, 7) -= 4;
2694 x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
2695 m68k_areg (regs, 7) -= 2;
2696 x_put_word (m68k_areg (regs, 7), regs.sr);
2697 goto kludge_me_do;
2698
2699 }
2700
2701 } else {
2702 m68k_areg (regs, 7) -= 4;
2703 x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2704 m68k_areg (regs, 7) -= 2;
2705 x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
2706 }
2707 } else {
2708 // 68020 address error
2709 uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2710 ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
2711 ssw |= 0x20;
2712 for (i = 0 ; i < 36; i++) {
2713 m68k_areg (regs, 7) -= 2;
2714 x_put_word (m68k_areg (regs, 7), 0);
2715 }
2716 m68k_areg (regs, 7) -= 4;
2717 x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2718 m68k_areg (regs, 7) -= 2;
2719 x_put_word (m68k_areg (regs, 7), 0);
2720 m68k_areg (regs, 7) -= 2;
2721 x_put_word (m68k_areg (regs, 7), 0);
2722 m68k_areg (regs, 7) -= 2;
2723 x_put_word (m68k_areg (regs, 7), 0);
2724 m68k_areg (regs, 7) -= 2;
2725 x_put_word (m68k_areg (regs, 7), ssw);
2726 m68k_areg (regs, 7) -= 2;
2727 x_put_word (m68k_areg (regs, 7), 0xb000 + nr * 4);
2728 }
2729 write_log (_T("Exception 20 %d (%x) at %x -> %x!\n"), nr, regs.instruction_pc, currpc, x_get_long (regs.vbr + 4*nr));
2730 } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
2731 m68k_areg (regs, 7) -= 4;
2732 x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
2733 m68k_areg (regs, 7) -= 2;
2734 x_put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
2735 } else if (regs.m && nr >= 24 && nr < 32) { /* M + Interrupt */
2736 m68k_areg (regs, 7) -= 2;
2737 x_put_word (m68k_areg (regs, 7), nr * 4);
2738 m68k_areg (regs, 7) -= 4;
2739 x_put_long (m68k_areg (regs, 7), currpc);
2740 m68k_areg (regs, 7) -= 2;
2741 x_put_word (m68k_areg (regs, 7), regs.sr);
2742 regs.sr |= (1 << 13);
2743 regs.msp = m68k_areg (regs, 7);
2744 m68k_areg (regs, 7) = regs.isp;
2745 m68k_areg (regs, 7) -= 2;
2746 x_put_word (m68k_areg (regs, 7), 0x1000 + nr * 4);
2747 } else {
2748 m68k_areg (regs, 7) -= 2;
2749 x_put_word (m68k_areg (regs, 7), nr * 4);
2750 }
2751 } else {
2752 currpc = m68k_getpc ();
2753 if (nr == 2 || nr == 3) {
2754 // 68000 address error
2755 uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2756 mode |= last_writeaccess_for_exception_3 ? 0 : 16;
2757 m68k_areg (regs, 7) -= 14;
2758 /* fixme: bit3=I/N */
2759 x_put_word (m68k_areg (regs, 7) + 0, mode);
2760 x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
2761 x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
2762 x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
2763 x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
2764 write_log (_T("Exception 00 %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, x_get_long (regs.vbr + 4*nr));
2765 goto kludge_me_do;
2766 }
2767 }
2768 m68k_areg (regs, 7) -= 4;
2769 x_put_long (m68k_areg (regs, 7), currpc);
2770 m68k_areg (regs, 7) -= 2;
2771 x_put_word (m68k_areg (regs, 7), regs.sr);
2772 kludge_me_do:
2773 newpc = x_get_long (regs.vbr + 4 * nr);
2774 if (newpc & 1) {
2775 if (nr == 2 || nr == 3)
2776 cpu_halt (2);
2777 else
2778 exception3 (regs.ir, newpc);
2779 return;
2780 }
2781 m68k_setpc (newpc);
2782 #ifdef JIT
2783 set_special (SPCFLAG_END_COMPILE);
2784 #endif
2785 fill_prefetch ();
2786 exception_trace (nr);
2787 }
2788
2789 // address = format $2 stack frame address field
ExceptionX(int nr,uaecptr address)2790 static void ExceptionX (int nr, uaecptr address)
2791 {
2792 regs.exception = nr;
2793 if (cpu_tracer) {
2794 cputrace.state = nr;
2795 }
2796
2797 #ifdef JIT
2798 if (currprefs.cachesize)
2799 regs.instruction_pc = address == (uaecptr)-1 ? m68k_getpc () : address;
2800 #endif
2801 #ifdef CPUEMU_12
2802 if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000)
2803 Exception_ce000 (nr);
2804 else
2805 #endif
2806 #ifdef MMUEMU
2807 if (currprefs.mmu_model) {
2808 if (currprefs.cpu_model == 68030)
2809 Exception_mmu030 (nr, m68k_getpc ());
2810 else
2811 Exception_mmu (nr, m68k_getpc ());
2812 } else {
2813 Exception_normal (nr);
2814 }
2815 #endif
2816
2817 if (debug_illegal && !in_rom (M68K_GETPC)) {
2818 int v = nr;
2819 if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) {
2820 write_log (_T("Exception %d breakpoint\n"), nr);
2821 activate_debugger ();
2822 }
2823 }
2824 regs.exception = 0;
2825 if (cpu_tracer) {
2826 cputrace.state = 0;
2827 }
2828 }
2829
Exception(int nr)2830 void REGPARAM2 Exception (int nr)
2831 {
2832 ExceptionX (nr, -1);
2833 }
2834
do_interrupt(int nr)2835 STATIC_INLINE void do_interrupt (int nr)
2836 {
2837 #ifdef DEBUG
2838 if (debug_dma)
2839 record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos);
2840 #endif
2841 if (inputrecord_debug & 2) {
2842 if (input_record > 0)
2843 inprec_recorddebug_cpu (2);
2844 else if (input_play > 0)
2845 inprec_playdebug_cpu (2);
2846 }
2847
2848 regs.stopped = 0;
2849 unset_special (SPCFLAG_STOP);
2850 assert (nr < 8 && nr >= 0);
2851
2852 Exception (nr + 24);
2853
2854 regs.intmask = nr;
2855 doint ();
2856 }
2857
NMI(void)2858 void NMI (void)
2859 {
2860 do_interrupt (7);
2861 }
2862
2863 #ifndef CPUEMU_68000_ONLY
2864
movec_illg(int regno)2865 int movec_illg (int regno)
2866 {
2867 int regno2 = regno & 0x7ff;
2868
2869 if (currprefs.cpu_model == 68060) {
2870 if (regno <= 8)
2871 return 0;
2872 if (regno == 0x800 || regno == 0x801 ||
2873 regno == 0x806 || regno == 0x807 || regno == 0x808)
2874 return 0;
2875 return 1;
2876 } else if (currprefs.cpu_model == 68010) {
2877 if (regno2 < 2)
2878 return 0;
2879 return 1;
2880 } else if (currprefs.cpu_model == 68020) {
2881 if (regno == 3)
2882 return 1; /* 68040/060 only */
2883 /* 4 is >=68040, but 0x804 is in 68020 */
2884 if (regno2 < 4 || regno == 0x804)
2885 return 0;
2886 return 1;
2887 } else if (currprefs.cpu_model == 68030) {
2888 if (regno2 <= 2)
2889 return 0;
2890 if (regno == 0x803 || regno == 0x804)
2891 return 0;
2892 return 1;
2893 } else if (currprefs.cpu_model == 68040) {
2894 if (regno == 0x802)
2895 return 1; /* 68020 only */
2896 if (regno2 < 8) return 0;
2897 return 1;
2898 }
2899 return 1;
2900 }
2901
m68k_move2c(int regno,uae_u32 * regp)2902 int m68k_move2c (int regno, uae_u32 *regp)
2903 {
2904 #if MOVEC_DEBUG > 0
2905 write_log (_T("move2c %04X <- %08X PC=%x\n"), regno, *regp, M68K_GETPC);
2906 #endif
2907 if (movec_illg (regno)) {
2908 op_illg (0x4E7B);
2909 return 0;
2910 } else {
2911 switch (regno) {
2912 case 0: regs.sfc = *regp & 7; break;
2913 case 1: regs.dfc = *regp & 7; break;
2914 case 2:
2915 {
2916 uae_u32 cacr_mask = 0;
2917 if (currprefs.cpu_model == 68020)
2918 cacr_mask = 0x0000000f;
2919 else if (currprefs.cpu_model == 68030)
2920 cacr_mask = 0x00003f1f;
2921 else if (currprefs.cpu_model == 68040)
2922 cacr_mask = 0x80008000;
2923 else if (currprefs.cpu_model == 68060)
2924 cacr_mask = 0xf8e0e000;
2925 regs.cacr = *regp & cacr_mask;
2926 set_cpu_caches ();
2927 }
2928 break;
2929 /* 68040/060 only */
2930 case 3:
2931 regs.tcr = *regp & (currprefs.cpu_model == 68060 ? 0xfffe : 0xc000);
2932 #ifdef MMUEMU
2933 if (currprefs.mmu_model)
2934 mmu_set_tc (regs.tcr);
2935 #endif
2936 break;
2937
2938 /* no differences between 68040 and 68060 */
2939 case 4: regs.itt0 = *regp & 0xffffe364; mmu_tt_modified (); break;
2940 case 5: regs.itt1 = *regp & 0xffffe364; mmu_tt_modified (); break;
2941 case 6: regs.dtt0 = *regp & 0xffffe364; mmu_tt_modified (); break;
2942 case 7: regs.dtt1 = *regp & 0xffffe364; mmu_tt_modified (); break;
2943 /* 68060 only */
2944 case 8: regs.buscr = *regp & 0xf0000000; break;
2945
2946 case 0x800: regs.usp = *regp; break;
2947 case 0x801: regs.vbr = *regp; break;
2948 case 0x802: regs.caar = *regp & 0xfc; break;
2949 case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (regs, 7) = regs.msp; break;
2950 case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (regs, 7) = regs.isp; break;
2951 /* 68040 only */
2952 case 0x805: regs.mmusr = *regp; break;
2953 /* 68040/060 */
2954 case 0x806: regs.urp = *regp & 0xfffffe00; break;
2955 case 0x807: regs.srp = *regp & 0xfffffe00; break;
2956 /* 68060 only */
2957 case 0x808:
2958 {
2959 uae_u32 opcr = regs.pcr;
2960 regs.pcr &= ~(0x40 | 2 | 1);
2961 regs.pcr |= (*regp) & (0x40 | 2 | 1);
2962 if (currprefs.fpu_model <= 0)
2963 regs.pcr |= 2;
2964 if (((opcr ^ regs.pcr) & 2) == 2) {
2965 write_log (_T("68060 FPU state: %s\n"), regs.pcr & 2 ? _T("disabled") : _T("enabled"));
2966 #ifdef JIT
2967 /* flush possible already translated FPU instructions */
2968 flush_icache (0, 3);
2969 #endif
2970 }
2971 }
2972 break;
2973 default:
2974 op_illg (0x4E7B);
2975 return 0;
2976 }
2977 }
2978 return 1;
2979 }
2980
m68k_movec2(int regno,uae_u32 * regp)2981 int m68k_movec2 (int regno, uae_u32 *regp)
2982 {
2983 #if MOVEC_DEBUG > 0
2984 write_log (_T("movec2 %04X PC=%x\n"), regno, M68K_GETPC);
2985 #endif
2986 if (movec_illg (regno)) {
2987 op_illg (0x4E7A);
2988 return 0;
2989 } else {
2990 switch (regno) {
2991 case 0: *regp = regs.sfc; break;
2992 case 1: *regp = regs.dfc; break;
2993 case 2:
2994 {
2995 uae_u32 v = regs.cacr;
2996 uae_u32 cacr_mask = 0;
2997 if (currprefs.cpu_model == 68020)
2998 cacr_mask = 0x00000003;
2999 else if (currprefs.cpu_model == 68030)
3000 cacr_mask = 0x00003313;
3001 else if (currprefs.cpu_model == 68040)
3002 cacr_mask = 0x80008000;
3003 else if (currprefs.cpu_model == 68060)
3004 cacr_mask = 0xf880e000;
3005 *regp = v & cacr_mask;
3006 }
3007 break;
3008 case 3: *regp = regs.tcr; break;
3009 case 4: *regp = regs.itt0; break;
3010 case 5: *regp = regs.itt1; break;
3011 case 6: *regp = regs.dtt0; break;
3012 case 7: *regp = regs.dtt1; break;
3013 case 8: *regp = regs.buscr; break;
3014
3015 case 0x800: *regp = regs.usp; break;
3016 case 0x801: *regp = regs.vbr; break;
3017 case 0x802: *regp = regs.caar; break;
3018 case 0x803: *regp = regs.m == 1 ? m68k_areg (regs, 7) : regs.msp; break;
3019 case 0x804: *regp = regs.m == 0 ? m68k_areg (regs, 7) : regs.isp; break;
3020 case 0x805: *regp = regs.mmusr; break;
3021 case 0x806: *regp = regs.urp; break;
3022 case 0x807: *regp = regs.srp; break;
3023 case 0x808: *regp = regs.pcr; break;
3024
3025 default:
3026 op_illg (0x4E7A);
3027 return 0;
3028 }
3029 }
3030 #if MOVEC_DEBUG > 0
3031 write_log (_T("-> %08X\n"), *regp);
3032 #endif
3033 return 1;
3034 }
3035
div_unsigned(uae_u32 src_hi,uae_u32 src_lo,uae_u32 div,uae_u32 * quot,uae_u32 * rem)3036 STATIC_INLINE int div_unsigned (uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
3037 {
3038 uae_u32 q = 0, cbit = 0;
3039 int i;
3040
3041 if (div <= src_hi) {
3042 return 1;
3043 }
3044 for (i = 0 ; i < 32 ; i++) {
3045 cbit = src_hi & 0x80000000ul;
3046 src_hi <<= 1;
3047 if (src_lo & 0x80000000ul) src_hi++;
3048 src_lo <<= 1;
3049 q = q << 1;
3050 if (cbit || div <= src_hi) {
3051 q |= 1;
3052 src_hi -= div;
3053 }
3054 }
3055 *quot = q;
3056 *rem = src_hi;
3057 return 0;
3058 }
3059
m68k_divl(uae_u32 opcode,uae_u32 src,uae_u16 extra)3060 void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra)
3061 {
3062 if ((extra & 0x400) && currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
3063 op_unimpl (opcode);
3064 return;
3065 }
3066 if (src == 0) {
3067 Exception (5);
3068 return;
3069 }
3070 #if defined (HAS_uae_64)
3071 if (extra & 0x800) {
3072 /* signed variant */
3073 uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
3074 uae_s64 quot, rem;
3075
3076 if (extra & 0x400) {
3077 a &= 0xffffffffu;
3078 a |= (uae_s64)m68k_dreg (regs, extra & 7) << 32;
3079 }
3080
3081 if (a == 0x8000000000000000 && src == -1) {
3082 SET_VFLG (1);
3083 SET_NFLG (1);
3084 SET_CFLG (0);
3085 } else {
3086 rem = a % (uae_s64)(uae_s32)src;
3087 quot = a / (uae_s64)(uae_s32)src;
3088 if ((quot & UVAL64 (0xffffffff80000000)) != 0
3089 && (quot & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
3090 {
3091 SET_VFLG (1);
3092 SET_NFLG (1);
3093 SET_CFLG (0);
3094 } else {
3095 if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
3096 SET_VFLG (0);
3097 SET_CFLG (0);
3098 SET_ZFLG (((uae_s32)quot) == 0);
3099 SET_NFLG (((uae_s32)quot) < 0);
3100 m68k_dreg (regs, extra & 7) = (uae_u32)rem;
3101 m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
3102 }
3103 }
3104 } else {
3105 /* unsigned */
3106 uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
3107 uae_u64 quot, rem;
3108
3109 if (extra & 0x400) {
3110 a &= 0xffffffffu;
3111 a |= (uae_u64)m68k_dreg (regs, extra & 7) << 32;
3112 }
3113 rem = a % (uae_u64)src;
3114 quot = a / (uae_u64)src;
3115 if (quot > 0xffffffffu) {
3116 SET_VFLG (1);
3117 SET_NFLG (1);
3118 SET_CFLG (0);
3119 } else {
3120 SET_VFLG (0);
3121 SET_CFLG (0);
3122 SET_ZFLG (((uae_s32)quot) == 0);
3123 SET_NFLG (((uae_s32)quot) < 0);
3124 m68k_dreg (regs, extra & 7) = (uae_u32)rem;
3125 m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)quot;
3126 }
3127 }
3128 #else
3129 if (extra & 0x800) {
3130 /* signed variant */
3131 uae_s32 lo = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
3132 uae_s32 hi = lo < 0 ? -1 : 0;
3133 uae_s32 save_high;
3134 uae_u32 quot = 0, rem = 0;
3135 uae_u32 sign;
3136
3137 if (extra & 0x400) {
3138 hi = (uae_s32)m68k_dreg (regs, extra & 7);
3139 }
3140 save_high = hi;
3141 sign = (hi ^ src);
3142 if (hi < 0) {
3143 hi = ~hi;
3144 lo = -lo;
3145 if (lo == 0) hi++;
3146 }
3147 if ((uae_s32)src < 0) src = -src;
3148 if (div_unsigned (hi, lo, src, ", &rem) ||
3149 (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
3150 SET_VFLG (1);
3151 SET_NFLG (1);
3152 SET_CFLG (0);
3153 } else {
3154 if (sign & 0x80000000) quot = -quot;
3155 if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
3156 SET_VFLG (0);
3157 SET_CFLG (0);
3158 SET_ZFLG (((uae_s32)quot) == 0);
3159 SET_NFLG (((uae_s32)quot) < 0);
3160 m68k_dreg (regs, extra & 7) = rem;
3161 m68k_dreg (regs, (extra >> 12) & 7) = quot;
3162 }
3163 } else {
3164 /* unsigned */
3165 uae_u32 lo = (uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
3166 uae_u32 hi = 0;
3167 uae_u32 quot, rem;
3168
3169 if (extra & 0x400) {
3170 hi = (uae_u32)m68k_dreg (regs, extra & 7);
3171 }
3172 if (div_unsigned (hi, lo, src, ", &rem)) {
3173 SET_VFLG (1);
3174 SET_NFLG (1);
3175 SET_CFLG (0);
3176 } else {
3177 SET_VFLG (0);
3178 SET_CFLG (0);
3179 SET_ZFLG (((uae_s32)quot) == 0);
3180 SET_NFLG (((uae_s32)quot) < 0);
3181 m68k_dreg (regs, extra & 7) = rem;
3182 m68k_dreg (regs, (extra >> 12) & 7) = quot;
3183 }
3184 }
3185 #endif
3186 }
3187
mul_unsigned(uae_u32 src1,uae_u32 src2,uae_u32 * dst_hi,uae_u32 * dst_lo)3188 STATIC_INLINE void mul_unsigned (uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
3189 {
3190 uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
3191 uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
3192 uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
3193 uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
3194 uae_u32 lo;
3195
3196 lo = r0 + ((r1 << 16) & 0xffff0000ul);
3197 if (lo < r0) r3++;
3198 r0 = lo;
3199 lo = r0 + ((r2 << 16) & 0xffff0000ul);
3200 if (lo < r0) r3++;
3201 r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
3202 *dst_lo = lo;
3203 *dst_hi = r3;
3204 }
3205
m68k_mull(uae_u32 opcode,uae_u32 src,uae_u16 extra)3206 void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
3207 {
3208 if ((extra & 0x400) && currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
3209 op_unimpl (opcode);
3210 return;
3211 }
3212 #if defined (HAS_uae_64)
3213 if (extra & 0x800) {
3214 /* signed variant */
3215 uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
3216
3217 a *= (uae_s64)(uae_s32)src;
3218 SET_VFLG (0);
3219 SET_CFLG (0);
3220 SET_ZFLG (a == 0);
3221 SET_NFLG (a < 0);
3222 if (extra & 0x400)
3223 m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
3224 else if ((a & UVAL64 (0xffffffff80000000)) != 0
3225 && (a & UVAL64 (0xffffffff80000000)) != UVAL64 (0xffffffff80000000))
3226 {
3227 SET_VFLG (1);
3228 }
3229 m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
3230 } else {
3231 /* unsigned */
3232 uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (regs, (extra >> 12) & 7);
3233
3234 a *= (uae_u64)src;
3235 SET_VFLG (0);
3236 SET_CFLG (0);
3237 SET_ZFLG (a == 0);
3238 SET_NFLG (((uae_s64)a) < 0);
3239 if (extra & 0x400)
3240 m68k_dreg (regs, extra & 7) = (uae_u32)(a >> 32);
3241 else if ((a & UVAL64 (0xffffffff00000000)) != 0) {
3242 SET_VFLG (1);
3243 }
3244 m68k_dreg (regs, (extra >> 12) & 7) = (uae_u32)a;
3245 }
3246 #else
3247 if (extra & 0x800) {
3248 /* signed variant */
3249 uae_s32 src1, src2;
3250 uae_u32 dst_lo, dst_hi;
3251 uae_u32 sign;
3252
3253 src1 = (uae_s32)src;
3254 src2 = (uae_s32)m68k_dreg (regs, (extra >> 12) & 7);
3255 sign = (src1 ^ src2);
3256 if (src1 < 0) src1 = -src1;
3257 if (src2 < 0) src2 = -src2;
3258 mul_unsigned ((uae_u32)src1, (uae_u32)src2, &dst_hi, &dst_lo);
3259 if (sign & 0x80000000) {
3260 dst_hi = ~dst_hi;
3261 dst_lo = -dst_lo;
3262 if (dst_lo == 0) dst_hi++;
3263 }
3264 SET_VFLG (0);
3265 SET_CFLG (0);
3266 SET_ZFLG (dst_hi == 0 && dst_lo == 0);
3267 SET_NFLG (((uae_s32)dst_hi) < 0);
3268 if (extra & 0x400)
3269 m68k_dreg (regs, extra & 7) = dst_hi;
3270 else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
3271 && ((dst_hi & 0xffffffff) != 0xffffffff
3272 || (dst_lo & 0x80000000) != 0x80000000))
3273 {
3274 SET_VFLG (1);
3275 }
3276 m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
3277 } else {
3278 /* unsigned */
3279 uae_u32 dst_lo, dst_hi;
3280
3281 mul_unsigned (src, (uae_u32)m68k_dreg (regs, (extra >> 12) & 7), &dst_hi, &dst_lo);
3282
3283 SET_VFLG (0);
3284 SET_CFLG (0);
3285 SET_ZFLG (dst_hi == 0 && dst_lo == 0);
3286 SET_NFLG (((uae_s32)dst_hi) < 0);
3287 if (extra & 0x400)
3288 m68k_dreg (regs, extra & 7) = dst_hi;
3289 else if (dst_hi != 0) {
3290 SET_VFLG (1);
3291 }
3292 m68k_dreg (regs, (extra >> 12) & 7) = dst_lo;
3293 }
3294 #endif
3295 }
3296
3297 #endif
3298
m68k_reset(bool hardreset)3299 static void m68k_reset (bool hardreset)
3300 {
3301 regs.spcflags = 0;
3302 regs.ipl = regs.ipl_pin = 0;
3303 #ifdef SAVESTATE
3304 if (isrestore ()) {
3305 m68k_setpc (regs.pc);
3306 SET_XFLG ((regs.sr >> 4) & 1);
3307 SET_NFLG ((regs.sr >> 3) & 1);
3308 SET_ZFLG ((regs.sr >> 2) & 1);
3309 SET_VFLG ((regs.sr >> 1) & 1);
3310 SET_CFLG (regs.sr & 1);
3311 regs.t1 = (regs.sr >> 15) & 1;
3312 regs.t0 = (regs.sr >> 14) & 1;
3313 regs.s = (regs.sr >> 13) & 1;
3314 regs.m = (regs.sr >> 12) & 1;
3315 regs.intmask = (regs.sr >> 8) & 7;
3316 /* set stack pointer */
3317 if (regs.s)
3318 m68k_areg (regs, 7) = regs.isp;
3319 else
3320 m68k_areg (regs, 7) = regs.usp;
3321 return;
3322 }
3323 #endif
3324 m68k_areg (regs, 7) = get_long (0);
3325 m68k_setpc (get_long (4));
3326 regs.s = 1;
3327 regs.m = 0;
3328 regs.stopped = 0;
3329 regs.t1 = 0;
3330 regs.t0 = 0;
3331 SET_ZFLG (0);
3332 SET_XFLG (0);
3333 SET_CFLG (0);
3334 SET_VFLG (0);
3335 SET_NFLG (0);
3336 regs.intmask = 7;
3337 regs.vbr = regs.sfc = regs.dfc = 0;
3338 regs.irc = 0xffff;
3339 #ifdef FPUEMU
3340 fpu_reset ();
3341 #endif
3342 regs.caar = regs.cacr = 0;
3343 regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
3344 regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
3345 mmu_tt_modified ();
3346 if (currprefs.cpu_model == 68020) {
3347 regs.cacr |= 8;
3348 set_cpu_caches ();
3349 }
3350
3351 #ifdef MMUEMU
3352 mmufixup[0].reg = -1;
3353 mmufixup[1].reg = -1;
3354 if (currprefs.mmu_model >= 68040) {
3355 mmu_reset ();
3356 mmu_set_tc (regs.tcr);
3357 mmu_set_super (regs.s != 0);
3358 } else if (currprefs.mmu_model == 68030) {
3359 mmu030_reset (hardreset || regs.halted);
3360 } else {
3361 a3000_fakekick (0);
3362 /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
3363 fake_tc_030 &= ~0x80000000;
3364 fake_tt0_030 &= ~0x80000000;
3365 fake_tt1_030 &= ~0x80000000;
3366 if (hardreset || regs.halted) {
3367 fake_srp_030 = fake_crp_030 = 0;
3368 fake_tt0_030 = fake_tt1_030 = fake_tc_030 = 0;
3369 }
3370 fake_mmusr_030 = 0;
3371 }
3372 #endif
3373
3374 regs.halted = 0;
3375 gui_data.cpu_halted = false;
3376 gui_led (LED_CPU, 0);
3377
3378 /* 68060 FPU is not compatible with 68040,
3379 * 68060 accelerators' boot ROM disables the FPU
3380 */
3381 regs.pcr = 0;
3382 if (currprefs.cpu_model == 68060) {
3383 regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
3384 regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
3385 if (kickstart_rom)
3386 regs.pcr |= 2; /* disable FPU */
3387 }
3388 regs.ce020tmpcycles = MAX68020CYCLES;
3389 regs.ce020memcycles = 0;
3390 fill_prefetch_quick ();
3391 }
3392
op_unimpl(uae_u16 opcode)3393 void REGPARAM2 op_unimpl (uae_u16 opcode)
3394 {
3395 static int warned;
3396 if (warned < 20) {
3397 write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
3398 warned++;
3399 }
3400 ExceptionX (61, regs.instruction_pc);
3401 }
3402
op_illg(uae_u32 opcode)3403 uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
3404 {
3405 uaecptr pc = m68k_getpc ();
3406 static int warned;
3407 int inrom = in_rom (pc);
3408 int inrt = in_rtarea (pc);
3409
3410 if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
3411 m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
3412 m68k_incpc (2);
3413 fill_prefetch ();
3414 return 4;
3415 }
3416
3417 if (opcode == 0x4E7B && inrom && get_long (0x10) == 0) {
3418 notify_user (NUMSG_KS68020);
3419 uae_restart (-1, NULL);
3420 }
3421
3422 #ifdef AUTOCONFIG
3423 if (opcode == 0xFF0D && inrt) {
3424 /* User-mode STOP replacement */
3425 m68k_setstopped ();
3426 return 4;
3427 }
3428
3429 if ((opcode & 0xF000) == 0xA000 && inrt) {
3430 /* Calltrap. */
3431 m68k_incpc (2);
3432 m68k_handle_trap (opcode & 0xFFF);
3433 fill_prefetch ();
3434 return 4;
3435 }
3436 #endif
3437
3438 if ((opcode & 0xF000) == 0xF000) {
3439 if (warned < 20) {
3440 write_log (_T("B-Trap %x at %x (%p)\n"), opcode, pc, regs.pc_p);
3441 warned++;
3442 }
3443 Exception (0xB);
3444 //activate_debugger ();
3445 return 4;
3446 }
3447 if ((opcode & 0xF000) == 0xA000) {
3448 if (warned < 20) {
3449 write_log (_T("A-Trap %x at %x (%p)\n"), opcode, pc, regs.pc_p);
3450 warned++;
3451 }
3452 Exception (0xA);
3453 //activate_debugger();
3454 return 4;
3455 }
3456 if (warned < 20) {
3457 write_log (_T("Illegal instruction: %04x at %08X -> %08X\n"), opcode, pc, get_long (regs.vbr + 0x10));
3458 warned++;
3459 //activate_debugger();
3460 }
3461
3462 Exception (4);
3463 return 4;
3464 }
3465
3466 #ifdef CPUEMU_0
3467
3468 static TCHAR *mmu30regs[] = { _T("TCR"), _T(""), _T("SRP"), _T("CRP"), _T(""), _T(""), _T(""), _T("") };
3469
mmu_op30fake_pmove(uaecptr pc,uae_u32 opcode,uae_u16 next,uaecptr extra)3470 static void mmu_op30fake_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
3471 {
3472 int mode = (opcode >> 3) & 7;
3473 int preg = (next >> 10) & 31;
3474 int rw = (next >> 9) & 1;
3475 int fd = (next >> 8) & 1;
3476 TCHAR *reg = NULL;
3477 uae_u32 otc = fake_tc_030;
3478 int siz;
3479
3480 // Dn, An, (An)+, -(An), abs and indirect
3481 if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode >= 6) {
3482 op_illg (opcode);
3483 return;
3484 }
3485
3486 switch (preg)
3487 {
3488 case 0x10: // TC
3489 reg = _T("TC");
3490 siz = 4;
3491 if (rw)
3492 x_put_long (extra, fake_tc_030);
3493 else
3494 fake_tc_030 = x_get_long (extra);
3495 break;
3496 case 0x12: // SRP
3497 reg = _T("SRP");
3498 siz = 8;
3499 if (rw) {
3500 x_put_long (extra, fake_srp_030 >> 32);
3501 x_put_long (extra + 4, fake_srp_030);
3502 } else {
3503 fake_srp_030 = (uae_u64)x_get_long (extra) << 32;
3504 fake_srp_030 |= x_get_long (extra + 4);
3505 }
3506 break;
3507 case 0x13: // CRP
3508 reg = _T("CRP");
3509 siz = 8;
3510 if (rw) {
3511 x_put_long (extra, fake_crp_030 >> 32);
3512 x_put_long (extra + 4, fake_crp_030);
3513 } else {
3514 fake_crp_030 = (uae_u64)x_get_long (extra) << 32;
3515 fake_crp_030 |= x_get_long (extra + 4);
3516 }
3517 break;
3518 case 0x18: // MMUSR
3519 reg = _T("MMUSR");
3520 siz = 2;
3521 if (rw)
3522 x_put_word (extra, fake_mmusr_030);
3523 else
3524 fake_mmusr_030 = x_get_word (extra);
3525 break;
3526 case 0x02: // TT0
3527 reg = _T("TT0");
3528 siz = 4;
3529 if (rw)
3530 x_put_long (extra, fake_tt0_030);
3531 else
3532 fake_tt0_030 = x_get_long (extra);
3533 break;
3534 case 0x03: // TT1
3535 reg = _T("TT1");
3536 siz = 4;
3537 if (rw)
3538 x_put_long (extra, fake_tt1_030);
3539 else
3540 fake_tt1_030 = x_get_long (extra);
3541 break;
3542 }
3543
3544 if (!reg) {
3545 op_illg (opcode);
3546 return;
3547 }
3548 #if MMUOP_DEBUG > 0
3549 {
3550 uae_u32 val;
3551 if (siz == 8) {
3552 uae_u32 val2 = x_get_long (extra);
3553 val = x_get_long (extra + 4);
3554 if (rw)
3555 write_log (_T("PMOVE %s,%08X%08X"), reg, val2, val);
3556 else
3557 write_log (_T("PMOVE %08X%08X,%s"), val2, val, reg);
3558 } else {
3559 if (siz == 4)
3560 val = x_get_long (extra);
3561 else
3562 val = x_get_word (extra);
3563 if (rw)
3564 write_log (_T("PMOVE %s,%08X"), reg, val);
3565 else
3566 write_log (_T("PMOVE %08X,%s"), val, reg);
3567 }
3568 write_log (_T(" PC=%08X\n"), pc);
3569 }
3570 #endif
3571 if (currprefs.cs_mbdmac == 1 && currprefs.mbresmem_low_size > 0) {
3572 if (otc != fake_tc_030) {
3573 a3000_fakekick (fake_tc_030 & 0x80000000);
3574 }
3575 }
3576 }
3577
mmu_op30fake_ptest(uaecptr pc,uae_u32 opcode,uae_u16 next,uaecptr extra)3578 static void mmu_op30fake_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
3579 {
3580 #if MMUOP_DEBUG > 0
3581 TCHAR tmp[10];
3582
3583 tmp[0] = 0;
3584 if ((next >> 8) & 1)
3585 _stprintf (tmp, _T(",A%d"), (next >> 4) & 15);
3586 write_log (_T("PTEST%c %02X,%08X,#%X%s PC=%08X\n"),
3587 ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc);
3588 #endif
3589 fake_mmusr_030 = 0;
3590 }
3591
mmu_op30fake_pflush(uaecptr pc,uae_u32 opcode,uae_u16 next,uaecptr extra)3592 static void mmu_op30fake_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
3593 {
3594 int mode = (opcode >> 3) & 7;
3595 int reg = opcode & 7;
3596 int flushmode = (next >> 10) & 7;
3597 int fc = next & 31;
3598 int mask = (next >> 5) & 3;
3599 TCHAR fname[100];
3600
3601 switch (flushmode)
3602 {
3603 case 6:
3604 // Dn, An, (An)+, -(An), abs and indirect
3605 if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode >= 6) {
3606 op_illg (opcode);
3607 return;
3608 }
3609 _stprintf (fname, _T("FC=%x MASK=%x EA=%08x"), fc, mask, 0);
3610 break;
3611 case 4:
3612 _stprintf (fname, _T("FC=%x MASK=%x"), fc, mask);
3613 break;
3614 case 1:
3615 _tcscpy (fname, _T("ALL"));
3616 break;
3617 default:
3618 op_illg (opcode);
3619 return;
3620 }
3621 #if MMUOP_DEBUG > 0
3622 write_log (_T("PFLUSH %s PC=%08X\n"), fname, pc);
3623 #endif
3624 }
3625
3626 // 68030 (68851) MMU instructions only
mmu_op30(uaecptr pc,uae_u32 opcode,uae_u16 extra,uaecptr extraa)3627 void mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
3628 {
3629 if (currprefs.mmu_model) {
3630 if (extra & 0x8000)
3631 mmu_op30_ptest (pc, opcode, extra, extraa);
3632 else if ((extra&0xE000)==0x2000 && (extra & 0x1C00))
3633 mmu_op30_pflush (pc, opcode, extra, extraa);
3634 else if ((extra&0xE000)==0x2000 && !(extra & 0x1C00))
3635 mmu_op30_pload (pc, opcode, extra, extraa);
3636 else
3637 mmu_op30_pmove (pc, opcode, extra, extraa);
3638 return;
3639 }
3640
3641 int type = extra >> 13;
3642
3643 switch (type)
3644 {
3645 case 0:
3646 case 2:
3647 case 3:
3648 mmu_op30fake_pmove (pc, opcode, extra, extraa);
3649 break;
3650 case 1:
3651 mmu_op30fake_pflush (pc, opcode, extra, extraa);
3652 break;
3653 case 4:
3654 mmu_op30fake_ptest (pc, opcode, extra, extraa);
3655 break;
3656 default:
3657 op_illg (opcode);
3658 break;
3659 }
3660 }
3661
3662 // 68040+ MMU instructions only
mmu_op(uae_u32 opcode,uae_u32 extra)3663 void mmu_op (uae_u32 opcode, uae_u32 extra)
3664 {
3665 #ifdef MMUEMU
3666 if (currprefs.mmu_model) {
3667 mmu_op_real (opcode, extra);
3668 return;
3669 }
3670 #endif
3671 #if MMUOP_DEBUG > 1
3672 write_log (_T("mmu_op %04X PC=%08X\n"), opcode, m68k_getpc ());
3673 #endif
3674 if ((opcode & 0xFE0) == 0x0500) {
3675 /* PFLUSH */
3676 regs.mmusr = 0;
3677 #if MMUOP_DEBUG > 0
3678 write_log (_T("PFLUSH\n"));
3679 #endif
3680 return;
3681 } else if ((opcode & 0x0FD8) == 0x548) {
3682 if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
3683 /* PTEST */
3684 #if MMUOP_DEBUG > 0
3685 write_log (_T("PTEST\n"));
3686 #endif
3687 return;
3688 }
3689 } else if ((opcode & 0x0FB8) == 0x588) {
3690 /* PLPA */
3691 if (currprefs.cpu_model == 68060) {
3692 #if MMUOP_DEBUG > 0
3693 write_log (_T("PLPA\n"));
3694 #endif
3695 return;
3696 }
3697 }
3698 #if MMUOP_DEBUG > 0
3699 write_log (_T("Unknown MMU OP %04X\n"), opcode);
3700 #endif
3701 m68k_setpc (m68k_getpc () - 2);
3702 op_illg (opcode);
3703 }
3704
3705 #endif
3706
3707 static uaecptr last_trace_ad = 0;
3708
do_trace(void)3709 static void do_trace (void)
3710 {
3711 if (regs.t0 && currprefs.cpu_model >= 68020) {
3712 uae_u16 opcode;
3713 /* should also include TRAP, CHK, SR modification FPcc */
3714 /* probably never used so why bother */
3715 /* We can afford this to be inefficient... */
3716 m68k_setpc (m68k_getpc ());
3717 fill_prefetch ();
3718 opcode = x_get_word (regs.pc);
3719 if (opcode == 0x4e73 /* RTE */
3720 || opcode == 0x4e74 /* RTD */
3721 || opcode == 0x4e75 /* RTS */
3722 || opcode == 0x4e77 /* RTR */
3723 || opcode == 0x4e76 /* TRAPV */
3724 || (opcode & 0xffc0) == 0x4e80 /* JSR */
3725 || (opcode & 0xffc0) == 0x4ec0 /* JMP */
3726 || (opcode & 0xff00) == 0x6100 /* BSR */
3727 || ((opcode & 0xf000) == 0x6000 /* Bcc */
3728 && cctrue ((opcode >> 8) & 0xf))
3729 || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
3730 && !cctrue ((opcode >> 8) & 0xf)
3731 && (uae_s16)m68k_dreg (regs, opcode & 7) != 0))
3732 {
3733 last_trace_ad = m68k_getpc ();
3734 unset_special (SPCFLAG_TRACE);
3735 set_special (SPCFLAG_DOTRACE);
3736 }
3737 } else if (regs.t1) {
3738 last_trace_ad = m68k_getpc ();
3739 unset_special (SPCFLAG_TRACE);
3740 set_special (SPCFLAG_DOTRACE);
3741 }
3742 }
3743
3744
3745 // handle interrupt delay (few cycles)
time_for_interrupt(void)3746 STATIC_INLINE bool time_for_interrupt (void)
3747 {
3748 return regs.ipl > regs.intmask || regs.ipl == 7;
3749 }
3750
doint(void)3751 void doint (void)
3752 {
3753 if (currprefs.cpu_cycle_exact) {
3754 regs.ipl_pin = intlev ();
3755 unset_special (SPCFLAG_INT);
3756 return;
3757 }
3758 if (currprefs.cpu_compatible && currprefs.cpu_model < 68020)
3759 set_special (SPCFLAG_INT);
3760 else
3761 set_special (SPCFLAG_DOINT);
3762 }
3763
3764 #define sleep_resolution 1000 / 1
3765 #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 1000)
3766
do_specialties(int cycles)3767 STATIC_INLINE int do_specialties (int cycles)
3768 {
3769 regs.instruction_pc = m68k_getpc ();
3770 #ifdef ACTION_REPLAY
3771 #ifdef ACTION_REPLAY_HRTMON
3772 if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
3773 int isinhrt = (m68k_getpc () >= hrtmem_start && m68k_getpc () < hrtmem_start + hrtmem_size);
3774 /* exit from HRTMon? */
3775 if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt)
3776 hrtmon_hide ();
3777 /* HRTMon breakpoint? (not via IRQ7) */
3778 if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt)
3779 hrtmon_breakenter ();
3780 if (hrtmon_flag == ACTION_REPLAY_ACTIVATE)
3781 hrtmon_enter ();
3782 }
3783 #endif
3784 if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) {
3785 /*if (action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom ())*/
3786 /* write_log (_T("PC:%p\n"), m68k_getpc ());*/
3787
3788 if (action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
3789 action_replay_enter ();
3790 if (action_replay_flag == ACTION_REPLAY_HIDE && !is_ar_pc_in_rom ()) {
3791 action_replay_hide ();
3792 unset_special (SPCFLAG_ACTION_REPLAY);
3793 }
3794 if (action_replay_flag == ACTION_REPLAY_WAIT_PC) {
3795 /*write_log (_T("Waiting for PC: %p, current PC= %p\n"), wait_for_pc, m68k_getpc ());*/
3796 if (m68k_getpc () == wait_for_pc) {
3797 action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
3798 }
3799 }
3800 }
3801 #endif
3802
3803 if (regs.spcflags & SPCFLAG_COPPER)
3804 do_copper ();
3805
3806 #ifdef JIT
3807 unset_special (SPCFLAG_END_COMPILE); /* has done its job */
3808 #endif
3809
3810 while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
3811 int c = blitnasty ();
3812 if (c < 0) {
3813 break;
3814 } else if (c > 0) {
3815 cycles -= c * CYCLE_UNIT * 2;
3816 if (cycles < CYCLE_UNIT)
3817 cycles = 0;
3818 } else {
3819 c = 4;
3820 }
3821 x_do_cycles (c * CYCLE_UNIT);
3822 if (regs.spcflags & SPCFLAG_COPPER)
3823 do_copper ();
3824 }
3825
3826 if (regs.spcflags & SPCFLAG_DOTRACE)
3827 Exception (9);
3828
3829 if (regs.spcflags & SPCFLAG_TRAP) {
3830 unset_special (SPCFLAG_TRAP);
3831 Exception (3);
3832 }
3833
3834 while (regs.spcflags & SPCFLAG_STOP) {
3835
3836 if (uae_int_requested) {
3837 INTREQ_f (0x8008);
3838 set_special (SPCFLAG_INT);
3839 }
3840 #ifdef UAENET
3841 {
3842 extern int volatile uaenet_int_requested;
3843 if (uaenet_int_requested) {
3844 INTREQ_f (0x8000 | 0x2000);
3845 set_special (SPCFLAG_INT);
3846 }
3847 }
3848 #endif
3849 #ifdef BSDSOCKET
3850 {
3851 extern void bsdsock_fake_int_handler (void);
3852 extern int volatile bsd_int_requested;
3853 if (bsd_int_requested)
3854 bsdsock_fake_int_handler ();
3855 }
3856 #endif
3857 if (cpu_tracer > 0) {
3858 cputrace.stopped = regs.stopped;
3859 cputrace.intmask = regs.intmask;
3860 cputrace.sr = regs.sr;
3861 cputrace.state = 1;
3862 cputrace.pc = m68k_getpc ();
3863 cputrace.memoryoffset = 0;
3864 cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
3865 cputrace.readcounter = cputrace.writecounter = 0;
3866 }
3867 x_do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
3868 if (regs.spcflags & SPCFLAG_COPPER)
3869 do_copper ();
3870
3871 if (currprefs.cpu_cycle_exact) {
3872 ipl_fetch ();
3873 if (time_for_interrupt ()) {
3874 do_interrupt (regs.ipl);
3875 }
3876 } else {
3877 if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
3878 int intr = intlev ();
3879 unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
3880 if (intr > 0 && intr > regs.intmask)
3881 do_interrupt (intr);
3882 }
3883 }
3884
3885 if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
3886 unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
3887 // SPCFLAG_BRK breaks STOP condition, need to prefetch
3888 m68k_resumestopped ();
3889 return 1;
3890 }
3891
3892 if (!uae_int_requested && currprefs.cpu_idle && currprefs.m68k_speed != 0 && (regs.spcflags & SPCFLAG_STOP)) {
3893 /* sleep 1ms if STOP-instruction is executed
3894 * but only if we have free frametime left to prevent slowdown
3895 */
3896 {
3897 static int sleepcnt, lvpos, zerocnt;
3898 if (vpos != lvpos) {
3899 lvpos = vpos;
3900 frame_time_t rpt = read_processor_time ();
3901 if ((int)rpt - (int)vsyncmaxtime < 0) {
3902 sleepcnt--;
3903 #if 0
3904 if (pissoff == 0 && currprefs.cachesize && --zerocnt < 0) {
3905 sleepcnt = -1;
3906 zerocnt = IDLETIME / 4;
3907 }
3908 #endif
3909 if (sleepcnt < 0) {
3910 sleepcnt = IDLETIME / 2;
3911 sleep_millis_main (1);
3912 }
3913 }
3914 }
3915 }
3916 }
3917 }
3918
3919 if (regs.spcflags & SPCFLAG_TRACE)
3920 do_trace ();
3921
3922 if (currprefs.cpu_cycle_exact) {
3923 if (time_for_interrupt ()) {
3924 do_interrupt (regs.ipl);
3925 }
3926 } else {
3927 if (regs.spcflags & SPCFLAG_INT) {
3928 int intr = intlev ();
3929 unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
3930 if (intr > 0 && (intr > regs.intmask || intr == 7))
3931 do_interrupt (intr);
3932 }
3933 }
3934
3935 if (regs.spcflags & SPCFLAG_DOINT) {
3936 unset_special (SPCFLAG_DOINT);
3937 set_special (SPCFLAG_INT);
3938 }
3939
3940 if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
3941 return 1;
3942 return 0;
3943 }
3944
3945 //static uae_u32 pcs[1000];
3946
3947 #if DEBUG_CD32CDTVIO
3948
3949 static uae_u32 cd32nextpc, cd32request;
3950
out_cd32io2(void)3951 static void out_cd32io2 (void)
3952 {
3953 uae_u32 request = cd32request;
3954 write_log (_T("%08x returned\n"), request);
3955 //write_log (_T("ACTUAL=%d ERROR=%d\n"), get_long (request + 32), get_byte (request + 31));
3956 cd32nextpc = 0;
3957 cd32request = 0;
3958 }
3959
out_cd32io(uae_u32 pc)3960 static void out_cd32io (uae_u32 pc)
3961 {
3962 TCHAR out[100];
3963 int ioreq = 0;
3964 uae_u32 request = m68k_areg (regs, 1);
3965
3966 if (pc == cd32nextpc) {
3967 out_cd32io2 ();
3968 return;
3969 }
3970 out[0] = 0;
3971 switch (pc)
3972 {
3973 case 0xe57cc0:
3974 case 0xf04c34:
3975 _stprintf (out, _T("opendevice"));
3976 break;
3977 case 0xe57ce6:
3978 case 0xf04c56:
3979 _stprintf (out, _T("closedevice"));
3980 break;
3981 case 0xe57e44:
3982 case 0xf04f2c:
3983 _stprintf (out, _T("beginio"));
3984 ioreq = 1;
3985 break;
3986 case 0xe57ef2:
3987 case 0xf0500e:
3988 _stprintf (out, _T("abortio"));
3989 ioreq = -1;
3990 break;
3991 }
3992 if (out[0] == 0)
3993 return;
3994 if (cd32request)
3995 write_log (_T("old request still not returned!\n"));
3996 cd32request = request;
3997 cd32nextpc = get_long (m68k_areg (regs, 7));
3998 write_log (_T("%s A1=%08X\n"), out, request);
3999 if (ioreq) {
4000 static int cnt = 0;
4001 int cmd = get_word (request + 28);
4002 #if 0
4003 if (cmd == 37) {
4004 cnt--;
4005 if (cnt <= 0)
4006 activate_debugger ();
4007 }
4008 #endif
4009 write_log (_T("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n"),
4010 cmd, get_long (request + 40),
4011 get_long (request + 36), get_long (request + 44), M68K_GETPC);
4012 }
4013 //if (ioreq < 0)
4014 //activate_debugger ();
4015 }
4016
4017 #endif
4018
adjust_cycles(int cycles)4019 STATIC_INLINE int adjust_cycles (int cycles)
4020 {
4021 if (currprefs.m68k_speed < 0 || cycles_mult == 0)
4022 return cycles;
4023 cpu_cycles *= cycles_mult;
4024 cpu_cycles /= CYCLES_DIV;
4025 return cpu_cycles;
4026 }
4027
4028 #ifndef CPUEMU_11
4029
m68k_run_1(void)4030 static void m68k_run_1 (void)
4031 {
4032 }
4033
4034 #else
4035
4036 /* It's really sad to have two almost identical functions for this, but we
4037 do it all for performance... :(
4038 This version emulates 68000's prefetch "cache" */
m68k_run_1(void)4039 static void m68k_run_1 (void)
4040 {
4041 struct regstruct *r = ®s;
4042
4043 for (;;) {
4044 uae_u16 opcode = r->ir;
4045
4046 count_instr (opcode);
4047
4048 #if DEBUG_CD32CDTVIO
4049 out_cd32io (m68k_getpc ());
4050 #endif
4051
4052 #if 0
4053 int pc = m68k_getpc ();
4054 if (pc == 0xdff002)
4055 write_log (_T("hip\n"));
4056 if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) {
4057 memmove (pcs + 1, pcs, 998 * 4);
4058 pcs[0] = pc;
4059 //write_log (_T("%08X-%04X "), pc, opcode);
4060 }
4061 #endif
4062 do_cycles (cpu_cycles);
4063 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4064 cpu_cycles = adjust_cycles (cpu_cycles);
4065 if (r->spcflags) {
4066 if (do_specialties (cpu_cycles)) {
4067 regs.ipl = regs.ipl_pin;
4068 return;
4069 }
4070 }
4071 regs.ipl = regs.ipl_pin;
4072 if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68000))
4073 return;
4074 }
4075 }
4076
4077 #endif /* CPUEMU_11 */
4078
4079 #ifndef CPUEMU_12
4080
m68k_run_1_ce(void)4081 static void m68k_run_1_ce (void)
4082 {
4083 }
4084
4085 #else
4086
4087 /* cycle-exact m68k_run () */
4088
m68k_run_1_ce(void)4089 static void m68k_run_1_ce (void)
4090 {
4091 struct regstruct *r = ®s;
4092 uae_u16 opcode;
4093
4094 if (cpu_tracer < 0) {
4095 memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
4096 r->ir = cputrace.ir;
4097 r->irc = cputrace.irc;
4098 r->sr = cputrace.sr;
4099 r->usp = cputrace.usp;
4100 r->isp = cputrace.isp;
4101 r->intmask = cputrace.intmask;
4102 r->stopped = cputrace.stopped;
4103 m68k_setpc (cputrace.pc);
4104 if (!r->stopped) {
4105 if (cputrace.state > 1) {
4106 write_log (_T("CPU TRACE: EXCEPTION %d\n"), cputrace.state);
4107 Exception (cputrace.state);
4108 } else if (cputrace.state == 1) {
4109 write_log (_T("CPU TRACE: %04X\n"), cputrace.opcode);
4110 (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
4111 }
4112 } else {
4113 write_log (_T("CPU TRACE: STOPPED\n"));
4114 }
4115 if (r->stopped)
4116 set_special (SPCFLAG_STOP);
4117 set_cpu_tracer (false);
4118 goto cont;
4119 }
4120
4121 set_cpu_tracer (false);
4122
4123 for (;;) {
4124 opcode = r->ir;
4125
4126 #if DEBUG_CD32CDTVIO
4127 out_cd32io (m68k_getpc ());
4128 #endif
4129 if (cpu_tracer) {
4130 memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
4131 cputrace.opcode = opcode;
4132 cputrace.ir = r->ir;
4133 cputrace.irc = r->irc;
4134 cputrace.sr = r->sr;
4135 cputrace.usp = r->usp;
4136 cputrace.isp = r->isp;
4137 cputrace.intmask = r->intmask;
4138 cputrace.stopped = r->stopped;
4139 cputrace.state = 1;
4140 cputrace.pc = m68k_getpc ();
4141 cputrace.startcycles = get_cycles ();
4142 cputrace.memoryoffset = 0;
4143 cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
4144 cputrace.readcounter = cputrace.writecounter = 0;
4145 }
4146
4147 if (inputrecord_debug & 4) {
4148 if (input_record > 0)
4149 inprec_recorddebug_cpu (1);
4150 else if (input_play > 0)
4151 inprec_playdebug_cpu (1);
4152 }
4153
4154 (*cpufunctbl[opcode])(opcode);
4155 if (cpu_tracer) {
4156 cputrace.state = 0;
4157 }
4158 cont:
4159 if (cputrace.needendcycles) {
4160 cputrace.needendcycles = 0;
4161 write_log (_T("STARTCYCLES=%08x ENDCYCLES=%08x\n"), cputrace.startcycles, get_cycles ());
4162 log_dma_record ();
4163 }
4164
4165 if (r->spcflags || time_for_interrupt ()) {
4166 if (do_specialties (0))
4167 return;
4168 }
4169
4170 if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68000)
4171 return;
4172 }
4173 }
4174
4175 #endif
4176
4177 #ifdef CPUEMU_20
4178 // emulate simple prefetch
get_word_020_prefetchf(uae_u32 pc)4179 static uae_u32 get_word_020_prefetchf (uae_u32 pc)
4180 {
4181 if (pc == regs.prefetch020addr) {
4182 uae_u32 v = regs.prefetch020[0];
4183 regs.prefetch020[0] = regs.prefetch020[1];
4184 regs.prefetch020[1] = regs.prefetch020[2];
4185 regs.prefetch020[2] = x_get_word (pc + 6);
4186 regs.prefetch020addr += 2;
4187 return v;
4188 } else if (pc == regs.prefetch020addr + 2) {
4189 uae_u32 v = regs.prefetch020[1];
4190 regs.prefetch020[0] = regs.prefetch020[2];
4191 regs.prefetch020[1] = x_get_word (pc + 4);
4192 regs.prefetch020[2] = x_get_word (pc + 6);
4193 regs.prefetch020addr += 4;
4194 return v;
4195 } else if (pc == regs.prefetch020addr + 4) {
4196 uae_u32 v = regs.prefetch020[2];
4197 regs.prefetch020[0] = x_get_word (pc + 2);
4198 regs.prefetch020[1] = x_get_word (pc + 4);
4199 regs.prefetch020[2] = x_get_word (pc + 6);
4200 regs.prefetch020addr += 6;
4201 return v;
4202 } else {
4203 regs.prefetch020addr = pc + 2;
4204 regs.prefetch020[0] = x_get_word (pc + 2);
4205 regs.prefetch020[1] = x_get_word (pc + 4);
4206 regs.prefetch020[2] = x_get_word (pc + 6);
4207 return x_get_word (pc);
4208 }
4209 }
4210 #endif
4211
4212 #ifdef JIT /* Completely different run_2 replacement */
4213
do_nothing(void)4214 void do_nothing (void)
4215 {
4216 /* What did you expect this to do? */
4217 do_cycles (0);
4218 /* I bet you didn't expect *that* ;-) */
4219 }
4220
exec_nostats(void)4221 void exec_nostats (void)
4222 {
4223 struct regstruct *r = ®s;
4224
4225 for (;;)
4226 {
4227 uae_u16 opcode = get_iword (0);
4228 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4229 cpu_cycles = adjust_cycles (cpu_cycles);
4230 do_cycles (cpu_cycles);
4231
4232 if (end_block (opcode) || r->spcflags || uae_int_requested)
4233 return; /* We will deal with the spcflags in the caller */
4234 }
4235 }
4236
4237 static int triggered;
4238
execute_normal(void)4239 void execute_normal (void)
4240 {
4241 struct regstruct *r = ®s;
4242 int blocklen;
4243 cpu_history pc_hist[MAXRUN];
4244 int total_cycles;
4245
4246 if (check_for_cache_miss ())
4247 return;
4248
4249 total_cycles = 0;
4250 blocklen = 0;
4251 start_pc_p = r->pc_oldp;
4252 start_pc = r->pc;
4253 for (;;) {
4254 /* Take note: This is the do-it-normal loop */
4255 uae_u16 opcode;
4256
4257 regs.instruction_pc = m68k_getpc ();
4258 if (currprefs.cpu_compatible) {
4259 opcode = get_word_020_prefetchf (regs.instruction_pc);
4260 } else {
4261 opcode = get_iword (0);
4262 }
4263
4264 special_mem = DISTRUST_CONSISTENT_MEM;
4265 pc_hist[blocklen].location = (uae_u16*)r->pc_p;
4266
4267 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4268 cpu_cycles = adjust_cycles (cpu_cycles);
4269 do_cycles (cpu_cycles);
4270 total_cycles += cpu_cycles;
4271 pc_hist[blocklen].specmem = special_mem;
4272 blocklen++;
4273 if (end_block (opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested) {
4274 compile_block (pc_hist, blocklen, total_cycles);
4275 return; /* We will deal with the spcflags in the caller */
4276 }
4277 /* No need to check regs.spcflags, because if they were set,
4278 we'd have ended up inside that "if" */
4279 }
4280 }
4281
m68k_run_jit(void)4282 static void m68k_run_jit (void)
4283 {
4284 // pushall_call_handler already disassembled in create_popalls()
4285 for (;;) {
4286 CALL_CODE_DIRECT(pushall_call_handler)
4287 /* Whenever we return from that, we should check spcflags */
4288 if (uae_int_requested) {
4289 INTREQ_f (0x8008);
4290 set_special (SPCFLAG_INT);
4291 }
4292 if (regs.spcflags) {
4293 if (do_specialties (0)) {
4294 return;
4295 }
4296 }
4297 }
4298 }
4299 #endif /* JIT */
4300
4301 #ifndef CPUEMU_0
4302
m68k_run_2(void)4303 static void m68k_run_2 (void)
4304 {
4305 }
4306
4307 #else
4308
4309 #if defined(OPCODE_DEBUG)
opcodedebug(uae_u32 pc,uae_u16 opcode,bool full)4310 static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full)
4311 {
4312 struct mnemolookup *lookup;
4313 struct instr *dp;
4314 uae_u32 addr;
4315 int fault;
4316
4317 if (cpufunctbl[opcode] == op_illg_1)
4318 opcode = 0x4AFC;
4319 dp = table68k + opcode;
4320 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
4321 ;
4322 fault = 0;
4323 TRY(prb) {
4324 addr = mmu_translate (pc, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0);
4325 } CATCH (prb) {
4326 fault = 1;
4327 }
4328 if (!fault) {
4329 TCHAR buf[100];
4330 if (full)
4331 write_log (_T("mmufixup=%d %04x %04x\n"), mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw);
4332 m68k_disasm_2 (buf, sizeof buf / sizeof (TCHAR), addr, NULL, 1, NULL, NULL, 0);
4333 write_log (_T("%s\n"), buf);
4334 if (full)
4335 m68k_dumpstate (NULL);
4336 }
4337 }
4338 #endif
4339
cpu_halt(int id)4340 void cpu_halt (int id)
4341 {
4342 if (!regs.halted) {
4343 write_log (_T("CPU halted: reason = %d\n"), id);
4344 regs.halted = id;
4345 gui_data.cpu_halted = true;
4346 gui_led (LED_CPU, 0);
4347 regs.intmask = 7;
4348 MakeSR ();
4349 }
4350 while (regs.halted) {
4351 x_do_cycles (8 * CYCLE_UNIT);
4352 cpu_cycles = adjust_cycles (cpu_cycles);
4353 if (regs.spcflags) {
4354 if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
4355 return;
4356 }
4357 }
4358 }
4359
4360 #ifdef CPUEMU_33
4361
4362 /* MMU 68060 */
m68k_run_mmu060(void)4363 static void m68k_run_mmu060 (void)
4364 {
4365 uae_u16 opcode;
4366 uaecptr pc;
4367 struct flag_struct f;
4368
4369 retry:
4370 TRY (prb) {
4371 for (;;) {
4372 f.cznv = regflags.cznv;
4373 f.x = regflags.x;
4374 pc = regs.instruction_pc = m68k_getpc ();
4375
4376 do_cycles (cpu_cycles);
4377
4378 mmu_opcode = -1;
4379 mmu060_state = 0;
4380 mmu_opcode = opcode = x_prefetch (0);
4381 mmu060_state = 1;
4382
4383 count_instr (opcode);
4384 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4385
4386 cpu_cycles = adjust_cycles (cpu_cycles);
4387 if (regs.spcflags) {
4388 if (do_specialties (cpu_cycles))
4389 return;
4390 }
4391 }
4392 } CATCH (prb) {
4393
4394 m68k_setpc (regs.instruction_pc);
4395 regflags.cznv = f.cznv;
4396 regflags.x = f.x;
4397
4398 if (mmufixup[0].reg >= 0) {
4399 m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
4400 mmufixup[0].reg = -1;
4401 }
4402 if (mmufixup[1].reg >= 0) {
4403 m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
4404 mmufixup[1].reg = -1;
4405 }
4406
4407 TRY (prb2) {
4408 Exception (0); //prb
4409 } CATCH (prb2) {
4410 cpu_halt (1);
4411 return;
4412 }
4413 goto retry;
4414 }
4415
4416 }
4417
4418 #endif
4419
4420 #ifdef CPUEMU_31
4421
4422 /* Aranym MMU 68040 */
m68k_run_mmu040(void)4423 static void m68k_run_mmu040 (void)
4424 {
4425 uae_u16 opcode;
4426 struct flag_struct f;
4427 uaecptr pc;
4428
4429 retry:
4430 TRY (prb) {
4431 for (;;) {
4432 f.cznv = regflags.cznv;
4433 f.x = regflags.x;
4434 mmu_restart = true;
4435 pc = regs.instruction_pc = m68k_getpc ();
4436
4437 do_cycles (cpu_cycles);
4438
4439 mmu_opcode = -1;
4440 mmu_opcode = opcode = x_prefetch (0);
4441 count_instr (opcode);
4442 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4443 cpu_cycles = adjust_cycles (cpu_cycles);
4444
4445 if (regs.spcflags) {
4446 if (do_specialties (cpu_cycles))
4447 return;
4448 }
4449 }
4450 } CATCH (prb) {
4451
4452 if (mmu_restart) {
4453 /* restore state if instruction restart */
4454 regflags.cznv = f.cznv;
4455 regflags.x = f.x;
4456 m68k_setpc (regs.instruction_pc);
4457 }
4458
4459 if (mmufixup[0].reg >= 0) {
4460 m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
4461 mmufixup[0].reg = -1;
4462 }
4463
4464 TRY (prb2) {
4465 Exception (0); //prb
4466 } CATCH (prb2) {
4467 cpu_halt (1);
4468 return;
4469 }
4470 goto retry;
4471 }
4472
4473 }
4474
4475 #endif
4476
4477 #ifdef CPUEMU_32
4478
4479 // Previous MMU 68030
m68k_run_mmu030(void)4480 static void m68k_run_mmu030 (void)
4481 {
4482 uae_u16 opcode;
4483 uaecptr pc;
4484 struct flag_struct f;
4485
4486 mmu030_opcode_stageb = -1;
4487 retry:
4488 TRY (prb) {
4489 for (;;) {
4490 int cnt;
4491 insretry:
4492 pc = regs.instruction_pc = m68k_getpc ();
4493 f.cznv = regflags.cznv;
4494 f.x = regflags.x;
4495
4496 mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
4497 mmu030_opcode = -1;
4498 if (mmu030_opcode_stageb < 0) {
4499 opcode = get_iword_mmu030 (0);
4500 } else {
4501 opcode = mmu030_opcode_stageb;
4502 mmu030_opcode_stageb = -1;
4503 }
4504
4505 mmu030_opcode = opcode;
4506 mmu030_ad[0].done = false;
4507
4508 cnt = 50;
4509 for (;;) {
4510 opcode = mmu030_opcode;
4511 mmu030_idx = 0;
4512 count_instr (opcode);
4513 do_cycles (cpu_cycles);
4514 mmu030_retry = false;
4515 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4516 cnt--; // so that we don't get in infinite loop if things go horribly wrong
4517 if (!mmu030_retry)
4518 break;
4519 if (cnt < 0) {
4520 cpu_halt (9);
4521 break;
4522 }
4523 if (mmu030_retry && mmu030_opcode == -1)
4524 goto insretry; // urgh
4525 }
4526
4527 mmu030_opcode = -1;
4528
4529 cpu_cycles = adjust_cycles (cpu_cycles);
4530 if (regs.spcflags) {
4531 if (do_specialties (cpu_cycles))
4532 return;
4533 }
4534 }
4535 } CATCH (prb) {
4536
4537 regflags.cznv = f.cznv;
4538 regflags.x = f.x;
4539
4540 m68k_setpc (regs.instruction_pc);
4541
4542 if (mmufixup[0].reg >= 0) {
4543 m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
4544 mmufixup[0].reg = -1;
4545 }
4546 if (mmufixup[1].reg >= 0) {
4547 m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
4548 mmufixup[1].reg = -1;
4549 }
4550
4551 TRY (prb2) {
4552 Exception (0); //prb
4553 } CATCH (prb2) {
4554 cpu_halt (1);
4555 return;
4556 }
4557 goto retry;
4558 }
4559
4560 }
4561
4562 #endif
4563
4564
4565 /* "cycle exact" 68020/030 */
4566
docodece020(uae_u32 opcode)4567 STATIC_INLINE void docodece020 (uae_u32 opcode)
4568 {
4569 (*cpufunctbl[opcode])(opcode);
4570 if (regs.ce020memcycles > 0) {
4571 regs.ce020tmpcycles = CYCLE_UNIT * MAX68020CYCLES;
4572 x_do_cycles (regs.ce020memcycles);
4573 regs.ce020memcycles = 0;
4574 }
4575 }
4576
m68k_run_2ce(void)4577 static void m68k_run_2ce (void)
4578 {
4579 struct regstruct *r = ®s;
4580 uae_u16 opcode;
4581 bool exit = false;
4582
4583 if (cpu_tracer < 0) {
4584 memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
4585 r->ir = cputrace.ir;
4586 r->irc = cputrace.irc;
4587 r->sr = cputrace.sr;
4588 r->usp = cputrace.usp;
4589 r->isp = cputrace.isp;
4590 r->intmask = cputrace.intmask;
4591 r->stopped = cputrace.stopped;
4592
4593 r->msp = cputrace.msp;
4594 r->vbr = cputrace.vbr;
4595 r->caar = cputrace.caar;
4596 r->cacr = cputrace.cacr;
4597 r->cacheholdingdata020 = cputrace.cacheholdingdata020;
4598 r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
4599 r->prefetch020addr = cputrace.prefetch020addr;
4600 memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
4601 memcpy (&caches020, &cputrace.caches020, sizeof caches020);
4602
4603 m68k_setpc (cputrace.pc);
4604 if (!r->stopped) {
4605 if (cputrace.state > 1)
4606 Exception (cputrace.state);
4607 else if (cputrace.state == 1)
4608 docodece020 (cputrace.opcode);
4609 }
4610 if (regs.stopped)
4611 set_special (SPCFLAG_STOP);
4612 set_cpu_tracer (false);
4613 goto cont;
4614 }
4615
4616 set_cpu_tracer (false);
4617
4618 for (;;) {
4619 r->instruction_pc = m68k_getpc ();
4620 opcode = get_word_ce020_prefetch (0);
4621
4622
4623 #if DEBUG_CD32CDTVIO
4624 out_cd32io (r->instruction_pc);
4625 #endif
4626
4627 if (cpu_tracer) {
4628
4629 #if CPUTRACE_DEBUG
4630 validate_trace ();
4631 #endif
4632 memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
4633 cputrace.opcode = opcode;
4634 cputrace.ir = r->ir;
4635 cputrace.irc = r->irc;
4636 cputrace.sr = r->sr;
4637 cputrace.usp = r->usp;
4638 cputrace.isp = r->isp;
4639 cputrace.intmask = r->intmask;
4640 cputrace.stopped = r->stopped;
4641 cputrace.state = 1;
4642 cputrace.pc = m68k_getpc ();
4643
4644 cputrace.msp = r->msp;
4645 cputrace.vbr = r->vbr;
4646 cputrace.caar = r->caar;
4647 cputrace.cacr = r->cacr;
4648 cputrace.cacheholdingdata020 = r->cacheholdingdata020;
4649 cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
4650 cputrace.prefetch020addr = r->prefetch020addr;
4651 memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u16));
4652 memcpy (&cputrace.caches020, &caches020, sizeof caches020);
4653
4654 cputrace.memoryoffset = 0;
4655 cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
4656 cputrace.readcounter = cputrace.writecounter = 0;
4657 }
4658
4659 if (inputrecord_debug & 4) {
4660 if (input_record > 0)
4661 inprec_recorddebug_cpu (1);
4662 else if (input_play > 0)
4663 inprec_playdebug_cpu (1);
4664 }
4665
4666 docodece020 (opcode);
4667
4668 cont:
4669 if (r->spcflags || time_for_interrupt ()) {
4670 if (do_specialties (0))
4671 exit = true;
4672 }
4673
4674 regs.ce020tmpcycles -= cpucycleunit;
4675 if (regs.ce020tmpcycles <= 0) {
4676 x_do_cycles (1 * CYCLE_UNIT);
4677 regs.ce020tmpcycles = CYCLE_UNIT * MAX68020CYCLES;;
4678 }
4679 regs.ipl = regs.ipl_pin;
4680
4681 if (exit)
4682 return;
4683 }
4684 }
4685
4686 #ifdef CPUEMU_20
4687
4688 // only opcode fetch prefetch
m68k_run_2pf(void)4689 static void m68k_run_2pf (void)
4690 {
4691 struct regstruct *r = ®s;
4692
4693 for (;;) {
4694 uae_u16 opcode;
4695
4696 r->instruction_pc = m68k_getpc ();
4697
4698 #if DEBUG_CD32CDTVIO
4699 out_cd32io (m68k_getpc ());
4700 #endif
4701
4702 x_do_cycles (cpu_cycles);
4703
4704 opcode = get_word_020_prefetchf (r->instruction_pc);
4705
4706 count_instr (opcode);
4707
4708 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4709 cpu_cycles = adjust_cycles (cpu_cycles);
4710 if (r->spcflags) {
4711 if (do_specialties (cpu_cycles))
4712 return;
4713 }
4714 }
4715 }
4716
get_word_020_prefetch(int o)4717 uae_u32 get_word_020_prefetch (int o)
4718 {
4719 uae_u32 pc = m68k_getpc () + o;
4720
4721 if (pc == regs.prefetch020addr) {
4722 uae_u32 v = regs.prefetch020[0];
4723 regs.prefetch020[0] = regs.prefetch020[1];
4724 regs.prefetch020[1] = regs.prefetch020[2];
4725 regs.prefetch020[2] = x_get_word (pc + 6);
4726 regs.prefetch020addr += 2;
4727 return v;
4728 } else {
4729 regs.prefetch020addr = pc + 2;
4730 regs.prefetch020[0] = x_get_word (pc + 2);
4731 regs.prefetch020[1] = x_get_word (pc + 4);
4732 regs.prefetch020[2] = x_get_word (pc + 6);
4733 return x_get_word (pc);
4734 }
4735 }
4736
4737 // full prefetch 020+
m68k_run_2p(void)4738 static void m68k_run_2p (void)
4739 {
4740 struct regstruct *r = ®s;
4741
4742 for (;;) {
4743 uae_u16 opcode;
4744
4745 r->instruction_pc = m68k_getpc ();
4746
4747 #if DEBUG_CD32CDTVIO
4748 out_cd32io (m68k_getpc ());
4749 #endif
4750
4751 x_do_cycles (cpu_cycles);
4752
4753 opcode = get_word_020_prefetch (0);
4754
4755 count_instr (opcode);
4756
4757 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4758 cpu_cycles = adjust_cycles (cpu_cycles);
4759 if (r->spcflags) {
4760 if (do_specialties (cpu_cycles)) {
4761 ipl_fetch ();
4762 return;
4763 }
4764 }
4765 ipl_fetch ();
4766 }
4767 }
4768
4769 #endif
4770
4771 //static int used[65536];
4772
4773 /* Same thing, but don't use prefetch to get opcode. */
m68k_run_2(void)4774 static void m68k_run_2 (void)
4775 {
4776 struct regstruct *r = ®s;
4777
4778 for (;;) {
4779 r->instruction_pc = m68k_getpc ();
4780 uae_u16 opcode = get_iword (0);
4781 count_instr (opcode);
4782
4783 // if (regs.s == 0 && regs.regs[15] < 0x10040000 && regs.regs[15] > 0x10000000)
4784 // activate_debugger();
4785
4786 #if 0
4787 if (!used[opcode]) {
4788 write_log (_T("%04X "), opcode);
4789 used[opcode] = 1;
4790 }
4791 #endif
4792 do_cycles (cpu_cycles);
4793 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4794 cpu_cycles = adjust_cycles (cpu_cycles);
4795 if (r->spcflags) {
4796 if (do_specialties (cpu_cycles))
4797 return;
4798 }
4799 }
4800 }
4801
4802 /* fake MMU 68k */
m68k_run_mmu(void)4803 static void m68k_run_mmu (void)
4804 {
4805 for (;;) {
4806 uae_u16 opcode = get_iword (0);
4807 do_cycles (cpu_cycles);
4808 mmu_backup_regs = regs;
4809 cpu_cycles = (*cpufunctbl[opcode])(opcode);
4810 cpu_cycles = adjust_cycles (cpu_cycles);
4811 if (mmu_triggered)
4812 mmu_do_hit ();
4813 if (regs.spcflags) {
4814 if (do_specialties (cpu_cycles))
4815 return;
4816 }
4817 }
4818 }
4819
4820 #endif /* CPUEMU_0 */
4821
4822 int in_m68k_go = 0;
4823
exception2_handle(uaecptr addr,uaecptr fault)4824 static void exception2_handle (uaecptr addr, uaecptr fault)
4825 {
4826 last_addr_for_exception_3 = addr;
4827 last_fault_for_exception_3 = fault;
4828 last_writeaccess_for_exception_3 = 0;
4829 last_instructionaccess_for_exception_3 = 0;
4830 Exception (2);
4831 }
4832
m68k_go(int may_quit)4833 void m68k_go (int may_quit)
4834 {
4835 int hardboot = 1;
4836 int startup = 1;
4837
4838 if (in_m68k_go || !may_quit) {
4839 write_log (_T("Bug! m68k_go is not reentrant.\n"));
4840 abort ();
4841 }
4842
4843 reset_frame_rate_hack ();
4844 update_68k_cycles ();
4845 start_cycles = 0;
4846
4847 set_cpu_tracer (false);
4848
4849 in_m68k_go++;
4850 for (;;) {
4851 void (*run_func)(void);
4852
4853 cputrace.state = -1;
4854
4855 if (currprefs.inprecfile[0] && input_play) {
4856 inprec_open (currprefs.inprecfile, NULL);
4857 changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0;
4858 quit_program = UAE_RESET;
4859 }
4860 if (input_play || input_record)
4861 inprec_startup ();
4862
4863 if (quit_program > 0) {
4864 int hardreset = (quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot;
4865 bool kbreset = quit_program == UAE_RESET_KEYBOARD;
4866 if (quit_program == UAE_QUIT)
4867 break;
4868 int restored = 0;
4869
4870 hsync_counter = 0;
4871 vsync_counter = 0;
4872 quit_program = 0;
4873 hardboot = 0;
4874
4875 #ifdef SAVESTATE
4876 if (savestate_state == STATE_DORESTORE)
4877 savestate_state = STATE_RESTORE;
4878 if (savestate_state == STATE_RESTORE)
4879 restore_state (savestate_fname);
4880 else if (savestate_state == STATE_REWIND)
4881 savestate_rewind ();
4882 #endif
4883 set_cycles (start_cycles);
4884 custom_reset (hardreset != 0, kbreset);
4885 m68k_reset (hardreset != 0);
4886 if (hardreset) {
4887 memory_clear ();
4888 write_log (_T("hardreset, memory cleared\n"));
4889 }
4890 #ifdef SAVESTATE
4891 /* We may have been restoring state, but we're done now. */
4892 if (isrestore ()) {
4893 if (debug_dma) {
4894 record_dma_reset ();
4895 record_dma_reset ();
4896 }
4897 savestate_restore_finish ();
4898 memory_map_dump ();
4899 #ifdef MMUEMU
4900 if (currprefs.mmu_model == 68030) {
4901 mmu030_decode_tc (tc_030);
4902 } else if (currprefs.mmu_model >= 68040) {
4903 mmu_set_tc (regs.tcr);
4904 }
4905 #endif
4906 startup = 1;
4907 restored = 1;
4908 }
4909 #endif
4910 if (currprefs.produce_sound == 0)
4911 eventtab[ev_audio].active = 0;
4912 m68k_setpc (regs.pc);
4913 check_prefs_changed_audio ();
4914
4915 if (!restored || hsync_counter == 0)
4916 savestate_check ();
4917 if (input_record == INPREC_RECORD_START)
4918 input_record = INPREC_RECORD_NORMAL;
4919 } else {
4920 if (input_record == INPREC_RECORD_START) {
4921 input_record = INPREC_RECORD_NORMAL;
4922 savestate_init ();
4923 hsync_counter = 0;
4924 vsync_counter = 0;
4925 savestate_check ();
4926 }
4927 }
4928
4929 if (changed_prefs.inprecfile[0] && input_record)
4930 inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL);
4931
4932 set_cpu_tracer (false);
4933
4934 #ifdef DEBUGGER
4935 if (debugging)
4936 debug ();
4937 #endif
4938 if (regs.panic) {
4939 regs.panic = 0;
4940 /* program jumped to non-existing memory and cpu was >= 68020 */
4941 get_real_address (regs.isp); /* stack in no one's land? -> halt */
4942 if (regs.isp & 1)
4943 regs.panic = 5;
4944 if (!regs.panic)
4945 exception2_handle (regs.panic_pc, regs.panic_addr);
4946 if (regs.panic) {
4947 int id = regs.panic;
4948 /* system is very badly confused */
4949 write_log (_T("double bus error or corrupted stack, halting..\n"));
4950 regs.panic = 0;
4951 cpu_halt (id);
4952 }
4953 }
4954
4955 #if 0 /* what was the meaning of this? this breaks trace emulation if debugger is used */
4956 if (regs.spcflags) {
4957 uae_u32 of = regs.spcflags;
4958 regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
4959 do_specialties (0);
4960 regs.spcflags |= of & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
4961 }
4962 #endif
4963 set_x_funcs ();
4964 if (startup) {
4965 custom_prepare ();
4966 #ifdef NATMEM_OFFSET
4967 protect_roms (true);
4968 #endif
4969 }
4970 startup = 0;
4971 if (regs.halted) {
4972 cpu_halt (regs.halted);
4973 continue;
4974 }
4975 #if 0
4976 if (mmu_enabled && !currprefs.cachesize) {
4977 run_func = m68k_run_mmu;
4978 } else {
4979 #endif
4980 run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000 ? m68k_run_1_ce :
4981 currprefs.cpu_compatible && currprefs.cpu_model == 68000 ? m68k_run_1 :
4982 #ifdef JIT
4983 currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit :
4984 #endif
4985 #ifdef MMUEMU
4986 currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
4987 currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
4988 currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
4989 #endif
4990 currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
4991 currprefs.cpu_compatible ? (currprefs.cpu_model <= 68020 ? m68k_run_2p : m68k_run_2pf) : m68k_run_2;
4992 #if 0
4993 }
4994 #endif
4995 run_func ();
4996 unset_special (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
4997 }
4998 #ifdef NATMEM_OFFSET
4999 protect_roms (false);
5000 #endif
5001 in_m68k_go--;
5002 }
5003
5004 #if 0
5005 static void m68k_verify (uaecptr addr, uaecptr *nextpc)
5006 {
5007 uae_u16 opcode, val;
5008 struct instr *dp;
5009
5010 opcode = get_iword_1 (0);
5011 last_op_for_exception_3 = opcode;
5012 m68kpc_offset = 2;
5013
5014 if (cpufunctbl[opcode] == op_illg_1) {
5015 opcode = 0x4AFC;
5016 }
5017 dp = table68k + opcode;
5018
5019 if (dp->suse) {
5020 if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
5021 ExceptionX (3, 0);
5022 return;
5023 }
5024 }
5025 if (dp->duse) {
5026 if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
5027 ExceptionX (3, 0);
5028 return;
5029 }
5030 }
5031 }
5032 #endif
5033
5034 static const TCHAR *ccnames[] =
5035 { _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
5036 _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE") };
5037
addmovemreg(TCHAR * out,int * prevreg,int * lastreg,int * first,int reg)5038 static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg)
5039 {
5040 TCHAR *p = out + _tcslen (out);
5041 if (*prevreg < 0) {
5042 *prevreg = reg;
5043 *lastreg = reg;
5044 return;
5045 }
5046 if ((*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
5047 _stprintf (p, _T("%s%c%d"), (*first) ? _T("") : _T("/"), (*lastreg) < 8 ? 'D' : 'A', (*lastreg) & 7);
5048 p = p + _tcslen (p);
5049 if ((*lastreg) + 2 == reg) {
5050 _stprintf (p, _T("/%c%d"), (*prevreg) < 8 ? 'D' : 'A', (*prevreg) & 7);
5051 } else if ((*lastreg) != (*prevreg)) {
5052 _stprintf (p, _T("-%c%d"), (*prevreg) < 8 ? 'D' : 'A', (*prevreg) & 7);
5053 }
5054 *lastreg = reg;
5055 *first = 0;
5056 }
5057 *prevreg = reg;
5058 }
5059
movemout(TCHAR * out,uae_u16 mask,int mode)5060 static void movemout (TCHAR *out, uae_u16 mask, int mode)
5061 {
5062 unsigned int dmask, amask;
5063 int prevreg = -1, lastreg = -1, first = 1;
5064
5065 if (mode == Apdi) {
5066 int i;
5067 uae_u8 dmask2 = (mask >> 8) & 0xff;
5068 uae_u8 amask2 = mask & 0xff;
5069 dmask = 0;
5070 amask = 0;
5071 for (i = 0; i < 8; i++) {
5072 if (dmask2 & (1 << i))
5073 dmask |= 1 << (7 - i);
5074 if (amask2 & (1 << i))
5075 amask |= 1 << (7 - i);
5076 }
5077 } else {
5078 dmask = mask & 0xff;
5079 amask = (mask >> 8) & 0xff;
5080 }
5081 while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask]); dmask = movem_next[dmask]; }
5082 while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8); amask = movem_next[amask]; }
5083 addmovemreg (out, &prevreg, &lastreg, &first, -1);
5084 }
5085
5086 #if defined(DEBUGGER) || defined (ENFORCER)
disasm_size(TCHAR * instrname,struct instr * dp)5087 static void disasm_size (TCHAR *instrname, struct instr *dp)
5088 {
5089 #if 0
5090 int i, size;
5091 uae_u16 mnemo = dp->mnemo;
5092
5093 size = dp->size;
5094 for (i = 0; i < 65536; i++) {
5095 struct instr *in = &table68k[i];
5096 if (in->mnemo == mnemo && in != dp) {
5097 if (size != in->size)
5098 break;
5099 }
5100 }
5101 if (i == 65536)
5102 size = -1;
5103 #endif
5104 switch (dp->size)
5105 {
5106 case sz_byte:
5107 _tcscat (instrname, _T(".B "));
5108 break;
5109 case sz_word:
5110 _tcscat (instrname, _T(".W "));
5111 break;
5112 case sz_long:
5113 _tcscat (instrname, _T(".L "));
5114 break;
5115 default:
5116 _tcscat (instrname, _T(" "));
5117 break;
5118 }
5119 }
5120
m68k_disasm_2(TCHAR * buf,int bufsize,uaecptr pc,uaecptr * nextpc,int cnt,uae_u32 * seaddr,uae_u32 * deaddr,int safemode)5121 void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
5122 {
5123 uae_u32 seaddr2;
5124 uae_u32 deaddr2;
5125
5126 if (buf)
5127 memset (buf, 0, bufsize * sizeof (TCHAR));
5128 if (!table68k)
5129 return;
5130 while (cnt-- > 0) {
5131 TCHAR instrname[100], *ccpt;
5132 uaecptr i;
5133 uae_u32 opcode;
5134 struct mnemolookup *lookup;
5135 struct instr *dp;
5136 int oldpc;
5137 uaecptr m68kpc_illg = 0;
5138 bool illegal = false;
5139
5140 seaddr2 = deaddr2 = 0;
5141 oldpc = pc;
5142 opcode = get_word_debug (pc);
5143 if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
5144 m68kpc_illg = pc + 2;
5145 illegal = true;
5146 }
5147
5148 dp = table68k + opcode;
5149 if (dp->mnemo == i_ILLG) {
5150 illegal = false;
5151 opcode = 0x4AFC;
5152 dp = table68k + opcode;
5153 }
5154 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
5155 ;
5156
5157 buf = buf_out (buf, &bufsize, _T("%08lX "), pc);
5158
5159 pc += 2;
5160
5161 if (lookup->friendlyname)
5162 _tcscpy (instrname, lookup->friendlyname);
5163 else
5164 _tcscpy (instrname, lookup->name);
5165 ccpt = _tcsstr (instrname, _T("cc"));
5166 if (ccpt != 0) {
5167 _tcsncpy (ccpt, ccnames[dp->cc], 2);
5168 }
5169 disasm_size (instrname, dp);
5170
5171 if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
5172 uae_u16 imm = get_word_debug (pc);
5173 uae_u16 creg = imm & 0x0fff;
5174 uae_u16 r = imm >> 12;
5175 TCHAR regs[16], *cname = _T("?");
5176 int i;
5177 for (i = 0; m2cregs[i].regname; i++) {
5178 if (m2cregs[i].regno == creg)
5179 break;
5180 }
5181 _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
5182 if (m2cregs[i].regname)
5183 cname = m2cregs[i].regname;
5184 if (lookup->mnemo == i_MOVE2C) {
5185 _tcscat (instrname, regs);
5186 _tcscat (instrname, _T(","));
5187 _tcscat (instrname, cname);
5188 } else {
5189 _tcscat (instrname, cname);
5190 _tcscat (instrname, _T(","));
5191 _tcscat (instrname, regs);
5192 }
5193 pc += 2;
5194 } else if (lookup->mnemo == i_MVMEL) {
5195 uae_u16 mask = get_word_debug (pc);
5196 pc += 2;
5197 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
5198 _tcscat (instrname, _T(","));
5199 movemout (instrname, mask, dp->dmode);
5200 } else if (lookup->mnemo == i_MVMLE) {
5201 uae_u16 mask = get_word_debug (pc);
5202 pc += 2;
5203 movemout (instrname, mask, dp->dmode);
5204 _tcscat (instrname, _T(","));
5205 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
5206 } else {
5207 if (dp->suse) {
5208 pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
5209 }
5210 if (dp->suse && dp->duse)
5211 _tcscat (instrname, _T(","));
5212 if (dp->duse) {
5213 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
5214 }
5215 }
5216
5217 for (i = 0; i < (pc - oldpc) / 2; i++) {
5218 buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
5219 }
5220 while (i++ < 5)
5221 buf = buf_out (buf, &bufsize, _T(" "));
5222
5223 if (illegal)
5224 buf = buf_out (buf, &bufsize, _T("[ "));
5225 buf = buf_out (buf, &bufsize, instrname);
5226 if (illegal)
5227 buf = buf_out (buf, &bufsize, _T(" ]"));
5228
5229 if (ccpt != 0) {
5230 uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
5231 if (deaddr)
5232 *deaddr = pc;
5233 if (cctrue (dp->cc))
5234 buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
5235 else
5236 buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
5237 } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
5238 if (deaddr)
5239 *deaddr = pc;
5240 buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
5241 }
5242 buf = buf_out (buf, &bufsize, _T("\n"));
5243
5244 if (illegal)
5245 pc = m68kpc_illg;
5246 }
5247 if (nextpc)
5248 *nextpc = pc;
5249 if (seaddr)
5250 *seaddr = seaddr2;
5251 if (deaddr)
5252 *deaddr = deaddr2;
5253 }
5254
m68k_disasm_ea(uaecptr addr,uaecptr * nextpc,int cnt,uae_u32 * seaddr,uae_u32 * deaddr)5255 void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
5256 {
5257 TCHAR *buf;
5258
5259 buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
5260 if (!buf)
5261 return;
5262 m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1);
5263 xfree (buf);
5264 }
m68k_disasm(uaecptr addr,uaecptr * nextpc,int cnt)5265 void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
5266 {
5267 TCHAR *buf;
5268
5269 buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
5270 if (!buf)
5271 return;
5272 m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
5273 console_out_f (_T("%s"), buf);
5274 xfree (buf);
5275 }
5276
5277 /*************************************************************
5278 Disasm the m68kcode at the given address into instrname
5279 and instrcode
5280 *************************************************************/
sm68k_disasm(TCHAR * instrname,TCHAR * instrcode,uaecptr addr,uaecptr * nextpc)5281 void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
5282 {
5283 TCHAR *ccpt;
5284 uae_u32 opcode;
5285 struct mnemolookup *lookup;
5286 struct instr *dp;
5287 uaecptr pc, oldpc;
5288
5289 pc = oldpc = addr;
5290 opcode = get_word_debug (pc);
5291 if (cpufunctbl[opcode] == op_illg_1) {
5292 opcode = 0x4AFC;
5293 }
5294 dp = table68k + opcode;
5295 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
5296
5297 pc += 2;
5298
5299 _tcscpy (instrname, lookup->name);
5300 ccpt = _tcsstr (instrname, _T("cc"));
5301 if (ccpt != 0) {
5302 _tcsncpy (ccpt, ccnames[dp->cc], 2);
5303 }
5304 switch (dp->size){
5305 case sz_byte: _tcscat (instrname, _T(".B ")); break;
5306 case sz_word: _tcscat (instrname, _T(".W ")); break;
5307 case sz_long: _tcscat (instrname, _T(".L ")); break;
5308 default: _tcscat (instrname, _T(" ")); break;
5309 }
5310
5311 if (dp->suse) {
5312 pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
5313 }
5314 if (dp->suse && dp->duse)
5315 _tcscat (instrname, _T(","));
5316 if (dp->duse) {
5317 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
5318 }
5319
5320 if (instrcode)
5321 {
5322 uaecptr i;
5323 for (i = 0; i < (pc - oldpc) / 2; i++)
5324 {
5325 _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
5326 instrcode += _tcslen (instrcode);
5327 }
5328 }
5329
5330 if (nextpc)
5331 *nextpc = pc;
5332 }
5333
5334 struct cpum2c m2cregs[] = {
5335 { 0, _T("SFC") },
5336 { 1, _T("DFC") },
5337 { 2, _T("CACR") },
5338 { 3, _T("TC") },
5339 { 4, _T("ITT0") },
5340 { 5, _T("ITT1") },
5341 { 6, _T("DTT0") },
5342 { 7, _T("DTT1") },
5343 { 8, _T("BUSC") },
5344 { 0x800, _T("USP") },
5345 { 0x801, _T("VBR") },
5346 { 0x802, _T("CAAR") },
5347 { 0x803, _T("MSP") },
5348 { 0x804, _T("ISP") },
5349 { 0x805, _T("MMUS") },
5350 { 0x806, _T("URP") },
5351 { 0x807, _T("SRP") },
5352 { 0x808, _T("PCR") },
5353 { -1, NULL }
5354 };
5355
val_move2c2(int regno,uae_u32 val)5356 void val_move2c2 (int regno, uae_u32 val)
5357 {
5358 switch (regno) {
5359 case 0: regs.sfc = val; break;
5360 case 1: regs.dfc = val; break;
5361 case 2: regs.cacr = val; break;
5362 case 3: regs.tcr = val; break;
5363 case 4: regs.itt0 = val; break;
5364 case 5: regs.itt1 = val; break;
5365 case 6: regs.dtt0 = val; break;
5366 case 7: regs.dtt1 = val; break;
5367 case 8: regs.buscr = val; break;
5368 case 0x800: regs.usp = val; break;
5369 case 0x801: regs.vbr = val; break;
5370 case 0x802: regs.caar = val; break;
5371 case 0x803: regs.msp = val; break;
5372 case 0x804: regs.isp = val; break;
5373 case 0x805: regs.mmusr = val; break;
5374 case 0x806: regs.urp = val; break;
5375 case 0x807: regs.srp = val; break;
5376 case 0x808: regs.pcr = val; break;
5377 }
5378 }
5379
val_move2c(int regno)5380 uae_u32 val_move2c (int regno)
5381 {
5382 switch (regno) {
5383 case 0: return regs.sfc;
5384 case 1: return regs.dfc;
5385 case 2: return regs.cacr;
5386 case 3: return regs.tcr;
5387 case 4: return regs.itt0;
5388 case 5: return regs.itt1;
5389 case 6: return regs.dtt0;
5390 case 7: return regs.dtt1;
5391 case 8: return regs.buscr;
5392 case 0x800: return regs.usp;
5393 case 0x801: return regs.vbr;
5394 case 0x802: return regs.caar;
5395 case 0x803: return regs.msp;
5396 case 0x804: return regs.isp;
5397 case 0x805: return regs.mmusr;
5398 case 0x806: return regs.urp;
5399 case 0x807: return regs.srp;
5400 case 0x808: return regs.pcr;
5401 default: return 0;
5402 }
5403 }
5404
m68k_dumpstate2(uaecptr pc,uaecptr * nextpc)5405 void m68k_dumpstate2 (uaecptr pc, uaecptr *nextpc)
5406 {
5407 int i, j;
5408
5409 for (i = 0; i < 8; i++){
5410 console_out_f (_T(" D%d %08lX "), i, m68k_dreg (regs, i));
5411 if ((i & 3) == 3) console_out_f (_T("\n"));
5412 }
5413 for (i = 0; i < 8; i++){
5414 console_out_f (_T(" A%d %08lX "), i, m68k_areg (regs, i));
5415 if ((i & 3) == 3) console_out_f (_T("\n"));
5416 }
5417 if (regs.s == 0)
5418 regs.usp = m68k_areg (regs, 7);
5419 if (regs.s && regs.m)
5420 regs.msp = m68k_areg (regs, 7);
5421 if (regs.s && regs.m == 0)
5422 regs.isp = m68k_areg (regs, 7);
5423 j = 2;
5424 console_out_f (_T("USP %08X ISP %08X "), regs.usp, regs.isp);
5425 for (i = 0; m2cregs[i].regno>= 0; i++) {
5426 if (!movec_illg (m2cregs[i].regno)) {
5427 if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
5428 continue;
5429 if (j > 0 && (j % 4) == 0)
5430 console_out_f (_T("\n"));
5431 console_out_f (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
5432 j++;
5433 }
5434 }
5435 if (j > 0)
5436 console_out_f (_T("\n"));
5437 console_out_f (_T("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d STP=%d\n"),
5438 regs.t1, regs.t0, regs.s, regs.m,
5439 GET_XFLG (), GET_NFLG (), GET_ZFLG (),
5440 GET_VFLG (), GET_CFLG (),
5441 regs.intmask, regs.stopped);
5442 #ifdef FPUEMU
5443 if (currprefs.fpu_model) {
5444 uae_u32 fpsr;
5445 for (i = 0; i < 8; i++){
5446 console_out_f (_T("FP%d: %g "), i, regs.fp[i]);
5447 if ((i & 3) == 3)
5448 console_out_f (_T("\n"));
5449 }
5450 fpsr = get_fpsr ();
5451 console_out_f (_T("FPSR: %04X FPCR: %08x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
5452 fpsr, regs.fpcr, regs.fpiar,
5453 (fpsr & 0x8000000) != 0,
5454 (fpsr & 0x4000000) != 0,
5455 (fpsr & 0x2000000) != 0,
5456 (fpsr & 0x1000000) != 0);
5457 }
5458 #endif
5459 if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
5460 struct instr *dp;
5461 struct mnemolookup *lookup1, *lookup2;
5462 dp = table68k + regs.irc;
5463 for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
5464 dp = table68k + regs.ir;
5465 for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
5466 console_out_f (_T("Prefetch %04x (%s) %04x (%s)\n"), regs.irc, lookup1->name, regs.ir, lookup2->name);
5467 }
5468
5469 if (pc != 0xffffffff) {
5470 m68k_disasm (pc, nextpc, 1);
5471 if (nextpc)
5472 console_out_f (_T("Next PC: %08lx\n"), *nextpc);
5473 }
5474 }
m68k_dumpstate(uaecptr * nextpc)5475 void m68k_dumpstate (uaecptr *nextpc)
5476 {
5477 m68k_dumpstate2 (m68k_getpc (), nextpc);
5478 }
5479
5480 #else
5481
m68k_dumpstate2(uaecptr pc,uaecptr * nextpc)5482 void m68k_dumpstate2 (uaecptr pc, uaecptr *nextpc) {}
m68k_dumpstate(uaecptr * nextpc)5483 void m68k_dumpstate (uaecptr *nextpc) {}
5484
5485 #endif
5486
5487 #ifdef SAVESTATE
5488
5489 /* CPU save/restore code */
5490
5491 #define CPUTYPE_EC 1
5492 #define CPUMODE_HALT 1
5493
5494
5495
restore_cpu(uae_u8 * src)5496 uae_u8 *restore_cpu (uae_u8 *src)
5497 {
5498 int i, flags, model;
5499 uae_u32 l;
5500
5501 currprefs.cpu_model = changed_prefs.cpu_model = model = restore_u32 ();
5502 flags = restore_u32 ();
5503 changed_prefs.address_space_24 = 0;
5504 if (flags & CPUTYPE_EC)
5505 changed_prefs.address_space_24 = 1;
5506 currprefs.address_space_24 = changed_prefs.address_space_24;
5507 currprefs.cpu_compatible = changed_prefs.cpu_compatible;
5508 currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
5509 currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
5510 currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0;
5511 currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0;
5512 for (i = 0; i < 15; i++)
5513 regs.regs[i] = restore_u32 ();
5514 regs.pc = restore_u32 ();
5515 regs.irc = restore_u16 ();
5516 regs.ir = restore_u16 ();
5517 regs.usp = restore_u32 ();
5518 regs.isp = restore_u32 ();
5519 regs.sr = restore_u16 ();
5520 l = restore_u32 ();
5521 if (l & CPUMODE_HALT) {
5522 regs.stopped = 1;
5523 } else {
5524 regs.stopped = 0;
5525 }
5526 if (model >= 68010) {
5527 regs.dfc = restore_u32 ();
5528 regs.sfc = restore_u32 ();
5529 regs.vbr = restore_u32 ();
5530 }
5531 if (model >= 68020) {
5532 regs.caar = restore_u32 ();
5533 regs.cacr = restore_u32 ();
5534 regs.msp = restore_u32 ();
5535 }
5536 if (model >= 68030) {
5537 crp_030 = fake_crp_030 = restore_u64 ();
5538 srp_030 = fake_srp_030 = restore_u64 ();
5539 tt0_030 = fake_tt0_030 = restore_u32 ();
5540 tt1_030 = fake_tt1_030 = restore_u32 ();
5541 tc_030 = fake_tc_030 = restore_u32 ();
5542 mmusr_030 = fake_mmusr_030 = restore_u16 ();
5543 }
5544 if (model >= 68040) {
5545 regs.itt0 = restore_u32 ();
5546 regs.itt1 = restore_u32 ();
5547 regs.dtt0 = restore_u32 ();
5548 regs.dtt1 = restore_u32 ();
5549 regs.tcr = restore_u32 ();
5550 regs.urp = restore_u32 ();
5551 regs.srp = restore_u32 ();
5552 }
5553 if (model >= 68060) {
5554 regs.buscr = restore_u32 ();
5555 regs.pcr = restore_u32 ();
5556 }
5557 if (flags & 0x80000000) {
5558 int khz = restore_u32 ();
5559 restore_u32 ();
5560 if (khz > 0 && khz < 800000)
5561 currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
5562 }
5563 set_cpu_caches ();
5564 if (flags & 0x40000000) {
5565 if (model == 68020) {
5566 for (int i = 0; i < CACHELINES020; i++) {
5567 caches020[i].data = restore_u32 ();
5568 caches020[i].tag = restore_u32 ();
5569 caches020[i].valid = restore_u8 () != 0;
5570 }
5571 regs.prefetch020addr = restore_u32 ();
5572 regs.cacheholdingaddr020 = restore_u32 ();
5573 regs.cacheholdingdata020 = restore_u32 ();
5574 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
5575 regs.prefetch020[i] = restore_u16 ();
5576 } else if (model == 68030) {
5577 for (int i = 0; i < CACHELINES030; i++) {
5578 for (int j = 0; j < 4; j++) {
5579 icaches030[i].data[j] = restore_u32 ();
5580 icaches030[i].valid[j] = restore_u8 () != 0;
5581 }
5582 icaches030[i].tag = restore_u32 ();
5583 }
5584 for (int i = 0; i < CACHELINES030; i++) {
5585 for (int j = 0; j < 4; j++) {
5586 dcaches030[i].data[j] = restore_u32 ();
5587 dcaches030[i].valid[j] = restore_u8 () != 0;
5588 }
5589 dcaches030[i].tag = restore_u32 ();
5590 }
5591 }
5592 if (model >= 68020) {
5593 regs.ce020memcycles = restore_u32 ();
5594 regs.ce020tmpcycles = restore_u32 ();
5595 }
5596 }
5597
5598 write_log (_T("CPU: %d%s%03d, PC=%08X\n"),
5599 model / 1000, flags & 1 ? _T("EC") : _T(""), model % 1000, regs.pc);
5600
5601 return src;
5602 }
5603
restore_cpu_finish(void)5604 void restore_cpu_finish (void)
5605 {
5606 init_m68k ();
5607 m68k_setpc (regs.pc);
5608 doint ();
5609 fill_prefetch_quick ();
5610 set_cycles (start_cycles);
5611 events_schedule ();
5612 if (regs.stopped)
5613 set_special (SPCFLAG_STOP);
5614 //activate_debugger ();
5615 }
5616
save_cpu_trace(int * len,uae_u8 * dstptr)5617 uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
5618 {
5619 uae_u8 *dstbak, *dst;
5620
5621 if (cputrace.state <= 0)
5622 return NULL;
5623
5624 if (dstptr)
5625 dstbak = dst = dstptr;
5626 else
5627 dstbak = dst = xmalloc (uae_u8, 1000);
5628
5629 save_u32 (2 | 4);
5630 save_u16 (cputrace.opcode);
5631 for (int i = 0; i < 16; i++)
5632 save_u32 (cputrace.regs[i]);
5633 save_u32 (cputrace.pc);
5634 save_u16 (cputrace.irc);
5635 save_u16 (cputrace.ir);
5636 save_u32 (cputrace.usp);
5637 save_u32 (cputrace.isp);
5638 save_u16 (cputrace.sr);
5639 save_u16 (cputrace.intmask);
5640 save_u16 ((cputrace.stopped ? 1 : 0) | (regs.stopped ? 2 : 0));
5641 save_u16 (cputrace.state);
5642 save_u32 (cputrace.cyclecounter);
5643 save_u32 (cputrace.cyclecounter_pre);
5644 save_u32 (cputrace.cyclecounter_post);
5645 save_u32 (cputrace.readcounter);
5646 save_u32 (cputrace.writecounter);
5647 save_u32 (cputrace.memoryoffset);
5648 write_log (_T("CPUT SAVE: PC=%08x C=%08X %08x %08x %08x %d %d %d\n"),
5649 cputrace.pc, cputrace.startcycles,
5650 cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
5651 cputrace.readcounter, cputrace.writecounter, cputrace.memoryoffset);
5652 for (int i = 0; i < cputrace.memoryoffset; i++) {
5653 save_u32 (cputrace.ctm[i].addr);
5654 save_u32 (cputrace.ctm[i].data);
5655 save_u32 (cputrace.ctm[i].mode);
5656 write_log (_T("CPUT%d: %08x %08x %08x\n"), i, cputrace.ctm[i].addr, cputrace.ctm[i].data, cputrace.ctm[i].mode);
5657 }
5658 save_u32 (cputrace.startcycles);
5659
5660 if (currprefs.cpu_model == 68020) {
5661 for (int i = 0; i < CACHELINES020; i++) {
5662 save_u32 (cputrace.caches020[i].data);
5663 save_u32 (cputrace.caches020[i].tag);
5664 save_u8 (cputrace.caches020[i].valid ? 1 : 0);
5665 }
5666 save_u32 (cputrace.prefetch020addr);
5667 save_u32 (cputrace.cacheholdingaddr020);
5668 save_u32 (cputrace.cacheholdingdata020);
5669 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
5670 save_u16 (cputrace.prefetch020[i]);
5671 }
5672
5673 *len = dst - dstbak;
5674 cputrace.needendcycles = 1;
5675 return dstbak;
5676 }
5677
restore_cpu_trace(uae_u8 * src)5678 uae_u8 *restore_cpu_trace (uae_u8 *src)
5679 {
5680 cpu_tracer = 0;
5681 cputrace.state = 0;
5682 uae_u32 v = restore_u32 ();
5683 if (!(v & 2))
5684 return src;
5685 cputrace.opcode = restore_u16 ();
5686 for (int i = 0; i < 16; i++)
5687 cputrace.regs[i] = restore_u32 ();
5688 cputrace.pc = restore_u32 ();
5689 cputrace.irc = restore_u16 ();
5690 cputrace.ir = restore_u16 ();
5691 cputrace.usp = restore_u32 ();
5692 cputrace.isp = restore_u32 ();
5693 cputrace.sr = restore_u16 ();
5694 cputrace.intmask = restore_u16 ();
5695 cputrace.stopped = restore_u16 ();
5696 cputrace.state = restore_u16 ();
5697 cputrace.cyclecounter = restore_u32 ();
5698 cputrace.cyclecounter_pre = restore_u32 ();
5699 cputrace.cyclecounter_post = restore_u32 ();
5700 cputrace.readcounter = restore_u32 ();
5701 cputrace.writecounter = restore_u32 ();
5702 cputrace.memoryoffset = restore_u32 ();
5703 for (int i = 0; i < cputrace.memoryoffset; i++) {
5704 cputrace.ctm[i].addr = restore_u32 ();
5705 cputrace.ctm[i].data = restore_u32 ();
5706 cputrace.ctm[i].mode = restore_u32 ();
5707 }
5708 cputrace.startcycles = restore_u32 ();
5709
5710 if (v & 4) {
5711 if (currprefs.cpu_model == 68020) {
5712 for (int i = 0; i < CACHELINES020; i++) {
5713 cputrace.caches020[i].data = restore_u32 ();
5714 cputrace.caches020[i].tag = restore_u32 ();
5715 cputrace.caches020[i].valid = restore_u8 () != 0;
5716 }
5717 cputrace.prefetch020addr = restore_u32 ();
5718 cputrace.cacheholdingaddr020 = restore_u32 ();
5719 cputrace.cacheholdingdata020 = restore_u32 ();
5720 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
5721 cputrace.prefetch020[i] = restore_u16 ();
5722 }
5723 }
5724
5725 cputrace.needendcycles = 1;
5726 if (v && cputrace.state) {
5727 if (currprefs.cpu_model > 68000) {
5728 if (v & 4)
5729 cpu_tracer = -1;
5730 } else {
5731 cpu_tracer = -1;
5732 }
5733 }
5734
5735 return src;
5736 }
5737
restore_cpu_extra(uae_u8 * src)5738 uae_u8 *restore_cpu_extra (uae_u8 *src)
5739 {
5740 restore_u32 ();
5741 uae_u32 flags = restore_u32 ();
5742
5743 currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false;
5744 currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact;
5745 currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false;
5746 currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 ();
5747 currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 ();
5748 #ifdef JIT
5749 //currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0;
5750 #endif
5751
5752 currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
5753 if (flags & 4)
5754 currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
5755 if (flags & 16)
5756 currprefs.m68k_speed = changed_prefs.m68k_speed = (flags >> 24) * CYCLE_UNIT;
5757
5758 currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 ();
5759 currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 ();
5760
5761 return src;
5762 }
5763
save_cpu_extra(int * len,uae_u8 * dstptr)5764 uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr)
5765 {
5766 uae_u8 *dstbak, *dst;
5767 uae_u32 flags;
5768
5769 if (dstptr)
5770 dstbak = dst = dstptr;
5771 else
5772 dstbak = dst = xmalloc (uae_u8, 1000);
5773 save_u32 (0); // version
5774 flags = 0;
5775 flags |= currprefs.cpu_cycle_exact ? 1 : 0;
5776 flags |= currprefs.cpu_compatible ? 2 : 0;
5777 flags |= currprefs.m68k_speed < 0 ? 4 : 0;
5778 #ifdef JIT
5779 flags |= currprefs.cachesize > 0 ? 8 : 0;
5780 #endif
5781 flags |= currprefs.m68k_speed > 0 ? 16 : 0;
5782 if (currprefs.m68k_speed > 0)
5783 flags |= (currprefs.m68k_speed / CYCLE_UNIT) << 24;
5784 save_u32 (flags);
5785 save_u32 (currprefs.cpu_frequency);
5786 save_u32 (currprefs.cpu_clock_multiplier);
5787 save_u8 (currprefs.cpu060_revision);
5788 save_u8 (currprefs.fpu_revision);
5789 *len = dst - dstbak;
5790 return dstbak;
5791 }
5792
save_cpu(int * len,uae_u8 * dstptr)5793 uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
5794 {
5795 uae_u8 *dstbak, *dst;
5796 int model, i, khz;
5797
5798 if (dstptr)
5799 dstbak = dst = dstptr;
5800 else
5801 dstbak = dst = xmalloc (uae_u8, 1000);
5802 model = currprefs.cpu_model;
5803 save_u32 (model); /* MODEL */
5804 save_u32 (0x80000000 | 0x40000000 | (currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
5805 for (i = 0;i < 15; i++)
5806 save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */
5807 save_u32 (m68k_getpc ()); /* PC */
5808 save_u16 (regs.irc); /* prefetch */
5809 save_u16 (regs.ir); /* instruction prefetch */
5810 MakeSR ();
5811 save_u32 (!regs.s ? regs.regs[15] : regs.usp); /* USP */
5812 save_u32 (regs.s ? regs.regs[15] : regs.isp); /* ISP */
5813 save_u16 (regs.sr); /* SR/CCR */
5814 save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */
5815 if (model >= 68010) {
5816 save_u32 (regs.dfc); /* DFC */
5817 save_u32 (regs.sfc); /* SFC */
5818 save_u32 (regs.vbr); /* VBR */
5819 }
5820 if (model >= 68020) {
5821 save_u32 (regs.caar); /* CAAR */
5822 save_u32 (regs.cacr); /* CACR */
5823 save_u32 (regs.msp); /* MSP */
5824 }
5825 if (model >= 68030) {
5826 if (currprefs.mmu_model) {
5827 save_u64 (crp_030); /* CRP */
5828 save_u64 (srp_030); /* SRP */
5829 save_u32 (tt0_030); /* TT0/AC0 */
5830 save_u32 (tt1_030); /* TT1/AC1 */
5831 save_u32 (tc_030); /* TCR */
5832 save_u16 (mmusr_030); /* MMUSR/ACUSR */
5833 } else {
5834 save_u64 (fake_crp_030); /* CRP */
5835 save_u64 (fake_srp_030); /* SRP */
5836 save_u32 (fake_tt0_030); /* TT0/AC0 */
5837 save_u32 (fake_tt1_030); /* TT1/AC1 */
5838 save_u32 (fake_tc_030); /* TCR */
5839 save_u16 (fake_mmusr_030); /* MMUSR/ACUSR */
5840 }
5841 }
5842 if (model >= 68040) {
5843 save_u32 (regs.itt0); /* ITT0 */
5844 save_u32 (regs.itt1); /* ITT1 */
5845 save_u32 (regs.dtt0); /* DTT0 */
5846 save_u32 (regs.dtt1); /* DTT1 */
5847 save_u32 (regs.tcr); /* TCR */
5848 save_u32 (regs.urp); /* URP */
5849 save_u32 (regs.srp); /* SRP */
5850 }
5851 if (model >= 68060) {
5852 save_u32 (regs.buscr); /* BUSCR */
5853 save_u32 (regs.pcr); /* PCR */
5854 }
5855 khz = -1;
5856 if (currprefs.m68k_speed == 0) {
5857 khz = currprefs.ntscmode ? 715909 : 709379;
5858 if (currprefs.cpu_model >= 68020)
5859 khz *= 2;
5860 }
5861 save_u32 (khz); // clock rate in KHz: -1 = fastest possible
5862 save_u32 (0); // spare
5863 if (model == 68020) {
5864 for (int i = 0; i < CACHELINES020; i++) {
5865 save_u32 (caches020[i].data);
5866 save_u32 (caches020[i].tag);
5867 save_u8 (caches020[i].valid ? 1 : 0);
5868 }
5869 save_u32 (regs.prefetch020addr);
5870 save_u32 (regs.cacheholdingaddr020);
5871 save_u32 (regs.cacheholdingdata020);
5872 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
5873 save_u16 (regs.prefetch020[i]);
5874 } else if (model == 68030) {
5875 for (int i = 0; i < CACHELINES030; i++) {
5876 for (int j = 0; j < 4; j++) {
5877 save_u32 (icaches030[i].data[j]);
5878 save_u8 (icaches030[i].valid[j] ? 1 : 0);
5879 }
5880 save_u32 (icaches030[i].tag);
5881 }
5882 for (int i = 0; i < CACHELINES030; i++) {
5883 for (int j = 0; j < 4; j++) {
5884 save_u32 (dcaches030[i].data[j]);
5885 save_u8 (dcaches030[i].valid[j] ? 1 : 0);
5886 }
5887 save_u32 (dcaches030[i].tag);
5888 }
5889 }
5890 if (currprefs.cpu_model >= 68020) {
5891 save_u32 (regs.ce020memcycles);
5892 save_u32 (regs.ce020tmpcycles);
5893 }
5894 *len = dst - dstbak;
5895 return dstbak;
5896 }
5897
5898 #ifdef MMUEMU
save_mmu(int * len,uae_u8 * dstptr)5899 uae_u8 *save_mmu (int *len, uae_u8 *dstptr)
5900 {
5901 uae_u8 *dstbak, *dst;
5902 int model;
5903
5904 model = currprefs.mmu_model;
5905 if (model != 68030 && model != 68040 && model != 68060)
5906 return NULL;
5907 if (dstptr)
5908 dstbak = dst = dstptr;
5909 else
5910 dstbak = dst = xmalloc (uae_u8, 1000);
5911 save_u32 (model); /* MODEL */
5912 save_u32 (0); /* FLAGS */
5913 *len = dst - dstbak;
5914 return dstbak;
5915 }
5916
restore_mmu(uae_u8 * src)5917 uae_u8 *restore_mmu (uae_u8 *src)
5918 {
5919 int flags, model;
5920
5921 changed_prefs.mmu_model = model = restore_u32 ();
5922 flags = restore_u32 ();
5923 write_log (_T("MMU: %d\n"), model);
5924 return src;
5925 }
5926 #endif //MMUEMU
5927 #endif /* SAVESTATE */
5928
exception3f(uae_u32 opcode,uaecptr addr,int writeaccess,int instructionaccess,uae_u32 pc)5929 static void exception3f (uae_u32 opcode, uaecptr addr, int writeaccess, int instructionaccess, uae_u32 pc)
5930 {
5931 if (currprefs.cpu_model >= 68040)
5932 addr &= ~1;
5933 if (currprefs.cpu_model >= 68020) {
5934 if (pc == 0xffffffff)
5935 last_addr_for_exception_3 = regs.instruction_pc;
5936 else
5937 last_addr_for_exception_3 = pc;
5938 } else if (pc == 0xffffffff) {
5939 last_addr_for_exception_3 = m68k_getpc () + 2;
5940 } else {
5941 last_addr_for_exception_3 = pc;
5942 }
5943 last_fault_for_exception_3 = addr;
5944 last_op_for_exception_3 = opcode;
5945 last_writeaccess_for_exception_3 = writeaccess;
5946 last_instructionaccess_for_exception_3 = instructionaccess;
5947 Exception (3);
5948 #if EXCEPTION3_DEBUGGER
5949 //activate_debugger();
5950 #endif
5951 }
5952
exception3(uae_u32 opcode,uaecptr addr)5953 void exception3 (uae_u32 opcode, uaecptr addr)
5954 {
5955 exception3f (opcode, addr, 0, 0, 0xffffffff);
5956 }
exception3i(uae_u32 opcode,uaecptr addr)5957 void exception3i (uae_u32 opcode, uaecptr addr)
5958 {
5959 exception3f (opcode, addr, 0, 1, 0xffffffff);
5960 }
exception3pc(uae_u32 opcode,uaecptr addr,bool w,bool i,uaecptr pc)5961 void exception3pc (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
5962 {
5963 exception3f (opcode, addr, w, i, pc);
5964 }
5965
exception2(uaecptr addr)5966 void exception2 (uaecptr addr)
5967 {
5968 write_log (_T("delayed exception2!\n"));
5969 regs.panic_pc = m68k_getpc ();
5970 regs.panic_addr = addr;
5971 regs.panic = 6;
5972 set_special (SPCFLAG_BRK);
5973 m68k_setpc (0xf80000);
5974 #ifdef JIT
5975 set_special (SPCFLAG_END_COMPILE);
5976 #endif
5977 fill_prefetch ();
5978 }
5979
cpureset(void)5980 void cpureset (void)
5981 {
5982 /* RESET hasn't increased PC yet, 1 word offset */
5983 uaecptr pc;
5984 uaecptr ksboot = 0xf80002 - 2;
5985 uae_u16 ins;
5986 addrbank *ab;
5987
5988 send_internalevent (INTERNALEVENT_CPURESET);
5989 if ((currprefs.cpu_compatible || currprefs.cpu_cycle_exact) && currprefs.cpu_model <= 68020) {
5990 custom_reset (false, false);
5991 return;
5992 }
5993 pc = m68k_getpc () + 2;
5994 ab = &get_mem_bank (pc);
5995 if (ab->check (pc, 2)) {
5996 write_log (_T("CPU reset PC=%x (%s)..\n"), pc - 2, ab->name);
5997 ins = get_word (pc);
5998 custom_reset (false, false);
5999 // did memory disappear under us?
6000 if (ab == &get_mem_bank (pc))
6001 return;
6002 // it did
6003 if ((ins & ~7) == 0x4ed0) {
6004 int reg = ins & 7;
6005 uae_u32 addr = m68k_areg (regs, reg);
6006 if (addr < 0x80000)
6007 addr += 0xf80000;
6008 write_log (_T("reset/jmp (ax) combination emulated -> %x\n"), addr);
6009 m68k_setpc (addr - 2);
6010 return;
6011 }
6012 }
6013 // the best we can do, jump directly to ROM entrypoint
6014 // (which is probably what program wanted anyway)
6015 write_log (_T("CPU Reset PC=%x (%s), invalid memory -> %x.\n"), pc, ab->name, ksboot + 2);
6016 custom_reset (false, false);
6017 m68k_setpc (ksboot);
6018 }
6019
6020
m68k_setstopped(void)6021 void m68k_setstopped (void)
6022 {
6023 regs.stopped = 1;
6024 /* A traced STOP instruction drops through immediately without
6025 actually stopping. */
6026 if ((regs.spcflags & SPCFLAG_DOTRACE) == 0)
6027 set_special (SPCFLAG_STOP);
6028 else
6029 m68k_resumestopped ();
6030 }
6031
m68k_resumestopped(void)6032 void m68k_resumestopped (void)
6033 {
6034 if (!regs.stopped)
6035 return;
6036 regs.stopped = 0;
6037 if (currprefs.cpu_cycle_exact) {
6038 if (currprefs.cpu_model == 68000)
6039 x_do_cycles (6 * cpucycleunit);
6040 }
6041 fill_prefetch ();
6042 unset_special (SPCFLAG_STOP);
6043 }
6044
6045 /*
6046 * Compute exact number of CPU cycles taken
6047 * by DIVU and DIVS on a 68000 processor.
6048 *
6049 * Copyright (c) 2005 by Jorge Cwik, pasti@fxatari.com
6050 *
6051 * This is free software; you can redistribute it and/or modify
6052 * it under the terms of the GNU General Public License as published by
6053 * the Free Software Foundation; either version 2 of the License, or
6054 * (at your option) any later version.
6055 *
6056 * This software is distributed in the hope that it will be useful,
6057 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6058 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6059 * GNU General Public License for more details.
6060 *
6061 * You should have received a copy of the GNU General Public License
6062 * along with this software; if not, write to the Free Software
6063 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6064 *
6065 */
6066
6067
6068 /*
6069
6070 The routines below take dividend and divisor as parameters.
6071 They return 0 if division by zero, or exact number of cycles otherwise.
6072
6073 The number of cycles returned assumes a register operand.
6074 Effective address time must be added if memory operand.
6075
6076 For 68000 only (not 68010, 68012, 68020, etc).
6077 Probably valid for 68008 after adding the extra prefetch cycle.
6078
6079
6080 Best and worst cases for register operand:
6081 (Note the difference with the documented range.)
6082
6083
6084 DIVU:
6085
6086 Overflow (always): 10 cycles.
6087 Worst case: 136 cycles.
6088 Best case: 76 cycles.
6089
6090
6091 DIVS:
6092
6093 Absolute overflow: 16-18 cycles.
6094 Signed overflow is not detected prematurely.
6095
6096 Worst case: 156 cycles.
6097 Best case without signed overflow: 122 cycles.
6098 Best case with signed overflow: 120 cycles
6099
6100
6101 */
6102
6103 // DIVU
6104 // Unsigned division
getDivu68kCycles(uae_u32 dividend,uae_u16 divisor)6105 int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor)
6106 {
6107 int mcycles;
6108 uae_u32 hdivisor;
6109 int i;
6110
6111 if (divisor == 0)
6112 return 0;
6113
6114 // Overflow
6115 if ((dividend >> 16) >= divisor)
6116 return (mcycles = 5) * 2;
6117
6118 mcycles = 38;
6119 hdivisor = divisor << 16;
6120
6121 for (i = 0; i < 15; i++) {
6122 uae_u32 temp;
6123 temp = dividend;
6124
6125 dividend <<= 1;
6126
6127 // If carry from shift
6128 if ((uae_s32)temp < 0)
6129 dividend -= hdivisor;
6130 else {
6131 mcycles += 2;
6132 if (dividend >= hdivisor) {
6133 dividend -= hdivisor;
6134 mcycles--;
6135 }
6136 }
6137 }
6138 return mcycles * 2;
6139 }
6140
6141 // DIVS
6142 // Signed division
getDivs68kCycles(uae_s32 dividend,uae_s16 divisor)6143 int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
6144 {
6145 int mcycles;
6146 uae_u32 aquot;
6147 int i;
6148
6149 if (divisor == 0)
6150 return 0;
6151
6152 mcycles = 6;
6153
6154 if (dividend < 0)
6155 mcycles++;
6156
6157 // Check for absolute overflow
6158 if (((uae_u32)abs (dividend) >> 16) >= (uae_u16)abs (divisor))
6159 return (mcycles + 2) * 2;
6160
6161 // Absolute quotient
6162 aquot = (uae_u32) abs (dividend) / (uae_u16)abs (divisor);
6163
6164 mcycles += 55;
6165
6166 if (divisor >= 0) {
6167 if (dividend >= 0)
6168 mcycles--;
6169 else
6170 mcycles++;
6171 }
6172
6173 // Count 15 msbits in absolute of quotient
6174
6175 for (i = 0; i < 15; i++) {
6176 if ((uae_s16)aquot >= 0)
6177 mcycles++;
6178 aquot <<= 1;
6179 }
6180
6181 return mcycles * 2;
6182 }
6183
6184 /* 68000 Z=1. NVC=0
6185 * 68020 and 68030: Signed: Z=1 NVC=0. Unsigned: V=1, N<dst, Z=!N, C=0.
6186 * 68040/68060 C=0.
6187 */
divbyzero_special(bool issigned,uae_s32 dst)6188 void divbyzero_special (bool issigned, uae_s32 dst)
6189 {
6190 if (currprefs.cpu_model == 68020 || currprefs.cpu_model == 68030) {
6191 CLEAR_CZNV ();
6192 if (issigned == false) {
6193 if (dst < 0)
6194 SET_NFLG (1);
6195 SET_ZFLG (!GET_NFLG ());
6196 SET_VFLG (1);
6197 } else {
6198 SET_ZFLG (1);
6199 }
6200 } else if (currprefs.cpu_model >= 68040) {
6201 SET_CFLG (0);
6202 } else {
6203 // 68000/010
6204 CLEAR_CZNV ();
6205 }
6206 }
6207
fill_cache040(uae_u32 addr)6208 STATIC_INLINE void fill_cache040 (uae_u32 addr)
6209 {
6210 int index, i, lws;
6211 uae_u32 tag;
6212 uae_u32 data;
6213 struct cache040 *c;
6214 static int linecnt;
6215
6216 addr &= ~15;
6217 index = (addr >> 4) & (CACHESETS040 - 1);
6218 tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
6219 lws = (addr >> 2) & 3;
6220 c = &caches040[index];
6221 for (i = 0; i < CACHELINES040; i++) {
6222 if (c->valid[i] && c->tag[i] == tag) {
6223 // cache hit
6224 regs.cacheholdingaddr020 = addr;
6225 regs.cacheholdingdata020 = c->data[i][lws];
6226 return;
6227 }
6228 }
6229 // cache miss
6230 data = mem_access_delay_longi_read_ce020 (addr);
6231 int line = linecnt;
6232 for (i = 0; i < CACHELINES040; i++) {
6233 int line = (linecnt + i) & (CACHELINES040 - 1);
6234 if (c->tag[i] != tag || c->valid[i] == false) {
6235 c->tag[i] = tag;
6236 c->valid[i] = true;
6237 c->data[i][0] = data;
6238 }
6239 }
6240 regs.cacheholdingaddr020 = addr;
6241 regs.cacheholdingdata020 = data;
6242 }
6243
6244 // this one is really simple and easy
fill_icache020(uae_u32 addr)6245 static void fill_icache020 (uae_u32 addr)
6246 {
6247 int index;
6248 uae_u32 tag;
6249 uae_u32 data;
6250 struct cache020 *c;
6251
6252 addr &= ~3;
6253 index = (addr >> 2) & (CACHELINES020 - 1);
6254 tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
6255 c = &caches020[index];
6256 if (c->valid && c->tag == tag) {
6257 // cache hit
6258 regs.cacheholdingaddr020 = addr;
6259 regs.cacheholdingdata020 = c->data;
6260 return;
6261 }
6262 // cache miss
6263 data = x_get_long (addr);
6264 if (!(regs.cacr & 2)) {
6265 c->tag = tag;
6266 c->valid = !!(regs.cacr & 1);
6267 c->data = data;
6268 }
6269 regs.cacheholdingaddr020 = addr;
6270 regs.cacheholdingdata020 = data;
6271 }
6272
get_word_ce020_prefetch(int o)6273 uae_u32 get_word_ce020_prefetch (int o)
6274 {
6275 uae_u32 pc = m68k_getpc () + o;
6276
6277 if (pc == regs.prefetch020addr) {
6278 uae_u32 v = regs.prefetch020[0];
6279 regs.prefetch020[0] = regs.prefetch020[1];
6280 regs.prefetch020[1] = regs.prefetch020[2];
6281 pc += 4 + 2;
6282 if (regs.cacheholdingaddr020 != (pc & ~3))
6283 fill_icache020 (pc);
6284 regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6285 regs.prefetch020addr += 2;
6286 return v;
6287 } else {
6288 regs.prefetch020addr = pc;
6289 fill_icache020 (pc);
6290 regs.prefetch020[0] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6291 pc += 2;
6292 fill_icache020 (pc);
6293 regs.prefetch020[1] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6294 pc += 2;
6295 fill_icache020 (pc);
6296 regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6297 return get_word_ce020_prefetch (o);
6298 }
6299 }
6300
6301 // 68030 caches aren't so simple as 68020 cache..
getcache030(struct cache030 * cp,uaecptr addr,uae_u32 * tagp,int * lwsp)6302 STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
6303 {
6304 int index, lws;
6305 uae_u32 tag;
6306 struct cache030 *c;
6307
6308 addr &= ~3;
6309 index = (addr >> 4) & (CACHELINES030 - 1);
6310 tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1));
6311 lws = (addr >> 2) & 3;
6312 c = &cp[index];
6313 *tagp = tag;
6314 *lwsp = lws;
6315 return c;
6316 }
6317
update_cache030(struct cache030 * c,uae_u32 val,uae_u32 tag,int lws)6318 STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
6319 {
6320 if (c->tag != tag)
6321 c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
6322 c->tag = tag;
6323 c->valid[lws] = true;
6324 c->data[lws] = val;
6325 }
6326
fill_icache030(uae_u32 addr)6327 STATIC_INLINE void fill_icache030 (uae_u32 addr)
6328 {
6329 int lws;
6330 uae_u32 tag;
6331 uae_u32 data;
6332 struct cache030 *c;
6333
6334 addr &= ~3;
6335 if (addr == regs.cacheholdingaddr020)
6336 return;
6337 c = getcache030 (icaches030, addr, &tag, &lws);
6338 if (c->valid[lws] && c->tag == tag) {
6339 // cache hit
6340 regs.cacheholdingaddr020 = addr;
6341 regs.cacheholdingdata020 = c->data[lws];
6342 return;
6343 }
6344 // cache miss
6345 data = mem_access_delay_longi_read_ce020 (addr);
6346 if ((regs.cacr & 3) == 1) { // not frozen and enabled
6347 update_cache030 (c, data, tag, lws);
6348 #if 0
6349 if ((regs.cacr & 0x11) == 0x11 && lws == 0 && !c->valid[0] && !c->valid[1] && !c->valid[2] && !c->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST) {
6350 // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
6351 c->data[1] = mem_access_delay_long_read_ce020 (addr + 4);
6352 c->data[2] = mem_access_delay_long_read_ce020 (addr + 8);
6353 c->data[3] = mem_access_delay_long_read_ce020 (addr + 12);
6354 c->valid[1] = c->valid[2] = c->valid[3] = true;
6355 }
6356 #endif
6357 }
6358 regs.cacheholdingaddr020 = addr;
6359 regs.cacheholdingdata020 = data;
6360 }
6361
cancache030(uaecptr addr)6362 STATIC_INLINE bool cancache030 (uaecptr addr)
6363 {
6364 return ce_cachable[addr >> 16] != 0;
6365 }
6366
6367 // and finally the worst part, 68030 data cache..
write_dcache030(uaecptr addr,uae_u32 val,int size)6368 void write_dcache030 (uaecptr addr, uae_u32 val, int size)
6369 {
6370 struct cache030 *c1, *c2;
6371 int lws1, lws2;
6372 uae_u32 tag1, tag2;
6373 int aligned = addr & 3;
6374
6375 if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040) // data cache disabled? 68040 shares this too.
6376 return;
6377 if (!cancache030 (addr))
6378 return;
6379
6380 c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
6381 if (!(regs.cacr & 0x2000)) { // write allocate
6382 if (c1->tag != tag1 || c1->valid[lws1] == false)
6383 return;
6384 }
6385
6386 #if 0
6387 uaecptr a = 0x1db0c;
6388 if (addr - (1 << size) + 1 <= a && addr + (1 << size) >= a) {
6389 write_log (_T("%08x %d %d %08x %08x %d\n"), addr, aligned, size, val, tag1, lws1);
6390 if (aligned == 2)
6391 write_log (_T("*\n"));
6392 }
6393 #endif
6394
6395 // easy one
6396 if (size == 2 && aligned == 0) {
6397 update_cache030 (c1, val, tag1, lws1);
6398 #if 0
6399 if ((regs.cacr & 0x1100) == 0x1100 && lws1 == 0 && !c1->valid[0] && !c1->valid[1] && !c1->valid[2] && !c1->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST) {
6400 // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
6401 c1->data[1] = mem_access_delay_long_read_ce020 (addr + 4);
6402 c1->data[2] = mem_access_delay_long_read_ce020 (addr + 8);
6403 c1->data[3] = mem_access_delay_long_read_ce020 (addr + 12);
6404 c1->valid[1] = c1->valid[2] = c1->valid[3] = true;
6405 }
6406 #endif
6407 return;
6408 }
6409 // argh!! merge partial write
6410 c2 = getcache030 (dcaches030, addr + 4, &tag2, &lws2);
6411 if (size == 2) {
6412 if (c1->valid[lws1] && c1->tag == tag1) {
6413 c1->data[lws1] &= ~(0xffffffff >> (aligned * 8));
6414 c1->data[lws1] |= val >> (aligned * 8);
6415 }
6416 if (c2->valid[lws2] && c2->tag == tag2) {
6417 c2->data[lws2] &= 0xffffffff >> ((4 - aligned) * 8);
6418 c2->data[lws2] |= val << ((4 - aligned) * 8);
6419 }
6420 } else if (size == 1) {
6421 val <<= 16;
6422 if (c1->valid[lws1] && c1->tag == tag1) {
6423 c1->data[lws1] &= ~(0xffff0000 >> (aligned * 8));
6424 c1->data[lws1] |= val >> (aligned * 8);
6425 }
6426 if (c2->valid[lws2] && c2->tag == tag2 && aligned == 3) {
6427 c2->data[lws2] &= 0x00ffffff;
6428 c2->data[lws2] |= val << 8;
6429 }
6430 } else if (size == 0) {
6431 val <<= 24;
6432 if (c1->valid[lws1] && c1->tag == tag1) {
6433 c1->data[lws1] &= ~(0xff000000 >> (aligned * 8));
6434 c1->data[lws1] |= val >> (aligned * 8);
6435 }
6436 }
6437 }
6438
read_dcache030(uaecptr addr,int size)6439 uae_u32 read_dcache030 (uaecptr addr, int size)
6440 {
6441 struct cache030 *c1, *c2;
6442 int lws1, lws2;
6443 uae_u32 tag1, tag2;
6444 int aligned = addr & 3;
6445 int len = (1 << size) * 8;
6446 uae_u32 v1, v2;
6447
6448 if (!(regs.cacr & 0x100) || currprefs.cpu_model == 68040 || !cancache030 (addr)) { // data cache disabled? shared with 68040 "ce"
6449 if (size == 2)
6450 return mem_access_delay_long_read_ce020 (addr);
6451 else if (size == 1)
6452 return mem_access_delay_word_read_ce020 (addr);
6453 else
6454 return mem_access_delay_byte_read_ce020 (addr);
6455 }
6456
6457 c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
6458 addr &= ~3;
6459 if (!c1->valid[lws1] || c1->tag != tag1) {
6460 v1 = mem_access_delay_long_read_ce020 (addr);
6461 update_cache030 (c1, v1, tag1, lws1);
6462 } else {
6463 v1 = c1->data[lws1];
6464 if (get_long (addr) != v1) {
6465 write_log (_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
6466 size, aligned, addr, get_long (addr), v1, tag1, lws1, M68K_GETPC);
6467 v1 = get_long (addr);
6468 }
6469 }
6470 // only one long fetch needed?
6471 if (size == 0) {
6472 v1 >>= (3 - aligned) * 8;
6473 return v1;
6474 } else if (size == 1 && aligned <= 2) {
6475 v1 >>= (2 - aligned) * 8;
6476 return v1;
6477 } else if (size == 2 && aligned == 0) {
6478 return v1;
6479 }
6480 // need two longs
6481 addr += 4;
6482 c2 = getcache030 (dcaches030, addr, &tag2, &lws2);
6483 if (!c2->valid[lws2] || c2->tag != tag2) {
6484 v2 = mem_access_delay_long_read_ce020 (addr);
6485 update_cache030 (c2, v2, tag2, lws2);
6486 } else {
6487 v2 = c2->data[lws2];
6488 if (get_long (addr) != v2) {
6489 write_log (_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
6490 size, aligned, addr, get_long (addr), v2, tag2, lws2, M68K_GETPC);
6491 v2 = get_long (addr);
6492 }
6493 }
6494 if (size == 1 && aligned == 3)
6495 return (v1 << 8) | (v2 >> 24);
6496 else if (size == 2 && aligned == 1)
6497 return (v1 << 8) | (v2 >> 24);
6498 else if (size == 2 && aligned == 2)
6499 return (v1 << 16) | (v2 >> 16);
6500 else if (size == 2 && aligned == 3)
6501 return (v1 << 24) | (v2 >> 8);
6502
6503 write_log (_T("dcache030 weirdness!?\n"));
6504 return 0;
6505 }
6506
get_word_ce030_prefetch(int o)6507 uae_u32 get_word_ce030_prefetch (int o)
6508 {
6509 uae_u32 pc = m68k_getpc () + o;
6510
6511 if (pc == regs.prefetch020addr) {
6512 uae_u32 v = regs.prefetch020[0];
6513 regs.prefetch020[0] = regs.prefetch020[1];
6514 regs.prefetch020[1] = regs.prefetch020[2];
6515 pc += 4 + 2;
6516 fill_icache030 (pc);
6517 regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6518 regs.prefetch020addr += 2;
6519 fill_icache030 (pc + 4);
6520 return v;
6521 } else {
6522 regs.prefetch020addr = pc;
6523 fill_icache030 (pc);
6524 regs.prefetch020[0] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6525 pc += 2;
6526 fill_icache030 (pc);
6527 regs.prefetch020[1] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6528 pc += 2;
6529 fill_icache030 (pc);
6530 regs.prefetch020[2] = (regs.cacheholdingaddr020 == pc) ? (regs.cacheholdingdata020 >> 16) : (regs.cacheholdingdata020 >> 0);
6531 return get_word_ce030_prefetch (o);
6532 }
6533 }
6534
flush_dcache(uaecptr addr,int size)6535 void flush_dcache (uaecptr addr, int size)
6536 {
6537 if (!currprefs.cpu_cycle_exact)
6538 return;
6539 if (currprefs.cpu_model >= 68030) {
6540 for (int i = 0; i < CACHELINES030; i++) {
6541 dcaches030[i].valid[0] = 0;
6542 dcaches030[i].valid[1] = 0;
6543 dcaches030[i].valid[2] = 0;
6544 dcaches030[i].valid[3] = 0;
6545 }
6546 }
6547 }
6548
6549