1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * MC68000 emulation
5 *
6 * (c) 1995 Bernd Schmidt
7 */
8
9 #define MMUOP_DEBUG 2
10 #define DEBUG_CD32CDTVIO 0
11 #define EXCEPTION3_DEBUGGER 0
12 #define CPUTRACE_DEBUG 0
13
14 #define MORE_ACCURATE_68020_PIPELINE 1
15
16 #include "sysconfig.h"
17 #include "sysdeps.h"
18
19 #include "options.h"
20 #include "events.h"
21 #include "uae.h"
22 #include "uae/memory.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 "audio.h"
40 #include "md-fpp.h"
41 #include "statusline.h"
42 #include "uae/ppc.h"
43 #include "cpuboard.h"
44 #include "threaddep/thread.h"
45 #include "x86.h"
46 #include "bsdsocket.h"
47 #ifdef JIT
48 #include "jit/compemu.h"
49 #include <signal.h>
50 #endif
51 /* For faster JIT cycles handling */
52 uae_s32 pissoff = 0;
53
54 /* Opcode of faulting instruction */
55 static uae_u16 last_op_for_exception_3;
56 /* PC at fault time */
57 static uaecptr last_addr_for_exception_3;
58 /* Address that generated the exception */
59 static uaecptr last_fault_for_exception_3;
60 /* read (0) or write (1) access */
61 static bool last_writeaccess_for_exception_3;
62 /* instruction (1) or data (0) access */
63 static bool last_instructionaccess_for_exception_3;
64 /* not instruction */
65 static bool last_notinstruction_for_exception_3;
66 /* set when writing exception stack frame */
67 static int exception_in_exception;
68
69 int mmu_enabled, mmu_triggered;
70 int cpu_cycles;
71 int bus_error_offset;
72 static int baseclock;
73 int m68k_pc_indirect;
74 bool m68k_interrupt_delay;
75 static bool m68k_reset_delay;
76 static int cpu_prefs_changed_flag;
77
78 int cpucycleunit;
79 int cpu_tracer;
80
81 const int areg_byteinc[] = { 1, 1, 1, 1, 1, 1, 1, 2 };
82 const int imm8_table[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
83
84 int movem_index1[256];
85 int movem_index2[256];
86 int movem_next[256];
87
88 cpuop_func *cpufunctbl[65536];
89
90 struct cputbl_data
91 {
92 uae_s16 length;
93 uae_s8 disp020[2];
94 uae_u8 branch;
95 };
96 static struct cputbl_data cpudatatbl[65536];
97
98 struct mmufixup mmufixup[2];
99
100 #define COUNT_INSTRS 0
101 #define MC68060_PCR 0x04300000
102 #define MC68EC060_PCR 0x04310000
103
104 static uae_u64 fake_srp_030, fake_crp_030;
105 static uae_u32 fake_tt0_030, fake_tt1_030, fake_tc_030;
106 static uae_u16 fake_mmusr_030;
107
108 static struct cache020 caches020[CACHELINES020];
109 static struct cache030 icaches030[CACHELINES030];
110 static struct cache030 dcaches030[CACHELINES030];
111 static int icachelinecnt, dcachelinecnt;
112 static struct cache040 icaches040[CACHESETS040];
113 static struct cache040 dcaches040[CACHESETS040];
114
115 #if COUNT_INSTRS
116 static unsigned long int instrcount[65536];
117 static uae_u16 opcodenums[65536];
118
compfn(const void * el1,const void * el2)119 static int compfn (const void *el1, const void *el2)
120 {
121 return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
122 }
123
icountfilename(void)124 static TCHAR *icountfilename (void)
125 {
126 TCHAR *name = getenv ("INSNCOUNT");
127 if (name)
128 return name;
129 return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
130 }
131
dump_counts(void)132 void dump_counts (void)
133 {
134 FILE *f = fopen (icountfilename (), "w");
135 unsigned long int total;
136 int i;
137
138 write_log (_T("Writing instruction count file...\n"));
139 for (i = 0; i < 65536; i++) {
140 opcodenums[i] = i;
141 total += instrcount[i];
142 }
143 qsort (opcodenums, 65536, sizeof (uae_u16), compfn);
144
145 fprintf (f, "Total: %lu\n", total);
146 for (i=0; i < 65536; i++) {
147 unsigned long int cnt = instrcount[opcodenums[i]];
148 struct instr *dp;
149 struct mnemolookup *lookup;
150 if (!cnt)
151 break;
152 dp = table68k + opcodenums[i];
153 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
154 ;
155 fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
156 }
157 fclose (f);
158 }
159 #else
dump_counts(void)160 void dump_counts (void)
161 {
162 }
163 #endif
164
165 /*
166
167 ok, all this to "record" current instruction state
168 for later 100% cycle-exact restoring
169
170 */
171
172 static uae_u32 (*x2_prefetch)(int);
173 static uae_u32 (*x2_prefetch_long)(int);
174 static uae_u32 (*x2_next_iword)(void);
175 static uae_u32 (*x2_next_ilong)(void);
176 static uae_u32 (*x2_get_ilong)(int);
177 static uae_u32 (*x2_get_iword)(int);
178 static uae_u32 (*x2_get_ibyte)(int);
179 static uae_u32 (*x2_get_long)(uaecptr);
180 static uae_u32 (*x2_get_word)(uaecptr);
181 static uae_u32 (*x2_get_byte)(uaecptr);
182 static void (*x2_put_long)(uaecptr,uae_u32);
183 static void (*x2_put_word)(uaecptr,uae_u32);
184 static void (*x2_put_byte)(uaecptr,uae_u32);
185 static void (*x2_do_cycles)(unsigned long);
186 static void (*x2_do_cycles_pre)(unsigned long);
187 static void (*x2_do_cycles_post)(unsigned long, uae_u32);
188
189 uae_u32 (*x_prefetch)(int);
190 uae_u32 (*x_next_iword)(void);
191 uae_u32 (*x_next_ilong)(void);
192 uae_u32 (*x_get_ilong)(int);
193 uae_u32 (*x_get_iword)(int);
194 uae_u32 (*x_get_ibyte)(int);
195 uae_u32 (*x_get_long)(uaecptr);
196 uae_u32 (*x_get_word)(uaecptr);
197 uae_u32 (*x_get_byte)(uaecptr);
198 void (*x_put_long)(uaecptr,uae_u32);
199 void (*x_put_word)(uaecptr,uae_u32);
200 void (*x_put_byte)(uaecptr,uae_u32);
201
202 uae_u32 (*x_cp_next_iword)(void);
203 uae_u32 (*x_cp_next_ilong)(void);
204 uae_u32 (*x_cp_get_long)(uaecptr);
205 uae_u32 (*x_cp_get_word)(uaecptr);
206 uae_u32 (*x_cp_get_byte)(uaecptr);
207 void (*x_cp_put_long)(uaecptr,uae_u32);
208 void (*x_cp_put_word)(uaecptr,uae_u32);
209 void (*x_cp_put_byte)(uaecptr,uae_u32);
210 uae_u32 (REGPARAM3 *x_cp_get_disp_ea_020)(uae_u32 base, int idx) REGPARAM;
211
212 void (*x_do_cycles)(unsigned long);
213 void (*x_do_cycles_pre)(unsigned long);
214 void (*x_do_cycles_post)(unsigned long, uae_u32);
215
216 uae_u32(*x_phys_get_iword)(uaecptr);
217 uae_u32(*x_phys_get_ilong)(uaecptr);
218 uae_u32(*x_phys_get_byte)(uaecptr);
219 uae_u32(*x_phys_get_word)(uaecptr);
220 uae_u32(*x_phys_get_long)(uaecptr);
221 void(*x_phys_put_byte)(uaecptr, uae_u32);
222 void(*x_phys_put_word)(uaecptr, uae_u32);
223 void(*x_phys_put_long)(uaecptr, uae_u32);
224
set_x_cp_funcs(void)225 static void set_x_cp_funcs(void)
226 {
227 x_cp_put_long = x_put_long;
228 x_cp_put_word = x_put_word;
229 x_cp_put_byte = x_put_byte;
230 x_cp_get_long = x_get_long;
231 x_cp_get_word = x_get_word;
232 x_cp_get_byte = x_get_byte;
233 x_cp_next_iword = x_next_iword;
234 x_cp_next_ilong = x_next_ilong;
235 x_cp_get_disp_ea_020 = x_get_disp_ea_020;
236
237 if (currprefs.mmu_model == 68030) {
238 x_cp_put_long = put_long_mmu030_state;
239 x_cp_put_word = put_word_mmu030_state;
240 x_cp_put_byte = put_byte_mmu030_state;
241 x_cp_get_long = get_long_mmu030_state;
242 x_cp_get_word = get_word_mmu030_state;
243 x_cp_get_byte = get_byte_mmu030_state;
244 x_cp_next_iword = next_iword_mmu030_state;
245 x_cp_next_ilong = next_ilong_mmu030_state;
246 x_cp_get_disp_ea_020 = get_disp_ea_020_mmu030;
247 }
248 }
249
250 static struct cputracestruct cputrace;
251
252 #if CPUTRACE_DEBUG
validate_trace(void)253 static void validate_trace (void)
254 {
255 for (int i = 0; i < cputrace.memoryoffset; i++) {
256 struct cputracememory *ctm = &cputrace.ctm[i];
257 if (ctm->data == 0xdeadf00d) {
258 write_log (_T("unfinished write operation %d %08x\n"), i, ctm->addr);
259 }
260 }
261 }
262 #endif
263
debug_trace(void)264 static void debug_trace (void)
265 {
266 if (cputrace.writecounter > 10000 || cputrace.readcounter > 10000)
267 write_log (_T("cputrace.readcounter=%d cputrace.writecounter=%d\n"), cputrace.readcounter, cputrace.writecounter);
268 }
269
clear_trace(void)270 STATIC_INLINE void clear_trace (void)
271 {
272 #if CPUTRACE_DEBUG
273 validate_trace ();
274 #endif
275 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
276 ctm->mode = 0;
277 cputrace.cyclecounter = 0;
278 cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
279 }
set_trace(uaecptr addr,int accessmode,int size)280 static void set_trace (uaecptr addr, int accessmode, int size)
281 {
282 #if CPUTRACE_DEBUG
283 validate_trace ();
284 #endif
285 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset++];
286 ctm->addr = addr;
287 ctm->data = 0xdeadf00d;
288 ctm->mode = accessmode | (size << 4);
289 cputrace.cyclecounter_pre = -1;
290 if (accessmode == 1)
291 cputrace.writecounter++;
292 else
293 cputrace.readcounter++;
294 debug_trace ();
295 }
add_trace(uaecptr addr,uae_u32 val,int accessmode,int size)296 static void add_trace (uaecptr addr, uae_u32 val, int accessmode, int size)
297 {
298 if (cputrace.memoryoffset < 1) {
299 #if CPUTRACE_DEBUG
300 write_log (_T("add_trace memoryoffset=%d!\n"), cputrace.memoryoffset);
301 #endif
302 return;
303 }
304 int mode = accessmode | (size << 4);
305 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
306 ctm->addr = addr;
307 ctm->data = val;
308 if (!ctm->mode) {
309 ctm->mode = mode;
310 if (accessmode == 1)
311 cputrace.writecounter++;
312 else
313 cputrace.readcounter++;
314 }
315 debug_trace ();
316 cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
317 }
318
319
check_trace2(void)320 static void check_trace2 (void)
321 {
322 if (cputrace.readcounter || cputrace.writecounter ||
323 cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
324 write_log (_T("CPU tracer invalid state during playback!\n"));
325 }
326
check_trace(void)327 static bool check_trace (void)
328 {
329 if (!cpu_tracer)
330 return true;
331 if (!cputrace.readcounter && !cputrace.writecounter && !cputrace.cyclecounter) {
332 if (cpu_tracer != -2) {
333 write_log (_T("CPU trace: dma_cycle() enabled. %08x %08x NOW=%08lx\n"),
334 cputrace.cyclecounter_pre, cputrace.cyclecounter_post, get_cycles ());
335 cpu_tracer = -2; // dma_cycle() allowed to work now
336 }
337 }
338 if (cputrace.readcounter || cputrace.writecounter ||
339 cputrace.cyclecounter || cputrace.cyclecounter_pre || cputrace.cyclecounter_post)
340 return false;
341 x_prefetch = x2_prefetch;
342 x_get_ilong = x2_get_ilong;
343 x_get_iword = x2_get_iword;
344 x_get_ibyte = x2_get_ibyte;
345 x_next_iword = x2_next_iword;
346 x_next_ilong = x2_next_ilong;
347 x_put_long = x2_put_long;
348 x_put_word = x2_put_word;
349 x_put_byte = x2_put_byte;
350 x_get_long = x2_get_long;
351 x_get_word = x2_get_word;
352 x_get_byte = x2_get_byte;
353 x_do_cycles = x2_do_cycles;
354 x_do_cycles_pre = x2_do_cycles_pre;
355 x_do_cycles_post = x2_do_cycles_post;
356 set_x_cp_funcs();
357 write_log (_T("CPU tracer playback complete. STARTCYCLES=%08x NOWCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
358 cputrace.needendcycles = 1;
359 cpu_tracer = 0;
360 return true;
361 }
362
get_trace(uaecptr addr,int accessmode,int size,uae_u32 * data)363 static bool get_trace (uaecptr addr, int accessmode, int size, uae_u32 *data)
364 {
365 int mode = accessmode | (size << 4);
366 for (int i = 0; i < cputrace.memoryoffset; i++) {
367 struct cputracememory *ctm = &cputrace.ctm[i];
368 if (ctm->addr == addr && ctm->mode == mode) {
369 ctm->mode = 0;
370 write_log (_T("CPU trace: GET %d: PC=%08x %08x=%08x %d %d %08x/%08x/%08x %d/%d (%08lx)\n"),
371 i, cputrace.pc, addr, ctm->data, accessmode, size,
372 cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
373 cputrace.readcounter, cputrace.writecounter, get_cycles ());
374 if (accessmode == 1)
375 cputrace.writecounter--;
376 else
377 cputrace.readcounter--;
378 if (cputrace.writecounter == 0 && cputrace.readcounter == 0) {
379 if (cputrace.cyclecounter_post) {
380 int c = cputrace.cyclecounter_post;
381 cputrace.cyclecounter_post = 0;
382 x_do_cycles (c);
383 } else if (cputrace.cyclecounter_pre) {
384 check_trace ();
385 *data = ctm->data;
386 return true; // argh, need to rerun the memory access..
387 }
388 }
389 check_trace ();
390 *data = ctm->data;
391 return false;
392 }
393 }
394 if (cputrace.cyclecounter_post) {
395 int c = cputrace.cyclecounter_post;
396 cputrace.cyclecounter_post = 0;
397 check_trace ();
398 check_trace2 ();
399 x_do_cycles (c);
400 return false;
401 }
402 gui_message (_T("CPU trace: GET %08x %d %d NOT FOUND!\n"), addr, accessmode, size);
403 check_trace ();
404 *data = 0;
405 return false;
406 }
407
cputracefunc_x_prefetch(int o)408 static uae_u32 cputracefunc_x_prefetch (int o)
409 {
410 uae_u32 pc = m68k_getpc ();
411 set_trace (pc + o, 2, 2);
412 uae_u32 v = x2_prefetch (o);
413 add_trace (pc + o, v, 2, 2);
414 return v;
415 }
cputracefunc2_x_prefetch(int o)416 static uae_u32 cputracefunc2_x_prefetch (int o)
417 {
418 uae_u32 v;
419 if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
420 v = x2_prefetch (o);
421 check_trace2 ();
422 }
423 return v;
424 }
425
cputracefunc_x_next_iword(void)426 static uae_u32 cputracefunc_x_next_iword (void)
427 {
428 uae_u32 pc = m68k_getpc ();
429 set_trace (pc, 2, 2);
430 uae_u32 v = x2_next_iword ();
431 add_trace (pc, v, 2, 2);
432 return v;
433 }
cputracefunc_x_next_ilong(void)434 static uae_u32 cputracefunc_x_next_ilong (void)
435 {
436 uae_u32 pc = m68k_getpc ();
437 set_trace (pc, 2, 4);
438 uae_u32 v = x2_next_ilong ();
439 add_trace (pc, v, 2, 4);
440 return v;
441 }
cputracefunc2_x_next_iword(void)442 static uae_u32 cputracefunc2_x_next_iword (void)
443 {
444 uae_u32 v;
445 if (get_trace (m68k_getpc (), 2, 2, &v)) {
446 v = x2_next_iword ();
447 check_trace2 ();
448 }
449 return v;
450 }
cputracefunc2_x_next_ilong(void)451 static uae_u32 cputracefunc2_x_next_ilong (void)
452 {
453 uae_u32 v;
454 if (get_trace (m68k_getpc (), 2, 4, &v)) {
455 v = x2_next_ilong ();
456 check_trace2 ();
457 }
458 return v;
459 }
460
cputracefunc_x_get_ilong(int o)461 static uae_u32 cputracefunc_x_get_ilong (int o)
462 {
463 uae_u32 pc = m68k_getpc ();
464 set_trace (pc + o, 2, 4);
465 uae_u32 v = x2_get_ilong (o);
466 add_trace (pc + o, v, 2, 4);
467 return v;
468 }
cputracefunc_x_get_iword(int o)469 static uae_u32 cputracefunc_x_get_iword (int o)
470 {
471 uae_u32 pc = m68k_getpc ();
472 set_trace (pc + o, 2, 2);
473 uae_u32 v = x2_get_iword (o);
474 add_trace (pc + o, v, 2, 2);
475 return v;
476 }
cputracefunc_x_get_ibyte(int o)477 static uae_u32 cputracefunc_x_get_ibyte (int o)
478 {
479 uae_u32 pc = m68k_getpc ();
480 set_trace (pc + o, 2, 1);
481 uae_u32 v = x2_get_ibyte (o);
482 add_trace (pc + o, v, 2, 1);
483 return v;
484 }
cputracefunc2_x_get_ilong(int o)485 static uae_u32 cputracefunc2_x_get_ilong (int o)
486 {
487 uae_u32 v;
488 if (get_trace (m68k_getpc () + o, 2, 4, &v)) {
489 v = x2_get_ilong (o);
490 check_trace2 ();
491 }
492 return v;
493 }
cputracefunc2_x_get_iword(int o)494 static uae_u32 cputracefunc2_x_get_iword (int o)
495 {
496 uae_u32 v;
497 if (get_trace (m68k_getpc () + o, 2, 2, &v)) {
498 v = x2_get_iword (o);
499 check_trace2 ();
500 }
501 return v;
502 }
cputracefunc2_x_get_ibyte(int o)503 static uae_u32 cputracefunc2_x_get_ibyte (int o)
504 {
505 uae_u32 v;
506 if (get_trace (m68k_getpc () + o, 2, 1, &v)) {
507 v = x2_get_ibyte (o);
508 check_trace2 ();
509 }
510 return v;
511 }
512
cputracefunc_x_get_long(uaecptr o)513 static uae_u32 cputracefunc_x_get_long (uaecptr o)
514 {
515 set_trace (o, 0, 4);
516 uae_u32 v = x2_get_long (o);
517 add_trace (o, v, 0, 4);
518 return v;
519 }
cputracefunc_x_get_word(uaecptr o)520 static uae_u32 cputracefunc_x_get_word (uaecptr o)
521 {
522 set_trace (o, 0, 2);
523 uae_u32 v = x2_get_word (o);
524 add_trace (o, v, 0, 2);
525 return v;
526 }
cputracefunc_x_get_byte(uaecptr o)527 static uae_u32 cputracefunc_x_get_byte (uaecptr o)
528 {
529 set_trace (o, 0, 1);
530 uae_u32 v = x2_get_byte (o);
531 add_trace (o, v, 0, 1);
532 return v;
533 }
cputracefunc2_x_get_long(uaecptr o)534 static uae_u32 cputracefunc2_x_get_long (uaecptr o)
535 {
536 uae_u32 v;
537 if (get_trace (o, 0, 4, &v)) {
538 v = x2_get_long (o);
539 check_trace2 ();
540 }
541 return v;
542 }
cputracefunc2_x_get_word(uaecptr o)543 static uae_u32 cputracefunc2_x_get_word (uaecptr o)
544 {
545 uae_u32 v;
546 if (get_trace (o, 0, 2, &v)) {
547 v = x2_get_word (o);
548 check_trace2 ();
549 }
550 return v;
551 }
cputracefunc2_x_get_byte(uaecptr o)552 static uae_u32 cputracefunc2_x_get_byte (uaecptr o)
553 {
554 uae_u32 v;
555 if (get_trace (o, 0, 1, &v)) {
556 v = x2_get_byte (o);
557 check_trace2 ();
558 }
559 return v;
560 }
561
cputracefunc_x_put_long(uaecptr o,uae_u32 val)562 static void cputracefunc_x_put_long (uaecptr o, uae_u32 val)
563 {
564 clear_trace ();
565 add_trace (o, val, 1, 4);
566 x2_put_long (o, val);
567 }
cputracefunc_x_put_word(uaecptr o,uae_u32 val)568 static void cputracefunc_x_put_word (uaecptr o, uae_u32 val)
569 {
570 clear_trace ();
571 add_trace (o, val, 1, 2);
572 x2_put_word (o, val);
573 }
cputracefunc_x_put_byte(uaecptr o,uae_u32 val)574 static void cputracefunc_x_put_byte (uaecptr o, uae_u32 val)
575 {
576 clear_trace ();
577 add_trace (o, val, 1, 1);
578 x2_put_byte (o, val);
579 }
cputracefunc2_x_put_long(uaecptr o,uae_u32 val)580 static void cputracefunc2_x_put_long (uaecptr o, uae_u32 val)
581 {
582 uae_u32 v;
583 if (get_trace (o, 1, 4, &v)) {
584 x2_put_long (o, val);
585 check_trace2 ();
586 }
587 if (v != val)
588 write_log (_T("cputracefunc2_x_put_long %d <> %d\n"), v, val);
589 }
cputracefunc2_x_put_word(uaecptr o,uae_u32 val)590 static void cputracefunc2_x_put_word (uaecptr o, uae_u32 val)
591 {
592 uae_u32 v;
593 if (get_trace (o, 1, 2, &v)) {
594 x2_put_word (o, val);
595 check_trace2 ();
596 }
597 if (v != val)
598 write_log (_T("cputracefunc2_x_put_word %d <> %d\n"), v, val);
599 }
cputracefunc2_x_put_byte(uaecptr o,uae_u32 val)600 static void cputracefunc2_x_put_byte (uaecptr o, uae_u32 val)
601 {
602 uae_u32 v;
603 if (get_trace (o, 1, 1, &v)) {
604 x2_put_byte (o, val);
605 check_trace2 ();
606 }
607 if (v != val)
608 write_log (_T("cputracefunc2_x_put_byte %d <> %d\n"), v, val);
609 }
610
cputracefunc_x_do_cycles(unsigned long cycles)611 static void cputracefunc_x_do_cycles (unsigned long cycles)
612 {
613 while (cycles >= CYCLE_UNIT) {
614 cputrace.cyclecounter += CYCLE_UNIT;
615 cycles -= CYCLE_UNIT;
616 x2_do_cycles (CYCLE_UNIT);
617 }
618 if (cycles > 0) {
619 cputrace.cyclecounter += cycles;
620 x2_do_cycles (cycles);
621 }
622 }
623
cputracefunc2_x_do_cycles(unsigned long cycles)624 static void cputracefunc2_x_do_cycles (unsigned long cycles)
625 {
626 if (cputrace.cyclecounter > cycles) {
627 cputrace.cyclecounter -= cycles;
628 return;
629 }
630 cycles -= cputrace.cyclecounter;
631 cputrace.cyclecounter = 0;
632 check_trace ();
633 x_do_cycles = x2_do_cycles;
634 if (cycles > 0)
635 x_do_cycles (cycles);
636 }
637
cputracefunc_x_do_cycles_pre(unsigned long cycles)638 static void cputracefunc_x_do_cycles_pre (unsigned long cycles)
639 {
640 cputrace.cyclecounter_post = 0;
641 cputrace.cyclecounter_pre = 0;
642 while (cycles >= CYCLE_UNIT) {
643 cycles -= CYCLE_UNIT;
644 cputrace.cyclecounter_pre += CYCLE_UNIT;
645 x2_do_cycles (CYCLE_UNIT);
646 }
647 if (cycles > 0) {
648 x2_do_cycles (cycles);
649 cputrace.cyclecounter_pre += cycles;
650 }
651 cputrace.cyclecounter_pre = 0;
652 }
653 // cyclecounter_pre = how many cycles we need to SWALLOW
654 // -1 = rerun whole access
cputracefunc2_x_do_cycles_pre(unsigned long cycles)655 static void cputracefunc2_x_do_cycles_pre (unsigned long cycles)
656 {
657 if (cputrace.cyclecounter_pre == -1) {
658 cputrace.cyclecounter_pre = 0;
659 check_trace ();
660 check_trace2 ();
661 x_do_cycles (cycles);
662 return;
663 }
664 if (cputrace.cyclecounter_pre > cycles) {
665 cputrace.cyclecounter_pre -= cycles;
666 return;
667 }
668 cycles -= cputrace.cyclecounter_pre;
669 cputrace.cyclecounter_pre = 0;
670 check_trace ();
671 if (cycles > 0)
672 x_do_cycles (cycles);
673 }
674
cputracefunc_x_do_cycles_post(unsigned long cycles,uae_u32 v)675 static void cputracefunc_x_do_cycles_post (unsigned long cycles, uae_u32 v)
676 {
677 if (cputrace.memoryoffset < 1) {
678 #if CPUTRACE_DEBUG
679 write_log (_T("cputracefunc_x_do_cycles_post memoryoffset=%d!\n"), cputrace.memoryoffset);
680 #endif
681 return;
682 }
683 struct cputracememory *ctm = &cputrace.ctm[cputrace.memoryoffset - 1];
684 ctm->data = v;
685 cputrace.cyclecounter_post = cycles;
686 cputrace.cyclecounter_pre = 0;
687 while (cycles >= CYCLE_UNIT) {
688 cycles -= CYCLE_UNIT;
689 cputrace.cyclecounter_post -= CYCLE_UNIT;
690 x2_do_cycles (CYCLE_UNIT);
691 }
692 if (cycles > 0) {
693 cputrace.cyclecounter_post -= cycles;
694 x2_do_cycles (cycles);
695 }
696 cputrace.cyclecounter_post = 0;
697 }
698 // cyclecounter_post = how many cycles we need to WAIT
cputracefunc2_x_do_cycles_post(unsigned long cycles,uae_u32 v)699 static void cputracefunc2_x_do_cycles_post (unsigned long cycles, uae_u32 v)
700 {
701 uae_u32 c;
702 if (cputrace.cyclecounter_post) {
703 c = cputrace.cyclecounter_post;
704 cputrace.cyclecounter_post = 0;
705 } else {
706 c = cycles;
707 }
708 check_trace ();
709 if (c > 0)
710 x_do_cycles (c);
711 }
712
do_cycles_post(unsigned long cycles,uae_u32 v)713 static void do_cycles_post (unsigned long cycles, uae_u32 v)
714 {
715 do_cycles (cycles);
716 }
do_cycles_ce_post(unsigned long cycles,uae_u32 v)717 static void do_cycles_ce_post (unsigned long cycles, uae_u32 v)
718 {
719 do_cycles_ce (cycles);
720 }
do_cycles_ce020_post(unsigned long cycles,uae_u32 v)721 static void do_cycles_ce020_post (unsigned long cycles, uae_u32 v)
722 {
723 do_cycles_ce020 (cycles);
724 }
725
set_x_ifetches(void)726 static void set_x_ifetches(void)
727 {
728 if (m68k_pc_indirect) {
729 if (currprefs.cachesize) {
730 // indirect via addrbank
731 x_get_ilong = get_iilong_jit;
732 x_get_iword = get_iiword_jit;
733 x_get_ibyte = get_iibyte_jit;
734 x_next_iword = next_iiword_jit;
735 x_next_ilong = next_iilong_jit;
736 } else {
737 // indirect via addrbank
738 x_get_ilong = get_iilong;
739 x_get_iword = get_iiword;
740 x_get_ibyte = get_iibyte;
741 x_next_iword = next_iiword;
742 x_next_ilong = next_iilong;
743 }
744 } else {
745 // direct to memory
746 x_get_ilong = get_dilong;
747 x_get_iword = get_diword;
748 x_get_ibyte = get_dibyte;
749 x_next_iword = next_diword;
750 x_next_ilong = next_dilong;
751 }
752 }
753
754 // indirect memory access functions
set_x_funcs(void)755 static void set_x_funcs (void)
756 {
757 if (currprefs.mmu_model) {
758 if (currprefs.cpu_model == 68060) {
759 x_prefetch = get_iword_mmu060;
760 x_get_ilong = get_ilong_mmu060;
761 x_get_iword = get_iword_mmu060;
762 x_get_ibyte = get_ibyte_mmu060;
763 x_next_iword = next_iword_mmu060;
764 x_next_ilong = next_ilong_mmu060;
765 x_put_long = put_long_mmu060;
766 x_put_word = put_word_mmu060;
767 x_put_byte = put_byte_mmu060;
768 x_get_long = get_long_mmu060;
769 x_get_word = get_word_mmu060;
770 x_get_byte = get_byte_mmu060;
771 } else if (currprefs.cpu_model == 68040) {
772 x_prefetch = get_iword_mmu040;
773 x_get_ilong = get_ilong_mmu040;
774 x_get_iword = get_iword_mmu040;
775 x_get_ibyte = get_ibyte_mmu040;
776 x_next_iword = next_iword_mmu040;
777 x_next_ilong = next_ilong_mmu040;
778 x_put_long = put_long_mmu040;
779 x_put_word = put_word_mmu040;
780 x_put_byte = put_byte_mmu040;
781 x_get_long = get_long_mmu040;
782 x_get_word = get_word_mmu040;
783 x_get_byte = get_byte_mmu040;
784 } else {
785 x_prefetch = get_iword_mmu030;
786 x_get_ilong = get_ilong_mmu030;
787 x_get_iword = get_iword_mmu030;
788 x_get_ibyte = get_ibyte_mmu030;
789 x_next_iword = next_iword_mmu030;
790 x_next_ilong = next_ilong_mmu030;
791 x_put_long = put_long_mmu030;
792 x_put_word = put_word_mmu030;
793 x_put_byte = put_byte_mmu030;
794 x_get_long = get_long_mmu030;
795 x_get_word = get_word_mmu030;
796 x_get_byte = get_byte_mmu030;
797 }
798 x_do_cycles = do_cycles;
799 x_do_cycles_pre = do_cycles;
800 x_do_cycles_post = do_cycles_post;
801 } else if (currprefs.cpu_model < 68020) {
802 // 68000/010
803 if (currprefs.cpu_cycle_exact) {
804 x_prefetch = get_word_ce000_prefetch;
805 x_get_ilong = NULL;
806 x_get_iword = get_wordi_ce000;
807 x_get_ibyte = NULL;
808 x_next_iword = NULL;
809 x_next_ilong = NULL;
810 x_put_long = put_long_ce000;
811 x_put_word = put_word_ce000;
812 x_put_byte = put_byte_ce000;
813 x_get_long = get_long_ce000;
814 x_get_word = get_word_ce000;
815 x_get_byte = get_byte_ce000;
816 x_do_cycles = do_cycles_ce;
817 x_do_cycles_pre = do_cycles_ce;
818 x_do_cycles_post = do_cycles_ce_post;
819 } else if (currprefs.cpu_memory_cycle_exact) {
820 // cpu_memory_cycle_exact + cpu_compatible
821 x_prefetch = get_word_000_prefetch;
822 x_get_ilong = NULL;
823 x_get_iword = get_iiword;
824 x_get_ibyte = get_iibyte;
825 x_next_iword = NULL;
826 x_next_ilong = NULL;
827 x_put_long = put_long_ce000;
828 x_put_word = put_word_ce000;
829 x_put_byte = put_byte_ce000;
830 x_get_long = get_long_ce000;
831 x_get_word = get_word_ce000;
832 x_get_byte = get_byte_ce000;
833 x_do_cycles = do_cycles;
834 x_do_cycles_pre = do_cycles;
835 x_do_cycles_post = do_cycles_post;
836 } else if (currprefs.cpu_compatible) {
837 // cpu_compatible only
838 x_prefetch = get_word_000_prefetch;
839 x_get_ilong = NULL;
840 x_get_iword = get_iiword;
841 x_get_ibyte = get_iibyte;
842 x_next_iword = NULL;
843 x_next_ilong = NULL;
844 x_put_long = put_long;
845 x_put_word = put_word;
846 x_put_byte = put_byte;
847 x_get_long = get_long;
848 x_get_word = get_word;
849 x_get_byte = get_byte;
850 x_do_cycles = do_cycles;
851 x_do_cycles_pre = do_cycles;
852 x_do_cycles_post = do_cycles_post;
853 } else {
854 x_prefetch = NULL;
855 x_get_ilong = get_dilong;
856 x_get_iword = get_diword;
857 x_get_ibyte = get_dibyte;
858 x_next_iword = next_diword;
859 x_next_ilong = next_dilong;
860 x_put_long = put_long;
861 x_put_word = put_word;
862 x_put_byte = put_byte;
863 x_get_long = get_long;
864 x_get_word = get_word;
865 x_get_byte = get_byte;
866 x_do_cycles = do_cycles;
867 x_do_cycles_pre = do_cycles;
868 x_do_cycles_post = do_cycles_post;
869 }
870 } else if (!currprefs.cpu_cycle_exact) {
871 // 68020+ no ce
872 if (currprefs.cpu_memory_cycle_exact) {
873 // cpu_memory_cycle_exact + cpu_compatible
874 if (false) {
875 #ifdef CPUEMU_20
876 } else if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
877 x_prefetch = get_word_020_prefetch;
878 x_get_ilong = get_long_020_prefetch;
879 x_get_iword = get_word_020_prefetch;
880 x_get_ibyte = NULL;
881 x_next_iword = next_iword_020_prefetch;
882 x_next_ilong = next_ilong_020_prefetch;
883 x_put_long = put_long_ce020;
884 x_put_word = put_word_ce020;
885 x_put_byte = put_byte_ce020;
886 x_get_long = get_long_ce020;
887 x_get_word = get_word_ce020;
888 x_get_byte = get_byte_ce020;
889 x_do_cycles = do_cycles;
890 x_do_cycles_pre = do_cycles;
891 x_do_cycles_post = do_cycles_post;
892 #endif
893 #ifdef CPUEMU_22
894 } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
895 x_prefetch = get_word_030_prefetch;
896 x_get_ilong = get_long_030_prefetch;
897 x_get_iword = get_word_030_prefetch;
898 x_get_ibyte = NULL;
899 x_next_iword = next_iword_030_prefetch;
900 x_next_ilong = next_ilong_030_prefetch;
901 x_put_long = put_long_ce030;
902 x_put_word = put_word_ce030;
903 x_put_byte = put_byte_ce030;
904 x_get_long = get_long_ce030;
905 x_get_word = get_word_ce030;
906 x_get_byte = get_byte_ce030;
907 x_do_cycles = do_cycles;
908 x_do_cycles_pre = do_cycles;
909 x_do_cycles_post = do_cycles_post;
910 #endif
911 } else if (currprefs.cpu_model < 68040) {
912 // JIT or 68030+ does not have real prefetch only emulation
913 x_prefetch = NULL;
914 set_x_ifetches();
915 x_put_long = put_long;
916 x_put_word = put_word;
917 x_put_byte = put_byte;
918 x_get_long = get_long;
919 x_get_word = get_word;
920 x_get_byte = get_byte;
921 x_do_cycles = do_cycles;
922 x_do_cycles_pre = do_cycles;
923 x_do_cycles_post = do_cycles_post;
924 } else {
925 // 68040+ (same as below)
926 x_prefetch = NULL;
927 x_get_ilong = get_ilong_cache_040;
928 x_get_iword = get_iword_cache_040;
929 x_get_ibyte = NULL;
930 x_next_iword = next_iword_cache040;
931 x_next_ilong = next_ilong_cache040;
932 x_put_long = put_long_cache_040;
933 x_put_word = put_word_cache_040;
934 x_put_byte = put_byte_cache_040;
935 x_get_long = get_long_cache_040;
936 x_get_word = get_word_cache_040;
937 x_get_byte = get_byte_cache_040;
938 x_do_cycles = do_cycles;
939 x_do_cycles_pre = do_cycles;
940 x_do_cycles_post = do_cycles_post;
941 }
942 } else if (currprefs.cpu_compatible) {
943 // cpu_compatible only
944 if (false) {
945 #ifdef CPUEMU_20
946 } else if (currprefs.cpu_model == 68020 && !currprefs.cachesize) {
947 x_prefetch = get_word_020_prefetch;
948 x_get_ilong = get_long_020_prefetch;
949 x_get_iword = get_word_020_prefetch;
950 x_get_ibyte = NULL;
951 x_next_iword = next_iword_020_prefetch;
952 x_next_ilong = next_ilong_020_prefetch;
953 x_put_long = put_long;
954 x_put_word = put_word;
955 x_put_byte = put_byte;
956 x_get_long = get_long;
957 x_get_word = get_word;
958 x_get_byte = get_byte;
959 x_do_cycles = do_cycles;
960 x_do_cycles_pre = do_cycles;
961 x_do_cycles_post = do_cycles_post;
962 #endif
963 #ifdef CPUEMU_22
964 } else if (currprefs.cpu_model == 68030 && !currprefs.cachesize) {
965 x_prefetch = get_word_020_prefetch;
966 x_get_ilong = get_long_030_prefetch;
967 x_get_iword = get_word_030_prefetch;
968 x_get_ibyte = NULL;
969 x_next_iword = next_iword_030_prefetch;
970 x_next_ilong = next_ilong_030_prefetch;
971 x_put_long = put_long;
972 x_put_word = put_word;
973 x_put_byte = put_byte;
974 x_get_long = get_long;
975 x_get_word = get_word;
976 x_get_byte = get_byte;
977 x_do_cycles = do_cycles;
978 x_do_cycles_pre = do_cycles;
979 x_do_cycles_post = do_cycles_post;
980 #endif
981 } else if (currprefs.cpu_model < 68040) {
982 // JIT or 68030+ does not have real prefetch only emulation
983 x_prefetch = NULL;
984 set_x_ifetches();
985 x_put_long = put_long;
986 x_put_word = put_word;
987 x_put_byte = put_byte;
988 x_get_long = get_long;
989 x_get_word = get_word;
990 x_get_byte = get_byte;
991 x_do_cycles = do_cycles;
992 x_do_cycles_pre = do_cycles;
993 x_do_cycles_post = do_cycles_post;
994 } else {
995 x_prefetch = NULL;
996 x_get_ilong = get_ilong_cache_040;
997 x_get_iword = get_iword_cache_040;
998 x_get_ibyte = NULL;
999 x_next_iword = next_iword_cache040;
1000 x_next_ilong = next_ilong_cache040;
1001 x_put_long = put_long_cache_040;
1002 x_put_word = put_word_cache_040;
1003 x_put_byte = put_byte_cache_040;
1004 x_get_long = get_long_cache_040;
1005 x_get_word = get_word_cache_040;
1006 x_get_byte = get_byte_cache_040;
1007 x_do_cycles = do_cycles;
1008 x_do_cycles_pre = do_cycles;
1009 x_do_cycles_post = do_cycles_post;
1010 }
1011 } else {
1012 x_prefetch = NULL;
1013 set_x_ifetches();
1014 if (currprefs.cachesize) {
1015 x_put_long = put_long_jit;
1016 x_put_word = put_word_jit;
1017 x_put_byte = put_byte_jit;
1018 x_get_long = get_long_jit;
1019 x_get_word = get_word_jit;
1020 x_get_byte = get_byte_jit;
1021 } else {
1022 x_put_long = put_long;
1023 x_put_word = put_word;
1024 x_put_byte = put_byte;
1025 x_get_long = get_long;
1026 x_get_word = get_word;
1027 x_get_byte = get_byte;
1028 }
1029 x_do_cycles = do_cycles;
1030 x_do_cycles_pre = do_cycles;
1031 x_do_cycles_post = do_cycles_post;
1032 }
1033 // 68020+ cycle exact
1034 #ifdef CPUEMU_21
1035 } else if (currprefs.cpu_model == 68020) {
1036 x_prefetch = get_word_ce020_prefetch;
1037 x_get_ilong = get_long_ce020_prefetch;
1038 x_get_iword = get_word_ce020_prefetch;
1039 x_get_ibyte = NULL;
1040 x_next_iword = next_iword_020ce;
1041 x_next_ilong = next_ilong_020ce;
1042 x_put_long = put_long_ce020;
1043 x_put_word = put_word_ce020;
1044 x_put_byte = put_byte_ce020;
1045 x_get_long = get_long_ce020;
1046 x_get_word = get_word_ce020;
1047 x_get_byte = get_byte_ce020;
1048 x_do_cycles = do_cycles_ce020;
1049 x_do_cycles_pre = do_cycles_ce020;
1050 x_do_cycles_post = do_cycles_ce020_post;
1051 #endif
1052 #ifdef CPUEMU_23
1053 } else if (currprefs.cpu_model == 68030) {
1054 x_prefetch = get_word_ce030_prefetch;
1055 x_get_ilong = get_long_ce030_prefetch;
1056 x_get_iword = get_word_ce030_prefetch;
1057 x_get_ibyte = NULL;
1058 x_next_iword = next_iword_030ce;
1059 x_next_ilong = next_ilong_030ce;
1060 x_put_long = put_long_ce030;
1061 x_put_word = put_word_ce030;
1062 x_put_byte = put_byte_ce030;
1063 x_get_long = get_long_ce030;
1064 x_get_word = get_word_ce030;
1065 x_get_byte = get_byte_ce030;
1066 x_do_cycles = do_cycles_ce020;
1067 x_do_cycles_pre = do_cycles_ce020;
1068 x_do_cycles_post = do_cycles_ce020_post;
1069 #endif
1070 } else if (currprefs.cpu_model >= 68040) {
1071 x_prefetch = NULL;
1072 x_get_ilong = get_ilong_cache_040;
1073 x_get_iword = get_iword_cache_040;
1074 x_get_ibyte = NULL;
1075 x_next_iword = next_iword_cache040;
1076 x_next_ilong = next_ilong_cache040;
1077 x_put_long = put_long_cache_040;
1078 x_put_word = put_word_cache_040;
1079 x_put_byte = put_byte_cache_040;
1080 x_get_long = get_long_cache_040;
1081 x_get_word = get_word_cache_040;
1082 x_get_byte = get_byte_cache_040;
1083 x_do_cycles = do_cycles_ce020;
1084 x_do_cycles_pre = do_cycles_ce020;
1085 x_do_cycles_post = do_cycles_ce020_post;
1086 }
1087 x2_prefetch = x_prefetch;
1088 x2_get_ilong = x_get_ilong;
1089 x2_get_iword = x_get_iword;
1090 x2_get_ibyte = x_get_ibyte;
1091 x2_next_iword = x_next_iword;
1092 x2_next_ilong = x_next_ilong;
1093 x2_put_long = x_put_long;
1094 x2_put_word = x_put_word;
1095 x2_put_byte = x_put_byte;
1096 x2_get_long = x_get_long;
1097 x2_get_word = x_get_word;
1098 x2_get_byte = x_get_byte;
1099 x2_do_cycles = x_do_cycles;
1100 x2_do_cycles_pre = x_do_cycles_pre;
1101 x2_do_cycles_post = x_do_cycles_post;
1102
1103 if (cpu_tracer > 0) {
1104 x_prefetch = cputracefunc_x_prefetch;
1105 x_get_ilong = cputracefunc_x_get_ilong;
1106 x_get_iword = cputracefunc_x_get_iword;
1107 x_get_ibyte = cputracefunc_x_get_ibyte;
1108 x_next_iword = cputracefunc_x_next_iword;
1109 x_next_ilong = cputracefunc_x_next_ilong;
1110 x_put_long = cputracefunc_x_put_long;
1111 x_put_word = cputracefunc_x_put_word;
1112 x_put_byte = cputracefunc_x_put_byte;
1113 x_get_long = cputracefunc_x_get_long;
1114 x_get_word = cputracefunc_x_get_word;
1115 x_get_byte = cputracefunc_x_get_byte;
1116 x_do_cycles = cputracefunc_x_do_cycles;
1117 x_do_cycles_pre = cputracefunc_x_do_cycles_pre;
1118 x_do_cycles_post = cputracefunc_x_do_cycles_post;
1119 } else if (cpu_tracer < 0) {
1120 if (!check_trace ()) {
1121 x_prefetch = cputracefunc2_x_prefetch;
1122 x_get_ilong = cputracefunc2_x_get_ilong;
1123 x_get_iword = cputracefunc2_x_get_iword;
1124 x_get_ibyte = cputracefunc2_x_get_ibyte;
1125 x_next_iword = cputracefunc2_x_next_iword;
1126 x_next_ilong = cputracefunc2_x_next_ilong;
1127 x_put_long = cputracefunc2_x_put_long;
1128 x_put_word = cputracefunc2_x_put_word;
1129 x_put_byte = cputracefunc2_x_put_byte;
1130 x_get_long = cputracefunc2_x_get_long;
1131 x_get_word = cputracefunc2_x_get_word;
1132 x_get_byte = cputracefunc2_x_get_byte;
1133 x_do_cycles = cputracefunc2_x_do_cycles;
1134 x_do_cycles_pre = cputracefunc2_x_do_cycles_pre;
1135 x_do_cycles_post = cputracefunc2_x_do_cycles_post;
1136 }
1137 }
1138
1139 set_x_cp_funcs();
1140 mmu_set_funcs();
1141 mmu030_set_funcs();
1142
1143 }
1144
can_cpu_tracer(void)1145 bool can_cpu_tracer (void)
1146 {
1147 return (currprefs.cpu_model == 68000 || currprefs.cpu_model == 68020) && currprefs.cpu_memory_cycle_exact;
1148 }
1149
is_cpu_tracer(void)1150 bool is_cpu_tracer (void)
1151 {
1152 return cpu_tracer > 0;
1153 }
set_cpu_tracer(bool state)1154 bool set_cpu_tracer (bool state)
1155 {
1156 #ifdef FSUAE
1157 #if 0
1158 if (state) {
1159 printf("WARNING: ignoring call to set_cpu_tracer(%d)\n", state);
1160 }
1161 return false;
1162 #endif
1163 #endif
1164 if (cpu_tracer < 0)
1165 return false;
1166 int old = cpu_tracer;
1167 if (input_record)
1168 state = true;
1169 cpu_tracer = 0;
1170 if (state && can_cpu_tracer ()) {
1171 cpu_tracer = 1;
1172 set_x_funcs ();
1173 if (old != cpu_tracer)
1174 write_log (_T("CPU tracer enabled\n"));
1175 }
1176 if (old > 0 && state == false) {
1177 set_x_funcs ();
1178 write_log (_T("CPU tracer disabled\n"));
1179 }
1180 return is_cpu_tracer ();
1181 }
1182
flush_cpu_caches(bool force)1183 void flush_cpu_caches(bool force)
1184 {
1185 bool doflush = currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact;
1186
1187 if (currprefs.cpu_model == 68020) {
1188 if (regs.cacr & 0x08) { // clear instr cache
1189 for (int i = 0; i < CACHELINES020; i++)
1190 caches020[i].valid = 0;
1191 regs.cacr &= ~0x08;
1192 }
1193 if (regs.cacr & 0x04) { // clear entry in instr cache
1194 caches020[(regs.caar >> 2) & (CACHELINES020 - 1)].valid = 0;
1195 regs.cacr &= ~0x04;
1196 }
1197 } else if (currprefs.cpu_model == 68030) {
1198 if (regs.cacr & 0x08) { // clear instr cache
1199 if (doflush) {
1200 for (int i = 0; i < CACHELINES030; i++) {
1201 icaches030[i].valid[0] = 0;
1202 icaches030[i].valid[1] = 0;
1203 icaches030[i].valid[2] = 0;
1204 icaches030[i].valid[3] = 0;
1205 }
1206 }
1207 regs.cacr &= ~0x08;
1208 }
1209 if (regs.cacr & 0x04) { // clear entry in instr cache
1210 icaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1211 regs.cacr &= ~0x04;
1212 }
1213 if (regs.cacr & 0x800) { // clear data cache
1214 if (doflush) {
1215 for (int i = 0; i < CACHELINES030; i++) {
1216 dcaches030[i].valid[0] = 0;
1217 dcaches030[i].valid[1] = 0;
1218 dcaches030[i].valid[2] = 0;
1219 dcaches030[i].valid[3] = 0;
1220 }
1221 }
1222 regs.cacr &= ~0x800;
1223 }
1224 if (regs.cacr & 0x400) { // clear entry in data cache
1225 dcaches030[(regs.caar >> 4) & (CACHELINES030 - 1)].valid[(regs.caar >> 2) & 3] = 0;
1226 regs.cacr &= ~0x400;
1227 }
1228 } else if (currprefs.cpu_model >= 68040) {
1229 icachelinecnt = 0;
1230 dcachelinecnt = 0;
1231 if (doflush) {
1232 for (int i = 0; i < CACHESETS040; i++) {
1233 icaches040[i].valid[0] = 0;
1234 icaches040[i].valid[1] = 0;
1235 icaches040[i].valid[2] = 0;
1236 icaches040[i].valid[3] = 0;
1237 }
1238 }
1239 }
1240 }
1241
flush_cpu_caches_040(uae_u16 opcode)1242 void flush_cpu_caches_040(uae_u16 opcode)
1243 {
1244 int cache = (opcode >> 6) & 3;
1245 if (!(cache & 2))
1246 return;
1247 flush_cpu_caches(true);
1248 }
1249
set_cpu_caches(bool flush)1250 void set_cpu_caches (bool flush)
1251 {
1252 regs.prefetch020addr = 0xffffffff;
1253 regs.cacheholdingaddr020 = 0xffffffff;
1254
1255 #ifdef JIT
1256 if (currprefs.cachesize) {
1257 if (currprefs.cpu_model < 68040) {
1258 set_cache_state (regs.cacr & 1);
1259 if (regs.cacr & 0x08) {
1260 flush_icache (0, 3);
1261 }
1262 } else {
1263 set_cache_state ((regs.cacr & 0x8000) ? 1 : 0);
1264 }
1265 }
1266 #endif
1267 flush_cpu_caches(flush);
1268 }
1269
count_instr(unsigned int opcode)1270 STATIC_INLINE void count_instr (unsigned int opcode)
1271 {
1272 }
1273
op_illg_1(uae_u32 opcode)1274 static uae_u32 REGPARAM2 op_illg_1 (uae_u32 opcode)
1275 {
1276 op_illg (opcode);
1277 return 4;
1278 }
op_unimpl_1(uae_u32 opcode)1279 static uae_u32 REGPARAM2 op_unimpl_1 (uae_u32 opcode)
1280 {
1281 if ((opcode & 0xf000) == 0xf000 || currprefs.cpu_model < 68060)
1282 op_illg (opcode);
1283 else
1284 op_unimpl (opcode);
1285 return 4;
1286 }
1287
1288 #ifndef CPUEMU_0
1289 #define op_smalltbl_0_ff NULL
1290 #define op_smalltbl_1_ff NULL
1291 #define op_smalltbl_2_ff NULL
1292 #define op_smalltbl_3_ff NULL
1293 #define op_smalltbl_4_ff NULL
1294 #define op_smalltbl_5_ff NULL
1295 #endif
1296 #ifndef CPUEMU_11
1297 #define op_smalltbl_11_ff op_smalltbl_0_ff
1298 #define op_smalltbl_12_ff op_smalltbl_0_ff
1299 #endif
1300 #ifndef CPUEMU_20
1301 #define op_smalltbl_20_ff op_smalltbl_0_ff
1302 #endif
1303 #ifndef CPUEMU_21
1304 #define op_smalltbl_21_ff op_smalltbl_0_ff
1305 #endif
1306 #ifndef CPUEMU_22
1307 #define op_smalltbl_22_ff op_smalltbl_0_ff
1308 #endif
1309 #ifndef CPUEMU_23
1310 #define op_smalltbl_23_ff op_smalltbl_0_ff
1311 #endif
1312 #ifndef CPUEMU_24
1313 #define op_smalltbl_24_ff op_smalltbl_0_ff
1314 #endif
1315 #ifndef CPUEMU_25
1316 #define op_smalltbl_25_ff op_smalltbl_0_ff
1317 #endif
1318 #ifndef CPUEMU_31
1319 #define op_smalltbl_31_ff op_smalltbl_0_ff
1320 #endif
1321 #ifndef CPUEMU_32
1322 #define op_smalltbl_32_ff op_smalltbl_0_ff
1323 #endif
1324 #ifndef CPUEMU_33
1325 #define op_smalltbl_33_ff op_smalltbl_0_ff
1326 #endif
1327 #ifndef CPUEMU_40
1328 #define op_smalltbl_40_ff op_smalltbl_0_ff
1329 #define op_smalltbl_41_ff op_smalltbl_0_ff
1330 #define op_smalltbl_42_ff op_smalltbl_0_ff
1331 #define op_smalltbl_43_ff op_smalltbl_0_ff
1332 #define op_smalltbl_44_ff op_smalltbl_0_ff
1333 #define op_smalltbl_45_ff op_smalltbl_0_ff
1334 #endif
1335 #ifndef CPUEMU_50
1336 #define op_smalltbl_50_ff op_smalltbl_0_ff
1337 #define op_smalltbl_51_ff op_smalltbl_0_ff
1338 #define op_smalltbl_52_ff op_smalltbl_0_ff
1339 #define op_smalltbl_53_ff op_smalltbl_0_ff
1340 #define op_smalltbl_54_ff op_smalltbl_0_ff
1341 #define op_smalltbl_55_ff op_smalltbl_0_ff
1342 #endif
1343
1344 // generic+direct, generic+direct+jit, generic+indirect, more compatible, cycle-exact, mmu
1345 static const struct cputbl *cputbls[6][6] =
1346 {
1347 // 68000
1348 { op_smalltbl_5_ff, op_smalltbl_45_ff, op_smalltbl_55_ff, op_smalltbl_12_ff, op_smalltbl_14_ff, NULL },
1349 // 68010
1350 { op_smalltbl_4_ff, op_smalltbl_44_ff, op_smalltbl_54_ff, op_smalltbl_11_ff, op_smalltbl_13_ff, NULL },
1351 // 68020
1352 { op_smalltbl_3_ff, op_smalltbl_43_ff, op_smalltbl_53_ff, op_smalltbl_20_ff, op_smalltbl_21_ff, NULL },
1353 // 68030
1354 { op_smalltbl_2_ff, op_smalltbl_42_ff, op_smalltbl_52_ff, op_smalltbl_22_ff, op_smalltbl_23_ff, op_smalltbl_32_ff },
1355 // 68040
1356 { op_smalltbl_1_ff, op_smalltbl_41_ff, op_smalltbl_51_ff, op_smalltbl_25_ff, op_smalltbl_25_ff, op_smalltbl_31_ff },
1357 // 68060
1358 { op_smalltbl_0_ff, op_smalltbl_40_ff, op_smalltbl_50_ff, op_smalltbl_24_ff, op_smalltbl_24_ff, op_smalltbl_33_ff }
1359 };
1360
build_cpufunctbl(void)1361 static void build_cpufunctbl (void)
1362 {
1363 int i, opcnt;
1364 unsigned long opcode;
1365 const struct cputbl *tbl = 0;
1366 int lvl, mode;
1367
1368 if (!currprefs.cachesize) {
1369 if (currprefs.mmu_model)
1370 mode = 5;
1371 else if (currprefs.cpu_cycle_exact)
1372 mode = 4;
1373 else if (currprefs.cpu_compatible)
1374 mode = 3;
1375 else
1376 mode = 0;
1377 m68k_pc_indirect = mode != 0 ? 1 : 0;
1378 } else {
1379 mode = 1;
1380 m68k_pc_indirect = 0;
1381 if (currprefs.comptrustbyte) {
1382 mode = 2;
1383 m68k_pc_indirect = -1;
1384 }
1385 }
1386 lvl = (currprefs.cpu_model - 68000) / 10;
1387 if (lvl == 6)
1388 lvl = 5;
1389 tbl = cputbls[lvl][mode];
1390
1391 if (tbl == NULL) {
1392 write_log (_T("no CPU emulation cores available CPU=%d!"), currprefs.cpu_model);
1393 abort ();
1394 }
1395
1396 for (opcode = 0; opcode < 65536; opcode++)
1397 cpufunctbl[opcode] = op_illg_1;
1398 for (i = 0; tbl[i].handler != NULL; i++) {
1399 opcode = tbl[i].opcode;
1400 cpufunctbl[opcode] = tbl[i].handler;
1401 cpudatatbl[opcode].length = tbl[i].length;
1402 cpudatatbl[opcode].disp020[0] = tbl[i].disp020[0];
1403 cpudatatbl[opcode].disp020[1] = tbl[i].disp020[1];
1404 cpudatatbl[opcode].branch = tbl[i].branch;
1405 }
1406
1407 /* hack fpu to 68000/68010 mode */
1408 if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
1409 tbl = op_smalltbl_3_ff;
1410 for (i = 0; tbl[i].handler != NULL; i++) {
1411 if ((tbl[i].opcode & 0xfe00) == 0xf200) {
1412 cpufunctbl[tbl[i].opcode] = tbl[i].handler;
1413 cpudatatbl[tbl[i].opcode].length = tbl[i].length;
1414 cpudatatbl[tbl[i].opcode].disp020[0] = tbl[i].disp020[0];
1415 cpudatatbl[tbl[i].opcode].disp020[1] = tbl[i].disp020[1];
1416 cpudatatbl[tbl[i].opcode].branch = tbl[i].branch;
1417 }
1418 }
1419 }
1420
1421 opcnt = 0;
1422 for (opcode = 0; opcode < 65536; opcode++) {
1423 cpuop_func *f;
1424 instr *table = &table68k[opcode];
1425
1426 if (table->mnemo == i_ILLG)
1427 continue;
1428
1429 /* unimplemented opcode? */
1430 if (table->unimpclev > 0 && lvl >= table->unimpclev) {
1431 if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
1432 cpufunctbl[opcode] = op_unimpl_1;
1433 continue;
1434 } else {
1435 // emulate 68060 unimplemented instructions if int_no_unimplemented=false
1436 if (currprefs.cpu_model != 68060 && table->unimpclev != 5) {
1437 cpufunctbl[opcode] = op_illg_1;
1438 continue;
1439 }
1440 }
1441 }
1442
1443 if (currprefs.fpu_model && currprefs.cpu_model < 68020) {
1444 /* more hack fpu to 68000/68010 mode */
1445 if (table->clev > lvl && (opcode & 0xfe00) != 0xf200)
1446 continue;
1447 } else if (table->clev > lvl) {
1448 continue;
1449 }
1450
1451 if (table->handler != -1) {
1452 int idx = table->handler;
1453 f = cpufunctbl[idx];
1454 if (f == op_illg_1)
1455 abort ();
1456 cpufunctbl[opcode] = f;
1457 memcpy(&cpudatatbl[opcode], &cpudatatbl[idx], sizeof(struct cputbl_data));
1458 opcnt++;
1459 }
1460 }
1461 write_log (_T("Building CPU, %d opcodes (%d %d %d)\n"),
1462 opcnt, lvl,
1463 currprefs.cpu_cycle_exact ? -2 : currprefs.cpu_memory_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0, currprefs.address_space_24);
1464 #ifdef JIT
1465 write_log(_T("JIT: &countdown = %p\n"), &countdown);
1466 write_log(_T("JIT: &build_comp = %p\n"), &build_comp);
1467 build_comp ();
1468 #endif
1469
1470 write_log(_T("CPU=%d, FPU=%d, MMU=%d, JIT%s=%d."),
1471 currprefs.cpu_model, currprefs.fpu_model,
1472 currprefs.mmu_model,
1473 currprefs.cachesize ? (currprefs.compfpu ? _T("=CPU/FPU") : _T("=CPU")) : _T(""),
1474 currprefs.cachesize);
1475
1476 regs.address_space_mask = 0xffffffff;
1477 if (currprefs.cpu_compatible) {
1478 if (currprefs.address_space_24 && currprefs.cpu_model >= 68040)
1479 currprefs.address_space_24 = false;
1480 }
1481 m68k_interrupt_delay = false;
1482 if (currprefs.cpu_cycle_exact) {
1483 if (tbl == op_smalltbl_14_ff || tbl == op_smalltbl_13_ff || tbl == op_smalltbl_21_ff || tbl == op_smalltbl_23_ff)
1484 m68k_interrupt_delay = true;
1485 }
1486
1487 if (currprefs.cpu_cycle_exact) {
1488 if (currprefs.cpu_model == 68000)
1489 write_log(_T(" prefetch and cycle-exact"));
1490 else
1491 write_log(_T(" ~cycle-exact"));
1492 } else if (currprefs.cpu_memory_cycle_exact) {
1493 write_log(_T(" ~memory-cycle-exact"));
1494 } else if (currprefs.cpu_compatible) {
1495 if (currprefs.cpu_model <= 68020) {
1496 write_log(_T(" prefetch"));
1497 } else {
1498 write_log(_T(" fake prefetch"));
1499 }
1500 }
1501 if (currprefs.m68k_speed < 0)
1502 write_log(_T(" fast"));
1503 if (currprefs.int_no_unimplemented && currprefs.cpu_model == 68060) {
1504 write_log(_T(" no unimplemented integer instructions"));
1505 }
1506 if (currprefs.fpu_no_unimplemented && currprefs.fpu_model) {
1507 write_log(_T(" no unimplemented floating point instructions"));
1508 }
1509 if (currprefs.address_space_24) {
1510 regs.address_space_mask = 0x00ffffff;
1511 write_log(_T(" 24-bit"));
1512 }
1513 write_log(_T("\n"));
1514
1515 set_cpu_caches (true);
1516 }
1517
1518 #define CYCLES_DIV 8192
1519 static unsigned long cycles_mult;
1520
update_68k_cycles(void)1521 static void update_68k_cycles (void)
1522 {
1523 cycles_mult = 0;
1524 if (currprefs.m68k_speed >= 0 && !currprefs.cpu_cycle_exact) {
1525 if (currprefs.m68k_speed_throttle < 0) {
1526 cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
1527 } else if (currprefs.m68k_speed_throttle > 0) {
1528 cycles_mult = (unsigned long)(CYCLES_DIV * 1000 / (1000 + currprefs.m68k_speed_throttle));
1529 }
1530 }
1531 if (currprefs.m68k_speed == 0) {
1532 if (currprefs.cpu_model >= 68040) {
1533 if (!cycles_mult)
1534 cycles_mult = CYCLES_DIV / 8;
1535 else
1536 cycles_mult /= 8;
1537 } else if (currprefs.cpu_model >= 68020) {
1538 if (!cycles_mult)
1539 cycles_mult = CYCLES_DIV / 4;
1540 else
1541 cycles_mult /= 4;
1542 }
1543 }
1544
1545 currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier;
1546 currprefs.cpu_frequency = changed_prefs.cpu_frequency;
1547
1548 baseclock = (currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) * 8;
1549 cpucycleunit = CYCLE_UNIT / 2;
1550 if (currprefs.cpu_clock_multiplier) {
1551 if (currprefs.cpu_clock_multiplier >= 256) {
1552 cpucycleunit = CYCLE_UNIT / (currprefs.cpu_clock_multiplier >> 8);
1553 } else {
1554 cpucycleunit = CYCLE_UNIT * currprefs.cpu_clock_multiplier;
1555 }
1556 if (currprefs.cpu_model >= 68040)
1557 cpucycleunit /= 2;
1558 } else if (currprefs.cpu_frequency) {
1559 cpucycleunit = CYCLE_UNIT * baseclock / currprefs.cpu_frequency;
1560 } else if (currprefs.cpu_cycle_exact && currprefs.cpu_clock_multiplier == 0) {
1561 if (currprefs.cpu_model >= 68040) {
1562 cpucycleunit = CYCLE_UNIT / 16;
1563 } if (currprefs.cpu_model == 68030) {
1564 cpucycleunit = CYCLE_UNIT / 8;
1565 } else if (currprefs.cpu_model == 68020) {
1566 cpucycleunit = CYCLE_UNIT / 4;
1567 } else {
1568 cpucycleunit = CYCLE_UNIT / 2;
1569 }
1570 }
1571 if (cpucycleunit < 1)
1572 cpucycleunit = 1;
1573 if (currprefs.cpu_cycle_exact)
1574 write_log (_T("CPU cycleunit: %d (%.3f)\n"), cpucycleunit, (float)cpucycleunit / CYCLE_UNIT);
1575 set_config_changed ();
1576 }
1577
prefs_changed_cpu(void)1578 static void prefs_changed_cpu (void)
1579 {
1580 fixup_cpu (&changed_prefs);
1581 #ifdef JIT
1582 check_prefs_changed_comp(false);
1583 #endif
1584 currprefs.cpu_model = changed_prefs.cpu_model;
1585 currprefs.fpu_model = changed_prefs.fpu_model;
1586 currprefs.mmu_model = changed_prefs.mmu_model;
1587 currprefs.cpu_compatible = changed_prefs.cpu_compatible;
1588 currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
1589 currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact;
1590 currprefs.int_no_unimplemented = changed_prefs.int_no_unimplemented;
1591 currprefs.fpu_no_unimplemented = changed_prefs.fpu_no_unimplemented;
1592 currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
1593 }
1594
check_prefs_changed_cpu2(void)1595 static int check_prefs_changed_cpu2(void)
1596 {
1597 int changed = 0;
1598
1599 #ifdef JIT
1600 changed = check_prefs_changed_comp(true) ? 1 : 0;
1601 #endif
1602 if (changed
1603 || currprefs.cpu_model != changed_prefs.cpu_model
1604 || currprefs.fpu_model != changed_prefs.fpu_model
1605 || currprefs.mmu_model != changed_prefs.mmu_model
1606 || currprefs.int_no_unimplemented != changed_prefs.int_no_unimplemented
1607 || currprefs.fpu_no_unimplemented != changed_prefs.fpu_no_unimplemented
1608 || currprefs.cpu_compatible != changed_prefs.cpu_compatible
1609 || currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact
1610 || currprefs.cpu_memory_cycle_exact != changed_prefs.cpu_memory_cycle_exact) {
1611 cpu_prefs_changed_flag |= 1;
1612 }
1613 if (changed
1614 || currprefs.m68k_speed != changed_prefs.m68k_speed
1615 || currprefs.m68k_speed_throttle != changed_prefs.m68k_speed_throttle
1616 || currprefs.cpu_clock_multiplier != changed_prefs.cpu_clock_multiplier
1617 || currprefs.reset_delay != changed_prefs.reset_delay
1618 || currprefs.cpu_frequency != changed_prefs.cpu_frequency) {
1619 cpu_prefs_changed_flag |= 2;
1620 }
1621 return cpu_prefs_changed_flag;
1622 }
1623
check_prefs_changed_cpu(void)1624 void check_prefs_changed_cpu(void)
1625 {
1626 if (!config_changed)
1627 return;
1628
1629 currprefs.cpu_idle = changed_prefs.cpu_idle;
1630 currprefs.ppc_cpu_idle = changed_prefs.ppc_cpu_idle;
1631 currprefs.reset_delay = changed_prefs.reset_delay;
1632
1633 if (check_prefs_changed_cpu2()) {
1634 set_special(SPCFLAG_MODE_CHANGE);
1635 reset_frame_rate_hack();
1636 }
1637 }
1638
init_m68k(void)1639 void init_m68k (void)
1640 {
1641 prefs_changed_cpu ();
1642 update_68k_cycles ();
1643
1644 for (int i = 0 ; i < 256 ; i++) {
1645 int j;
1646 for (j = 0 ; j < 8 ; j++) {
1647 if (i & (1 << j)) break;
1648 }
1649 movem_index1[i] = j;
1650 movem_index2[i] = 7 - j;
1651 movem_next[i] = i & (~(1 << j));
1652 }
1653
1654 #if COUNT_INSTRS
1655 {
1656 FILE *f = fopen (icountfilename (), "r");
1657 memset (instrcount, 0, sizeof instrcount);
1658 if (f) {
1659 uae_u32 opcode, count, total;
1660 TCHAR name[20];
1661 write_log (_T("Reading instruction count file...\n"));
1662 fscanf (f, "Total: %lu\n", &total);
1663 while (fscanf (f, "%x: %lu %s\n", &opcode, &count, name) == 3) {
1664 instrcount[opcode] = count;
1665 }
1666 fclose (f);
1667 }
1668 }
1669 #endif
1670
1671 read_table68k ();
1672 do_merges ();
1673
1674 write_log (_T("%d CPU functions\n"), nr_cpuop_funcs);
1675
1676 build_cpufunctbl ();
1677 set_x_funcs ();
1678
1679 #ifdef JIT
1680 /* We need to check whether NATMEM settings have changed
1681 * before starting the CPU */
1682 check_prefs_changed_comp(false);
1683 #endif
1684 }
1685
1686 struct regstruct regs, mmu_backup_regs;
1687 struct flag_struct regflags;
1688 static int m68kpc_offset;
1689
1690 #if 0
1691 #define get_ibyte_1(o) get_byte (regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
1692 #define get_iword_1(o) get_word (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1693 #define get_ilong_1(o) get_long (regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
1694 #endif
1695
ShowEA(void * f,uaecptr pc,uae_u16 opcode,int reg,amodes mode,wordsizes size,TCHAR * buf,uae_u32 * eaddr,int safemode)1696 static uaecptr ShowEA (void *f, uaecptr pc, uae_u16 opcode, int reg, amodes mode, wordsizes size, TCHAR *buf, uae_u32 *eaddr, int safemode)
1697 {
1698 uae_u16 dp;
1699 uae_s8 disp8;
1700 uae_s16 disp16;
1701 int r;
1702 uae_u32 dispreg;
1703 uaecptr addr = pc;
1704 uae_s32 offset = 0;
1705 TCHAR buffer[80];
1706
1707 switch (mode){
1708 case Dreg:
1709 _stprintf (buffer, _T("D%d"), reg);
1710 break;
1711 case Areg:
1712 _stprintf (buffer, _T("A%d"), reg);
1713 break;
1714 case Aind:
1715 _stprintf (buffer, _T("(A%d)"), reg);
1716 addr = regs.regs[reg + 8];
1717 break;
1718 case Aipi:
1719 _stprintf (buffer, _T("(A%d)+"), reg);
1720 addr = regs.regs[reg + 8];
1721 break;
1722 case Apdi:
1723 _stprintf (buffer, _T("-(A%d)"), reg);
1724 addr = regs.regs[reg + 8];
1725 break;
1726 case Ad16:
1727 {
1728 TCHAR offtxt[80];
1729 disp16 = get_iword_debug (pc); pc += 2;
1730 if (disp16 < 0)
1731 _stprintf (offtxt, _T("-$%04x"), -disp16);
1732 else
1733 _stprintf (offtxt, _T("$%04x"), disp16);
1734 addr = m68k_areg (regs, reg) + disp16;
1735 _stprintf (buffer, _T("(A%d, %s) == $%08x"), reg, offtxt, addr);
1736 }
1737 break;
1738 case Ad8r:
1739 dp = get_iword_debug (pc); pc += 2;
1740 disp8 = dp & 0xFF;
1741 r = (dp & 0x7000) >> 12;
1742 dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1743 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1744 dispreg <<= (dp >> 9) & 3;
1745
1746 if (dp & 0x100) {
1747 uae_s32 outer = 0, disp = 0;
1748 uae_s32 base = m68k_areg (regs, reg);
1749 TCHAR name[10];
1750 _stprintf (name, _T("A%d, "), reg);
1751 if (dp & 0x80) { base = 0; name[0] = 0; }
1752 if (dp & 0x40) dispreg = 0;
1753 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1754 if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1755 base += disp;
1756
1757 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1758 if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1759
1760 if (!(dp & 4)) base += dispreg;
1761 if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1762 if (dp & 4) base += dispreg;
1763
1764 addr = base + outer;
1765 _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1766 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1767 1 << ((dp >> 9) & 3),
1768 disp, outer, addr);
1769 } else {
1770 addr = m68k_areg (regs, reg) + (uae_s32)((uae_s8)disp8) + dispreg;
1771 _stprintf (buffer, _T("(A%d, %c%d.%c*%d, $%02x) == $%08x"), reg,
1772 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1773 1 << ((dp >> 9) & 3), disp8, addr);
1774 }
1775 break;
1776 case PC16:
1777 disp16 = get_iword_debug (pc); pc += 2;
1778 addr += (uae_s16)disp16;
1779 _stprintf (buffer, _T("(PC,$%04x) == $%08x"), disp16 & 0xffff, addr);
1780 break;
1781 case PC8r:
1782 dp = get_iword_debug (pc); pc += 2;
1783 disp8 = dp & 0xFF;
1784 r = (dp & 0x7000) >> 12;
1785 dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1786 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1787 dispreg <<= (dp >> 9) & 3;
1788
1789 if (dp & 0x100) {
1790 uae_s32 outer = 0, disp = 0;
1791 uae_s32 base = addr;
1792 TCHAR name[10];
1793 _stprintf (name, _T("PC, "));
1794 if (dp & 0x80) { base = 0; name[0] = 0; }
1795 if (dp & 0x40) dispreg = 0;
1796 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1797 if ((dp & 0x30) == 0x30) { disp = get_ilong_debug (pc); pc += 4; }
1798 base += disp;
1799
1800 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_debug (pc); pc += 2; }
1801 if ((dp & 0x3) == 0x3) { outer = get_ilong_debug (pc); pc += 4; }
1802
1803 if (!(dp & 4)) base += dispreg;
1804 if ((dp & 3) && !safemode) base = get_ilong_debug (base);
1805 if (dp & 4) base += dispreg;
1806
1807 addr = base + outer;
1808 _stprintf (buffer, _T("(%s%c%d.%c*%d+%d)+%d == $%08x"), name,
1809 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
1810 1 << ((dp >> 9) & 3),
1811 disp, outer, addr);
1812 } else {
1813 addr += (uae_s32)((uae_s8)disp8) + dispreg;
1814 _stprintf (buffer, _T("(PC, %c%d.%c*%d, $%02x) == $%08x"), dp & 0x8000 ? 'A' : 'D',
1815 (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
1816 disp8, addr);
1817 }
1818 break;
1819 case absw:
1820 addr = (uae_s32)(uae_s16)get_iword_debug (pc);
1821 _stprintf (buffer, _T("$%08x"), addr);
1822 pc += 2;
1823 break;
1824 case absl:
1825 addr = get_ilong_debug (pc);
1826 _stprintf (buffer, _T("$%08x"), addr);
1827 pc += 4;
1828 break;
1829 case imm:
1830 switch (size){
1831 case sz_byte:
1832 _stprintf (buffer, _T("#$%02x"), (get_iword_debug (pc) & 0xff));
1833 pc += 2;
1834 break;
1835 case sz_word:
1836 _stprintf (buffer, _T("#$%04x"), (get_iword_debug (pc) & 0xffff));
1837 pc += 2;
1838 break;
1839 case sz_long:
1840 _stprintf(buffer, _T("#$%08x"), (get_ilong_debug(pc)));
1841 pc += 4;
1842 break;
1843 case sz_single:
1844 {
1845 fpdata fp;
1846 to_single(&fp, get_ilong_debug(pc));
1847 _stprintf(buffer, _T("#%e"), fp.fp);
1848 pc += 4;
1849 }
1850 break;
1851 case sz_double:
1852 {
1853 fpdata fp;
1854 to_double(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4));
1855 _stprintf(buffer, _T("#%e"), fp.fp);
1856 pc += 8;
1857 }
1858 break;
1859 case sz_extended:
1860 {
1861 fpdata fp;
1862 to_exten(&fp, get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
1863 #if USE_LONG_DOUBLE
1864 _stprintf(buffer, _T("#%Le"), fp.fp);
1865 #else
1866 _stprintf(buffer, _T("#%e"), fp.fp);
1867 #endif
1868 pc += 12;
1869 break;
1870 }
1871 case sz_packed:
1872 _stprintf(buffer, _T("#$%08x%08x%08x"), get_ilong_debug(pc), get_ilong_debug(pc + 4), get_ilong_debug(pc + 8));
1873 pc += 12;
1874 break;
1875 default:
1876 break;
1877 }
1878 break;
1879 case imm0:
1880 offset = (uae_s32)(uae_s8)get_iword_debug (pc);
1881 _stprintf (buffer, _T("#$%02x"), (uae_u32)(offset & 0xff));
1882 addr = pc + 2 + offset;
1883 pc += 2;
1884 break;
1885 case imm1:
1886 offset = (uae_s32)(uae_s16)get_iword_debug (pc);
1887 buffer[0] = 0;
1888 _stprintf (buffer, _T("#$%04x"), (uae_u32)(offset & 0xffff));
1889 addr = pc + offset;
1890 pc += 2;
1891 break;
1892 case imm2:
1893 offset = (uae_s32)get_ilong_debug (pc);
1894 _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
1895 addr = pc + offset;
1896 pc += 4;
1897 break;
1898 case immi:
1899 offset = (uae_s32)(uae_s8)(reg & 0xff);
1900 _stprintf (buffer, _T("#$%08x"), (uae_u32)offset);
1901 addr = pc + offset;
1902 break;
1903 default:
1904 break;
1905 }
1906 if (buf == 0)
1907 f_out (f, _T("%s"), buffer);
1908 else
1909 _tcscat (buf, buffer);
1910 if (eaddr)
1911 *eaddr = addr;
1912 return pc;
1913 }
1914
1915 #if 0
1916 /* The plan is that this will take over the job of exception 3 handling -
1917 * the CPU emulation functions will just do a longjmp to m68k_go whenever
1918 * they hit an odd address. */
1919 static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
1920 {
1921 uae_u16 dp;
1922 uae_s8 disp8;
1923 uae_s16 disp16;
1924 int r;
1925 uae_u32 dispreg;
1926 uaecptr addr;
1927 uae_s32 offset = 0;
1928
1929 switch (mode){
1930 case Dreg:
1931 *val = m68k_dreg (regs, reg);
1932 return 1;
1933 case Areg:
1934 *val = m68k_areg (regs, reg);
1935 return 1;
1936
1937 case Aind:
1938 case Aipi:
1939 addr = m68k_areg (regs, reg);
1940 break;
1941 case Apdi:
1942 addr = m68k_areg (regs, reg);
1943 break;
1944 case Ad16:
1945 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1946 addr = m68k_areg (regs, reg) + (uae_s16)disp16;
1947 break;
1948 case Ad8r:
1949 addr = m68k_areg (regs, reg);
1950 d8r_common:
1951 dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1952 disp8 = dp & 0xFF;
1953 r = (dp & 0x7000) >> 12;
1954 dispreg = dp & 0x8000 ? m68k_areg (regs, r) : m68k_dreg (regs, r);
1955 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
1956 dispreg <<= (dp >> 9) & 3;
1957
1958 if (dp & 0x100) {
1959 uae_s32 outer = 0, disp = 0;
1960 uae_s32 base = addr;
1961 if (dp & 0x80) base = 0;
1962 if (dp & 0x40) dispreg = 0;
1963 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
1964 if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1965 base += disp;
1966
1967 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
1968 if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
1969
1970 if (!(dp & 4)) base += dispreg;
1971 if (dp & 3) base = get_long (base);
1972 if (dp & 4) base += dispreg;
1973
1974 addr = base + outer;
1975 } else {
1976 addr += (uae_s32)((uae_s8)disp8) + dispreg;
1977 }
1978 break;
1979 case PC16:
1980 addr = m68k_getpc () + m68kpc_offset;
1981 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
1982 addr += (uae_s16)disp16;
1983 break;
1984 case PC8r:
1985 addr = m68k_getpc () + m68kpc_offset;
1986 goto d8r_common;
1987 case absw:
1988 addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
1989 m68kpc_offset += 2;
1990 break;
1991 case absl:
1992 addr = get_ilong_1 (m68kpc_offset);
1993 m68kpc_offset += 4;
1994 break;
1995 case imm:
1996 switch (size){
1997 case sz_byte:
1998 *val = get_iword_1 (m68kpc_offset) & 0xff;
1999 m68kpc_offset += 2;
2000 break;
2001 case sz_word:
2002 *val = get_iword_1 (m68kpc_offset) & 0xffff;
2003 m68kpc_offset += 2;
2004 break;
2005 case sz_long:
2006 *val = get_ilong_1 (m68kpc_offset);
2007 m68kpc_offset += 4;
2008 break;
2009 default:
2010 break;
2011 }
2012 return 1;
2013 case imm0:
2014 *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
2015 m68kpc_offset += 2;
2016 return 1;
2017 case imm1:
2018 *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
2019 m68kpc_offset += 2;
2020 return 1;
2021 case imm2:
2022 *val = get_ilong_1 (m68kpc_offset);
2023 m68kpc_offset += 4;
2024 return 1;
2025 case immi:
2026 *val = (uae_s32)(uae_s8)(reg & 0xff);
2027 return 1;
2028 default:
2029 addr = 0;
2030 break;
2031 }
2032 if ((addr & 1) == 0)
2033 return 1;
2034
2035 last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
2036 last_fault_for_exception_3 = addr;
2037 last_writeaccess_for_exception_3 = 0;
2038 last_instructionaccess_for_exception_3 = 0;
2039 return 0;
2040 }
2041 #endif
2042
get_cpu_model(void)2043 int get_cpu_model (void)
2044 {
2045 return currprefs.cpu_model;
2046 }
2047
2048
in_rom(uaecptr pc)2049 STATIC_INLINE int in_rom (uaecptr pc)
2050 {
2051 return (munge24 (pc) & 0xFFF80000) == 0xF80000;
2052 }
2053
in_rtarea(uaecptr pc)2054 STATIC_INLINE int in_rtarea (uaecptr pc)
2055 {
2056 return (munge24 (pc) & 0xFFFF0000) == rtarea_base && uae_boot_rom_type;
2057 }
2058
wait_memory_cycles(void)2059 STATIC_INLINE void wait_memory_cycles (void)
2060 {
2061 if (regs.memory_waitstate_cycles) {
2062 x_do_cycles(regs.memory_waitstate_cycles);
2063 regs.memory_waitstate_cycles = 0;
2064 }
2065 if (regs.ce020extracycles >= 16) {
2066 regs.ce020extracycles = 0;
2067 x_do_cycles(4 * CYCLE_UNIT);
2068 }
2069 }
2070
adjust_cycles(int cycles)2071 STATIC_INLINE int adjust_cycles (int cycles)
2072 {
2073 int mc = regs.memory_waitstate_cycles;
2074 regs.memory_waitstate_cycles = 0;
2075 if (currprefs.m68k_speed < 0 || cycles_mult == 0)
2076 return cycles + mc;
2077 cycles *= cycles_mult;
2078 cycles /= CYCLES_DIV;
2079 return cycles + mc;
2080 }
2081
MakeSR(void)2082 void REGPARAM2 MakeSR (void)
2083 {
2084 regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
2085 | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
2086 | (GET_XFLG () << 4) | (GET_NFLG () << 3)
2087 | (GET_ZFLG () << 2) | (GET_VFLG () << 1)
2088 | GET_CFLG ());
2089 }
2090
SetSR(uae_u16 sr)2091 static void SetSR (uae_u16 sr)
2092 {
2093 regs.sr &= 0xff00;
2094 regs.sr |= sr;
2095
2096 SET_XFLG ((regs.sr >> 4) & 1);
2097 SET_NFLG ((regs.sr >> 3) & 1);
2098 SET_ZFLG ((regs.sr >> 2) & 1);
2099 SET_VFLG ((regs.sr >> 1) & 1);
2100 SET_CFLG (regs.sr & 1);
2101 }
2102
MakeFromSR(void)2103 void REGPARAM2 MakeFromSR (void)
2104 {
2105 int oldm = regs.m;
2106 int olds = regs.s;
2107
2108 SET_XFLG ((regs.sr >> 4) & 1);
2109 SET_NFLG ((regs.sr >> 3) & 1);
2110 SET_ZFLG ((regs.sr >> 2) & 1);
2111 SET_VFLG ((regs.sr >> 1) & 1);
2112 SET_CFLG (regs.sr & 1);
2113 if (regs.t1 == ((regs.sr >> 15) & 1) &&
2114 regs.t0 == ((regs.sr >> 14) & 1) &&
2115 regs.s == ((regs.sr >> 13) & 1) &&
2116 regs.m == ((regs.sr >> 12) & 1) &&
2117 regs.intmask == ((regs.sr >> 8) & 7))
2118 return;
2119 regs.t1 = (regs.sr >> 15) & 1;
2120 regs.t0 = (regs.sr >> 14) & 1;
2121 regs.s = (regs.sr >> 13) & 1;
2122 regs.m = (regs.sr >> 12) & 1;
2123 regs.intmask = (regs.sr >> 8) & 7;
2124 if (currprefs.cpu_model >= 68020) {
2125 /* 68060 does not have MSP but does have M-bit.. */
2126 if (currprefs.cpu_model >= 68060)
2127 regs.msp = regs.isp;
2128 if (olds != regs.s) {
2129 if (olds) {
2130 if (oldm)
2131 regs.msp = m68k_areg (regs, 7);
2132 else
2133 regs.isp = m68k_areg (regs, 7);
2134 m68k_areg (regs, 7) = regs.usp;
2135 } else {
2136 regs.usp = m68k_areg (regs, 7);
2137 m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
2138 }
2139 } else if (olds && oldm != regs.m) {
2140 if (oldm) {
2141 regs.msp = m68k_areg (regs, 7);
2142 m68k_areg (regs, 7) = regs.isp;
2143 } else {
2144 regs.isp = m68k_areg (regs, 7);
2145 m68k_areg (regs, 7) = regs.msp;
2146 }
2147 }
2148 if (currprefs.cpu_model >= 68060)
2149 regs.t0 = 0;
2150 } else {
2151 regs.t0 = regs.m = 0;
2152 if (olds != regs.s) {
2153 if (olds) {
2154 regs.isp = m68k_areg (regs, 7);
2155 m68k_areg (regs, 7) = regs.usp;
2156 } else {
2157 regs.usp = m68k_areg (regs, 7);
2158 m68k_areg (regs, 7) = regs.isp;
2159 }
2160 }
2161 }
2162 if (currprefs.mmu_model)
2163 mmu_set_super (regs.s != 0);
2164
2165 doint ();
2166 if (regs.t1 || regs.t0)
2167 set_special (SPCFLAG_TRACE);
2168 else
2169 /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
2170 SR-modifying instructions (including STOP). */
2171 unset_special (SPCFLAG_TRACE);
2172 }
2173
exception_trace(int nr)2174 static void exception_trace (int nr)
2175 {
2176 unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
2177 if (regs.t1 && !regs.t0) {
2178 /* trace stays pending if exception is div by zero, chk,
2179 * trapv or trap #x
2180 */
2181 if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
2182 set_special (SPCFLAG_DOTRACE);
2183 }
2184 regs.t1 = regs.t0 = regs.m = 0;
2185 }
2186
exception_debug(int nr)2187 static void exception_debug (int nr)
2188 {
2189 #ifdef DEBUGGER
2190 if (!exception_debugging)
2191 return;
2192 console_out_f (_T("Exception %d, PC=%08X\n"), nr, M68K_GETPC);
2193 #endif
2194 }
2195
2196 #ifdef CPUEMU_13
2197
2198 /* cycle-exact exception handler, 68000 only */
2199
2200 /*
2201
2202 Address/Bus Error:
2203
2204 - 8 idle cycles
2205 - write PC low word
2206 - write SR
2207 - write PC high word
2208 - write instruction word
2209 - write fault address low word
2210 - write status code
2211 - write fault address high word
2212 - 2 idle cycles
2213 - read exception address high word
2214 - read exception address low word
2215 - prefetch
2216 - 2 idle cycles
2217 - prefetch
2218
2219 Division by Zero:
2220
2221 - 8 idle cycles
2222 - write PC low word
2223 - write SR
2224 - write PC high word
2225 - read exception address high word
2226 - read exception address low word
2227 - prefetch
2228 - 2 idle cycles
2229 - prefetch
2230
2231 Traps:
2232
2233 - 4 idle cycles
2234 - write PC low word
2235 - write SR
2236 - write PC high word
2237 - read exception address high word
2238 - read exception address low word
2239 - prefetch
2240 - 2 idle cycles
2241 - prefetch
2242
2243 TrapV:
2244
2245 (- normal prefetch done by TRAPV)
2246 - write PC low word
2247 - write SR
2248 - write PC high word
2249 - read exception address high word
2250 - read exception address low word
2251 - prefetch
2252 - 2 idle cycles
2253 - prefetch
2254
2255 CHK:
2256
2257 - 8 idle cycles
2258 - write PC low word
2259 - write SR
2260 - write PC high word
2261 - read exception address high word
2262 - read exception address low word
2263 - prefetch
2264 - 2 idle cycles
2265 - prefetch
2266
2267 Illegal Instruction:
2268 Privilege violation:
2269 Trace:
2270 Line A:
2271 Line F:
2272
2273 - 4 idle cycles
2274 - write PC low word
2275 - write SR
2276 - write PC high word
2277 - read exception address high word
2278 - read exception address low word
2279 - prefetch
2280 - 2 idle cycles
2281 - prefetch
2282
2283 Interrupt:
2284
2285 - 6 idle cycles
2286 - write PC low word
2287 - read exception number byte from (0xfffff1 | (interrupt number << 1))
2288 - 4 idle cycles
2289 - write SR
2290 - write PC high word
2291 - read exception address high word
2292 - read exception address low word
2293 - prefetch
2294 - 2 idle cycles
2295 - prefetch
2296
2297 */
2298
iack_cycle(int nr)2299 static int iack_cycle(int nr)
2300 {
2301 int vector;
2302
2303 if (1) {
2304 // non-autovectored
2305 vector = x_get_byte(0x00fffff1 | ((nr - 24) << 1));
2306 if (currprefs.cpu_cycle_exact)
2307 x_do_cycles(4 * cpucycleunit);
2308 } else {
2309 // autovectored
2310
2311 }
2312 return vector;
2313 }
2314
Exception_ce000(int nr)2315 static void Exception_ce000 (int nr)
2316 {
2317 uae_u32 currpc = m68k_getpc (), newpc;
2318 int sv = regs.s;
2319 int start, interrupt;
2320 int vector_nr = nr;
2321
2322 start = 6;
2323 interrupt = nr >= 24 && nr < 24 + 8;
2324 if (!interrupt) {
2325 start = 8;
2326 if (nr == 7) // TRAPV
2327 start = 0;
2328 else if (nr >= 32 && nr < 32 + 16) // TRAP #x
2329 start = 4;
2330 else if (nr == 4 || nr == 8 || nr == 9 || nr == 10 || nr == 11) // ILLG, PRIV, TRACE, LINEA, LINEF
2331 start = 4;
2332 }
2333
2334 if (start)
2335 x_do_cycles (start * cpucycleunit);
2336
2337 exception_debug (nr);
2338 MakeSR ();
2339
2340 if (!regs.s) {
2341 regs.usp = m68k_areg (regs, 7);
2342 m68k_areg (regs, 7) = regs.isp;
2343 regs.s = 1;
2344 }
2345 if (nr == 2 || nr == 3) { /* 2=bus error, 3=address error */
2346 if ((m68k_areg(regs, 7) & 1) || exception_in_exception < 0) {
2347 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2348 return;
2349 }
2350 uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2351 mode |= last_writeaccess_for_exception_3 ? 0 : 16;
2352 mode |= last_notinstruction_for_exception_3 ? 8 : 0;
2353 // undocumented bits seem to contain opcode
2354 mode |= last_op_for_exception_3 & ~31;
2355 m68k_areg (regs, 7) -= 14;
2356 exception_in_exception = -1;
2357 x_put_word (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
2358 x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
2359 x_put_word (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
2360 x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
2361 x_put_word (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
2362 x_put_word (m68k_areg (regs, 7) + 0, mode);
2363 x_put_word (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
2364 x_do_cycles (2 * cpucycleunit);
2365 write_log (_T("Exception %d (%04x %x) at %x -> %x!\n"),
2366 nr, last_op_for_exception_3, last_addr_for_exception_3, currpc, get_long_debug (4 * nr));
2367 goto kludge_me_do;
2368 }
2369 if (currprefs.cpu_model == 68010) {
2370 // 68010 creates only format 0 and 8 stack frames
2371 m68k_areg (regs, 7) -= 8;
2372 if (m68k_areg(regs, 7) & 1) {
2373 exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
2374 return;
2375 }
2376 exception_in_exception = 1;
2377 x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
2378 if (interrupt)
2379 vector_nr = iack_cycle(nr);
2380 x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
2381 x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
2382 x_put_word (m68k_areg (regs, 7) + 6, vector_nr * 4);
2383 } else {
2384 m68k_areg (regs, 7) -= 6;
2385 if (m68k_areg(regs, 7) & 1) {
2386 exception3_notinstruction(regs.ir, m68k_areg(regs, 7) + 4);
2387 return;
2388 }
2389 exception_in_exception = 1;
2390 x_put_word (m68k_areg (regs, 7) + 4, currpc); // write low address
2391 if (interrupt)
2392 vector_nr = iack_cycle(nr);
2393 x_put_word (m68k_areg (regs, 7) + 0, regs.sr); // write SR
2394 x_put_word (m68k_areg (regs, 7) + 2, currpc >> 16); // write high address
2395 }
2396 kludge_me_do:
2397 newpc = x_get_word (regs.vbr + 4 * vector_nr) << 16; // read high address
2398 newpc |= x_get_word (regs.vbr + 4 * vector_nr + 2); // read low address
2399 exception_in_exception = 0;
2400 if (newpc & 1) {
2401 if (nr == 2 || nr == 3)
2402 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2403 else
2404 exception3_notinstruction(regs.ir, newpc);
2405 return;
2406 }
2407 m68k_setpc (newpc);
2408 regs.ir = x_get_word (m68k_getpc ()); // prefetch 1
2409 x_do_cycles (2 * cpucycleunit);
2410 regs.ipl_pin = intlev();
2411 ipl_fetch();
2412 regs.irc = x_get_word (m68k_getpc () + 2); // prefetch 2
2413 #ifdef JIT
2414 set_special (SPCFLAG_END_COMPILE);
2415 #endif
2416 exception_trace (nr);
2417 }
2418 #endif
2419
exception_pc(int nr)2420 static uae_u32 exception_pc (int nr)
2421 {
2422 // bus error, address error, illegal instruction, privilege violation, a-line, f-line
2423 if (nr == 2 || nr == 3 || nr == 4 || nr == 8 || nr == 10 || nr == 11)
2424 return regs.instruction_pc;
2425 return m68k_getpc ();
2426 }
2427
Exception_build_stack_frame(uae_u32 oldpc,uae_u32 currpc,uae_u32 ssw,int nr,int format)2428 static void Exception_build_stack_frame (uae_u32 oldpc, uae_u32 currpc, uae_u32 ssw, int nr, int format)
2429 {
2430 int i;
2431
2432 #if 0
2433 if (nr < 24 || nr > 31) { // do not print debugging for interrupts
2434 write_log(_T("Building exception stack frame (format %X)\n"), format);
2435 }
2436 #endif
2437
2438 switch (format) {
2439 case 0x0: // four word stack frame
2440 case 0x1: // throwaway four word stack frame
2441 break;
2442 case 0x2: // six word stack frame
2443 m68k_areg (regs, 7) -= 4;
2444 x_put_long (m68k_areg (regs, 7), oldpc);
2445 break;
2446 case 0x7: // access error stack frame (68040)
2447
2448 for (i = 3; i >= 0; i--) {
2449 // WB1D/PD0,PD1,PD2,PD3
2450 m68k_areg (regs, 7) -= 4;
2451 x_put_long (m68k_areg (regs, 7), mmu040_move16[i]);
2452 }
2453
2454 m68k_areg (regs, 7) -= 4;
2455 x_put_long (m68k_areg (regs, 7), 0); // WB1A
2456 m68k_areg (regs, 7) -= 4;
2457 x_put_long (m68k_areg (regs, 7), 0); // WB2D
2458 m68k_areg (regs, 7) -= 4;
2459 x_put_long (m68k_areg (regs, 7), regs.wb2_address); // WB2A
2460 m68k_areg (regs, 7) -= 4;
2461 x_put_long (m68k_areg (regs, 7), regs.wb3_data); // WB3D
2462 m68k_areg (regs, 7) -= 4;
2463 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // WB3A
2464
2465 m68k_areg (regs, 7) -= 4;
2466 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // FA
2467
2468 m68k_areg (regs, 7) -= 2;
2469 x_put_word (m68k_areg (regs, 7), 0);
2470 m68k_areg (regs, 7) -= 2;
2471 x_put_word (m68k_areg (regs, 7), regs.wb2_status);
2472 regs.wb2_status = 0;
2473 m68k_areg (regs, 7) -= 2;
2474 x_put_word (m68k_areg (regs, 7), regs.wb3_status);
2475 regs.wb3_status = 0;
2476
2477 m68k_areg (regs, 7) -= 2;
2478 x_put_word (m68k_areg (regs, 7), ssw);
2479 m68k_areg (regs, 7) -= 4;
2480 x_put_long (m68k_areg (regs, 7), regs.mmu_effective_addr);
2481 break;
2482 case 0x9: // coprocessor mid-instruction stack frame (68020, 68030)
2483 m68k_areg (regs, 7) -= 4;
2484 x_put_long (m68k_areg (regs, 7), 0);
2485 m68k_areg (regs, 7) -= 4;
2486 x_put_long (m68k_areg (regs, 7), 0);
2487 m68k_areg (regs, 7) -= 4;
2488 x_put_long (m68k_areg (regs, 7), oldpc);
2489 break;
2490 case 0x3: // floating point post-instruction stack frame (68040)
2491 case 0x8: // bus and address error stack frame (68010)
2492 write_log(_T("Exception stack frame format %X not implemented\n"), format);
2493 return;
2494 case 0x4: // floating point unimplemented stack frame (68LC040, 68EC040)
2495 // or 68060 bus access fault stack frame
2496 if (currprefs.cpu_model == 68040) {
2497 // this is actually created in fpp.c
2498 write_log(_T("Exception stack frame format %X not implemented\n"), format);
2499 return;
2500 }
2501 // 68060 bus access fault
2502 m68k_areg (regs, 7) -= 4;
2503 x_put_long (m68k_areg (regs, 7), regs.mmu_fslw);
2504 m68k_areg (regs, 7) -= 4;
2505 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2506 break;
2507 case 0xB: // long bus cycle fault stack frame (68020, 68030)
2508 // We always use B frame because it is easier to emulate,
2509 // our PC always points at start of instruction but A frame assumes
2510 // it is + 2 and handling this properly is not easy.
2511 // Store state information to internal register space
2512 for (i = 0; i < mmu030_idx + 1; i++) {
2513 m68k_areg (regs, 7) -= 4;
2514 x_put_long (m68k_areg (regs, 7), mmu030_ad[i].val);
2515 }
2516 while (i < 9) {
2517 uae_u32 v = 0;
2518 m68k_areg (regs, 7) -= 4;
2519 // mmu030_idx is always small enough if instruction is FMOVEM.
2520 if (mmu030_state[1] & MMU030_STATEFLAG1_FMOVEM) {
2521 if (i == 7)
2522 v = mmu030_fmovem_store[0];
2523 else if (i == 8)
2524 v = mmu030_fmovem_store[1];
2525 }
2526 x_put_long (m68k_areg (regs, 7), v);
2527 i++;
2528 }
2529 // version & internal information (We store index here)
2530 m68k_areg (regs, 7) -= 2;
2531 x_put_word (m68k_areg (regs, 7), mmu030_idx);
2532 // 3* internal registers
2533 m68k_areg (regs, 7) -= 2;
2534 x_put_word (m68k_areg (regs, 7), mmu030_state[2]);
2535 m68k_areg (regs, 7) -= 2;
2536 x_put_word (m68k_areg (regs, 7), mmu030_state[1]);
2537 m68k_areg (regs, 7) -= 2;
2538 x_put_word (m68k_areg (regs, 7), mmu030_state[0]);
2539 // data input buffer = fault address
2540 m68k_areg (regs, 7) -= 4;
2541 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2542 // 2xinternal
2543 m68k_areg (regs, 7) -= 2;
2544 x_put_word (m68k_areg (regs, 7), 0);
2545 m68k_areg (regs, 7) -= 2;
2546 x_put_word (m68k_areg (regs, 7), 0);
2547 // stage b address
2548 m68k_areg (regs, 7) -= 4;
2549 x_put_long (m68k_areg (regs, 7), mm030_stageb_address);
2550 // 2xinternal
2551 m68k_areg (regs, 7) -= 4;
2552 x_put_long (m68k_areg (regs, 7), mmu030_disp_store[1]);
2553 /* fall through */
2554 case 0xA: // short bus cycle fault stack frame (68020, 68030)
2555 m68k_areg (regs, 7) -= 4;
2556 x_put_long (m68k_areg (regs, 7), mmu030_disp_store[0]);
2557 m68k_areg (regs, 7) -= 4;
2558 // Data output buffer = value that was going to be written
2559 x_put_long (m68k_areg (regs, 7), (mmu030_state[1] & MMU030_STATEFLAG1_MOVEM1) ? mmu030_data_buffer : mmu030_ad[mmu030_idx].val);
2560 m68k_areg (regs, 7) -= 4;
2561 x_put_long (m68k_areg (regs, 7), mmu030_opcode); // Internal register (opcode storage)
2562 m68k_areg (regs, 7) -= 4;
2563 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr); // data cycle fault address
2564 m68k_areg (regs, 7) -= 2;
2565 x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage B
2566 m68k_areg (regs, 7) -= 2;
2567 x_put_word (m68k_areg (regs, 7), 0); // Instr. pipe stage C
2568 m68k_areg (regs, 7) -= 2;
2569 x_put_word (m68k_areg (regs, 7), ssw);
2570 m68k_areg (regs, 7) -= 2;
2571 x_put_word (m68k_areg (regs, 7), 0); // Internal register
2572 break;
2573 default:
2574 write_log(_T("Unknown exception stack frame format: %X\n"), format);
2575 return;
2576 }
2577 m68k_areg (regs, 7) -= 2;
2578 x_put_word (m68k_areg (regs, 7), (format << 12) | (nr * 4));
2579 m68k_areg (regs, 7) -= 4;
2580 x_put_long (m68k_areg (regs, 7), currpc);
2581 m68k_areg (regs, 7) -= 2;
2582 x_put_word (m68k_areg (regs, 7), regs.sr);
2583 }
2584
2585
2586 // 68030 MMU
Exception_mmu030(int nr,uaecptr oldpc)2587 static void Exception_mmu030 (int nr, uaecptr oldpc)
2588 {
2589 uae_u32 currpc = m68k_getpc (), newpc;
2590 int interrupt;
2591
2592 interrupt = nr >= 24 && nr < 24 + 8;
2593
2594 exception_debug (nr);
2595 MakeSR ();
2596
2597 if (!regs.s) {
2598 regs.usp = m68k_areg (regs, 7);
2599 m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
2600 regs.s = 1;
2601 mmu_set_super (1);
2602 }
2603
2604 #if 0
2605 if (nr < 24 || nr > 31) { // do not print debugging for interrupts
2606 write_log (_T("Exception_mmu030: Exception %i: %08x %08x %08x\n"),
2607 nr, currpc, oldpc, regs.mmu_fault_addr);
2608 }
2609 #endif
2610
2611 #if 0
2612 write_log (_T("Exception %d -> %08x\n", nr, newpc));
2613 #endif
2614
2615
2616 newpc = x_get_long (regs.vbr + 4 * nr);
2617
2618 if (regs.m && interrupt) { /* M + Interrupt */
2619 Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
2620 MakeSR ();
2621 regs.m = 0;
2622 regs.msp = m68k_areg (regs, 7);
2623 m68k_areg (regs, 7) = regs.isp;
2624 Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x1);
2625 } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9 || nr == 56) {
2626 Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x2);
2627 } else if (nr == 2) {
2628 Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0xB);
2629 } else if (nr == 3) {
2630 regs.mmu_fault_addr = last_fault_for_exception_3;
2631 mmu030_state[0] = mmu030_state[1] = 0;
2632 mmu030_data_buffer = 0;
2633 Exception_build_stack_frame (last_fault_for_exception_3, currpc, MMU030_SSW_RW | MMU030_SSW_SIZE_W | (regs.s ? 6 : 2), nr, 0xA);
2634 } else {
2635 Exception_build_stack_frame (oldpc, currpc, regs.mmu_ssw, nr, 0x0);
2636 }
2637
2638 if (newpc & 1) {
2639 if (nr == 2 || nr == 3)
2640 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2641 else
2642 exception3_read(regs.ir, newpc);
2643 return;
2644 }
2645 m68k_setpci (newpc);
2646 fill_prefetch ();
2647 exception_trace (nr);
2648 }
2649
2650 // 68040/060 MMU
Exception_mmu(int nr,uaecptr oldpc)2651 static void Exception_mmu (int nr, uaecptr oldpc)
2652 {
2653 uae_u32 currpc = m68k_getpc (), newpc;
2654 int interrupt;
2655
2656 interrupt = nr >= 24 && nr < 24 + 8;
2657
2658 exception_debug (nr);
2659 MakeSR ();
2660
2661 if (!regs.s) {
2662 regs.usp = m68k_areg (regs, 7);
2663 if (currprefs.cpu_model == 68060) {
2664 m68k_areg (regs, 7) = regs.isp;
2665 if (interrupt)
2666 regs.m = 0;
2667 } else if (currprefs.cpu_model >= 68020) {
2668 m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
2669 } else {
2670 m68k_areg (regs, 7) = regs.isp;
2671 }
2672 regs.s = 1;
2673 mmu_set_super (1);
2674 }
2675
2676 newpc = x_get_long (regs.vbr + 4 * nr);
2677 #if 0
2678 write_log (_T("Exception %d: %08x -> %08x\n"), nr, currpc, newpc);
2679 #endif
2680
2681 if (nr == 2) { // bus error
2682 //write_log (_T("Exception_mmu %08x %08x %08x\n"), currpc, oldpc, regs.mmu_fault_addr);
2683 if (currprefs.mmu_model == 68040)
2684 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x7);
2685 else
2686 Exception_build_stack_frame(oldpc, currpc, regs.mmu_fslw, nr, 0x4);
2687 } else if (nr == 3) { // address error
2688 Exception_build_stack_frame(last_fault_for_exception_3, currpc, 0, nr, 0x2);
2689 write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * nr));
2690 } else if (nr == 5 || nr == 6 || nr == 7 || nr == 9) {
2691 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x2);
2692 } else if (regs.m && interrupt) { /* M + Interrupt */
2693 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x1);
2694 } else if (nr == 61) {
2695 Exception_build_stack_frame(oldpc, regs.instruction_pc, regs.mmu_ssw, nr, 0x0);
2696 } else {
2697 Exception_build_stack_frame(oldpc, currpc, regs.mmu_ssw, nr, 0x0);
2698 }
2699
2700 if (newpc & 1) {
2701 if (nr == 2 || nr == 3)
2702 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2703 else
2704 exception3_read(regs.ir, newpc);
2705 return;
2706 }
2707 m68k_setpci (newpc);
2708 fill_prefetch ();
2709 exception_trace (nr);
2710 }
2711
add_approximate_exception_cycles(int nr)2712 static void add_approximate_exception_cycles(int nr)
2713 {
2714 int cycles;
2715
2716 if (currprefs.cpu_model > 68000)
2717 return;
2718 if (nr >= 24 && nr <= 31) {
2719 /* Interrupts */
2720 cycles = 44 + 4;
2721 } else if (nr >= 32 && nr <= 47) {
2722 /* Trap (total is 34, but cpuemux.c already adds 4) */
2723 cycles = 34 -4;
2724 } else {
2725 switch (nr)
2726 {
2727 case 2: cycles = 50; break; /* Bus error */
2728 case 3: cycles = 50; break; /* Address error */
2729 case 4: cycles = 34; break; /* Illegal instruction */
2730 case 5: cycles = 38; break; /* Division by zero */
2731 case 6: cycles = 40; break; /* CHK */
2732 case 7: cycles = 34; break; /* TRAPV */
2733 case 8: cycles = 34; break; /* Privilege violation */
2734 case 9: cycles = 34; break; /* Trace */
2735 case 10: cycles = 34; break; /* Line-A */
2736 case 11: cycles = 34; break; /* Line-F */
2737 default:
2738 cycles = 4;
2739 break;
2740 }
2741 }
2742 cycles = adjust_cycles(cycles * CYCLE_UNIT / 2);
2743 x_do_cycles(cycles);
2744 }
2745
Exception_normal(int nr)2746 static void Exception_normal (int nr)
2747 {
2748 uae_u32 currpc, newpc;
2749 int sv = regs.s;
2750 int interrupt;
2751 int vector_nr = nr;
2752
2753 interrupt = nr >= 24 && nr < 24 + 8;
2754
2755 if (interrupt && currprefs.cpu_model <= 68010)
2756 vector_nr = iack_cycle(nr);
2757
2758 exception_debug (nr);
2759 MakeSR ();
2760
2761 if (!regs.s) {
2762 regs.usp = m68k_areg (regs, 7);
2763 if (currprefs.cpu_model == 68060) {
2764 m68k_areg (regs, 7) = regs.isp;
2765 if (interrupt)
2766 regs.m = 0;
2767 } else if (currprefs.cpu_model >= 68020) {
2768 m68k_areg (regs, 7) = regs.m ? regs.msp : regs.isp;
2769 } else {
2770 m68k_areg (regs, 7) = regs.isp;
2771 }
2772 regs.s = 1;
2773 if (currprefs.mmu_model)
2774 mmu_set_super (regs.s != 0);
2775 }
2776
2777 if ((m68k_areg(regs, 7) & 1) && currprefs.cpu_model < 68020) {
2778 if (nr == 2 || nr == 3)
2779 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2780 else
2781 exception3_notinstruction(regs.ir, m68k_areg(regs, 7));
2782 return;
2783 }
2784 if ((nr == 2 || nr == 3) && exception_in_exception < 0) {
2785 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2786 return;
2787 }
2788
2789 if (currprefs.cpu_model > 68000) {
2790 currpc = exception_pc (nr);
2791 if (nr == 2 || nr == 3) {
2792 int i;
2793 if (currprefs.cpu_model >= 68040) {
2794 if (nr == 2) {
2795 if (currprefs.mmu_model) {
2796 // 68040 mmu bus error
2797 for (i = 0 ; i < 7 ; i++) {
2798 m68k_areg (regs, 7) -= 4;
2799 x_put_long (m68k_areg (regs, 7), 0);
2800 }
2801 m68k_areg (regs, 7) -= 4;
2802 x_put_long (m68k_areg (regs, 7), regs.wb3_data);
2803 m68k_areg (regs, 7) -= 4;
2804 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2805 m68k_areg (regs, 7) -= 4;
2806 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2807 m68k_areg (regs, 7) -= 2;
2808 x_put_word (m68k_areg (regs, 7), 0);
2809 m68k_areg (regs, 7) -= 2;
2810 x_put_word (m68k_areg (regs, 7), 0);
2811 m68k_areg (regs, 7) -= 2;
2812 x_put_word (m68k_areg (regs, 7), regs.wb3_status);
2813 regs.wb3_status = 0;
2814 m68k_areg (regs, 7) -= 2;
2815 x_put_word (m68k_areg (regs, 7), regs.mmu_ssw);
2816 m68k_areg (regs, 7) -= 4;
2817 x_put_long (m68k_areg (regs, 7), regs.mmu_fault_addr);
2818
2819 m68k_areg (regs, 7) -= 2;
2820 x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
2821 m68k_areg (regs, 7) -= 4;
2822 x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
2823 m68k_areg (regs, 7) -= 2;
2824 x_put_word (m68k_areg (regs, 7), regs.sr);
2825 newpc = x_get_long (regs.vbr + 4 * vector_nr);
2826 if (newpc & 1) {
2827 if (nr == 2 || nr == 3)
2828 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2829 else
2830 exception3_read(regs.ir, newpc);
2831 return;
2832 }
2833 m68k_setpc (newpc);
2834 #ifdef JIT
2835 set_special (SPCFLAG_END_COMPILE);
2836 #endif
2837 exception_trace (nr);
2838 return;
2839
2840 } else {
2841
2842 // 68040 bus error (not really, some garbage?)
2843 for (i = 0 ; i < 18 ; i++) {
2844 m68k_areg (regs, 7) -= 2;
2845 x_put_word (m68k_areg (regs, 7), 0);
2846 }
2847 m68k_areg (regs, 7) -= 4;
2848 x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2849 m68k_areg (regs, 7) -= 2;
2850 x_put_word (m68k_areg (regs, 7), 0);
2851 m68k_areg (regs, 7) -= 2;
2852 x_put_word (m68k_areg (regs, 7), 0);
2853 m68k_areg (regs, 7) -= 2;
2854 x_put_word (m68k_areg (regs, 7), 0);
2855 m68k_areg (regs, 7) -= 2;
2856 x_put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
2857 m68k_areg (regs, 7) -= 4;
2858 x_put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
2859 m68k_areg (regs, 7) -= 2;
2860 x_put_word (m68k_areg (regs, 7), 0x7000 + vector_nr * 4);
2861 m68k_areg (regs, 7) -= 4;
2862 x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
2863 m68k_areg (regs, 7) -= 2;
2864 x_put_word (m68k_areg (regs, 7), regs.sr);
2865 goto kludge_me_do;
2866
2867 }
2868
2869 } else {
2870 m68k_areg (regs, 7) -= 4;
2871 x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2872 m68k_areg (regs, 7) -= 2;
2873 x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
2874 }
2875 } else {
2876 // 68020 address error
2877 uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2878 ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
2879 ssw |= 0x20;
2880 for (i = 0 ; i < 36; i++) {
2881 m68k_areg (regs, 7) -= 2;
2882 x_put_word (m68k_areg (regs, 7), 0);
2883 }
2884 m68k_areg (regs, 7) -= 4;
2885 x_put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
2886 m68k_areg (regs, 7) -= 2;
2887 x_put_word (m68k_areg (regs, 7), 0);
2888 m68k_areg (regs, 7) -= 2;
2889 x_put_word (m68k_areg (regs, 7), 0);
2890 m68k_areg (regs, 7) -= 2;
2891 x_put_word (m68k_areg (regs, 7), 0);
2892 m68k_areg (regs, 7) -= 2;
2893 x_put_word (m68k_areg (regs, 7), ssw);
2894 m68k_areg (regs, 7) -= 2;
2895 x_put_word (m68k_areg (regs, 7), 0xb000 + vector_nr * 4);
2896 }
2897 write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, regs.instruction_pc, currpc, get_long_debug (regs.vbr + 4 * vector_nr));
2898 } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
2899 m68k_areg (regs, 7) -= 4;
2900 x_put_long (m68k_areg (regs, 7), regs.instruction_pc);
2901 m68k_areg (regs, 7) -= 2;
2902 x_put_word (m68k_areg (regs, 7), 0x2000 + vector_nr * 4);
2903 } else if (regs.m && interrupt) { /* M + Interrupt */
2904 m68k_areg (regs, 7) -= 2;
2905 x_put_word (m68k_areg (regs, 7), vector_nr * 4);
2906 m68k_areg (regs, 7) -= 4;
2907 x_put_long (m68k_areg (regs, 7), currpc);
2908 m68k_areg (regs, 7) -= 2;
2909 x_put_word (m68k_areg (regs, 7), regs.sr);
2910 regs.sr |= (1 << 13);
2911 regs.msp = m68k_areg (regs, 7);
2912 regs.m = 0;
2913 m68k_areg (regs, 7) = regs.isp;
2914 m68k_areg (regs, 7) -= 2;
2915 x_put_word (m68k_areg (regs, 7), 0x1000 + vector_nr * 4);
2916 } else {
2917 m68k_areg (regs, 7) -= 2;
2918 x_put_word (m68k_areg (regs, 7), vector_nr * 4);
2919 }
2920 } else {
2921 add_approximate_exception_cycles(nr);
2922 currpc = m68k_getpc ();
2923 if (nr == 2 || nr == 3) {
2924 // 68000 address error
2925 uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
2926 mode |= last_writeaccess_for_exception_3 ? 0 : 16;
2927 mode |= last_notinstruction_for_exception_3 ? 8 : 0;
2928 // undocumented bits seem to contain opcode
2929 mode |= last_op_for_exception_3 & ~31;
2930 m68k_areg (regs, 7) -= 14;
2931 exception_in_exception = -1;
2932 x_put_word (m68k_areg (regs, 7) + 0, mode);
2933 x_put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
2934 x_put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
2935 x_put_word (m68k_areg (regs, 7) + 8, regs.sr);
2936 x_put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
2937 write_log (_T("Exception %d (%x) at %x -> %x!\n"), nr, last_fault_for_exception_3, currpc, get_long_debug (regs.vbr + 4 * vector_nr));
2938 goto kludge_me_do;
2939 }
2940 }
2941 m68k_areg (regs, 7) -= 4;
2942 x_put_long (m68k_areg (regs, 7), currpc);
2943 m68k_areg (regs, 7) -= 2;
2944 x_put_word (m68k_areg (regs, 7), regs.sr);
2945 kludge_me_do:
2946 newpc = x_get_long (regs.vbr + 4 * vector_nr);
2947 exception_in_exception = 0;
2948 if (newpc & 1) {
2949 if (nr == 2 || nr == 3)
2950 cpu_halt (CPU_HALT_DOUBLE_FAULT);
2951 else
2952 exception3_notinstruction(regs.ir, newpc);
2953 return;
2954 }
2955 m68k_setpc (newpc);
2956 #ifdef JIT
2957 set_special (SPCFLAG_END_COMPILE);
2958 #endif
2959 fill_prefetch ();
2960 exception_trace (nr);
2961 }
2962
2963 // address = format $2 stack frame address field
ExceptionX(int nr,uaecptr address)2964 static void ExceptionX (int nr, uaecptr address)
2965 {
2966 regs.exception = nr;
2967 if (cpu_tracer) {
2968 #ifdef FSUAE
2969 #if 0
2970 printf("set cputrace.state = nr %d\n", nr);
2971 #endif
2972 #endif
2973 cputrace.state = nr;
2974 }
2975
2976 #ifdef JIT
2977 if (currprefs.cachesize)
2978 regs.instruction_pc = address == -1 ? m68k_getpc () : address;
2979 #endif
2980 #ifdef CPUEMU_13
2981 if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010)
2982 Exception_ce000 (nr);
2983 else
2984 #endif
2985 if (currprefs.mmu_model) {
2986 if (currprefs.cpu_model == 68030)
2987 Exception_mmu030 (nr, m68k_getpc ());
2988 else
2989 Exception_mmu (nr, m68k_getpc ());
2990 } else {
2991 Exception_normal (nr);
2992 }
2993
2994 if (debug_illegal && !in_rom (M68K_GETPC)) {
2995 if (nr <= 63 && (debug_illegal_mask & ((uae_u64)1 << nr))) {
2996 write_log (_T("Exception %d breakpoint\n"), nr);
2997 activate_debugger ();
2998 }
2999 }
3000 regs.exception = 0;
3001 if (cpu_tracer) {
3002 cputrace.state = 0;
3003 }
3004 }
3005
Exception(int nr)3006 void REGPARAM2 Exception (int nr)
3007 {
3008 ExceptionX (nr, -1);
3009 }
ExceptionL(int nr,uaecptr address)3010 void REGPARAM2 ExceptionL (int nr, uaecptr address)
3011 {
3012 ExceptionX (nr, address);
3013 }
3014
do_interrupt(int nr)3015 static void do_interrupt (int nr)
3016 {
3017 if (debug_dma)
3018 record_dma_event (DMA_EVENT_CPUIRQ, current_hpos (), vpos);
3019
3020 if (inputrecord_debug & 2) {
3021 if (input_record > 0)
3022 inprec_recorddebug_cpu (2);
3023 else if (input_play > 0)
3024 inprec_playdebug_cpu (2);
3025 }
3026
3027 regs.stopped = 0;
3028 unset_special (SPCFLAG_STOP);
3029 assert (nr < 8 && nr >= 0);
3030
3031 for (;;) {
3032 Exception (nr + 24);
3033 regs.intmask = nr;
3034 if (!currprefs.cpu_compatible)
3035 break;
3036 if (m68k_interrupt_delay)
3037 nr = regs.ipl;
3038 else
3039 nr = intlev();
3040 if (nr <= 0 || regs.intmask >= nr)
3041 break;
3042 }
3043
3044 doint ();
3045 }
3046
NMI(void)3047 void NMI (void)
3048 {
3049 do_interrupt (7);
3050 }
3051
m68k_reset_sr(void)3052 static void m68k_reset_sr(void)
3053 {
3054 SET_XFLG ((regs.sr >> 4) & 1);
3055 SET_NFLG ((regs.sr >> 3) & 1);
3056 SET_ZFLG ((regs.sr >> 2) & 1);
3057 SET_VFLG ((regs.sr >> 1) & 1);
3058 SET_CFLG (regs.sr & 1);
3059 regs.t1 = (regs.sr >> 15) & 1;
3060 regs.t0 = (regs.sr >> 14) & 1;
3061 regs.s = (regs.sr >> 13) & 1;
3062 regs.m = (regs.sr >> 12) & 1;
3063 regs.intmask = (regs.sr >> 8) & 7;
3064 /* set stack pointer */
3065 if (regs.s)
3066 m68k_areg (regs, 7) = regs.isp;
3067 else
3068 m68k_areg (regs, 7) = regs.usp;
3069 }
3070
m68k_reset2(bool hardreset)3071 static void m68k_reset2(bool hardreset)
3072 {
3073 uae_u32 v;
3074
3075 regs.halted = 0;
3076 gui_data.cpu_halted = 0;
3077 gui_led (LED_CPU, 0, -1);
3078
3079 regs.spcflags = 0;
3080 m68k_reset_delay = 0;
3081 regs.ipl = regs.ipl_pin = 0;
3082
3083 #ifdef SAVESTATE
3084 if (isrestore ()) {
3085 m68k_reset_sr();
3086 m68k_setpc_normal (regs.pc);
3087 return;
3088 } else {
3089 m68k_reset_delay = currprefs.reset_delay;
3090 set_special(SPCFLAG_CHECK);
3091 }
3092 #endif
3093 regs.s = 1;
3094 if (currprefs.cpuboard_type) {
3095 uaecptr stack;
3096 v = cpuboard_get_reset_pc(&stack);
3097 m68k_areg (regs, 7) = stack;
3098 } else {
3099 v = get_long (4);
3100 m68k_areg (regs, 7) = get_long (0);
3101 }
3102 m68k_setpc_normal(v);
3103 regs.m = 0;
3104 regs.stopped = 0;
3105 regs.t1 = 0;
3106 regs.t0 = 0;
3107 SET_ZFLG (0);
3108 SET_XFLG (0);
3109 SET_CFLG (0);
3110 SET_VFLG (0);
3111 SET_NFLG (0);
3112 regs.intmask = 7;
3113 regs.vbr = regs.sfc = regs.dfc = 0;
3114 regs.irc = 0xffff;
3115 #ifdef FPUEMU
3116 fpu_reset ();
3117 #endif
3118 regs.caar = regs.cacr = 0;
3119 regs.itt0 = regs.itt1 = regs.dtt0 = regs.dtt1 = 0;
3120 regs.tcr = regs.mmusr = regs.urp = regs.srp = regs.buscr = 0;
3121 mmu_tt_modified ();
3122 if (currprefs.cpu_model == 68020) {
3123 regs.cacr |= 8;
3124 set_cpu_caches (false);
3125 }
3126
3127 mmufixup[0].reg = -1;
3128 mmufixup[1].reg = -1;
3129 if (currprefs.mmu_model >= 68040) {
3130 mmu_reset ();
3131 mmu_set_tc (regs.tcr);
3132 mmu_set_super (regs.s != 0);
3133 } else if (currprefs.mmu_model == 68030) {
3134 mmu030_reset (hardreset || regs.halted);
3135 } else {
3136 a3000_fakekick (0);
3137 /* only (E)nable bit is zeroed when CPU is reset, A3000 SuperKickstart expects this */
3138 fake_tc_030 &= ~0x80000000;
3139 fake_tt0_030 &= ~0x80000000;
3140 fake_tt1_030 &= ~0x80000000;
3141 if (hardreset || regs.halted) {
3142 fake_srp_030 = fake_crp_030 = 0;
3143 fake_tt0_030 = fake_tt1_030 = fake_tc_030 = 0;
3144 }
3145 fake_mmusr_030 = 0;
3146 }
3147
3148 /* 68060 FPU is not compatible with 68040,
3149 * 68060 accelerators' boot ROM disables the FPU
3150 */
3151 regs.pcr = 0;
3152 if (currprefs.cpu_model == 68060) {
3153 regs.pcr = currprefs.fpu_model == 68060 ? MC68060_PCR : MC68EC060_PCR;
3154 regs.pcr |= (currprefs.cpu060_revision & 0xff) << 8;
3155 if (kickstart_rom)
3156 regs.pcr |= 2; /* disable FPU */
3157 }
3158 regs.ce020memcycles = 0;
3159 fill_prefetch ();
3160 }
m68k_reset(void)3161 void m68k_reset(void)
3162 {
3163 m68k_reset2(false);
3164 }
3165
3166
op_unimpl(uae_u16 opcode)3167 void REGPARAM2 op_unimpl (uae_u16 opcode)
3168 {
3169 static int warned;
3170 if (warned < 20) {
3171 write_log (_T("68060 unimplemented opcode %04X, PC=%08x\n"), opcode, regs.instruction_pc);
3172 warned++;
3173 }
3174 ExceptionL (61, regs.instruction_pc);
3175 }
3176
op_illg(uae_u32 opcode)3177 uae_u32 REGPARAM2 op_illg (uae_u32 opcode)
3178 {
3179 uaecptr pc = m68k_getpc ();
3180 static int warned;
3181 int inrom = in_rom (pc);
3182 int inrt = in_rtarea (pc);
3183
3184 if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
3185 m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
3186 m68k_incpc_normal (2);
3187 fill_prefetch ();
3188 return 4;
3189 }
3190
3191 if (opcode == 0x4E7B && inrom) {
3192 if (get_long (0x10) == 0) {
3193 notify_user (NUMSG_KS68020);
3194 uae_restart (-1, NULL);
3195 }
3196 }
3197
3198 #ifdef AUTOCONFIG
3199 if (opcode == 0xFF0D && inrt) {
3200 /* User-mode STOP replacement */
3201 m68k_setstopped ();
3202 return 4;
3203 }
3204
3205 if ((opcode & 0xF000) == 0xA000 && inrt) {
3206 /* Calltrap. */
3207 m68k_incpc_normal (2);
3208 m68k_handle_trap(opcode & 0xFFF);
3209 fill_prefetch ();
3210 return 4;
3211 }
3212 #endif
3213
3214 if ((opcode & 0xF000) == 0xF000) {
3215 if (warned < 20) {
3216 write_log(_T("B-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x2c));
3217 warned++;
3218 }
3219 Exception (0xB);
3220 //activate_debugger ();
3221 return 4;
3222 }
3223 if ((opcode & 0xF000) == 0xA000) {
3224 if (warned < 20) {
3225 write_log(_T("A-Trap %04X at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x28));
3226 warned++;
3227 }
3228 Exception (0xA);
3229 //activate_debugger();
3230 return 4;
3231 }
3232 if (warned < 20) {
3233 write_log (_T("Illegal instruction: %04x at %08X -> %08X\n"), opcode, pc, get_long_debug(regs.vbr + 0x10));
3234 warned++;
3235 //activate_debugger();
3236 }
3237
3238 Exception (4);
3239 return 4;
3240 }
3241
3242 #ifdef CPUEMU_0
3243
mmu_op30fake_pmove(uaecptr pc,uae_u32 opcode,uae_u16 next,uaecptr extra)3244 static bool mmu_op30fake_pmove (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
3245 {
3246 int mode = (opcode >> 3) & 7;
3247 int rreg = opcode & 7;
3248 int preg = (next >> 10) & 31;
3249 int rw = (next >> 9) & 1;
3250 int fd = (next >> 8) & 1;
3251 const TCHAR *reg = NULL;
3252 uae_u32 otc = fake_tc_030;
3253 int siz;
3254
3255 // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
3256 if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode == 6 || (mode == 7 && rreg > 1)) {
3257 op_illg (opcode);
3258 return true;
3259 }
3260
3261 switch (preg)
3262 {
3263 case 0x10: // TC
3264 reg = _T("TC");
3265 siz = 4;
3266 if (rw)
3267 x_put_long (extra, fake_tc_030);
3268 else
3269 fake_tc_030 = x_get_long (extra);
3270 break;
3271 case 0x12: // SRP
3272 reg = _T("SRP");
3273 siz = 8;
3274 if (rw) {
3275 x_put_long (extra, fake_srp_030 >> 32);
3276 x_put_long (extra + 4, (uae_u32)fake_srp_030);
3277 } else {
3278 fake_srp_030 = (uae_u64)x_get_long (extra) << 32;
3279 fake_srp_030 |= x_get_long (extra + 4);
3280 }
3281 break;
3282 case 0x13: // CRP
3283 reg = _T("CRP");
3284 siz = 8;
3285 if (rw) {
3286 x_put_long (extra, fake_crp_030 >> 32);
3287 x_put_long (extra + 4, (uae_u32)fake_crp_030);
3288 } else {
3289 fake_crp_030 = (uae_u64)x_get_long (extra) << 32;
3290 fake_crp_030 |= x_get_long (extra + 4);
3291 }
3292 break;
3293 case 0x18: // MMUSR
3294 reg = _T("MMUSR");
3295 siz = 2;
3296 if (rw)
3297 x_put_word (extra, fake_mmusr_030);
3298 else
3299 fake_mmusr_030 = x_get_word (extra);
3300 break;
3301 case 0x02: // TT0
3302 reg = _T("TT0");
3303 siz = 4;
3304 if (rw)
3305 x_put_long (extra, fake_tt0_030);
3306 else
3307 fake_tt0_030 = x_get_long (extra);
3308 break;
3309 case 0x03: // TT1
3310 reg = _T("TT1");
3311 siz = 4;
3312 if (rw)
3313 x_put_long (extra, fake_tt1_030);
3314 else
3315 fake_tt1_030 = x_get_long (extra);
3316 break;
3317 }
3318
3319 if (!reg) {
3320 op_illg (opcode);
3321 return true;
3322 }
3323 #if MMUOP_DEBUG > 0
3324 {
3325 uae_u32 val;
3326 if (siz == 8) {
3327 uae_u32 val2 = x_get_long (extra);
3328 val = x_get_long (extra + 4);
3329 if (rw)
3330 write_log (_T("PMOVE %s,%08X%08X"), reg, val2, val);
3331 else
3332 write_log (_T("PMOVE %08X%08X,%s"), val2, val, reg);
3333 } else {
3334 if (siz == 4)
3335 val = x_get_long (extra);
3336 else
3337 val = x_get_word (extra);
3338 if (rw)
3339 write_log (_T("PMOVE %s,%08X"), reg, val);
3340 else
3341 write_log (_T("PMOVE %08X,%s"), val, reg);
3342 }
3343 write_log (_T(" PC=%08X\n"), pc);
3344 }
3345 #endif
3346 if ((currprefs.cs_mbdmac & 1) && currprefs.mbresmem_low_size > 0) {
3347 if (otc != fake_tc_030) {
3348 a3000_fakekick (fake_tc_030 & 0x80000000);
3349 }
3350 }
3351 return false;
3352 }
3353
mmu_op30fake_ptest(uaecptr pc,uae_u32 opcode,uae_u16 next,uaecptr extra)3354 static bool mmu_op30fake_ptest (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
3355 {
3356 #if MMUOP_DEBUG > 0
3357 TCHAR tmp[10];
3358
3359 tmp[0] = 0;
3360 if ((next >> 8) & 1)
3361 _stprintf (tmp, _T(",A%d"), (next >> 4) & 15);
3362 write_log (_T("PTEST%c %02X,%08X,#%X%s PC=%08X\n"),
3363 ((next >> 9) & 1) ? 'W' : 'R', (next & 15), extra, (next >> 10) & 7, tmp, pc);
3364 #endif
3365 fake_mmusr_030 = 0;
3366 return false;
3367 }
3368
mmu_op30fake_pflush(uaecptr pc,uae_u32 opcode,uae_u16 next,uaecptr extra)3369 static bool mmu_op30fake_pflush (uaecptr pc, uae_u32 opcode, uae_u16 next, uaecptr extra)
3370 {
3371 int mode = (opcode >> 3) & 7;
3372 int rreg = opcode & 7;
3373 int flushmode = (next >> 10) & 7;
3374 int fc = next & 31;
3375 int mask = (next >> 5) & 3;
3376 TCHAR fname[100];
3377
3378 switch (flushmode)
3379 {
3380 case 6:
3381 // Dn, An, (An)+, -(An), immediate and PC-relative not allowed
3382 if (mode == 0 || mode == 1 || mode == 3 || mode == 4 || mode == 6 || (mode == 7 && rreg > 1)) {
3383 op_illg (opcode);
3384 return true;
3385 }
3386 _stprintf (fname, _T("FC=%x MASK=%x EA=%08x"), fc, mask, 0);
3387 break;
3388 case 4:
3389 _stprintf (fname, _T("FC=%x MASK=%x"), fc, mask);
3390 break;
3391 case 1:
3392 _tcscpy (fname, _T("ALL"));
3393 break;
3394 default:
3395 op_illg (opcode);
3396 return true;
3397 }
3398 #if MMUOP_DEBUG > 0
3399 write_log (_T("PFLUSH %s PC=%08X\n"), fname, pc);
3400 #endif
3401 return false;
3402 }
3403
3404 // 68030 (68851) MMU instructions only
mmu_op30(uaecptr pc,uae_u32 opcode,uae_u16 extra,uaecptr extraa)3405 bool mmu_op30 (uaecptr pc, uae_u32 opcode, uae_u16 extra, uaecptr extraa)
3406 {
3407 if (currprefs.mmu_model) {
3408 if (extra & 0x8000) {
3409 return mmu_op30_ptest (pc, opcode, extra, extraa);
3410 } else if ((extra&0xE000)==0x2000 && (extra & 0x1C00)) {
3411 return mmu_op30_pflush (pc, opcode, extra, extraa);
3412 } else if ((extra&0xE000)==0x2000 && !(extra & 0x1C00)) {
3413 return mmu_op30_pload (pc, opcode, extra, extraa);
3414 } else {
3415 return mmu_op30_pmove (pc, opcode, extra, extraa);
3416 }
3417 return false;
3418 }
3419
3420 int type = extra >> 13;
3421
3422 switch (type)
3423 {
3424 case 0:
3425 case 2:
3426 case 3:
3427 return mmu_op30fake_pmove (pc, opcode, extra, extraa);
3428 break;
3429 case 1:
3430 return mmu_op30fake_pflush (pc, opcode, extra, extraa);
3431 break;
3432 case 4:
3433 return mmu_op30fake_ptest (pc, opcode, extra, extraa);
3434 break;
3435 default:
3436 op_illg (opcode);
3437 return true;
3438 break;
3439 }
3440 }
3441
3442 // 68040+ MMU instructions only
mmu_op(uae_u32 opcode,uae_u32 extra)3443 void mmu_op (uae_u32 opcode, uae_u32 extra)
3444 {
3445 if (currprefs.mmu_model) {
3446 mmu_op_real (opcode, extra);
3447 return;
3448 }
3449 #if MMUOP_DEBUG > 1
3450 write_log (_T("mmu_op %04X PC=%08X\n"), opcode, m68k_getpc ());
3451 #endif
3452 if ((opcode & 0xFE0) == 0x0500) {
3453 /* PFLUSH */
3454 regs.mmusr = 0;
3455 #if MMUOP_DEBUG > 0
3456 write_log (_T("PFLUSH\n"));
3457 #endif
3458 return;
3459 } else if ((opcode & 0x0FD8) == 0x548) {
3460 if (currprefs.cpu_model < 68060) { /* PTEST not in 68060 */
3461 /* PTEST */
3462 #if MMUOP_DEBUG > 0
3463 write_log (_T("PTEST\n"));
3464 #endif
3465 return;
3466 }
3467 } else if ((opcode & 0x0FB8) == 0x588) {
3468 /* PLPA */
3469 if (currprefs.cpu_model == 68060) {
3470 #if MMUOP_DEBUG > 0
3471 write_log (_T("PLPA\n"));
3472 #endif
3473 return;
3474 }
3475 }
3476 #if MMUOP_DEBUG > 0
3477 write_log (_T("Unknown MMU OP %04X\n"), opcode);
3478 #endif
3479 m68k_setpc_normal (m68k_getpc () - 2);
3480 op_illg (opcode);
3481 }
3482
3483 #endif
3484
3485 static uaecptr last_trace_ad = 0;
3486
do_trace(void)3487 static void do_trace (void)
3488 {
3489 if (regs.t0 && currprefs.cpu_model >= 68020) {
3490 uae_u16 opcode;
3491 /* should also include TRAP, CHK, SR modification FPcc */
3492 /* probably never used so why bother */
3493 /* We can afford this to be inefficient... */
3494 m68k_setpc_normal (m68k_getpc ());
3495 fill_prefetch ();
3496 opcode = x_get_word (regs.pc);
3497 if (opcode == 0x4e73 /* RTE */
3498 || opcode == 0x4e74 /* RTD */
3499 || opcode == 0x4e75 /* RTS */
3500 || opcode == 0x4e77 /* RTR */
3501 || opcode == 0x4e76 /* TRAPV */
3502 || (opcode & 0xffc0) == 0x4e80 /* JSR */
3503 || (opcode & 0xffc0) == 0x4ec0 /* JMP */
3504 || (opcode & 0xff00) == 0x6100 /* BSR */
3505 || ((opcode & 0xf000) == 0x6000 /* Bcc */
3506 && cctrue ((opcode >> 8) & 0xf))
3507 || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
3508 && !cctrue ((opcode >> 8) & 0xf)
3509 && (uae_s16)m68k_dreg (regs, opcode & 7) != 0))
3510 {
3511 last_trace_ad = m68k_getpc ();
3512 unset_special (SPCFLAG_TRACE);
3513 set_special (SPCFLAG_DOTRACE);
3514 }
3515 } else if (regs.t1) {
3516 last_trace_ad = m68k_getpc ();
3517 unset_special (SPCFLAG_TRACE);
3518 set_special (SPCFLAG_DOTRACE);
3519 }
3520 }
3521
check_uae_int_request(void)3522 static void check_uae_int_request(void)
3523 {
3524 if (uae_int_requested || uaenet_int_requested) {
3525 bool irq = false;
3526 if ((uae_int_requested & 0x00ff) || uaenet_int_requested) {
3527 INTREQ_f(0x8000 | 0x0008);
3528 irq = true;
3529 }
3530 if (uae_int_requested & 0xff00) {
3531 INTREQ_f(0x8000 | 0x2000);
3532 irq = true;
3533 }
3534 if (uae_int_requested & 0xff0000) {
3535 if (!cpuboard_is_ppcboard_irq())
3536 uae_int_requested &= ~0x010000;
3537 }
3538 if (irq)
3539 set_special(SPCFLAG_INT);
3540 }
3541 }
3542
execute_other_cpu_single(void)3543 void execute_other_cpu_single(void)
3544 {
3545 #ifdef WITH_X86
3546 if (!x86_turbo_on)
3547 return;
3548 x86_bridge_execute_until(0);
3549 #endif
3550 }
3551
execute_other_cpu(int until)3552 bool execute_other_cpu(int until)
3553 {
3554 #ifdef WITH_X86
3555 if (!x86_turbo_on)
3556 return false;
3557 if (!until)
3558 until++;
3559 x86_bridge_execute_until(until);
3560 #endif
3561 return true;
3562 }
3563
cpu_sleep_millis(int ms)3564 void cpu_sleep_millis(int ms)
3565 {
3566 #ifdef WITH_THREADED_CPU
3567 cpu_semaphore_release();
3568 #endif
3569 #ifdef WITH_PPC
3570 int state = ppc_state;
3571 if (state)
3572 uae_ppc_spinlock_release();
3573 #endif
3574 #ifdef WITH_X86
3575 if (x86_turbo_on) {
3576 execute_other_cpu(read_processor_time() + vsynctimebase / 20);
3577 } else {
3578 sleep_millis_main(ms);
3579 }
3580 #else
3581 sleep_millis_main(ms);
3582 #endif
3583 #ifdef WITH_PPC
3584 if (state)
3585 uae_ppc_spinlock_get();
3586 #endif
3587 #ifdef WITH_THREADED_CPU
3588 cpu_semaphore_get();
3589 #endif
3590 }
3591
3592 #define PPC_HALTLOOP_SCANLINES 25
3593 // ppc_cpu_idle
3594 // 0 = busy
3595 // 1-9 = wait, levels
3596 // 10 = max wait
3597
haltloop(void)3598 static bool haltloop(void)
3599 {
3600 #ifdef WITH_PPC
3601 if (regs.halted < 0) {
3602 int rpt_end = 0;
3603 int ovpos = vpos;
3604
3605 while (regs.halted) {
3606 int vsynctimeline = vsynctimebase / (maxvpos_display + 1);
3607 int lines;
3608 int rpt_scanline = read_processor_time();
3609 int rpt_end = rpt_scanline + vsynctimeline;
3610
3611 // See expansion handling.
3612 // Dialog must be opened from main thread.
3613 if (regs.halted == -2) {
3614 regs.halted = -1;
3615 notify_user (NUMSG_UAEBOOTROM_PPC);
3616 }
3617
3618 if (currprefs.ppc_cpu_idle) {
3619
3620 int maxlines = 100 - (currprefs.ppc_cpu_idle - 1) * 10;
3621 int i;
3622
3623 event_wait = false;
3624 for (i = 0; i < ev_max; i++) {
3625 if (i == ev_hsync)
3626 continue;
3627 if (i == ev_audio)
3628 continue;
3629 if (!eventtab[i].active)
3630 continue;
3631 if (eventtab[i].evtime - currcycle < maxlines * maxhpos * CYCLE_UNIT)
3632 break;
3633 }
3634 if (currprefs.ppc_cpu_idle >= 10 || (i == ev_max && vpos > 0 && vpos < maxvpos - maxlines)) {
3635 cpu_sleep_millis(1);
3636 }
3637 check_uae_int_request();
3638 uae_ppc_execute_check();
3639
3640 lines = (read_processor_time() - rpt_scanline) / vsynctimeline + 1;
3641
3642 } else {
3643
3644 event_wait = true;
3645 lines = 0;
3646
3647 }
3648
3649 if (lines > maxvpos / 2)
3650 lines = maxvpos / 2;
3651
3652 while (lines-- >= 0) {
3653 ovpos = vpos;
3654 while (ovpos == vpos) {
3655 x_do_cycles(8 * CYCLE_UNIT);
3656 uae_ppc_execute_check();
3657 if (regs.spcflags & SPCFLAG_COPPER)
3658 do_copper();
3659 if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
3660 if (regs.spcflags & SPCFLAG_BRK) {
3661 unset_special(SPCFLAG_BRK);
3662 #ifdef DEBUGGER
3663 if (debugging)
3664 debug();
3665 #endif
3666 }
3667 return true;
3668 }
3669 }
3670
3671 // sync chipset with real time
3672 for (;;) {
3673 check_uae_int_request();
3674 ppc_interrupt(intlev());
3675 uae_ppc_execute_check();
3676 if (event_wait)
3677 break;
3678 int d = read_processor_time() - rpt_end;
3679 if (d < -2 * vsynctimeline || d >= 0)
3680 break;
3681 }
3682 }
3683
3684
3685 }
3686
3687 } else {
3688 #endif
3689 while (regs.halted) {
3690 static int prevvpos;
3691 if (vpos == 0 && prevvpos) {
3692 prevvpos = 0;
3693 cpu_sleep_millis(8);
3694 }
3695 if (vpos)
3696 prevvpos = 1;
3697 x_do_cycles(8 * CYCLE_UNIT);
3698
3699 if (regs.spcflags & SPCFLAG_COPPER)
3700 do_copper();
3701
3702 if (regs.spcflags) {
3703 if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
3704 return true;
3705 }
3706 }
3707 #ifdef WITH_PPC
3708 }
3709 #endif
3710
3711 return false;
3712 }
3713
3714 #ifdef WITH_PPC
uae_ppc_poll_check_halt(void)3715 static bool uae_ppc_poll_check_halt(void)
3716 {
3717 if (regs.halted) {
3718 if (haltloop())
3719 return true;
3720 }
3721 return false;
3722 }
3723 #endif
3724
3725
3726 // handle interrupt delay (few cycles)
time_for_interrupt(void)3727 STATIC_INLINE bool time_for_interrupt (void)
3728 {
3729 return regs.ipl > regs.intmask || regs.ipl == 7;
3730 }
3731
doint(void)3732 void doint (void)
3733 {
3734 #ifdef WITH_PPC
3735 if (ppc_state) {
3736 if (!ppc_interrupt(intlev()))
3737 return;
3738 }
3739 #endif
3740 if (m68k_interrupt_delay) {
3741 regs.ipl_pin = intlev ();
3742 unset_special (SPCFLAG_INT);
3743 return;
3744 }
3745 if (currprefs.cpu_compatible && currprefs.cpu_model < 68020)
3746 set_special (SPCFLAG_INT);
3747 else
3748 set_special (SPCFLAG_DOINT);
3749 }
3750
3751 #define IDLETIME (currprefs.cpu_idle * sleep_resolution / 1000)
3752
do_specialties(int cycles)3753 static int do_specialties (int cycles)
3754 {
3755 if (regs.spcflags & SPCFLAG_MODE_CHANGE)
3756 return 1;
3757
3758 if (regs.spcflags & SPCFLAG_CHECK) {
3759 if (regs.halted) {
3760 if (haltloop())
3761 return 1;
3762 }
3763 if (m68k_reset_delay) {
3764 int vsynccnt = 60;
3765 int vsyncstate = -1;
3766 while (vsynccnt > 0 && !quit_program) {
3767 x_do_cycles(8 * CYCLE_UNIT);
3768 if (regs.spcflags & SPCFLAG_COPPER)
3769 do_copper();
3770 if (timeframes != vsyncstate) {
3771 vsyncstate = timeframes;
3772 vsynccnt--;
3773 }
3774 }
3775 }
3776 m68k_reset_delay = 0;
3777 unset_special(SPCFLAG_CHECK);
3778 }
3779
3780 #ifdef ACTION_REPLAY
3781 #ifdef ACTION_REPLAY_HRTMON
3782 if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
3783 int isinhrt = (m68k_getpc () >= hrtmem_start && m68k_getpc () < hrtmem_start + hrtmem_size);
3784 /* exit from HRTMon? */
3785 if (hrtmon_flag == ACTION_REPLAY_ACTIVE && !isinhrt)
3786 hrtmon_hide ();
3787 /* HRTMon breakpoint? (not via IRQ7) */
3788 if (hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt)
3789 hrtmon_breakenter ();
3790 if (hrtmon_flag == ACTION_REPLAY_ACTIVATE)
3791 hrtmon_enter ();
3792 }
3793 #endif
3794 if ((regs.spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE) {
3795 /*if (action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom ())*/
3796 /* write_log (_T("PC:%p\n"), m68k_getpc ());*/
3797
3798 if (action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
3799 action_replay_enter ();
3800 if ((action_replay_flag == ACTION_REPLAY_HIDE || action_replay_flag == ACTION_REPLAY_ACTIVE) && !is_ar_pc_in_rom ()) {
3801 action_replay_hide ();
3802 unset_special (SPCFLAG_ACTION_REPLAY);
3803 }
3804 if (action_replay_flag == ACTION_REPLAY_WAIT_PC) {
3805 /*write_log (_T("Waiting for PC: %p, current PC= %p\n"), wait_for_pc, m68k_getpc ());*/
3806 if (m68k_getpc () == wait_for_pc) {
3807 action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
3808 }
3809 }
3810 }
3811 #endif
3812
3813 if (regs.spcflags & SPCFLAG_COPPER)
3814 do_copper ();
3815
3816 #ifdef JIT
3817 unset_special (SPCFLAG_END_COMPILE); /* has done its job */
3818 #endif
3819
3820 while ((regs.spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
3821 int c = blitnasty ();
3822 if (c < 0) {
3823 break;
3824 } else if (c > 0) {
3825 cycles -= c * CYCLE_UNIT * 2;
3826 if (cycles < CYCLE_UNIT)
3827 cycles = 0;
3828 } else {
3829 c = 4;
3830 }
3831 x_do_cycles (c * CYCLE_UNIT);
3832 if (regs.spcflags & SPCFLAG_COPPER)
3833 do_copper ();
3834 #ifdef WITH_PPC
3835 if (ppc_state) {
3836 if (uae_ppc_poll_check_halt())
3837 return true;
3838 uae_ppc_execute_check();
3839 }
3840 #endif
3841 }
3842
3843 if (regs.spcflags & SPCFLAG_DOTRACE)
3844 Exception (9);
3845
3846 if (regs.spcflags & SPCFLAG_TRAP) {
3847 unset_special (SPCFLAG_TRAP);
3848 Exception (3);
3849 }
3850 bool first = true;
3851 while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
3852 isstopped:
3853 check_uae_int_request();
3854 {
3855 if (bsd_int_requested)
3856 bsdsock_fake_int_handler ();
3857 }
3858
3859 if (cpu_tracer > 0) {
3860 cputrace.stopped = regs.stopped;
3861 cputrace.intmask = regs.intmask;
3862 cputrace.sr = regs.sr;
3863 #ifdef FSUAE
3864 #if 0
3865 printf("set cputrace.state (3) = 1\n");
3866 #endif
3867 #endif
3868 cputrace.state = 1;
3869 cputrace.pc = m68k_getpc ();
3870 cputrace.memoryoffset = 0;
3871 cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
3872 cputrace.readcounter = cputrace.writecounter = 0;
3873 }
3874 if (!first)
3875 x_do_cycles (currprefs.cpu_cycle_exact ? 2 * CYCLE_UNIT : 4 * CYCLE_UNIT);
3876 first = false;
3877 if (regs.spcflags & SPCFLAG_COPPER)
3878 do_copper ();
3879
3880 if (m68k_interrupt_delay) {
3881 ipl_fetch ();
3882 if (time_for_interrupt ()) {
3883 do_interrupt (regs.ipl);
3884 }
3885 } else {
3886 if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
3887 int intr = intlev ();
3888 unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
3889 #ifdef WITH_PPC
3890 bool m68kint = true;
3891 if (ppc_state) {
3892 m68kint = ppc_interrupt(intr);
3893 }
3894 if (m68kint) {
3895 #endif
3896 if (intr > 0 && intr > regs.intmask)
3897 do_interrupt (intr);
3898 #ifdef WITH_PPC
3899 }
3900 #endif
3901 }
3902 }
3903
3904 if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
3905 m68k_resumestopped();
3906 return 1;
3907 }
3908
3909 #ifdef WITH_PPC
3910 if (ppc_state) {
3911 uae_ppc_execute_check();
3912 uae_ppc_poll_check_halt();
3913 }
3914 #endif
3915
3916 }
3917
3918 if (regs.spcflags & SPCFLAG_TRACE)
3919 do_trace ();
3920
3921 if (m68k_interrupt_delay) {
3922 if (time_for_interrupt ()) {
3923 do_interrupt (regs.ipl);
3924 }
3925 } else {
3926 if (regs.spcflags & SPCFLAG_INT) {
3927 int intr = intlev ();
3928 unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
3929 if (intr > 0 && (intr > regs.intmask || intr == 7))
3930 do_interrupt (intr);
3931 }
3932 }
3933
3934 if (regs.spcflags & SPCFLAG_DOINT) {
3935 unset_special (SPCFLAG_DOINT);
3936 set_special (SPCFLAG_INT);
3937 }
3938
3939 if (regs.spcflags & SPCFLAG_BRK) {
3940 unset_special(SPCFLAG_BRK);
3941 #ifdef DEBUGGER
3942 if (debugging) {
3943 debug();
3944 if (regs.stopped)
3945 goto isstopped;
3946 }
3947 #endif
3948 }
3949
3950 return 0;
3951 }
3952
3953 //static uae_u32 pcs[1000];
3954
3955 #if DEBUG_CD32CDTVIO
3956
3957 static uae_u32 cd32nextpc, cd32request;
3958
out_cd32io2(void)3959 static void out_cd32io2 (void)
3960 {
3961 uae_u32 request = cd32request;
3962 write_log (_T("%08x returned\n"), request);
3963 //write_log (_T("ACTUAL=%d ERROR=%d\n"), get_long (request + 32), get_byte (request + 31));
3964 cd32nextpc = 0;
3965 cd32request = 0;
3966 }
3967
out_cd32io(uae_u32 pc)3968 static void out_cd32io (uae_u32 pc)
3969 {
3970 TCHAR out[100];
3971 int ioreq = 0;
3972 uae_u32 request = m68k_areg (regs, 1);
3973
3974 if (pc == cd32nextpc) {
3975 out_cd32io2 ();
3976 return;
3977 }
3978 out[0] = 0;
3979 switch (pc)
3980 {
3981 case 0xe57cc0:
3982 case 0xf04c34:
3983 _stprintf (out, _T("opendevice"));
3984 break;
3985 case 0xe57ce6:
3986 case 0xf04c56:
3987 _stprintf (out, _T("closedevice"));
3988 break;
3989 case 0xe57e44:
3990 case 0xf04f2c:
3991 _stprintf (out, _T("beginio"));
3992 ioreq = 1;
3993 break;
3994 case 0xe57ef2:
3995 case 0xf0500e:
3996 _stprintf (out, _T("abortio"));
3997 ioreq = -1;
3998 break;
3999 }
4000 if (out[0] == 0)
4001 return;
4002 if (cd32request)
4003 write_log (_T("old request still not returned!\n"));
4004 cd32request = request;
4005 cd32nextpc = get_long (m68k_areg (regs, 7));
4006 write_log (_T("%s A1=%08X\n"), out, request);
4007 if (ioreq) {
4008 static int cnt = 0;
4009 int cmd = get_word (request + 28);
4010 #if 0
4011 if (cmd == 33) {
4012 uaecptr data = get_long (request + 40);
4013 write_log (_T("CD_CONFIG:\n"));
4014 for (int i = 0; i < 16; i++) {
4015 write_log (_T("%08X=%08X\n"), get_long (data), get_long (data + 4));
4016 data += 8;
4017 }
4018 }
4019 #endif
4020 #if 0
4021 if (cmd == 37) {
4022 cnt--;
4023 if (cnt <= 0)
4024 activate_debugger ();
4025 }
4026 #endif
4027 write_log (_T("CMD=%d DATA=%08X LEN=%d %OFF=%d PC=%x\n"),
4028 cmd, get_long (request + 40),
4029 get_long (request + 36), get_long (request + 44), M68K_GETPC);
4030 }
4031 if (ioreq < 0)
4032 ;//activate_debugger ();
4033 }
4034
4035 #endif
4036
bus_error(void)4037 static void bus_error(void)
4038 {
4039 TRY (prb2) {
4040 Exception (2);
4041 } CATCH (prb2) {
4042 cpu_halt (CPU_HALT_BUS_ERROR_DOUBLE_FAULT);
4043 } ENDTRY
4044 }
4045
4046 #ifndef CPUEMU_11
4047
m68k_run_1(void)4048 static void m68k_run_1 (void)
4049 {
4050 }
4051
4052 #else
4053
4054 /* It's really sad to have two almost identical functions for this, but we
4055 do it all for performance... :(
4056 This version emulates 68000's prefetch "cache" */
m68k_run_1(void)4057 static void m68k_run_1 (void)
4058 {
4059 struct regstruct *r = ®s;
4060 bool exit = false;
4061
4062 while (!exit) {
4063 TRY (prb) {
4064 while (!exit) {
4065 r->opcode = r->ir;
4066
4067 count_instr (r->opcode);
4068
4069 #if DEBUG_CD32CDTVIO
4070 out_cd32io (m68k_getpc ());
4071 #endif
4072
4073 #if 0
4074 int pc = m68k_getpc ();
4075 if (pc == 0xdff002)
4076 write_log (_T("hip\n"));
4077 if (pc != pcs[0] && (pc < 0xd00000 || pc > 0x1000000)) {
4078 memmove (pcs + 1, pcs, 998 * 4);
4079 pcs[0] = pc;
4080 //write_log (_T("%08X-%04X "), pc, r->opcode);
4081 }
4082 #endif
4083 do_cycles (cpu_cycles);
4084 r->instruction_pc = m68k_getpc ();
4085 cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
4086 cpu_cycles = adjust_cycles (cpu_cycles);
4087 if (r->spcflags) {
4088 if (do_specialties (cpu_cycles))
4089 exit = true;
4090 }
4091 regs.ipl = regs.ipl_pin;
4092 if (!currprefs.cpu_compatible || (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010))
4093 exit = true;
4094 }
4095 } CATCH (prb) {
4096 bus_error();
4097 if (r->spcflags) {
4098 if (do_specialties(cpu_cycles))
4099 exit = true;
4100 }
4101 regs.ipl = regs.ipl_pin;
4102 } ENDTRY
4103 }
4104 }
4105
4106 #endif /* CPUEMU_11 */
4107
4108 #ifndef CPUEMU_13
4109
m68k_run_1_ce(void)4110 static void m68k_run_1_ce (void)
4111 {
4112 }
4113
4114 #else
4115
4116 /* cycle-exact m68k_run () */
4117
m68k_run_1_ce(void)4118 static void m68k_run_1_ce (void)
4119 {
4120 struct regstruct *r = ®s;
4121 bool first = true;
4122 bool exit = false;
4123
4124 while (!exit) {
4125 TRY (prb) {
4126 if (first) {
4127 if (cpu_tracer < 0) {
4128 memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
4129 r->ir = cputrace.ir;
4130 r->irc = cputrace.irc;
4131 r->sr = cputrace.sr;
4132 r->usp = cputrace.usp;
4133 r->isp = cputrace.isp;
4134 r->intmask = cputrace.intmask;
4135 r->stopped = cputrace.stopped;
4136 m68k_setpc (cputrace.pc);
4137 if (!r->stopped) {
4138 if (cputrace.state > 1) {
4139 write_log (_T("CPU TRACE: EXCEPTION %d\n"), cputrace.state);
4140 Exception (cputrace.state);
4141 } else if (cputrace.state == 1) {
4142 write_log (_T("CPU TRACE: %04X\n"), cputrace.opcode);
4143 (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
4144 }
4145 } else {
4146 write_log (_T("CPU TRACE: STOPPED\n"));
4147 }
4148 if (r->stopped)
4149 set_special (SPCFLAG_STOP);
4150 set_cpu_tracer (false);
4151 goto cont;
4152 }
4153 set_cpu_tracer (false);
4154 first = false;
4155 }
4156
4157 while (!exit) {
4158 r->opcode = r->ir;
4159
4160 #if DEBUG_CD32CDTVIO
4161 out_cd32io (m68k_getpc ());
4162 #endif
4163 if (cpu_tracer) {
4164 memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
4165 cputrace.opcode = r->opcode;
4166 cputrace.ir = r->ir;
4167 cputrace.irc = r->irc;
4168 cputrace.sr = r->sr;
4169 cputrace.usp = r->usp;
4170 cputrace.isp = r->isp;
4171 cputrace.intmask = r->intmask;
4172 cputrace.stopped = r->stopped;
4173 cputrace.state = 1;
4174 cputrace.pc = m68k_getpc ();
4175 cputrace.startcycles = get_cycles ();
4176 cputrace.memoryoffset = 0;
4177 cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
4178 cputrace.readcounter = cputrace.writecounter = 0;
4179 }
4180
4181 if (inputrecord_debug & 4) {
4182 if (input_record > 0)
4183 inprec_recorddebug_cpu (1);
4184 else if (input_play > 0)
4185 inprec_playdebug_cpu (1);
4186 }
4187
4188 r->instruction_pc = m68k_getpc ();
4189 (*cpufunctbl[r->opcode])(r->opcode);
4190 wait_memory_cycles();
4191 if (cpu_tracer) {
4192 cputrace.state = 0;
4193 }
4194 cont:
4195 if (cputrace.needendcycles) {
4196 cputrace.needendcycles = 0;
4197 write_log (_T("STARTCYCLES=%08x ENDCYCLES=%08lx\n"), cputrace.startcycles, get_cycles ());
4198 log_dma_record ();
4199 }
4200
4201 if (r->spcflags || time_for_interrupt ()) {
4202 if (do_specialties (0))
4203 exit = true;
4204 }
4205
4206 if (!currprefs.cpu_cycle_exact || currprefs.cpu_model > 68010)
4207 exit = true;
4208 }
4209 } CATCH (prb) {
4210 bus_error();
4211 if (r->spcflags || time_for_interrupt()) {
4212 if (do_specialties(0))
4213 exit = true;
4214 }
4215 } ENDTRY
4216 }
4217 }
4218
4219 #endif
4220
4221 #if defined(CPUEMU_20) && defined(JIT)
4222 // emulate simple prefetch
get_word_020_prefetchf(uae_u32 pc)4223 static uae_u16 get_word_020_prefetchf (uae_u32 pc)
4224 {
4225 if (pc == regs.prefetch020addr) {
4226 uae_u16 v = regs.prefetch020[0];
4227 regs.prefetch020[0] = regs.prefetch020[1];
4228 regs.prefetch020[1] = regs.prefetch020[2];
4229 regs.prefetch020[2] = x_get_word (pc + 6);
4230 regs.prefetch020addr += 2;
4231 return v;
4232 } else if (pc == regs.prefetch020addr + 2) {
4233 uae_u16 v = regs.prefetch020[1];
4234 regs.prefetch020[0] = regs.prefetch020[2];
4235 regs.prefetch020[1] = x_get_word (pc + 4);
4236 regs.prefetch020[2] = x_get_word (pc + 6);
4237 regs.prefetch020addr = pc + 2;
4238 return v;
4239 } else if (pc == regs.prefetch020addr + 4) {
4240 uae_u16 v = regs.prefetch020[2];
4241 regs.prefetch020[0] = x_get_word (pc + 2);
4242 regs.prefetch020[1] = x_get_word (pc + 4);
4243 regs.prefetch020[2] = x_get_word (pc + 6);
4244 regs.prefetch020addr = pc + 2;
4245 return v;
4246 } else {
4247 regs.prefetch020addr = pc + 2;
4248 regs.prefetch020[0] = x_get_word (pc + 2);
4249 regs.prefetch020[1] = x_get_word (pc + 4);
4250 regs.prefetch020[2] = x_get_word (pc + 6);
4251 return x_get_word (pc);
4252 }
4253 }
4254 #endif
4255
4256 #ifdef WITH_THREADED_CPU
4257 static volatile int cpu_thread_active;
4258
4259 #define SPINLOCK_DEBUG 0
4260 static volatile int m68k_spinlock_cnt;
4261 static volatile long m68k_spinlock_waiting;
4262 #ifdef _WIN32
4263 #define CRITICAL_SECTION_SPIN_COUNT 5000
4264 static CRITICAL_SECTION m68k_cs1;
4265 static bool m68k_cs_initialized;
4266 static DWORD m68k_cs_owner;
4267 #else
4268 #include <glib.h>
4269 static GMutex mutex;
4270 #endif
4271
do_specialties_thread(void)4272 static int do_specialties_thread(void)
4273 {
4274 if (regs.spcflags & SPCFLAG_MODE_CHANGE)
4275 return 1;
4276
4277 if (regs.spcflags & SPCFLAG_CHECK) {
4278 if (regs.halted) {
4279 if (haltloop())
4280 return 1;
4281 }
4282 if (m68k_reset_delay) {
4283 int vsynccnt = 60;
4284 int vsyncstate = -1;
4285 while (vsynccnt > 0) {
4286 int vp = vpos;
4287 while (vp == vpos) {
4288 sleep_millis(1);
4289 }
4290 vsynccnt--;
4291 }
4292 }
4293 m68k_reset_delay = 0;
4294 unset_special(SPCFLAG_CHECK);
4295 }
4296
4297 #ifdef JIT
4298 unset_special(SPCFLAG_END_COMPILE); /* has done its job */
4299 #endif
4300
4301 if (regs.spcflags & SPCFLAG_DOTRACE)
4302 Exception(9);
4303
4304 if (regs.spcflags & SPCFLAG_TRAP) {
4305 unset_special(SPCFLAG_TRAP);
4306 Exception(3);
4307 }
4308 bool first = true;
4309 while ((regs.spcflags & SPCFLAG_STOP) && !(regs.spcflags & SPCFLAG_BRK)) {
4310 if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
4311 int intr = intlev();
4312 unset_special(SPCFLAG_INT | SPCFLAG_DOINT);
4313 if (intr > 0 && intr > regs.intmask)
4314 do_interrupt(intr);
4315 }
4316
4317 if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
4318 m68k_resumestopped();
4319 return 1;
4320 }
4321 }
4322
4323 if (regs.spcflags & SPCFLAG_TRACE)
4324 do_trace();
4325
4326 if (regs.spcflags & SPCFLAG_INT) {
4327 int intr = intlev();
4328 unset_special(SPCFLAG_INT | SPCFLAG_DOINT);
4329 if (intr > 0 && (intr > regs.intmask || intr == 7))
4330 do_interrupt(intr);
4331 }
4332
4333 if (regs.spcflags & SPCFLAG_DOINT) {
4334 unset_special(SPCFLAG_DOINT);
4335 set_special(SPCFLAG_INT);
4336 }
4337
4338 if (regs.spcflags & SPCFLAG_BRK) {
4339 return 1;
4340 }
4341
4342 return 0;
4343 }
4344
cpu_semaphore_get(void)4345 void cpu_semaphore_get(void)
4346 {
4347 if (!currprefs.cpu_thread)
4348 return;
4349 DWORD tid = GetCurrentThreadId();
4350
4351 if (tid == m68k_cs_owner) {
4352 m68k_spinlock_cnt++;
4353 return;
4354 }
4355
4356 #ifdef _WIN32
4357 _InterlockedIncrement(&m68k_spinlock_waiting);
4358 EnterCriticalSection(&m68k_cs1);
4359 _InterlockedDecrement(&m68k_spinlock_waiting);
4360 m68k_cs_owner = tid;
4361 m68k_spinlock_cnt++;
4362 #else
4363 g_mutex_lock(&mutex); // FIXME
4364 #endif
4365 }
cpu_semaphore_release(void)4366 void cpu_semaphore_release(void)
4367 {
4368 if (!currprefs.cpu_thread)
4369 return;
4370 #ifdef _WIN32
4371 m68k_spinlock_cnt--;
4372 if (m68k_spinlock_cnt == 0) {
4373 m68k_cs_owner = 0;
4374 LeaveCriticalSection(&m68k_cs1);
4375 }
4376 #else
4377 g_mutex_unlock(&mutex); // FIXME
4378 #endif
4379 }
4380
init_cpu_thread(void)4381 static void init_cpu_thread(void)
4382 {
4383 if (!currprefs.cpu_thread)
4384 return;
4385 #ifdef _WIN32
4386 if (m68k_cs_initialized) {
4387 DeleteCriticalSection(&m68k_cs1);
4388 }
4389 InitializeCriticalSectionAndSpinCount(&m68k_cs1, CRITICAL_SECTION_SPIN_COUNT);
4390 #endif
4391 }
4392
run_cpu_thread(void * (* f)(void *))4393 static void run_cpu_thread(void *(*f)(void *))
4394 {
4395 cpu_thread_active = 0;
4396 #if SPINLOCK_DEBUG
4397 m68k_spinlock_cnt = 0;
4398 #endif
4399 m68k_cs_initialized = true;
4400 if (uae_start_thread(_T("cpu"), f, NULL, NULL)) {
4401 while (!cpu_thread_active) {
4402 sleep_millis(1);
4403 }
4404 while (!(regs.spcflags & SPCFLAG_MODE_CHANGE)) {
4405
4406 cpu_semaphore_get();
4407 frame_time_t c = read_processor_time();
4408 while (cpu_thread_active) {
4409 int vsynctimeperline = vsynctimebase / (maxvpos_display + 1);
4410
4411 int vp = vpos;
4412 while ((int)read_processor_time() - (int)c > -vsynctimebase / 10) {
4413 if (vp != vpos) {
4414 vp = vpos;
4415 if (vpos + 1 == maxvpos + lof_store) {
4416 c = read_processor_time();
4417 }
4418 c += vsynctimeperline;
4419 }
4420 cycles_do_special();
4421 do_cycles(maxhpos / 2 * CYCLE_UNIT);
4422 if (regs.spcflags & SPCFLAG_COPPER) {
4423 do_copper();
4424 }
4425 check_uae_int_request();
4426 int w = m68k_spinlock_waiting;
4427 if (w) {
4428 cpu_semaphore_release();
4429 while (m68k_spinlock_waiting == w);
4430 cpu_semaphore_get();
4431 }
4432 }
4433 cpu_semaphore_release();
4434 sleep_millis(1);
4435 cpu_semaphore_get();
4436 while ((int)read_processor_time() - (int)c < 0) {
4437 check_uae_int_request();
4438 int w = m68k_spinlock_waiting;
4439 if (w) {
4440 cpu_semaphore_release();
4441 while (m68k_spinlock_waiting == w);
4442 cpu_semaphore_get();
4443 }
4444 }
4445 }
4446 cpu_semaphore_release();
4447
4448 unset_special(SPCFLAG_BRK);
4449 #ifdef DEBUGGER
4450 if (debugging) {
4451 debug();
4452 }
4453 #endif
4454 }
4455 }
4456 }
4457 #endif
4458
4459 #ifdef JIT /* Completely different run_2 replacement */
4460
do_nothing(void)4461 void do_nothing (void)
4462 {
4463 if (!currprefs.cpu_thread) {
4464 /* What did you expect this to do? */
4465 do_cycles (0);
4466 /* I bet you didn't expect *that* ;-) */
4467 }
4468 }
4469
exec_nostats(void)4470 void exec_nostats (void)
4471 {
4472 struct regstruct *r = ®s;
4473
4474 for (;;)
4475 {
4476 if (currprefs.cpu_compatible) {
4477 r->opcode = get_word_020_prefetchf(m68k_getpc());
4478 } else {
4479 r->opcode = x_get_iword(0);
4480 }
4481 cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
4482 cpu_cycles = adjust_cycles (cpu_cycles);
4483
4484 if (!currprefs.cpu_thread) {
4485 do_cycles (cpu_cycles);
4486
4487 #ifdef WITH_PPC
4488 if (ppc_state)
4489 ppc_interrupt(intlev());
4490 #endif
4491 }
4492
4493 if (end_block(r->opcode) || r->spcflags || uae_int_requested || uaenet_int_requested)
4494 return; /* We will deal with the spcflags in the caller */
4495 }
4496 }
4497
execute_normal(void)4498 void execute_normal (void)
4499 {
4500 struct regstruct *r = ®s;
4501 int blocklen;
4502 cpu_history pc_hist[MAXRUN];
4503 int total_cycles;
4504
4505 if (check_for_cache_miss ())
4506 return;
4507
4508 total_cycles = 0;
4509 blocklen = 0;
4510 start_pc_p = r->pc_oldp;
4511 start_pc = r->pc;
4512 for (;;) {
4513 /* Take note: This is the do-it-normal loop */
4514 regs.instruction_pc = m68k_getpc ();
4515 if (currprefs.cpu_compatible) {
4516 r->opcode = get_word_020_prefetchf (regs.instruction_pc);
4517 } else {
4518 r->opcode = x_get_iword(0);
4519 }
4520
4521 special_mem = DISTRUST_CONSISTENT_MEM;
4522 pc_hist[blocklen].location = (uae_u16*)r->pc_p;
4523
4524 cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
4525 cpu_cycles = adjust_cycles(cpu_cycles);
4526 if (!currprefs.cpu_thread) {
4527 do_cycles (cpu_cycles);
4528 }
4529 total_cycles += cpu_cycles;
4530 pc_hist[blocklen].specmem = special_mem;
4531 blocklen++;
4532 if (end_block (r->opcode) || blocklen >= MAXRUN || r->spcflags || uae_int_requested || uaenet_int_requested) {
4533 compile_block (pc_hist, blocklen, total_cycles);
4534 return; /* We will deal with the spcflags in the caller */
4535 }
4536 /* No need to check regs.spcflags, because if they were set,
4537 we'd have ended up inside that "if" */
4538
4539 #ifdef WITH_PPC
4540 if (ppc_state)
4541 ppc_interrupt(intlev());
4542 #endif
4543 }
4544 }
4545
4546 typedef void compiled_handler (void);
4547
4548 #ifdef WITH_THREADED_CPU
cpu_thread_run_jit(void * v)4549 static void *cpu_thread_run_jit(void *v)
4550 {
4551 cpu_thread_active = 1;
4552 for (;;) {
4553 ((compiled_handler*)(pushall_call_handler))();
4554 /* Whenever we return from that, we should check spcflags */
4555 if (regs.spcflags) {
4556 if (do_specialties_thread()) {
4557 break;
4558 }
4559 }
4560 }
4561 cpu_thread_active = 0;
4562 return 0;
4563 }
4564 #endif
4565
m68k_run_jit(void)4566 static void m68k_run_jit(void)
4567 {
4568 #ifdef WITH_THREADED_CPU
4569 if (currprefs.cpu_thread) {
4570 run_cpu_thread(cpu_thread_run_jit);
4571 return;
4572 }
4573 #endif
4574
4575 for (;;) {
4576 ((compiled_handler*)(pushall_call_handler))();
4577 /* Whenever we return from that, we should check spcflags */
4578 check_uae_int_request();
4579 if (regs.spcflags) {
4580 if (do_specialties (0)) {
4581 return;
4582 }
4583 }
4584 }
4585 }
4586 #endif /* JIT */
4587
4588 //#ifndef CPUEMU_0
4589 #if 0
4590
4591 static void m68k_run_2 (void)
4592 {
4593 }
4594
4595 #else
4596
opcodedebug(uae_u32 pc,uae_u16 opcode,bool full)4597 static void opcodedebug (uae_u32 pc, uae_u16 opcode, bool full)
4598 {
4599 struct mnemolookup *lookup;
4600 struct instr *dp;
4601 uae_u32 addr;
4602 int fault;
4603
4604 if (cpufunctbl[opcode] == op_illg_1)
4605 opcode = 0x4AFC;
4606 dp = table68k + opcode;
4607 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
4608 ;
4609 fault = 0;
4610 TRY(prb) {
4611 addr = mmu_translate (pc, (regs.mmu_ssw & 4) ? 1 : 0, 0, 0);
4612 } CATCH (prb) {
4613 fault = 1;
4614 } ENDTRY
4615 if (!fault) {
4616 TCHAR buf[100];
4617 if (full)
4618 write_log (_T("mmufixup=%d %04x %04x\n"), mmufixup[0].reg, regs.wb3_status, regs.mmu_ssw);
4619 m68k_disasm_2 (buf, sizeof buf / sizeof (TCHAR), addr, NULL, 1, NULL, NULL, 0);
4620 write_log (_T("%s\n"), buf);
4621 if (full)
4622 m68k_dumpstate (NULL);
4623 }
4624 }
4625
cpu_halt(int id)4626 void cpu_halt (int id)
4627 {
4628 // id < 0: m68k halted, PPC active.
4629 // id > 0: emulation halted.
4630 if (!regs.halted) {
4631 write_log (_T("CPU halted: reason = %d PC=%08x\n"), id, M68K_GETPC);
4632 regs.halted = id;
4633 gui_data.cpu_halted = id;
4634 gui_led(LED_CPU, 0, -1);
4635 if (id >= 0) {
4636 regs.intmask = 7;
4637 MakeSR ();
4638 audio_deactivate ();
4639 }
4640 set_special(SPCFLAG_CHECK);
4641 }
4642 }
4643
4644 #ifdef CPUEMU_33
4645
4646 /* MMU 68060 */
m68k_run_mmu060(void)4647 static void m68k_run_mmu060 (void)
4648 {
4649 struct flag_struct f;
4650 int halt = 0;
4651
4652 while (!halt) {
4653 TRY (prb) {
4654 for (;;) {
4655 f.cznv = regflags.cznv;
4656 f.x = regflags.x;
4657 regs.instruction_pc = m68k_getpc ();
4658
4659 do_cycles (cpu_cycles);
4660
4661 mmu_opcode = -1;
4662 mmu060_state = 0;
4663 mmu_opcode = regs.opcode = x_prefetch (0);
4664 mmu060_state = 1;
4665
4666 count_instr (regs.opcode);
4667 cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
4668
4669 cpu_cycles = adjust_cycles (cpu_cycles);
4670
4671 if (regs.spcflags) {
4672 if (do_specialties (cpu_cycles))
4673 return;
4674 }
4675 }
4676 } CATCH (prb) {
4677 m68k_setpci (regs.instruction_pc);
4678 regflags.cznv = f.cznv;
4679 regflags.x = f.x;
4680
4681 if (mmufixup[0].reg >= 0) {
4682 m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
4683 mmufixup[0].reg = -1;
4684 }
4685 if (mmufixup[1].reg >= 0) {
4686 m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
4687 mmufixup[1].reg = -1;
4688 }
4689
4690 TRY (prb2) {
4691 Exception (prb);
4692 } CATCH (prb2) {
4693 halt = 1;
4694 } ENDTRY
4695 } ENDTRY
4696 }
4697 cpu_halt(halt);
4698 }
4699
4700 #endif
4701
4702 #ifdef CPUEMU_31
4703
4704 /* Aranym MMU 68040 */
m68k_run_mmu040(void)4705 static void m68k_run_mmu040 (void)
4706 {
4707 flag_struct f;
4708 int halt = 0;
4709
4710 while (!halt) {
4711 TRY (prb) {
4712 for (;;) {
4713 f.cznv = regflags.cznv;
4714 f.x = regflags.x;
4715 mmu_restart = true;
4716 regs.instruction_pc = m68k_getpc ();
4717
4718 do_cycles (cpu_cycles);
4719
4720 mmu_opcode = -1;
4721 mmu_opcode = regs.opcode = x_prefetch (0);
4722 count_instr (regs.opcode);
4723 cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
4724 cpu_cycles = adjust_cycles (cpu_cycles);
4725
4726 if (regs.spcflags) {
4727 if (do_specialties (cpu_cycles))
4728 return;
4729 }
4730 }
4731 } CATCH (prb) {
4732
4733 if (mmu_restart) {
4734 /* restore state if instruction restart */
4735 regflags.cznv = f.cznv;
4736 regflags.x = f.x;
4737 m68k_setpci (regs.instruction_pc);
4738 }
4739
4740 if (mmufixup[0].reg >= 0) {
4741 m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
4742 mmufixup[0].reg = -1;
4743 }
4744
4745 TRY (prb2) {
4746 Exception (prb);
4747 } CATCH (prb2) {
4748 halt = 1;
4749 } ENDTRY
4750 } ENDTRY
4751 }
4752 cpu_halt(halt);
4753 }
4754
4755 #endif
4756
4757 #ifdef CPUEMU_32
4758
4759 // Previous MMU 68030
m68k_run_mmu030(void)4760 static void m68k_run_mmu030 (void)
4761 {
4762 struct flag_struct f;
4763 int halt = 0;
4764
4765 mmu030_opcode_stageb = -1;
4766 mmu030_fake_prefetch = -1;
4767 while(!halt) {
4768 TRY (prb) {
4769 for (;;) {
4770 int cnt;
4771 insretry:
4772 regs.instruction_pc = m68k_getpc ();
4773 f.cznv = regflags.cznv;
4774 f.x = regflags.x;
4775
4776 mmu030_state[0] = mmu030_state[1] = mmu030_state[2] = 0;
4777 mmu030_opcode = -1;
4778 if (mmu030_fake_prefetch >= 0) {
4779 // use fake prefetch opcode only if mapping changed
4780 uaecptr new_addr = mmu030_translate(regs.instruction_pc, regs.s != 0, false, false);
4781 if (mmu030_fake_prefetch_addr != new_addr) {
4782 regs.opcode = mmu030_fake_prefetch;
4783 write_log(_T("MMU030 fake prefetch remap: %04x, %08x -> %08x\n"), mmu030_fake_prefetch, mmu030_fake_prefetch_addr, new_addr);
4784 } else {
4785 if (mmu030_opcode_stageb < 0) {
4786 regs.opcode = x_prefetch (0);
4787 } else {
4788 regs.opcode = mmu030_opcode_stageb;
4789 mmu030_opcode_stageb = -1;
4790 }
4791 }
4792 mmu030_fake_prefetch = -1;
4793 } else if (mmu030_opcode_stageb < 0) {
4794 regs.opcode = x_prefetch (0);
4795 } else {
4796 regs.opcode = mmu030_opcode_stageb;
4797 mmu030_opcode_stageb = -1;
4798 }
4799
4800 mmu030_opcode = regs.opcode;
4801 mmu030_ad[0].done = false;
4802
4803 cnt = 50;
4804 for (;;) {
4805 regs.opcode = mmu030_opcode;
4806 mmu030_idx = 0;
4807 count_instr (regs.opcode);
4808 do_cycles (cpu_cycles);
4809 mmu030_retry = false;
4810
4811 cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
4812 cnt--; // so that we don't get in infinite loop if things go horribly wrong
4813 if (!mmu030_retry)
4814 break;
4815 if (cnt < 0) {
4816 cpu_halt (CPU_HALT_CPU_STUCK);
4817 break;
4818 }
4819 if (mmu030_retry && mmu030_opcode == -1)
4820 goto insretry; // urgh
4821 }
4822
4823 mmu030_opcode = -1;
4824
4825 cpu_cycles = adjust_cycles (cpu_cycles);
4826 if (regs.spcflags) {
4827 if (do_specialties (cpu_cycles))
4828 return;
4829 }
4830 }
4831 } CATCH (prb) {
4832
4833 regflags.cznv = f.cznv;
4834 regflags.x = f.x;
4835
4836 m68k_setpci (regs.instruction_pc);
4837
4838 if (mmufixup[0].reg >= 0) {
4839 m68k_areg (regs, mmufixup[0].reg) = mmufixup[0].value;
4840 mmufixup[0].reg = -1;
4841 }
4842 if (mmufixup[1].reg >= 0) {
4843 m68k_areg (regs, mmufixup[1].reg) = mmufixup[1].value;
4844 mmufixup[1].reg = -1;
4845 }
4846
4847 TRY (prb2) {
4848 Exception (prb);
4849 } CATCH (prb2) {
4850 halt = 1;
4851 } ENDTRY
4852 } ENDTRY
4853 }
4854 cpu_halt (halt);
4855 }
4856
4857 #endif
4858
4859
4860 /* "cycle exact" 68040/060 */
4861
m68k_run_3ce(void)4862 static void m68k_run_3ce (void)
4863 {
4864 struct regstruct *r = ®s;
4865 bool exit = false;
4866
4867 while (!exit) {
4868 TRY(prb) {
4869 while (!exit) {
4870 r->instruction_pc = m68k_getpc();
4871 r->opcode = get_iword_cache_040(0);
4872 // "prefetch"
4873 if (regs.cacr & 0x8000)
4874 fill_icache040(r->instruction_pc + 16);
4875
4876 (*cpufunctbl[r->opcode])(r->opcode);
4877
4878 if (r->spcflags) {
4879 if (do_specialties (0))
4880 exit = true;
4881 }
4882 }
4883 } CATCH(prb) {
4884 bus_error();
4885 if (r->spcflags) {
4886 if (do_specialties(0))
4887 exit = true;
4888 }
4889 } ENDTRY
4890 }
4891 }
4892
4893 /* "prefetch" 68040/060 */
4894
m68k_run_3p(void)4895 static void m68k_run_3p(void)
4896 {
4897 struct regstruct *r = ®s;
4898 bool exit = false;
4899 int cycles;
4900
4901 while (!exit) {
4902 TRY(prb) {
4903 while (!exit) {
4904 r->instruction_pc = m68k_getpc();
4905 r->opcode = get_iword_cache_040(0);
4906 // "prefetch"
4907 if (regs.cacr & 0x8000)
4908 fill_icache040(r->instruction_pc + 16);
4909
4910 (*cpufunctbl[r->opcode])(r->opcode);
4911
4912 cpu_cycles = 1 * CYCLE_UNIT;
4913 cycles = adjust_cycles(cpu_cycles);
4914 do_cycles(cycles);
4915
4916 if (r->spcflags) {
4917 if (do_specialties(0))
4918 exit = true;
4919 }
4920
4921 }
4922 } CATCH(prb) {
4923 bus_error();
4924 if (r->spcflags) {
4925 if (do_specialties(0))
4926 exit = true;
4927 }
4928 } ENDTRY
4929 }
4930 }
4931
4932 /* "cycle exact" 68020/030 */
4933
m68k_run_2ce(void)4934 static void m68k_run_2ce (void)
4935 {
4936 struct regstruct *r = ®s;
4937 bool exit = false;
4938 bool first = true;
4939
4940 while (!exit) {
4941 TRY(prb) {
4942 if (first) {
4943 if (cpu_tracer < 0) {
4944 memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
4945 r->ir = cputrace.ir;
4946 r->irc = cputrace.irc;
4947 r->sr = cputrace.sr;
4948 r->usp = cputrace.usp;
4949 r->isp = cputrace.isp;
4950 r->intmask = cputrace.intmask;
4951 r->stopped = cputrace.stopped;
4952
4953 r->msp = cputrace.msp;
4954 r->vbr = cputrace.vbr;
4955 r->caar = cputrace.caar;
4956 r->cacr = cputrace.cacr;
4957 r->cacheholdingdata020 = cputrace.cacheholdingdata020;
4958 r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
4959 r->prefetch020addr = cputrace.prefetch020addr;
4960 memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
4961 memcpy (&caches020, &cputrace.caches020, sizeof caches020);
4962
4963 m68k_setpc (cputrace.pc);
4964 if (!r->stopped) {
4965 if (cputrace.state > 1)
4966 Exception (cputrace.state);
4967 else if (cputrace.state == 1)
4968 (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
4969 }
4970 if (regs.stopped)
4971 set_special (SPCFLAG_STOP);
4972 set_cpu_tracer (false);
4973 goto cont;
4974 }
4975 set_cpu_tracer (false);
4976 first = false;
4977 }
4978
4979 while (!exit) {
4980 #if 0
4981 static int prevopcode;
4982 #endif
4983 r->instruction_pc = m68k_getpc ();
4984
4985 #if 0
4986 if (regs.irc == 0xfffb) {
4987 gui_message (_T("OPCODE %04X HAS FAULTY PREFETCH! PC=%08X"), prevopcode, r->instruction_pc);
4988 }
4989 #endif
4990
4991 //write_log (_T("%x %04x\n"), r->instruction_pc, regs.irc);
4992
4993 r->opcode = regs.irc;
4994 #if 0
4995 prevopcode = r->opcode;
4996 regs.irc = 0xfffb;
4997 #endif
4998 //write_log (_T("%08x %04x\n"), r->instruction_pc, opcode);
4999
5000 #if DEBUG_CD32CDTVIO
5001 out_cd32io (r->instruction_pc);
5002 #endif
5003
5004 if (cpu_tracer) {
5005
5006 #if CPUTRACE_DEBUG
5007 validate_trace ();
5008 #endif
5009 memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
5010 cputrace.opcode = r->opcode;
5011 cputrace.ir = r->ir;
5012 cputrace.irc = r->irc;
5013 cputrace.sr = r->sr;
5014 cputrace.usp = r->usp;
5015 cputrace.isp = r->isp;
5016 cputrace.intmask = r->intmask;
5017 cputrace.stopped = r->stopped;
5018 cputrace.state = 1;
5019 cputrace.pc = m68k_getpc ();
5020
5021 cputrace.msp = r->msp;
5022 cputrace.vbr = r->vbr;
5023 cputrace.caar = r->caar;
5024 cputrace.cacr = r->cacr;
5025 cputrace.cacheholdingdata020 = r->cacheholdingdata020;
5026 cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
5027 cputrace.prefetch020addr = r->prefetch020addr;
5028 memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
5029 memcpy (&cputrace.caches020, &caches020, sizeof caches020);
5030
5031 cputrace.memoryoffset = 0;
5032 cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
5033 cputrace.readcounter = cputrace.writecounter = 0;
5034 }
5035
5036 if (inputrecord_debug & 4) {
5037 if (input_record > 0)
5038 inprec_recorddebug_cpu (1);
5039 else if (input_play > 0)
5040 inprec_playdebug_cpu (1);
5041 }
5042
5043 (*cpufunctbl[r->opcode])(r->opcode);
5044
5045 wait_memory_cycles();
5046
5047 cont:
5048 if (r->spcflags || time_for_interrupt ()) {
5049 if (do_specialties (0))
5050 exit = true;
5051 }
5052
5053 regs.ipl = regs.ipl_pin;
5054
5055 }
5056 } CATCH(prb) {
5057 bus_error();
5058 if (r->spcflags || time_for_interrupt()) {
5059 if (do_specialties(0))
5060 exit = true;
5061 }
5062 regs.ipl = regs.ipl_pin;
5063 } ENDTRY
5064 }
5065 }
5066
5067 #if defined CPUEMU_20 || defined CPUEMU_22
5068
5069 // full prefetch 020 (more compatible)
m68k_run_2p(void)5070 static void m68k_run_2p (void)
5071 {
5072 struct regstruct *r = ®s;
5073 bool exit = false;
5074 bool first = true;
5075
5076 while (!exit) {
5077 TRY(prb) {
5078
5079 if (first) {
5080 if (cpu_tracer < 0) {
5081 memcpy (&r->regs, &cputrace.regs, 16 * sizeof (uae_u32));
5082 r->ir = cputrace.ir;
5083 r->irc = cputrace.irc;
5084 r->sr = cputrace.sr;
5085 r->usp = cputrace.usp;
5086 r->isp = cputrace.isp;
5087 r->intmask = cputrace.intmask;
5088 r->stopped = cputrace.stopped;
5089
5090 r->msp = cputrace.msp;
5091 r->vbr = cputrace.vbr;
5092 r->caar = cputrace.caar;
5093 r->cacr = cputrace.cacr;
5094 r->cacheholdingdata020 = cputrace.cacheholdingdata020;
5095 r->cacheholdingaddr020 = cputrace.cacheholdingaddr020;
5096 r->prefetch020addr = cputrace.prefetch020addr;
5097 memcpy (&r->prefetch020, &cputrace.prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
5098 memcpy (&caches020, &cputrace.caches020, sizeof caches020);
5099
5100 m68k_setpc (cputrace.pc);
5101 if (!r->stopped) {
5102 if (cputrace.state > 1)
5103 Exception (cputrace.state);
5104 else if (cputrace.state == 1)
5105 (*cpufunctbl[cputrace.opcode])(cputrace.opcode);
5106 }
5107 if (regs.stopped)
5108 set_special (SPCFLAG_STOP);
5109 set_cpu_tracer (false);
5110 goto cont;
5111 }
5112 set_cpu_tracer (false);
5113 first = false;
5114 }
5115
5116 while (!exit) {
5117 r->instruction_pc = m68k_getpc ();
5118 r->opcode = regs.irc;
5119
5120 #if DEBUG_CD32CDTVIO
5121 out_cd32io (m68k_getpc ());
5122 #endif
5123
5124 if (cpu_tracer) {
5125
5126 #if CPUTRACE_DEBUG
5127 validate_trace ();
5128 #endif
5129 memcpy (&cputrace.regs, &r->regs, 16 * sizeof (uae_u32));
5130 cputrace.opcode = r->opcode;
5131 cputrace.ir = r->ir;
5132 cputrace.irc = r->irc;
5133 cputrace.sr = r->sr;
5134 cputrace.usp = r->usp;
5135 cputrace.isp = r->isp;
5136 cputrace.intmask = r->intmask;
5137 cputrace.stopped = r->stopped;
5138 cputrace.state = 1;
5139 cputrace.pc = m68k_getpc ();
5140
5141 cputrace.msp = r->msp;
5142 cputrace.vbr = r->vbr;
5143 cputrace.caar = r->caar;
5144 cputrace.cacr = r->cacr;
5145 cputrace.cacheholdingdata020 = r->cacheholdingdata020;
5146 cputrace.cacheholdingaddr020 = r->cacheholdingaddr020;
5147 cputrace.prefetch020addr = r->prefetch020addr;
5148 memcpy (&cputrace.prefetch020, &r->prefetch020, CPU_PIPELINE_MAX * sizeof (uae_u32));
5149 memcpy (&cputrace.caches020, &caches020, sizeof caches020);
5150
5151 cputrace.memoryoffset = 0;
5152 cputrace.cyclecounter = cputrace.cyclecounter_pre = cputrace.cyclecounter_post = 0;
5153 cputrace.readcounter = cputrace.writecounter = 0;
5154 }
5155
5156 if (inputrecord_debug & 4) {
5157 if (input_record > 0)
5158 inprec_recorddebug_cpu (1);
5159 else if (input_play > 0)
5160 inprec_playdebug_cpu (1);
5161 }
5162
5163 x_do_cycles (cpu_cycles);
5164
5165 cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
5166 cpu_cycles = adjust_cycles (cpu_cycles);
5167 cont:
5168 if (r->spcflags) {
5169 if (do_specialties (cpu_cycles))
5170 exit = true;;
5171 }
5172 ipl_fetch ();
5173 }
5174 } CATCH(prb) {
5175 bus_error();
5176 if (r->spcflags) {
5177 if (do_specialties(cpu_cycles))
5178 exit = true;
5179 }
5180 ipl_fetch();
5181 } ENDTRY
5182 }
5183 }
5184
5185 #endif /* defined CPUEMU_20 || defined CPUEMU_22 */
5186
5187 #ifdef WITH_THREADED_CPU
cpu_thread_run_2(void * v)5188 static void *cpu_thread_run_2(void *v)
5189 {
5190 bool exit = false;
5191 struct regstruct *r = ®s;
5192
5193 cpu_thread_active = 1;
5194 while (!exit) {
5195 TRY(prb)
5196 {
5197 while (!exit) {
5198 r->instruction_pc = m68k_getpc();
5199
5200 r->opcode = x_get_iword(0);
5201
5202 (*cpufunctbl[r->opcode])(r->opcode);
5203
5204 if (r->spcflags) {
5205 if (do_specialties_thread())
5206 exit = true;
5207 }
5208 }
5209 } CATCH(prb)
5210 {
5211 bus_error();
5212 if (r->spcflags) {
5213 if (do_specialties_thread())
5214 exit = true;
5215 }
5216 } ENDTRY
5217 }
5218 cpu_thread_active = 0;
5219 return 0;
5220 }
5221 #endif
5222
5223 /* Same thing, but don't use prefetch to get opcode. */
m68k_run_2(void)5224 static void m68k_run_2 (void)
5225 {
5226 #ifdef WITH_THREADED_CPU
5227 if (currprefs.cpu_thread) {
5228 run_cpu_thread(cpu_thread_run_2);
5229 return;
5230 }
5231 #endif
5232
5233 struct regstruct *r = ®s;
5234 bool exit = false;
5235
5236 while (!exit) {
5237 TRY(prb) {
5238 while (!exit) {
5239 r->instruction_pc = m68k_getpc ();
5240
5241 r->opcode = x_get_iword(0);
5242 count_instr (r->opcode);
5243
5244 do_cycles (cpu_cycles);
5245
5246 cpu_cycles = (*cpufunctbl[r->opcode])(r->opcode);
5247 cpu_cycles = adjust_cycles (cpu_cycles);
5248
5249 if (r->spcflags) {
5250 if (do_specialties (cpu_cycles))
5251 exit = true;
5252 }
5253 }
5254 } CATCH(prb) {
5255 bus_error();
5256 if (r->spcflags) {
5257 if (do_specialties(cpu_cycles))
5258 exit = true;
5259 }
5260 } ENDTRY
5261 }
5262 }
5263
5264 /* fake MMU 68k */
5265 #if 0
5266 static void m68k_run_mmu (void)
5267 {
5268 for (;;) {
5269 regs.opcode = get_iiword (0);
5270 do_cycles (cpu_cycles);
5271 mmu_backup_regs = regs;
5272 cpu_cycles = (*cpufunctbl[regs.opcode])(regs.opcode);
5273 cpu_cycles = adjust_cycles (cpu_cycles);
5274 if (mmu_triggered)
5275 mmu_do_hit ();
5276 if (regs.spcflags) {
5277 if (do_specialties (cpu_cycles))
5278 return;
5279 }
5280 }
5281 }
5282 #endif
5283
5284 #endif /* CPUEMU_0 */
5285
5286 int in_m68k_go = 0;
5287
5288 #if 0
5289 static void exception2_handle (uaecptr addr, uaecptr fault)
5290 {
5291 last_addr_for_exception_3 = addr;
5292 last_fault_for_exception_3 = fault;
5293 last_writeaccess_for_exception_3 = 0;
5294 last_instructionaccess_for_exception_3 = 0;
5295 Exception (2);
5296 }
5297 #endif
5298
5299 static bool cpu_hardreset, cpu_keyboardreset;
5300
is_hardreset(void)5301 bool is_hardreset(void)
5302 {
5303 return cpu_hardreset;
5304 }
is_keyboardreset(void)5305 bool is_keyboardreset(void)
5306 {
5307 return cpu_keyboardreset;
5308 }
5309
m68k_go(int may_quit)5310 void m68k_go (int may_quit)
5311 {
5312 int hardboot = 1;
5313 int startup = 1;
5314
5315 #ifdef WITH_THREADED_CPU
5316 init_cpu_thread();
5317 #endif
5318 if (in_m68k_go || !may_quit) {
5319 write_log (_T("Bug! m68k_go is not reentrant.\n"));
5320 abort ();
5321 }
5322
5323 reset_frame_rate_hack ();
5324 update_68k_cycles ();
5325 start_cycles = 0;
5326
5327 set_cpu_tracer (false);
5328
5329 cpu_prefs_changed_flag = 0;
5330 in_m68k_go++;
5331 for (;;) {
5332 void (*run_func)(void);
5333
5334 cputrace.state = -1;
5335
5336 if (currprefs.inprecfile[0] && input_play) {
5337 inprec_open (currprefs.inprecfile, NULL);
5338 changed_prefs.inprecfile[0] = currprefs.inprecfile[0] = 0;
5339 quit_program = UAE_RESET;
5340 }
5341 if (input_play || input_record)
5342 inprec_startup ();
5343
5344 if (quit_program > 0) {
5345 int restored = 0;
5346 cpu_keyboardreset = quit_program == UAE_RESET_KEYBOARD;
5347 cpu_hardreset = ((quit_program == UAE_RESET_HARD ? 1 : 0) | hardboot) != 0;
5348
5349 if (quit_program == UAE_QUIT)
5350 break;
5351
5352 hsync_counter = 0;
5353 vsync_counter = 0;
5354 quit_program = 0;
5355 hardboot = 0;
5356
5357 #ifdef SAVESTATE
5358 if (savestate_state == STATE_DORESTORE)
5359 savestate_state = STATE_RESTORE;
5360 if (savestate_state == STATE_RESTORE)
5361 restore_state (savestate_fname);
5362 else if (savestate_state == STATE_REWIND)
5363 savestate_rewind ();
5364 #endif
5365 set_cycles (start_cycles);
5366 custom_reset (cpu_hardreset != 0, cpu_keyboardreset);
5367 m68k_reset2 (cpu_hardreset != 0);
5368 if (cpu_hardreset) {
5369 memory_clear ();
5370 write_log (_T("hardreset, memory cleared\n"));
5371 }
5372 cpu_hardreset = false;
5373 #ifdef SAVESTATE
5374 /* We may have been restoring state, but we're done now. */
5375 if (isrestore ()) {
5376 if (debug_dma) {
5377 record_dma_reset ();
5378 record_dma_reset ();
5379 }
5380 savestate_restore_finish ();
5381 memory_map_dump ();
5382 if (currprefs.mmu_model == 68030) {
5383 mmu030_decode_tc (tc_030);
5384 } else if (currprefs.mmu_model >= 68040) {
5385 mmu_set_tc (regs.tcr);
5386 }
5387 startup = 1;
5388 restored = 1;
5389 }
5390 #endif
5391 if (currprefs.produce_sound == 0)
5392 eventtab[ev_audio].active = 0;
5393 m68k_setpc_normal (regs.pc);
5394 check_prefs_changed_audio ();
5395 #ifdef SAVESTATE
5396 if (!restored || hsync_counter == 0)
5397 savestate_check ();
5398 if (input_record == INPREC_RECORD_START)
5399 input_record = INPREC_RECORD_NORMAL;
5400 #endif
5401 statusline_clear();
5402 } else {
5403 #ifdef SAVESTATE
5404 if (input_record == INPREC_RECORD_START) {
5405 input_record = INPREC_RECORD_NORMAL;
5406 savestate_init ();
5407 hsync_counter = 0;
5408 vsync_counter = 0;
5409 savestate_check ();
5410 }
5411 #endif
5412 }
5413
5414 #ifdef SAVESTATE
5415 if (changed_prefs.inprecfile[0] && input_record)
5416 inprec_prepare_record (savestate_fname[0] ? savestate_fname : NULL);
5417 #endif
5418
5419 set_cpu_tracer (false);
5420
5421 #ifdef DEBUGGER
5422 if (debugging)
5423 debug ();
5424 #endif
5425 if (regs.spcflags & SPCFLAG_MODE_CHANGE) {
5426 if (cpu_prefs_changed_flag & 1) {
5427 uaecptr pc = m68k_getpc();
5428 prefs_changed_cpu();
5429 build_cpufunctbl();
5430 m68k_setpc_normal(pc);
5431 fill_prefetch();
5432 }
5433 if (cpu_prefs_changed_flag & 2) {
5434 fixup_cpu(&changed_prefs);
5435 currprefs.m68k_speed = changed_prefs.m68k_speed;
5436 currprefs.m68k_speed_throttle = changed_prefs.m68k_speed_throttle;
5437 update_68k_cycles();
5438 }
5439 cpu_prefs_changed_flag = 0;
5440 }
5441
5442 set_x_funcs();
5443 if (startup) {
5444 custom_prepare ();
5445 protect_roms (true);
5446 }
5447 startup = 0;
5448 event_wait = true;
5449 unset_special(SPCFLAG_MODE_CHANGE);
5450
5451 if (regs.halted) {
5452 cpu_halt (regs.halted);
5453 if (regs.halted < 0) {
5454 haltloop();
5455 continue;
5456 }
5457 }
5458
5459 #if 0
5460 if (mmu_enabled && !currprefs.cachesize) {
5461 run_func = m68k_run_mmu;
5462 } else {
5463 #endif
5464 run_func = currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68010 ? m68k_run_1_ce :
5465 currprefs.cpu_compatible && currprefs.cpu_model <= 68010 ? m68k_run_1 :
5466 #ifdef JIT
5467 currprefs.cpu_model >= 68020 && currprefs.cachesize ? m68k_run_jit :
5468 #endif
5469 #ifdef CPUEMU_32
5470 currprefs.cpu_model == 68030 && currprefs.mmu_model ? m68k_run_mmu030 :
5471 #endif
5472 #ifdef CPUEMU_31
5473 currprefs.cpu_model == 68040 && currprefs.mmu_model ? m68k_run_mmu040 :
5474 #endif
5475 #ifdef CPUEMU_33
5476 currprefs.cpu_model == 68060 && currprefs.mmu_model ? m68k_run_mmu060 :
5477 #endif
5478 #if defined CPUEMU_24 || defined CPUEMU_25
5479 currprefs.cpu_model >= 68040 && currprefs.cpu_cycle_exact ? m68k_run_3ce :
5480 #endif
5481 #if defined CPUEMU_21 || defined CPUEMU_23
5482 currprefs.cpu_model >= 68020 && currprefs.cpu_cycle_exact ? m68k_run_2ce :
5483 #endif
5484 #ifdef CPUEMU_20
5485 currprefs.cpu_model <= 68020 && currprefs.cpu_compatible ? m68k_run_2p :
5486 #endif
5487 #ifdef CPUEMU_22
5488 currprefs.cpu_model == 68030 && currprefs.cpu_compatible ? m68k_run_2p :
5489 #endif
5490 #ifdef CPUEMU_0
5491 currprefs.cpu_model >= 68040 && currprefs.cpu_compatible ? m68k_run_3p :
5492 #endif
5493 m68k_run_2;
5494 #if 0
5495 }
5496 #endif
5497 run_func();
5498 }
5499 protect_roms (false);
5500 in_m68k_go--;
5501 }
5502
5503 #if 0
5504 static void m68k_verify (uaecptr addr, uaecptr *nextpc)
5505 {
5506 uae_u16 opcode, val;
5507 struct instr *dp;
5508
5509 opcode = get_iword_1 (0);
5510 last_op_for_exception_3 = opcode;
5511 m68kpc_offset = 2;
5512
5513 if (cpufunctbl[opcode] == op_illg_1) {
5514 opcode = 0x4AFC;
5515 }
5516 dp = table68k + opcode;
5517
5518 if (dp->suse) {
5519 if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
5520 Exception (3, 0);
5521 return;
5522 }
5523 }
5524 if (dp->duse) {
5525 if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
5526 Exception (3, 0);
5527 return;
5528 }
5529 }
5530 }
5531 #endif
5532
5533 static const TCHAR *ccnames[] =
5534 {
5535 _T("T "),_T("F "),_T("HI"),_T("LS"),_T("CC"),_T("CS"),_T("NE"),_T("EQ"),
5536 _T("VC"),_T("VS"),_T("PL"),_T("MI"),_T("GE"),_T("LT"),_T("GT"),_T("LE")
5537 };
5538 static const TCHAR *fpccnames[] =
5539 {
5540 _T("F"),
5541 _T("EQ"),
5542 _T("OGT"),
5543 _T("OGE"),
5544 _T("OLT"),
5545 _T("OLE"),
5546 _T("OGL"),
5547 _T("OR"),
5548 _T("UN"),
5549 _T("UEQ"),
5550 _T("UGT"),
5551 _T("UGE"),
5552 _T("ULT"),
5553 _T("ULE"),
5554 _T("NE"),
5555 _T("T"),
5556 _T("SF"),
5557 _T("SEQ"),
5558 _T("GT"),
5559 _T("GE"),
5560 _T("LT"),
5561 _T("LE"),
5562 _T("GL"),
5563 _T("GLE"),
5564 _T("NGLE"),
5565 _T("NGL"),
5566 _T("NLE"),
5567 _T("NLT"),
5568 _T("NGE"),
5569 _T("NGT"),
5570 _T("SNE"),
5571 _T("ST")
5572 };
5573 static const TCHAR *fpuopcodes[] =
5574 {
5575 _T("FMOVE"),
5576 _T("FINT"),
5577 _T("FSINH"),
5578 _T("FINTRZ"),
5579 _T("FSQRT"),
5580 NULL,
5581 _T("FLOGNP1"),
5582 NULL,
5583 _T("FETOXM1"),
5584 _T("FTANH"),
5585 _T("FATAN"),
5586 NULL,
5587 _T("FASIN"),
5588 _T("FATANH"),
5589 _T("FSIN"),
5590 _T("FTAN"),
5591 _T("FETOX"), // 0x10
5592 _T("FTWOTOX"),
5593 _T("FTENTOX"),
5594 NULL,
5595 _T("FLOGN"),
5596 _T("FLOG10"),
5597 _T("FLOG2"),
5598 NULL,
5599 _T("FABS"),
5600 _T("FCOSH"),
5601 _T("FNEG"),
5602 NULL,
5603 _T("FACOS"),
5604 _T("FCOS"),
5605 _T("FGETEXP"),
5606 _T("FGETMAN"),
5607 _T("FDIV"), // 0x20
5608 _T("FMOD"),
5609 _T("FADD"),
5610 _T("FMUL"),
5611 _T("FSGLDIV"),
5612 _T("FREM"),
5613 _T("FSCALE"),
5614 _T("FSGLMUL"),
5615 _T("FSUB"),
5616 NULL,
5617 NULL,
5618 NULL,
5619 NULL,
5620 NULL,
5621 NULL,
5622 NULL,
5623 _T("FSINCOS"), // 0x30
5624 _T("FSINCOS"),
5625 _T("FSINCOS"),
5626 _T("FSINCOS"),
5627 _T("FSINCOS"),
5628 _T("FSINCOS"),
5629 _T("FSINCOS"),
5630 _T("FSINCOS"),
5631 _T("FCMP"),
5632 NULL,
5633 _T("FTST"),
5634 NULL,
5635 NULL,
5636 NULL,
5637 NULL,
5638 NULL
5639 };
5640
5641 static const TCHAR *movemregs[] =
5642 {
5643 _T("D0"),
5644 _T("D1"),
5645 _T("D2"),
5646 _T("D3"),
5647 _T("D4"),
5648 _T("D5"),
5649 _T("D6"),
5650 _T("D7"),
5651 _T("A0"),
5652 _T("A1"),
5653 _T("A2"),
5654 _T("A3"),
5655 _T("A4"),
5656 _T("A5"),
5657 _T("A6"),
5658 _T("A7"),
5659 _T("FP0"),
5660 _T("FP1"),
5661 _T("FP2"),
5662 _T("FP3"),
5663 _T("FP4"),
5664 _T("FP5"),
5665 _T("FP6"),
5666 _T("FP7"),
5667 _T("FPIAR"),
5668 _T("FPSR"),
5669 _T("FPCR")
5670 };
5671
addmovemreg(TCHAR * out,int * prevreg,int * lastreg,int * first,int reg,int fpmode)5672 static void addmovemreg (TCHAR *out, int *prevreg, int *lastreg, int *first, int reg, int fpmode)
5673 {
5674 TCHAR *p = out + _tcslen (out);
5675 if (*prevreg < 0) {
5676 *prevreg = reg;
5677 *lastreg = reg;
5678 return;
5679 }
5680 if (reg < 0 || fpmode == 2 || (*prevreg) + 1 != reg || (reg & 8) != ((*prevreg & 8))) {
5681 _stprintf (p, _T("%s%s"), (*first) ? _T("") : _T("/"), movemregs[*lastreg]);
5682 p = p + _tcslen (p);
5683 if (*lastreg != *prevreg) {
5684 if ((*lastreg) + 2 == reg) {
5685 _stprintf(p, _T("/%s"), movemregs[*prevreg]);
5686 } else if ((*lastreg) != (*prevreg)) {
5687 _stprintf(p, _T("-%s"), movemregs[*prevreg]);
5688 }
5689 }
5690 *lastreg = reg;
5691 *first = 0;
5692 }
5693 *prevreg = reg;
5694 }
5695
movemout(TCHAR * out,uae_u16 mask,int mode,int fpmode)5696 static void movemout (TCHAR *out, uae_u16 mask, int mode, int fpmode)
5697 {
5698 unsigned int dmask, amask;
5699 int prevreg = -1, lastreg = -1, first = 1;
5700
5701 if (mode == Apdi && !fpmode) {
5702 uae_u8 dmask2;
5703 uae_u8 amask2;
5704
5705 amask2 = mask & 0xff;
5706 dmask2 = (mask >> 8) & 0xff;
5707 dmask = 0;
5708 amask = 0;
5709 for (int i = 0; i < 8; i++) {
5710 if (dmask2 & (1 << i))
5711 dmask |= 1 << (7 - i);
5712 if (amask2 & (1 << i))
5713 amask |= 1 << (7 - i);
5714 }
5715 } else {
5716 dmask = mask & 0xff;
5717 amask = (mask >> 8) & 0xff;
5718 if (fpmode == 1 && mode != Apdi) {
5719 uae_u8 dmask2 = dmask;
5720 dmask = 0;
5721 for (int i = 0; i < 8; i++) {
5722 if (dmask2 & (1 << i))
5723 dmask |= 1 << (7 - i);
5724 }
5725 }
5726 }
5727 if (fpmode) {
5728 while (dmask) { addmovemreg(out, &prevreg, &lastreg, &first, movem_index1[dmask] + (fpmode == 2 ? 24 : 16), fpmode); dmask = movem_next[dmask]; }
5729 } else {
5730 while (dmask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[dmask], fpmode); dmask = movem_next[dmask]; }
5731 while (amask) { addmovemreg (out, &prevreg, &lastreg, &first, movem_index1[amask] + 8, fpmode); amask = movem_next[amask]; }
5732 }
5733 addmovemreg(out, &prevreg, &lastreg, &first, -1, fpmode);
5734 }
5735
5736 static const TCHAR *fpsizes[] = {
5737 _T("L"),
5738 _T("S"),
5739 _T("X"),
5740 _T("P"),
5741 _T("W"),
5742 _T("D"),
5743 _T("B"),
5744 _T("P")
5745 };
5746 static const int fpsizeconv[] = {
5747 sz_long,
5748 sz_single,
5749 sz_extended,
5750 sz_packed,
5751 sz_word,
5752 sz_double,
5753 sz_byte,
5754 sz_packed
5755 };
5756
disasm_size(TCHAR * instrname,struct instr * dp)5757 static void disasm_size (TCHAR *instrname, struct instr *dp)
5758 {
5759 if (dp->unsized) {
5760 _tcscat(instrname, _T(" "));
5761 return;
5762 }
5763 switch (dp->size)
5764 {
5765 case sz_byte:
5766 _tcscat (instrname, _T(".B "));
5767 break;
5768 case sz_word:
5769 _tcscat (instrname, _T(".W "));
5770 break;
5771 case sz_long:
5772 _tcscat (instrname, _T(".L "));
5773 break;
5774 default:
5775 _tcscat (instrname, _T(" "));
5776 break;
5777 }
5778 }
5779
m68k_disasm_2(TCHAR * buf,int bufsize,uaecptr pc,uaecptr * nextpc,int cnt,uae_u32 * seaddr,uae_u32 * deaddr,int safemode)5780 void m68k_disasm_2 (TCHAR *buf, int bufsize, uaecptr pc, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
5781 {
5782 uae_u32 seaddr2;
5783 uae_u32 deaddr2;
5784
5785 if (buf)
5786 memset (buf, 0, bufsize * sizeof (TCHAR));
5787 if (!table68k)
5788 return;
5789 while (cnt-- > 0) {
5790 TCHAR instrname[100], *ccpt;
5791 int i;
5792 uae_u32 opcode;
5793 uae_u16 extra;
5794 struct mnemolookup *lookup;
5795 struct instr *dp;
5796 uaecptr oldpc;
5797 uaecptr m68kpc_illg = 0;
5798 bool illegal = false;
5799
5800 seaddr2 = deaddr2 = 0;
5801 oldpc = pc;
5802 opcode = get_word_debug (pc);
5803 extra = get_word_debug (pc + 2);
5804 if (cpufunctbl[opcode] == op_illg_1 || cpufunctbl[opcode] == op_unimpl_1) {
5805 m68kpc_illg = pc + 2;
5806 illegal = TRUE;
5807 }
5808
5809 dp = table68k + opcode;
5810 if (dp->mnemo == i_ILLG) {
5811 illegal = FALSE;
5812 opcode = 0x4AFC;
5813 dp = table68k + opcode;
5814 }
5815 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
5816 ;
5817
5818 buf = buf_out (buf, &bufsize, _T("%08X "), pc);
5819
5820 pc += 2;
5821
5822 if (lookup->friendlyname)
5823 _tcscpy (instrname, lookup->friendlyname);
5824 else
5825 _tcscpy (instrname, lookup->name);
5826 ccpt = _tcsstr (instrname, _T("cc"));
5827 if (ccpt != 0) {
5828 if ((opcode & 0xf000) == 0xf000)
5829 _tcscpy (ccpt, fpccnames[extra & 0x1f]);
5830 else
5831 _tcsncpy (ccpt, ccnames[dp->cc], 2);
5832 }
5833 disasm_size (instrname, dp);
5834
5835 if (lookup->mnemo == i_MOVEC2 || lookup->mnemo == i_MOVE2C) {
5836 uae_u16 imm = extra;
5837 uae_u16 creg = imm & 0x0fff;
5838 uae_u16 r = imm >> 12;
5839 TCHAR regs[16];
5840 const TCHAR *cname = _T("?");
5841 int i;
5842 for (i = 0; m2cregs[i].regname; i++) {
5843 if (m2cregs[i].regno == creg)
5844 break;
5845 }
5846 _stprintf (regs, _T("%c%d"), r >= 8 ? 'A' : 'D', r >= 8 ? r - 8 : r);
5847 if (m2cregs[i].regname)
5848 cname = m2cregs[i].regname;
5849 if (lookup->mnemo == i_MOVE2C) {
5850 _tcscat (instrname, regs);
5851 _tcscat (instrname, _T(","));
5852 _tcscat (instrname, cname);
5853 } else {
5854 _tcscat (instrname, cname);
5855 _tcscat (instrname, _T(","));
5856 _tcscat (instrname, regs);
5857 }
5858 pc += 2;
5859 } else if (lookup->mnemo == i_MVMEL) {
5860 uae_u16 mask = extra;
5861 pc += 2;
5862 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
5863 _tcscat (instrname, _T(","));
5864 movemout (instrname, mask, dp->dmode, 0);
5865 } else if (lookup->mnemo == i_MVMLE) {
5866 uae_u16 mask = extra;
5867 pc += 2;
5868 movemout(instrname, mask, dp->dmode, 0);
5869 _tcscat(instrname, _T(","));
5870 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
5871 } else if (lookup->mnemo == i_DIVL || lookup->mnemo == i_MULL) {
5872 TCHAR *p;
5873 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
5874 extra = get_word_debug(pc);
5875 pc += 2;
5876 p = instrname + _tcslen(instrname);
5877 if (extra & 0x0400)
5878 _stprintf(p, _T(",D%d:D%d"), extra & 7, (extra >> 12) & 7);
5879 else
5880 _stprintf(p, _T(",D%d"), (extra >> 12) & 7);
5881 } else if (lookup->mnemo == i_MOVES) {
5882 TCHAR *p;
5883 pc += 2;
5884 if (!(extra & 0x1000)) {
5885 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
5886 p = instrname + _tcslen(instrname);
5887 _stprintf(p, _T(",%c%d"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
5888 } else {
5889 p = instrname + _tcslen(instrname);
5890 _stprintf(p, _T("%c%d,"), (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7);
5891 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
5892 }
5893 } else if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU ||
5894 lookup->mnemo == i_BFCHG || lookup->mnemo == i_BFCLR ||
5895 lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS ||
5896 lookup->mnemo == i_BFSET || lookup->mnemo == i_BFTST) {
5897 TCHAR *p;
5898 int reg = -1;
5899
5900 pc += 2;
5901 p = instrname + _tcslen(instrname);
5902 if (lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU || lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFINS)
5903 reg = (extra >> 12) & 7;
5904 if (lookup->mnemo == i_BFINS)
5905 _stprintf(p, _T("D%d,"), reg);
5906 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &seaddr2, safemode);
5907 _tcscat(instrname, _T(" {"));
5908 p = instrname + _tcslen(instrname);
5909 if (extra & 0x0800)
5910 _stprintf(p, _T("D%d"), (extra >> 6) & 7);
5911 else
5912 _stprintf(p, _T("%d"), (extra >> 6) & 31);
5913 _tcscat(instrname, _T(":"));
5914 p = instrname + _tcslen(instrname);
5915 if (extra & 0x0020)
5916 _stprintf(p, _T("D%d"), extra & 7);
5917 else
5918 _stprintf(p, _T("%d"), extra & 31);
5919 _tcscat(instrname, _T("}"));
5920 p = instrname + _tcslen(instrname);
5921 if (lookup->mnemo == i_BFFFO || lookup->mnemo == i_BFEXTS || lookup->mnemo == i_BFEXTU)
5922 _stprintf(p, _T(",D%d"), reg);
5923 } else if (lookup->mnemo == i_CPUSHA || lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP ||
5924 lookup->mnemo == i_CINVA || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
5925 if ((opcode & 0xc0) == 0xc0)
5926 _tcscat(instrname, _T("BC"));
5927 else if (opcode & 0x80)
5928 _tcscat(instrname, _T("IC"));
5929 else if (opcode & 0x40)
5930 _tcscat(instrname, _T("DC"));
5931 else
5932 _tcscat(instrname, _T("?"));
5933 if (lookup->mnemo == i_CPUSHL || lookup->mnemo == i_CPUSHP || lookup->mnemo == i_CINVL || lookup->mnemo == i_CINVP) {
5934 TCHAR *p = instrname + _tcslen(instrname);
5935 _stprintf(p, _T(",(A%d)"), opcode & 7);
5936 }
5937 } else if (lookup->mnemo == i_FPP) {
5938 TCHAR *p;
5939 int ins = extra & 0x3f;
5940 int size = (extra >> 10) & 7;
5941
5942 pc += 2;
5943 if ((extra & 0xfc00) == 0x5c00) { // FMOVECR (=i_FPP with source specifier = 7)
5944 fpdata fp;
5945 if (fpu_get_constant(&fp, extra))
5946 #if USE_LONG_DOUBLE
5947 _stprintf(instrname, _T("FMOVECR.X #%Le,FP%d"), fp.fp, (extra >> 7) & 7);
5948 #else
5949 _stprintf(instrname, _T("FMOVECR.X #%e,FP%d"), fp.fp, (extra >> 7) & 7);
5950 #endif
5951 else
5952 _stprintf(instrname, _T("FMOVECR.X #?,FP%d"), (extra >> 7) & 7);
5953 } else if ((extra & 0x8000) == 0x8000) { // FMOVEM
5954 int dr = (extra >> 13) & 1;
5955 int mode;
5956 int dreg = (extra >> 4) & 7;
5957 int regmask, fpmode;
5958
5959 if (extra & 0x4000) {
5960 mode = (extra >> 11) & 3;
5961 regmask = extra & 0xff; // FMOVEM FPx
5962 fpmode = 1;
5963 _tcscpy(instrname, _T("FMOVEM.X "));
5964 } else {
5965 mode = 0;
5966 regmask = (extra >> 10) & 7; // FMOVEM control
5967 fpmode = 2;
5968 _tcscpy(instrname, _T("FMOVEM.L "));
5969 if (regmask == 1 || regmask == 2 || regmask == 4)
5970 _tcscpy(instrname, _T("FMOVE.L "));
5971 }
5972 p = instrname + _tcslen(instrname);
5973 if (dr) {
5974 if (mode & 1)
5975 _stprintf(instrname, _T("D%d"), dreg);
5976 else
5977 movemout(instrname, regmask, dp->dmode, fpmode);
5978 _tcscat(instrname, _T(","));
5979 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
5980 } else {
5981 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
5982 _tcscat(instrname, _T(","));
5983 p = instrname + _tcslen(instrname);
5984 if (mode & 1)
5985 _stprintf(p, _T("D%d"), dreg);
5986 else
5987 movemout(p, regmask, dp->dmode, fpmode);
5988 }
5989 } else {
5990 if (fpuopcodes[ins])
5991 _tcscpy(instrname, fpuopcodes[ins]);
5992 else
5993 _tcscpy(instrname, _T("F?"));
5994
5995 if ((extra & 0xe000) == 0x6000) { // FMOVE to memory
5996 int kfactor = extra & 0x7f;
5997 _tcscpy(instrname, _T("FMOVE."));
5998 _tcscat(instrname, fpsizes[size]);
5999 _tcscat(instrname, _T(" "));
6000 p = instrname + _tcslen(instrname);
6001 _stprintf(p, _T("FP%d,"), (extra >> 7) & 7);
6002 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &deaddr2, safemode);
6003 p = instrname + _tcslen(instrname);
6004 if (size == 7) {
6005 _stprintf(p, _T(" {D%d}"), (kfactor >> 4));
6006 } else if (kfactor) {
6007 if (kfactor & 0x40)
6008 kfactor |= ~0x3f;
6009 _stprintf(p, _T(" {%d}"), kfactor);
6010 }
6011 } else {
6012 if (extra & 0x4000) { // source is EA
6013 _tcscat(instrname, _T("."));
6014 _tcscat(instrname, fpsizes[size]);
6015 _tcscat(instrname, _T(" "));
6016 pc = ShowEA(0, pc, opcode, dp->dreg, dp->dmode, fpsizeconv[size], instrname, &seaddr2, safemode);
6017 } else { // source is FPx
6018 p = instrname + _tcslen(instrname);
6019 _stprintf(p, _T(".X FP%d"), (extra >> 10) & 7);
6020 }
6021 p = instrname + _tcslen(instrname);
6022 if ((extra & 0x4000) || (((extra >> 7) & 7) != ((extra >> 10) & 7)))
6023 _stprintf(p, _T(",FP%d"), (extra >> 7) & 7);
6024 if (ins >= 0x30 && ins < 0x38) { // FSINCOS
6025 p = instrname + _tcslen(instrname);
6026 _stprintf(p, _T(",FP%d"), extra & 7);
6027 }
6028 }
6029 }
6030 } else if ((opcode & 0xf000) == 0xa000) {
6031 _tcscpy(instrname, _T("A-LINE"));
6032 } else {
6033 if (dp->suse) {
6034 pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, &seaddr2, safemode);
6035 }
6036 if (dp->suse && dp->duse)
6037 _tcscat (instrname, _T(","));
6038 if (dp->duse) {
6039 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, &deaddr2, safemode);
6040 }
6041 }
6042
6043 for (i = 0; i < (pc - oldpc) / 2 && i < 5; i++) {
6044 buf = buf_out (buf, &bufsize, _T("%04x "), get_word_debug (oldpc + i * 2));
6045 }
6046 while (i++ < 5)
6047 buf = buf_out (buf, &bufsize, _T(" "));
6048
6049 if (illegal)
6050 buf = buf_out (buf, &bufsize, _T("[ "));
6051 buf = buf_out (buf, &bufsize, instrname);
6052 if (illegal)
6053 buf = buf_out (buf, &bufsize, _T(" ]"));
6054
6055 if (ccpt != 0) {
6056 uaecptr addr2 = deaddr2 ? deaddr2 : seaddr2;
6057 if (deaddr)
6058 *deaddr = pc;
6059 if ((opcode & 0xf000) == 0xf000) {
6060 if (fpp_cond(dp->cc)) {
6061 buf = buf_out(buf, &bufsize, _T(" == $%08x (T)"), addr2);
6062 } else {
6063 buf = buf_out(buf, &bufsize, _T(" == $%08x (F)"), addr2);
6064 }
6065 } else {
6066 if (cctrue (dp->cc)) {
6067 buf = buf_out (buf, &bufsize, _T(" == $%08x (T)"), addr2);
6068 } else {
6069 buf = buf_out (buf, &bufsize, _T(" == $%08x (F)"), addr2);
6070 }
6071 }
6072 } else if ((opcode & 0xff00) == 0x6100) { /* BSR */
6073 if (deaddr)
6074 *deaddr = pc;
6075 buf = buf_out (buf, &bufsize, _T(" == $%08x"), seaddr2);
6076 }
6077 buf = buf_out (buf, &bufsize, _T("\n"));
6078
6079 if (illegal)
6080 pc = m68kpc_illg;
6081 }
6082 if (nextpc)
6083 *nextpc = pc;
6084 if (seaddr)
6085 *seaddr = seaddr2;
6086 if (deaddr)
6087 *deaddr = deaddr2;
6088 }
6089
m68k_disasm_ea(uaecptr addr,uaecptr * nextpc,int cnt,uae_u32 * seaddr,uae_u32 * deaddr)6090 void m68k_disasm_ea (uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
6091 {
6092 TCHAR *buf;
6093
6094 buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
6095 if (!buf)
6096 return;
6097 m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, seaddr, deaddr, 1);
6098 xfree (buf);
6099 }
m68k_disasm(uaecptr addr,uaecptr * nextpc,int cnt)6100 void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
6101 {
6102 TCHAR *buf;
6103
6104 buf = xmalloc (TCHAR, (MAX_LINEWIDTH + 1) * cnt);
6105 if (!buf)
6106 return;
6107 m68k_disasm_2 (buf, (MAX_LINEWIDTH + 1) * cnt, addr, nextpc, cnt, NULL, NULL, 0);
6108 console_out_f (_T("%s"), buf);
6109 xfree (buf);
6110 }
6111
6112 /*************************************************************
6113 Disasm the m68kcode at the given address into instrname
6114 and instrcode
6115 *************************************************************/
sm68k_disasm(TCHAR * instrname,TCHAR * instrcode,uaecptr addr,uaecptr * nextpc)6116 void sm68k_disasm (TCHAR *instrname, TCHAR *instrcode, uaecptr addr, uaecptr *nextpc)
6117 {
6118 TCHAR *ccpt;
6119 uae_u32 opcode;
6120 struct mnemolookup *lookup;
6121 struct instr *dp;
6122 uaecptr pc, oldpc;
6123
6124 pc = oldpc = addr;
6125 opcode = get_word_debug (pc);
6126 if (cpufunctbl[opcode] == op_illg_1) {
6127 opcode = 0x4AFC;
6128 }
6129 dp = table68k + opcode;
6130 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
6131
6132 pc += 2;
6133
6134 _tcscpy (instrname, lookup->name);
6135 ccpt = _tcsstr (instrname, _T("cc"));
6136 if (ccpt != 0) {
6137 _tcsncpy (ccpt, ccnames[dp->cc], 2);
6138 }
6139 switch (dp->size){
6140 case sz_byte: _tcscat (instrname, _T(".B ")); break;
6141 case sz_word: _tcscat (instrname, _T(".W ")); break;
6142 case sz_long: _tcscat (instrname, _T(".L ")); break;
6143 default: _tcscat (instrname, _T(" ")); break;
6144 }
6145
6146 if (dp->suse) {
6147 pc = ShowEA (0, pc, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
6148 }
6149 if (dp->suse && dp->duse)
6150 _tcscat (instrname, _T(","));
6151 if (dp->duse) {
6152 pc = ShowEA (0, pc, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
6153 }
6154 if (instrcode)
6155 {
6156 int i;
6157 for (i = 0; i < (pc - oldpc) / 2; i++)
6158 {
6159 _stprintf (instrcode, _T("%04x "), get_iword_debug (oldpc + i * 2));
6160 instrcode += _tcslen (instrcode);
6161 }
6162 }
6163 if (nextpc)
6164 *nextpc = pc;
6165 }
6166
6167 struct cpum2c m2cregs[] = {
6168 { 0, _T("SFC") },
6169 { 1, _T("DFC") },
6170 { 2, _T("CACR") },
6171 { 3, _T("TC") },
6172 { 4, _T("ITT0") },
6173 { 5, _T("ITT1") },
6174 { 6, _T("DTT0") },
6175 { 7, _T("DTT1") },
6176 { 8, _T("BUSC") },
6177 { 0x800, _T("USP") },
6178 { 0x801, _T("VBR") },
6179 { 0x802, _T("CAAR") },
6180 { 0x803, _T("MSP") },
6181 { 0x804, _T("ISP") },
6182 { 0x805, _T("MMUS") },
6183 { 0x806, _T("URP") },
6184 { 0x807, _T("SRP") },
6185 { 0x808, _T("PCR") },
6186 { -1, NULL }
6187 };
6188
m68k_dumpstate(uaecptr pc,uaecptr * nextpc)6189 void m68k_dumpstate (uaecptr pc, uaecptr *nextpc)
6190 {
6191 int i, j;
6192
6193 for (i = 0; i < 8; i++){
6194 console_out_f (_T(" D%d %08X "), i, m68k_dreg (regs, i));
6195 if ((i & 3) == 3) console_out_f (_T("\n"));
6196 }
6197 for (i = 0; i < 8; i++){
6198 console_out_f (_T(" A%d %08X "), i, m68k_areg (regs, i));
6199 if ((i & 3) == 3) console_out_f (_T("\n"));
6200 }
6201 if (regs.s == 0)
6202 regs.usp = m68k_areg (regs, 7);
6203 if (regs.s && regs.m)
6204 regs.msp = m68k_areg (regs, 7);
6205 if (regs.s && regs.m == 0)
6206 regs.isp = m68k_areg (regs, 7);
6207 j = 2;
6208 console_out_f (_T("USP %08X ISP %08X "), regs.usp, regs.isp);
6209 for (i = 0; m2cregs[i].regno>= 0; i++) {
6210 if (!movec_illg (m2cregs[i].regno)) {
6211 if (!_tcscmp (m2cregs[i].regname, _T("USP")) || !_tcscmp (m2cregs[i].regname, _T("ISP")))
6212 continue;
6213 if (j > 0 && (j % 4) == 0)
6214 console_out_f (_T("\n"));
6215 console_out_f (_T("%-4s %08X "), m2cregs[i].regname, val_move2c (m2cregs[i].regno));
6216 j++;
6217 }
6218 }
6219 if (j > 0)
6220 console_out_f (_T("\n"));
6221 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"),
6222 regs.t1, regs.t0, regs.s, regs.m,
6223 GET_XFLG (), GET_NFLG (), GET_ZFLG (),
6224 GET_VFLG (), GET_CFLG (),
6225 regs.intmask, regs.stopped);
6226 #ifdef FPUEMU
6227 if (currprefs.fpu_model) {
6228 uae_u32 fpsr;
6229 for (i = 0; i < 8; i++){
6230 console_out_f (_T("FP%d: %g "), i, regs.fp[i].fp);
6231 if ((i & 3) == 3)
6232 console_out_f (_T("\n"));
6233 }
6234 fpsr = fpp_get_fpsr ();
6235 console_out_f (_T("FPSR: %04X FPCR: %08x FPIAR: %08x N=%d Z=%d I=%d NAN=%d\n"),
6236 fpsr, regs.fpcr, regs.fpiar,
6237 (fpsr & 0x8000000) != 0,
6238 (fpsr & 0x4000000) != 0,
6239 (fpsr & 0x2000000) != 0,
6240 (fpsr & 0x1000000) != 0);
6241 }
6242 #endif
6243 if (currprefs.mmu_model == 68030) {
6244 console_out_f (_T("SRP: %llX CRP: %llX\n"), srp_030, crp_030);
6245 console_out_f (_T("TT0: %08X TT1: %08X TC: %08X\n"), tt0_030, tt1_030, tc_030);
6246 }
6247 if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
6248 struct instr *dp;
6249 struct mnemolookup *lookup1, *lookup2;
6250 dp = table68k + regs.irc;
6251 for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
6252 dp = table68k + regs.ir;
6253 for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
6254 console_out_f (_T("Prefetch %04x (%s) %04x (%s) Chip latch %08X\n"), regs.irc, lookup1->name, regs.ir, lookup2->name, regs.chipset_latch_rw);
6255 }
6256
6257 if (pc != 0xffffffff) {
6258 m68k_disasm (pc, nextpc, 1);
6259 if (nextpc)
6260 console_out_f (_T("Next PC: %08x\n"), *nextpc);
6261 }
6262 }
m68k_dumpstate(uaecptr * nextpc)6263 void m68k_dumpstate (uaecptr *nextpc)
6264 {
6265 m68k_dumpstate (m68k_getpc (), nextpc);
6266 }
m68k_dumpcache(void)6267 void m68k_dumpcache (void)
6268 {
6269 if (!currprefs.cpu_compatible)
6270 return;
6271 if (currprefs.cpu_model == 68020) {
6272 for (int i = 0; i < CACHELINES020; i += 4) {
6273 for (int j = 0; j < 4; j++) {
6274 int s = i + j;
6275 uaecptr addr;
6276 struct cache020 *c = &caches020[s];
6277 addr = c->tag & ~1;
6278 addr |= s << 2;
6279 console_out_f (_T("%08X:%08X%c "), addr, c->data, c->valid ? '*' : ' ');
6280 }
6281 console_out_f (_T("\n"));
6282 }
6283 } else if (currprefs.cpu_model == 68030) {
6284 for (int i = 0; i < CACHELINES030; i++) {
6285 struct cache030 *c = &icaches030[i];
6286 uaecptr addr;
6287 addr = c->tag & ~1;
6288 addr |= i << 4;
6289 console_out_f (_T("%08X: "), addr);
6290 for (int j = 0; j < 4; j++) {
6291 console_out_f (_T("%08X%c "), c->data[j], c->valid[j] ? '*' : ' ');
6292 }
6293 console_out_f (_T("\n"));
6294 }
6295 }
6296 }
6297
6298 #ifdef SAVESTATE
6299
6300 /* CPU save/restore code */
6301
6302 #define CPUTYPE_EC 1
6303 #define CPUMODE_HALT 1
6304
restore_cpu(uae_u8 * src)6305 uae_u8 *restore_cpu (uae_u8 *src)
6306 {
6307 int i, flags, model;
6308 uae_u32 l;
6309
6310 currprefs.cpu_model = changed_prefs.cpu_model = model = restore_u32 ();
6311 flags = restore_u32 ();
6312 changed_prefs.address_space_24 = 0;
6313 if (flags & CPUTYPE_EC)
6314 changed_prefs.address_space_24 = 1;
6315 currprefs.address_space_24 = changed_prefs.address_space_24;
6316 currprefs.cpu_compatible = changed_prefs.cpu_compatible;
6317 currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
6318 currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact;
6319 currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
6320 currprefs.cpu_frequency = changed_prefs.cpu_frequency = 0;
6321 currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = 0;
6322 for (i = 0; i < 15; i++)
6323 regs.regs[i] = restore_u32 ();
6324 regs.pc = restore_u32 ();
6325 regs.irc = restore_u16 ();
6326 regs.ir = restore_u16 ();
6327 regs.usp = restore_u32 ();
6328 regs.isp = restore_u32 ();
6329 regs.sr = restore_u16 ();
6330 l = restore_u32 ();
6331 if (l & CPUMODE_HALT) {
6332 regs.stopped = 1;
6333 } else {
6334 regs.stopped = 0;
6335 }
6336 if (model >= 68010) {
6337 regs.dfc = restore_u32 ();
6338 regs.sfc = restore_u32 ();
6339 regs.vbr = restore_u32 ();
6340 }
6341 if (model >= 68020) {
6342 regs.caar = restore_u32 ();
6343 regs.cacr = restore_u32 ();
6344 regs.msp = restore_u32 ();
6345 }
6346 if (model >= 68030) {
6347 crp_030 = fake_crp_030 = restore_u64 ();
6348 srp_030 = fake_srp_030 = restore_u64 ();
6349 tt0_030 = fake_tt0_030 = restore_u32 ();
6350 tt1_030 = fake_tt1_030 = restore_u32 ();
6351 tc_030 = fake_tc_030 = restore_u32 ();
6352 mmusr_030 = fake_mmusr_030 = restore_u16 ();
6353 }
6354 if (model >= 68040) {
6355 regs.itt0 = restore_u32 ();
6356 regs.itt1 = restore_u32 ();
6357 regs.dtt0 = restore_u32 ();
6358 regs.dtt1 = restore_u32 ();
6359 regs.tcr = restore_u32 ();
6360 regs.urp = restore_u32 ();
6361 regs.srp = restore_u32 ();
6362 }
6363 if (model >= 68060) {
6364 regs.buscr = restore_u32 ();
6365 regs.pcr = restore_u32 ();
6366 }
6367 if (flags & 0x80000000) {
6368 int khz = restore_u32 ();
6369 restore_u32 ();
6370 if (khz > 0 && khz < 800000)
6371 currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
6372 }
6373 set_cpu_caches (true);
6374 if (flags & 0x40000000) {
6375 if (model == 68020) {
6376 for (int i = 0; i < CACHELINES020; i++) {
6377 caches020[i].data = restore_u32 ();
6378 caches020[i].tag = restore_u32 ();
6379 caches020[i].valid = restore_u8 () != 0;
6380 }
6381 regs.prefetch020addr = restore_u32 ();
6382 regs.cacheholdingaddr020 = restore_u32 ();
6383 regs.cacheholdingdata020 = restore_u32 ();
6384 if (flags & 0x20000000) {
6385 // 2.7.0 new
6386 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6387 regs.prefetch020[i] = restore_u32 ();
6388 } else {
6389 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6390 regs.prefetch020[i] = restore_u16 ();
6391 }
6392 } else if (model == 68030) {
6393 for (int i = 0; i < CACHELINES030; i++) {
6394 for (int j = 0; j < 4; j++) {
6395 icaches030[i].data[j] = restore_u32 ();
6396 icaches030[i].valid[j] = restore_u8 () != 0;
6397 }
6398 icaches030[i].tag = restore_u32 ();
6399 }
6400 for (int i = 0; i < CACHELINES030; i++) {
6401 for (int j = 0; j < 4; j++) {
6402 dcaches030[i].data[j] = restore_u32 ();
6403 dcaches030[i].valid[j] = restore_u8 () != 0;
6404 }
6405 dcaches030[i].tag = restore_u32 ();
6406 }
6407 regs.prefetch020addr = restore_u32 ();
6408 regs.cacheholdingaddr020 = restore_u32 ();
6409 regs.cacheholdingdata020 = restore_u32 ();
6410 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6411 regs.prefetch020[i] = restore_u32 ();
6412 } else if (model == 68040) {
6413 if (flags & 0x8000000) {
6414 for (int i = 0; i < CACHESETS040; i++) {
6415 for (int j = 0; j < CACHELINES040; j++) {
6416 icaches040[i].data[j][0] = restore_u32();
6417 icaches040[i].data[j][1] = restore_u32();
6418 icaches040[i].data[j][2] = restore_u32();
6419 icaches040[i].data[j][3] = restore_u32();
6420 icaches040[i].tag[j] = restore_u32();
6421 icaches040[i].valid[j] = restore_u16() & 1;
6422 }
6423 }
6424 regs.prefetch020addr = restore_u32();
6425 regs.cacheholdingaddr020 = restore_u32();
6426 regs.cacheholdingdata020 = restore_u32();
6427 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6428 regs.prefetch020[i] = restore_u32();
6429 }
6430 }
6431 if (model >= 68020) {
6432 regs.ce020memcycles = restore_u32 ();
6433 restore_u32 ();
6434 }
6435 }
6436 if (flags & 0x10000000) {
6437 regs.chipset_latch_rw = restore_u32 ();
6438 regs.chipset_latch_read = restore_u32 ();
6439 regs.chipset_latch_write = restore_u32 ();
6440 }
6441
6442 m68k_reset_sr();
6443
6444 write_log (_T("CPU: %d%s%03d, PC=%08X\n"),
6445 model / 1000, flags & 1 ? _T("EC") : _T(""), model % 1000, regs.pc);
6446
6447 return src;
6448 }
6449
fill_prefetch_quick(void)6450 static void fill_prefetch_quick (void)
6451 {
6452 if (currprefs.cpu_model >= 68020) {
6453 fill_prefetch ();
6454 return;
6455 }
6456 // old statefile compatibility, this needs to done,
6457 // even in 68000 cycle-exact mode
6458 regs.ir = get_word (m68k_getpc ());
6459 regs.irc = get_word (m68k_getpc () + 2);
6460 }
6461
restore_cpu_finish(void)6462 void restore_cpu_finish (void)
6463 {
6464 init_m68k ();
6465 m68k_setpc_normal (regs.pc);
6466 doint ();
6467 fill_prefetch_quick ();
6468 set_cycles (start_cycles);
6469 events_schedule ();
6470 if (regs.stopped)
6471 set_special (SPCFLAG_STOP);
6472 //activate_debugger ();
6473 }
6474
save_cpu_trace(int * len,uae_u8 * dstptr)6475 uae_u8 *save_cpu_trace (int *len, uae_u8 *dstptr)
6476 {
6477 uae_u8 *dstbak, *dst;
6478
6479 if (cputrace.state <= 0)
6480 return NULL;
6481
6482 if (dstptr)
6483 dstbak = dst = dstptr;
6484 else
6485 dstbak = dst = xmalloc (uae_u8, 10000);
6486
6487 save_u32 (2 | 4 | 8);
6488 save_u16 (cputrace.opcode);
6489 for (int i = 0; i < 16; i++)
6490 save_u32 (cputrace.regs[i]);
6491 save_u32 (cputrace.pc);
6492 save_u16 (cputrace.irc);
6493 save_u16 (cputrace.ir);
6494 save_u32 (cputrace.usp);
6495 save_u32 (cputrace.isp);
6496 save_u16 (cputrace.sr);
6497 save_u16 (cputrace.intmask);
6498 save_u16 ((cputrace.stopped ? 1 : 0) | (regs.stopped ? 2 : 0));
6499 save_u16 (cputrace.state);
6500 save_u32 (cputrace.cyclecounter);
6501 save_u32 (cputrace.cyclecounter_pre);
6502 save_u32 (cputrace.cyclecounter_post);
6503 save_u32 (cputrace.readcounter);
6504 save_u32 (cputrace.writecounter);
6505 save_u32 (cputrace.memoryoffset);
6506 write_log (_T("CPUT SAVE: PC=%08x C=%08X %08x %08x %08x %d %d %d\n"),
6507 cputrace.pc, cputrace.startcycles,
6508 cputrace.cyclecounter, cputrace.cyclecounter_pre, cputrace.cyclecounter_post,
6509 cputrace.readcounter, cputrace.writecounter, cputrace.memoryoffset);
6510 for (int i = 0; i < cputrace.memoryoffset; i++) {
6511 save_u32 (cputrace.ctm[i].addr);
6512 save_u32 (cputrace.ctm[i].data);
6513 save_u32 (cputrace.ctm[i].mode);
6514 write_log (_T("CPUT%d: %08x %08x %08x\n"), i, cputrace.ctm[i].addr, cputrace.ctm[i].data, cputrace.ctm[i].mode);
6515 }
6516 save_u32 (cputrace.startcycles);
6517
6518 if (currprefs.cpu_model == 68020) {
6519 for (int i = 0; i < CACHELINES020; i++) {
6520 save_u32 (cputrace.caches020[i].data);
6521 save_u32 (cputrace.caches020[i].tag);
6522 save_u8 (cputrace.caches020[i].valid ? 1 : 0);
6523 }
6524 save_u32 (cputrace.prefetch020addr);
6525 save_u32 (cputrace.cacheholdingaddr020);
6526 save_u32 (cputrace.cacheholdingdata020);
6527 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6528 save_u16 (cputrace.prefetch020[i]);
6529 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6530 save_u32 (cputrace.prefetch020[i]);
6531 }
6532
6533 *len = dst - dstbak;
6534 cputrace.needendcycles = 1;
6535 return dstbak;
6536 }
6537
restore_cpu_trace(uae_u8 * src)6538 uae_u8 *restore_cpu_trace (uae_u8 *src)
6539 {
6540 cpu_tracer = 0;
6541 cputrace.state = 0;
6542 uae_u32 v = restore_u32 ();
6543 if (!(v & 2))
6544 return src;
6545 cputrace.opcode = restore_u16 ();
6546 for (int i = 0; i < 16; i++)
6547 cputrace.regs[i] = restore_u32 ();
6548 cputrace.pc = restore_u32 ();
6549 cputrace.irc = restore_u16 ();
6550 cputrace.ir = restore_u16 ();
6551 cputrace.usp = restore_u32 ();
6552 cputrace.isp = restore_u32 ();
6553 cputrace.sr = restore_u16 ();
6554 cputrace.intmask = restore_u16 ();
6555 cputrace.stopped = restore_u16 ();
6556 cputrace.state = restore_u16 ();
6557 cputrace.cyclecounter = restore_u32 ();
6558 cputrace.cyclecounter_pre = restore_u32 ();
6559 cputrace.cyclecounter_post = restore_u32 ();
6560 cputrace.readcounter = restore_u32 ();
6561 cputrace.writecounter = restore_u32 ();
6562 cputrace.memoryoffset = restore_u32 ();
6563 for (int i = 0; i < cputrace.memoryoffset; i++) {
6564 cputrace.ctm[i].addr = restore_u32 ();
6565 cputrace.ctm[i].data = restore_u32 ();
6566 cputrace.ctm[i].mode = restore_u32 ();
6567 }
6568 cputrace.startcycles = restore_u32 ();
6569
6570 if (v & 4) {
6571 if (currprefs.cpu_model == 68020) {
6572 for (int i = 0; i < CACHELINES020; i++) {
6573 cputrace.caches020[i].data = restore_u32 ();
6574 cputrace.caches020[i].tag = restore_u32 ();
6575 cputrace.caches020[i].valid = restore_u8 () != 0;
6576 }
6577 cputrace.prefetch020addr = restore_u32 ();
6578 cputrace.cacheholdingaddr020 = restore_u32 ();
6579 cputrace.cacheholdingdata020 = restore_u32 ();
6580 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6581 cputrace.prefetch020[i] = restore_u16 ();
6582 if (v & 8) {
6583 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6584 cputrace.prefetch020[i] = restore_u32 ();
6585 }
6586 }
6587 }
6588
6589 cputrace.needendcycles = 1;
6590 if (v && cputrace.state) {
6591 if (currprefs.cpu_model > 68000) {
6592 if (v & 4)
6593 cpu_tracer = -1;
6594 // old format?
6595 if ((v & (4 | 8)) != (4 | 8))
6596 cpu_tracer = 0;
6597 } else {
6598 cpu_tracer = -1;
6599 }
6600 }
6601
6602 return src;
6603 }
6604
restore_cpu_extra(uae_u8 * src)6605 uae_u8 *restore_cpu_extra (uae_u8 *src)
6606 {
6607 restore_u32 ();
6608 uae_u32 flags = restore_u32 ();
6609
6610 currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = (flags & 1) ? true : false;
6611 currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = currprefs.cpu_cycle_exact;
6612 if ((flags & 32) && !(flags & 1))
6613 currprefs.cpu_memory_cycle_exact = changed_prefs.cpu_memory_cycle_exact = true;
6614 currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact = currprefs.cpu_cycle_exact;
6615 currprefs.cpu_compatible = changed_prefs.cpu_compatible = (flags & 2) ? true : false;
6616 currprefs.cpu_frequency = changed_prefs.cpu_frequency = restore_u32 ();
6617 currprefs.cpu_clock_multiplier = changed_prefs.cpu_clock_multiplier = restore_u32 ();
6618 //currprefs.cachesize = changed_prefs.cachesize = (flags & 8) ? 8192 : 0;
6619
6620 currprefs.m68k_speed = changed_prefs.m68k_speed = 0;
6621 if (flags & 4)
6622 currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
6623 if (flags & 16)
6624 currprefs.m68k_speed = changed_prefs.m68k_speed = (flags >> 24) * CYCLE_UNIT;
6625
6626 currprefs.cpu060_revision = changed_prefs.cpu060_revision = restore_u8 ();
6627 currprefs.fpu_revision = changed_prefs.fpu_revision = restore_u8 ();
6628
6629 return src;
6630 }
6631
save_cpu_extra(int * len,uae_u8 * dstptr)6632 uae_u8 *save_cpu_extra (int *len, uae_u8 *dstptr)
6633 {
6634 uae_u8 *dstbak, *dst;
6635 uae_u32 flags;
6636
6637 if (dstptr)
6638 dstbak = dst = dstptr;
6639 else
6640 dstbak = dst = xmalloc (uae_u8, 1000);
6641 save_u32 (0); // version
6642 flags = 0;
6643 flags |= currprefs.cpu_cycle_exact ? 1 : 0;
6644 flags |= currprefs.cpu_compatible ? 2 : 0;
6645 flags |= currprefs.m68k_speed < 0 ? 4 : 0;
6646 flags |= currprefs.cachesize > 0 ? 8 : 0;
6647 flags |= currprefs.m68k_speed > 0 ? 16 : 0;
6648 flags |= currprefs.cpu_memory_cycle_exact ? 32 : 0;
6649 if (currprefs.m68k_speed > 0)
6650 flags |= (currprefs.m68k_speed / CYCLE_UNIT) << 24;
6651 save_u32 (flags);
6652 save_u32 (currprefs.cpu_frequency);
6653 save_u32 (currprefs.cpu_clock_multiplier);
6654 save_u8 (currprefs.cpu060_revision);
6655 save_u8 (currprefs.fpu_revision);
6656 *len = dst - dstbak;
6657 return dstbak;
6658 }
6659
save_cpu(int * len,uae_u8 * dstptr)6660 uae_u8 *save_cpu (int *len, uae_u8 *dstptr)
6661 {
6662 uae_u8 *dstbak, *dst;
6663 int model, i, khz;
6664
6665 if (dstptr)
6666 dstbak = dst = dstptr;
6667 else
6668 dstbak = dst = xmalloc (uae_u8, 1000 + 20000);
6669 model = currprefs.cpu_model;
6670 save_u32 (model); /* MODEL */
6671 save_u32(0x80000000 | 0x40000000 | 0x20000000 | 0x10000000 | 0x8000000 |(currprefs.address_space_24 ? 1 : 0)); /* FLAGS */
6672 for (i = 0;i < 15; i++)
6673 save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */
6674 save_u32 (m68k_getpc ()); /* PC */
6675 save_u16 (regs.irc); /* prefetch */
6676 save_u16 (regs.ir); /* instruction prefetch */
6677 MakeSR ();
6678 save_u32 (!regs.s ? regs.regs[15] : regs.usp); /* USP */
6679 save_u32 (regs.s ? regs.regs[15] : regs.isp); /* ISP */
6680 save_u16 (regs.sr); /* SR/CCR */
6681 save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */
6682 if (model >= 68010) {
6683 save_u32 (regs.dfc); /* DFC */
6684 save_u32 (regs.sfc); /* SFC */
6685 save_u32 (regs.vbr); /* VBR */
6686 }
6687 if (model >= 68020) {
6688 save_u32 (regs.caar); /* CAAR */
6689 save_u32 (regs.cacr); /* CACR */
6690 save_u32 (regs.msp); /* MSP */
6691 }
6692 if (model >= 68030) {
6693 if (currprefs.mmu_model) {
6694 save_u64 (crp_030); /* CRP */
6695 save_u64 (srp_030); /* SRP */
6696 save_u32 (tt0_030); /* TT0/AC0 */
6697 save_u32 (tt1_030); /* TT1/AC1 */
6698 save_u32 (tc_030); /* TCR */
6699 save_u16 (mmusr_030); /* MMUSR/ACUSR */
6700 } else {
6701 save_u64 (fake_crp_030); /* CRP */
6702 save_u64 (fake_srp_030); /* SRP */
6703 save_u32 (fake_tt0_030); /* TT0/AC0 */
6704 save_u32 (fake_tt1_030); /* TT1/AC1 */
6705 save_u32 (fake_tc_030); /* TCR */
6706 save_u16 (fake_mmusr_030); /* MMUSR/ACUSR */
6707 }
6708 }
6709 if (model >= 68040) {
6710 save_u32 (regs.itt0); /* ITT0 */
6711 save_u32 (regs.itt1); /* ITT1 */
6712 save_u32 (regs.dtt0); /* DTT0 */
6713 save_u32 (regs.dtt1); /* DTT1 */
6714 save_u32 (regs.tcr); /* TCR */
6715 save_u32 (regs.urp); /* URP */
6716 save_u32 (regs.srp); /* SRP */
6717 }
6718 if (model >= 68060) {
6719 save_u32 (regs.buscr); /* BUSCR */
6720 save_u32 (regs.pcr); /* PCR */
6721 }
6722 khz = -1;
6723 if (currprefs.m68k_speed == 0) {
6724 khz = currprefs.ntscmode ? 715909 : 709379;
6725 if (currprefs.cpu_model >= 68020)
6726 khz *= 2;
6727 }
6728 save_u32 (khz); // clock rate in KHz: -1 = fastest possible
6729 save_u32 (0); // spare
6730 if (model == 68020) {
6731 for (int i = 0; i < CACHELINES020; i++) {
6732 save_u32 (caches020[i].data);
6733 save_u32 (caches020[i].tag);
6734 save_u8 (caches020[i].valid ? 1 : 0);
6735 }
6736 save_u32 (regs.prefetch020addr);
6737 save_u32 (regs.cacheholdingaddr020);
6738 save_u32 (regs.cacheholdingdata020);
6739 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6740 save_u32 (regs.prefetch020[i]);
6741 } else if (model == 68030) {
6742 for (int i = 0; i < CACHELINES030; i++) {
6743 for (int j = 0; j < 4; j++) {
6744 save_u32 (icaches030[i].data[j]);
6745 save_u8 (icaches030[i].valid[j] ? 1 : 0);
6746 }
6747 save_u32 (icaches030[i].tag);
6748 }
6749 for (int i = 0; i < CACHELINES030; i++) {
6750 for (int j = 0; j < 4; j++) {
6751 save_u32 (dcaches030[i].data[j]);
6752 save_u8 (dcaches030[i].valid[j] ? 1 : 0);
6753 }
6754 save_u32 (dcaches030[i].tag);
6755 }
6756 save_u32 (regs.prefetch020addr);
6757 save_u32 (regs.cacheholdingaddr020);
6758 save_u32 (regs.cacheholdingdata020);
6759 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6760 save_u32 (regs.prefetch020[i]);
6761 } else if (model >= 68040) {
6762 for (int i = 0; i < CACHESETS040; i++) {
6763 for (int j = 0; j < CACHELINES040; j++) {
6764 save_u32(icaches040[i].data[j][0]);
6765 save_u32(icaches040[i].data[j][1]);
6766 save_u32(icaches040[i].data[j][2]);
6767 save_u32(icaches040[i].data[j][3]);
6768 save_u32(icaches040[i].tag[j]);
6769 save_u16(icaches040[i].valid[j] ? 1 : 0);
6770 }
6771 }
6772 save_u32(regs.prefetch020addr);
6773 save_u32(regs.cacheholdingaddr020);
6774 save_u32(regs.cacheholdingdata020);
6775 for (int i = 0; i < CPU_PIPELINE_MAX; i++)
6776 save_u32(regs.prefetch020[i]);
6777 }
6778 if (currprefs.cpu_model >= 68020) {
6779 save_u32 (regs.ce020memcycles);
6780 save_u32 (0);
6781 }
6782 save_u32 (regs.chipset_latch_rw);
6783 save_u32 (regs.chipset_latch_read);
6784 save_u32 (regs.chipset_latch_write);
6785 *len = dst - dstbak;
6786 return dstbak;
6787 }
6788
save_mmu(int * len,uae_u8 * dstptr)6789 uae_u8 *save_mmu (int *len, uae_u8 *dstptr)
6790 {
6791 uae_u8 *dstbak, *dst;
6792 int model;
6793
6794 model = currprefs.mmu_model;
6795 if (model != 68030 && model != 68040 && model != 68060)
6796 return NULL;
6797 if (dstptr)
6798 dstbak = dst = dstptr;
6799 else
6800 dstbak = dst = xmalloc (uae_u8, 1000);
6801 save_u32 (model); /* MODEL */
6802 save_u32 (0); /* FLAGS */
6803 *len = dst - dstbak;
6804 return dstbak;
6805 }
6806
restore_mmu(uae_u8 * src)6807 uae_u8 *restore_mmu (uae_u8 *src)
6808 {
6809 int flags, model;
6810
6811 changed_prefs.mmu_model = model = restore_u32 ();
6812 flags = restore_u32 ();
6813 write_log (_T("MMU: %d\n"), model);
6814 return src;
6815 }
6816
6817 #endif /* SAVESTATE */
6818
exception3f(uae_u32 opcode,uaecptr addr,bool writeaccess,bool instructionaccess,bool notinstruction,uaecptr pc,bool plus2)6819 static void exception3f (uae_u32 opcode, uaecptr addr, bool writeaccess, bool instructionaccess, bool notinstruction, uaecptr pc, bool plus2)
6820 {
6821 if (currprefs.cpu_model >= 68040)
6822 addr &= ~1;
6823 if (currprefs.cpu_model >= 68020) {
6824 if (pc == 0xffffffff)
6825 last_addr_for_exception_3 = regs.instruction_pc;
6826 else
6827 last_addr_for_exception_3 = pc;
6828 } else if (pc == 0xffffffff) {
6829 last_addr_for_exception_3 = m68k_getpc ();
6830 if (plus2)
6831 last_addr_for_exception_3 += 2;
6832 } else {
6833 last_addr_for_exception_3 = pc;
6834 }
6835 last_fault_for_exception_3 = addr;
6836 last_op_for_exception_3 = opcode;
6837 last_writeaccess_for_exception_3 = writeaccess;
6838 last_instructionaccess_for_exception_3 = instructionaccess;
6839 last_notinstruction_for_exception_3 = notinstruction;
6840 Exception (3);
6841 #if EXCEPTION3_DEBUGGER
6842 activate_debugger();
6843 #endif
6844 }
6845
exception3_notinstruction(uae_u32 opcode,uaecptr addr)6846 void exception3_notinstruction(uae_u32 opcode, uaecptr addr)
6847 {
6848 exception3f (opcode, addr, true, false, true, 0xffffffff, false);
6849 }
exception3_read(uae_u32 opcode,uaecptr addr)6850 void exception3_read(uae_u32 opcode, uaecptr addr)
6851 {
6852 exception3f (opcode, addr, false, 0, false, 0xffffffff, false);
6853 }
exception3_write(uae_u32 opcode,uaecptr addr)6854 void exception3_write(uae_u32 opcode, uaecptr addr)
6855 {
6856 exception3f (opcode, addr, true, 0, false, 0xffffffff, false);
6857 }
exception3i(uae_u32 opcode,uaecptr addr)6858 void exception3i (uae_u32 opcode, uaecptr addr)
6859 {
6860 exception3f (opcode, addr, 0, 1, false, 0xffffffff, true);
6861 }
exception3b(uae_u32 opcode,uaecptr addr,bool w,bool i,uaecptr pc)6862 void exception3b (uae_u32 opcode, uaecptr addr, bool w, bool i, uaecptr pc)
6863 {
6864 exception3f (opcode, addr, w, i, false, pc, true);
6865 }
6866
exception2(uaecptr addr,bool read,int size,uae_u32 fc)6867 void exception2 (uaecptr addr, bool read, int size, uae_u32 fc)
6868 {
6869 if (currprefs.mmu_model) {
6870 if (currprefs.mmu_model == 68030) {
6871 uae_u32 flags = size == 1 ? MMU030_SSW_SIZE_B : (size == 2 ? MMU030_SSW_SIZE_W : MMU030_SSW_SIZE_L);
6872 mmu030_page_fault (addr, read, flags, fc);
6873 } else {
6874 mmu_bus_error (addr, fc, read == false, size, false, 0, true);
6875 }
6876 } else {
6877 last_addr_for_exception_3 = m68k_getpc() + bus_error_offset;
6878 last_fault_for_exception_3 = addr;
6879 last_writeaccess_for_exception_3 = read == 0;
6880 last_instructionaccess_for_exception_3 = (fc & 1) == 0;
6881 last_op_for_exception_3 = regs.opcode;
6882 last_notinstruction_for_exception_3 = exception_in_exception != 0;
6883 THROW(2);
6884 }
6885 }
6886
cpureset(void)6887 void cpureset (void)
6888 {
6889 /* RESET hasn't increased PC yet, 1 word offset */
6890 uaecptr pc;
6891 uaecptr ksboot = 0xf80002 - 2;
6892 uae_u16 ins;
6893 addrbank *ab;
6894
6895 m68k_reset_delay = currprefs.reset_delay;
6896 set_special(SPCFLAG_CHECK);
6897 send_internalevent(INTERNALEVENT_CPURESET);
6898 if ((currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) && currprefs.cpu_model <= 68020) {
6899 custom_reset (false, false);
6900 return;
6901 }
6902 pc = m68k_getpc () + 2;
6903 ab = &get_mem_bank (pc);
6904 if (ab->check (pc, 2)) {
6905 write_log (_T("CPU reset PC=%x (%s)..\n"), pc - 2, ab->name);
6906 ins = get_word (pc);
6907 custom_reset (false, false);
6908 // did memory disappear under us?
6909 if (ab == &get_mem_bank (pc))
6910 return;
6911 // it did
6912 if ((ins & ~7) == 0x4ed0) {
6913 int reg = ins & 7;
6914 uae_u32 addr = m68k_areg (regs, reg);
6915 if (addr < 0x80000)
6916 addr += 0xf80000;
6917 write_log (_T("reset/jmp (ax) combination at %08x emulated -> %x\n"), pc, addr);
6918 m68k_setpc_normal (addr - 2);
6919 return;
6920 }
6921 }
6922 // the best we can do, jump directly to ROM entrypoint
6923 // (which is probably what program wanted anyway)
6924 write_log (_T("CPU Reset PC=%x (%s), invalid memory -> %x.\n"), pc, ab->name, ksboot + 2);
6925 custom_reset (false, false);
6926 m68k_setpc_normal (ksboot);
6927 }
6928
6929
m68k_setstopped(void)6930 void m68k_setstopped (void)
6931 {
6932 regs.stopped = 1;
6933 /* A traced STOP instruction drops through immediately without
6934 actually stopping. */
6935 if ((regs.spcflags & SPCFLAG_DOTRACE) == 0) {
6936 set_special (SPCFLAG_STOP);
6937 } else {
6938 m68k_resumestopped ();
6939 }
6940 }
6941
m68k_resumestopped(void)6942 void m68k_resumestopped (void)
6943 {
6944 if (!regs.stopped)
6945 return;
6946 regs.stopped = 0;
6947 if (currprefs.cpu_cycle_exact && currprefs.cpu_model == 68000) {
6948 x_do_cycles (6 * cpucycleunit);
6949 }
6950 fill_prefetch ();
6951 unset_special (SPCFLAG_STOP);
6952 }
6953
6954
mem_access_delay_word_read(uaecptr addr)6955 uae_u32 mem_access_delay_word_read (uaecptr addr)
6956 {
6957 uae_u32 v;
6958 switch (ce_banktype[addr >> 16])
6959 {
6960 case CE_MEMBANK_CHIP16:
6961 case CE_MEMBANK_CHIP32:
6962 v = wait_cpu_cycle_read (addr, 1);
6963 break;
6964 case CE_MEMBANK_FAST16:
6965 case CE_MEMBANK_FAST32:
6966 v = get_word (addr);
6967 x_do_cycles_post (4 * cpucycleunit, v);
6968 break;
6969 default:
6970 v = get_word (addr);
6971 break;
6972 }
6973 regs.db = v;
6974 return v;
6975 }
mem_access_delay_wordi_read(uaecptr addr)6976 uae_u32 mem_access_delay_wordi_read (uaecptr addr)
6977 {
6978 uae_u32 v;
6979 switch (ce_banktype[addr >> 16])
6980 {
6981 case CE_MEMBANK_CHIP16:
6982 case CE_MEMBANK_CHIP32:
6983 v = wait_cpu_cycle_read (addr, 2);
6984 break;
6985 case CE_MEMBANK_FAST16:
6986 case CE_MEMBANK_FAST32:
6987 v = get_wordi (addr);
6988 x_do_cycles_post (4 * cpucycleunit, v);
6989 break;
6990 default:
6991 v = get_wordi (addr);
6992 break;
6993 }
6994 regs.db = v;
6995 return v;
6996 }
6997
mem_access_delay_byte_read(uaecptr addr)6998 uae_u32 mem_access_delay_byte_read (uaecptr addr)
6999 {
7000 uae_u32 v;
7001 switch (ce_banktype[addr >> 16])
7002 {
7003 case CE_MEMBANK_CHIP16:
7004 case CE_MEMBANK_CHIP32:
7005 v = wait_cpu_cycle_read (addr, 0);
7006 break;
7007 case CE_MEMBANK_FAST16:
7008 case CE_MEMBANK_FAST32:
7009 v = get_byte (addr);
7010 x_do_cycles_post (4 * cpucycleunit, v);
7011 break;
7012 default:
7013 v = get_byte (addr);
7014 break;
7015 }
7016 regs.db = (v << 8) | v;
7017 return v;
7018 }
mem_access_delay_byte_write(uaecptr addr,uae_u32 v)7019 void mem_access_delay_byte_write (uaecptr addr, uae_u32 v)
7020 {
7021 regs.db = (v << 8) | v;
7022 switch (ce_banktype[addr >> 16])
7023 {
7024 case CE_MEMBANK_CHIP16:
7025 case CE_MEMBANK_CHIP32:
7026 wait_cpu_cycle_write (addr, 0, v);
7027 return;
7028 case CE_MEMBANK_FAST16:
7029 case CE_MEMBANK_FAST32:
7030 put_byte (addr, v);
7031 x_do_cycles_post (4 * cpucycleunit, v);
7032 return;
7033 }
7034 put_byte (addr, v);
7035 }
mem_access_delay_word_write(uaecptr addr,uae_u32 v)7036 void mem_access_delay_word_write (uaecptr addr, uae_u32 v)
7037 {
7038 regs.db = v;
7039 switch (ce_banktype[addr >> 16])
7040 {
7041 case CE_MEMBANK_CHIP16:
7042 case CE_MEMBANK_CHIP32:
7043 wait_cpu_cycle_write (addr, 1, v);
7044 return;
7045 case CE_MEMBANK_FAST16:
7046 case CE_MEMBANK_FAST32:
7047 put_word (addr, v);
7048 x_do_cycles_post (4 * cpucycleunit, v);
7049 return;
7050 }
7051 put_word (addr, v);
7052 }
7053
7054
7055 // this one is really simple and easy
fill_icache020(uae_u32 addr,uae_u32 (* fetch)(uaecptr))7056 static void fill_icache020 (uae_u32 addr, uae_u32 (*fetch)(uaecptr))
7057 {
7058 int index;
7059 uae_u32 tag;
7060 uae_u32 data;
7061 struct cache020 *c;
7062
7063 addr &= ~3;
7064 if (regs.cacheholdingaddr020 == addr)
7065 return;
7066 index = (addr >> 2) & (CACHELINES020 - 1);
7067 tag = regs.s | (addr & ~((CACHELINES020 << 2) - 1));
7068 c = &caches020[index];
7069 if (c->valid && c->tag == tag) {
7070 // cache hit
7071 regs.cacheholdingaddr020 = addr;
7072 regs.cacheholdingdata020 = c->data;
7073 return;
7074 }
7075 // cache miss
7076 // Prefetch apparently can be queued by bus controller
7077 // even if bus controller is currently processing
7078 // previous data access.
7079 // Other combinations are not possible.
7080 if (!regs.ce020memcycle_data)
7081 regs.ce020memcycles = 0;
7082 regs.ce020memcycle_data = false;
7083 unsigned long cycs = get_cycles ();
7084 data = fetch (addr);
7085 // add as available "free" internal CPU time.
7086 cycs = get_cycles () - cycs;
7087 regs.ce020memcycles += cycs;
7088 if (!(regs.cacr & 2)) {
7089 c->tag = tag;
7090 c->valid = !!(regs.cacr & 1);
7091 c->data = data;
7092 }
7093 regs.cacheholdingaddr020 = addr;
7094 regs.cacheholdingdata020 = data;
7095 }
7096
7097 #if MORE_ACCURATE_68020_PIPELINE
7098 #define PIPELINE_DEBUG 0
7099 #if PIPELINE_DEBUG
7100 static uae_u16 pipeline_opcode;
7101 #endif
pipeline_020(uae_u16 w,uaecptr pc)7102 static void pipeline_020(uae_u16 w, uaecptr pc)
7103 {
7104 if (regs.pipeline_pos < 0)
7105 return;
7106 if (regs.pipeline_pos > 0) {
7107 // handle annoying 68020+ addressing modes
7108 if (regs.pipeline_pos == regs.pipeline_r8[0]) {
7109 regs.pipeline_r8[0] = 0;
7110 if (w & 0x100) {
7111 int extra = 0;
7112 if ((w & 0x30) == 0x20)
7113 extra += 2;
7114 if ((w & 0x30) == 0x30)
7115 extra += 4;
7116 if ((w & 0x03) == 0x02)
7117 extra += 2;
7118 if ((w & 0x03) == 0x03)
7119 extra += 4;
7120 regs.pipeline_pos += extra;
7121 }
7122 return;
7123 }
7124 if (regs.pipeline_pos == regs.pipeline_r8[1]) {
7125 regs.pipeline_r8[1] = 0;
7126 if (w & 0x100) {
7127 int extra = 0;
7128 if ((w & 0x30) == 0x20)
7129 extra += 2;
7130 if ((w & 0x30) == 0x30)
7131 extra += 4;
7132 if ((w & 0x03) == 0x02)
7133 extra += 2;
7134 if ((w & 0x03) == 0x03)
7135 extra += 4;
7136 regs.pipeline_pos += extra;
7137 }
7138 return;
7139 }
7140 }
7141 if (regs.pipeline_pos > 2) {
7142 regs.pipeline_pos -= 2;
7143 // If stop set, prefetches stop 1 word early.
7144 if (regs.pipeline_stop > 0 && regs.pipeline_pos == 2)
7145 regs.pipeline_stop = -1;
7146 return;
7147 }
7148 if (regs.pipeline_stop) {
7149 regs.pipeline_stop = -1;
7150 return;
7151 }
7152 #if PIPELINE_DEBUG
7153 pipeline_opcode = w;
7154 #endif
7155 regs.pipeline_r8[0] = cpudatatbl[w].disp020[0];
7156 regs.pipeline_r8[1] = cpudatatbl[w].disp020[1];
7157 regs.pipeline_pos = cpudatatbl[w].length;
7158 #if PIPELINE_DEBUG
7159 if (!regs.pipeline_pos) {
7160 write_log(_T("Opcode %04x has no size PC=%08x!\n"), w, pc);
7161 }
7162 #endif
7163 // illegal instructions, TRAP, TRAPV, A-line, F-line don't stop prefetches
7164 int branch = cpudatatbl[w].branch;
7165 if (regs.pipeline_pos > 0 && branch) {
7166 // Short branches (Bcc.s) still do one more prefetch.
7167 #if 0
7168 // RTS and other unconditional single opcode instruction stop immediately.
7169 if (branch == 2) {
7170 // Immediate stop
7171 regs.pipeline_stop = -1;
7172 } else {
7173 // Stop 1 word early than normally
7174 regs.pipeline_stop = 1;
7175 }
7176 #else
7177 regs.pipeline_stop = 1;
7178 #endif
7179 }
7180 }
7181
7182 // Not exactly right, requires logic analyzer checks.
7183
7184 #if defined CPUEMU_21 || defined CPUEMU_23
continue_ce020_prefetch(void)7185 void continue_ce020_prefetch(void)
7186 {
7187 fill_prefetch_020();
7188 }
7189 #endif
7190
continue_020_prefetch(void)7191 void continue_020_prefetch(void)
7192 {
7193 fill_prefetch_020();
7194 }
7195 #endif
7196
7197 #if defined CPUEMU_21 || defined CPUEMU_22 || defined CPUEMU_23 || defined CPUEMU_32
get_word_ce020_prefetch(int o)7198 uae_u32 get_word_ce020_prefetch (int o)
7199 {
7200 uae_u32 pc = m68k_getpc () + o;
7201 uae_u32 v;
7202
7203 if (pc & 2) {
7204 v = regs.prefetch020[0] & 0xffff;
7205 #if MORE_ACCURATE_68020_PIPELINE
7206 pipeline_020(regs.prefetch020[1], pc );
7207 #endif
7208 regs.prefetch020[0] = regs.prefetch020[1];
7209 // branch instruction detected in pipeline: stop fetches until branch executed.
7210 if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
7211 fill_icache020 (pc + 2 + 4, mem_access_delay_longi_read_ce020);
7212 regs.prefetch020[1] = regs.cacheholdingdata020;
7213 }
7214 regs.db = regs.prefetch020[0] >> 16;
7215 } else {
7216 v = regs.prefetch020[0] >> 16;
7217 #if MORE_ACCURATE_68020_PIPELINE
7218 pipeline_020(regs.prefetch020[1] >> 16, pc);
7219 #endif
7220 regs.db = regs.prefetch020[1] >> 16;
7221 }
7222 do_cycles_ce020_internal (2);
7223 return v;
7224 }
7225 #endif
7226
get_word_020_prefetch(int o)7227 uae_u32 get_word_020_prefetch (int o)
7228 {
7229 uae_u32 pc = m68k_getpc () + o;
7230 uae_u32 v;
7231
7232 if (pc & 2) {
7233 v = regs.prefetch020[0] & 0xffff;
7234 #if MORE_ACCURATE_68020_PIPELINE
7235 pipeline_020(regs.prefetch020[1], pc);
7236 #endif
7237 regs.prefetch020[0] = regs.prefetch020[1];
7238 if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
7239 fill_icache020 (pc + 2 + 4, currprefs.cpu_memory_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi);
7240 regs.prefetch020[1] = regs.cacheholdingdata020;
7241 }
7242 regs.db = regs.prefetch020[0] >> 16;
7243 } else {
7244 v = regs.prefetch020[0] >> 16;
7245 #if MORE_ACCURATE_68020_PIPELINE
7246 pipeline_020(regs.prefetch020[1] >> 16, pc);
7247 #endif
7248 regs.db = regs.prefetch020[0];
7249 }
7250 return v;
7251 }
7252
7253 #if defined CPUEMU_21 || defined CPUEMU_22 || defined CPUEMU_23 || defined CPUEMU_32
7254
7255 // these are also used by 68030.
7256
7257 #define RESET_CE020_CYCLES \
7258 regs.ce020memcycles = 0; \
7259 regs.ce020memcycle_data = true;
7260 #define STORE_CE020_CYCLES \
7261 unsigned long cycs = get_cycles ()
7262 #define ADD_CE020_CYCLES \
7263 regs.ce020memcycles += get_cycles () - cycs
7264
mem_access_delay_long_read_ce020(uaecptr addr)7265 uae_u32 mem_access_delay_long_read_ce020 (uaecptr addr)
7266 {
7267 uae_u32 v;
7268 RESET_CE020_CYCLES;
7269 STORE_CE020_CYCLES;
7270 switch (ce_banktype[addr >> 16])
7271 {
7272 case CE_MEMBANK_CHIP16:
7273 v = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
7274 v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) << 0;
7275 break;
7276 case CE_MEMBANK_CHIP32:
7277 if ((addr & 3) != 0) {
7278 v = wait_cpu_cycle_read_ce020 (addr + 0, 1) << 16;
7279 v |= wait_cpu_cycle_read_ce020 (addr + 2, 1) << 0;
7280 } else {
7281 v = wait_cpu_cycle_read_ce020 (addr, -1);
7282 }
7283 break;
7284 case CE_MEMBANK_FAST32:
7285 v = get_long (addr);
7286 if ((addr & 3) != 0)
7287 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7288 else
7289 do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
7290 break;
7291 case CE_MEMBANK_FAST16:
7292 v = get_long (addr);
7293 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7294 break;
7295 default:
7296 v = get_long (addr);
7297 break;
7298 }
7299 ADD_CE020_CYCLES;
7300 return v;
7301 }
7302
mem_access_delay_longi_read_ce020(uaecptr addr)7303 uae_u32 mem_access_delay_longi_read_ce020 (uaecptr addr)
7304 {
7305 uae_u32 v;
7306 switch (ce_banktype[addr >> 16])
7307 {
7308 case CE_MEMBANK_CHIP16:
7309 v = wait_cpu_cycle_read_ce020 (addr + 0, 2) << 16;
7310 v |= wait_cpu_cycle_read_ce020 (addr + 2, 2) << 0;
7311 break;
7312 case CE_MEMBANK_CHIP32:
7313 if ((addr & 3) != 0) {
7314 v = wait_cpu_cycle_read_ce020 (addr + 0, 2) << 16;
7315 v |= wait_cpu_cycle_read_ce020 (addr + 2, 2) << 0;
7316 } else {
7317 v = wait_cpu_cycle_read_ce020 (addr, -2);
7318 }
7319 break;
7320 case CE_MEMBANK_FAST32:
7321 v = get_longi (addr);
7322 if ((addr & 3) != 0)
7323 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7324 else
7325 do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
7326 break;
7327 case CE_MEMBANK_FAST16:
7328 v = get_longi (addr);
7329 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7330 break;
7331 default:
7332 v = get_longi (addr);
7333 break;
7334 }
7335 return v;
7336 }
7337
mem_access_delay_word_read_ce020(uaecptr addr)7338 uae_u32 mem_access_delay_word_read_ce020 (uaecptr addr)
7339 {
7340 uae_u32 v;
7341 RESET_CE020_CYCLES;
7342 STORE_CE020_CYCLES;
7343 switch (ce_banktype[addr >> 16])
7344 {
7345 case CE_MEMBANK_CHIP16:
7346 case CE_MEMBANK_CHIP32:
7347 if ((addr & 3) == 3) {
7348 v = wait_cpu_cycle_read_ce020 (addr + 0, 0) << 8;
7349 v |= wait_cpu_cycle_read_ce020 (addr + 1, 0) << 0;
7350 } else {
7351 v = wait_cpu_cycle_read_ce020 (addr, 1);
7352 }
7353 break;
7354 case CE_MEMBANK_FAST16:
7355 case CE_MEMBANK_FAST32:
7356 v = get_word (addr);
7357 if ((addr & 3) == 3)
7358 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7359 else
7360 do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
7361 break;
7362 default:
7363 v = get_word (addr);
7364 break;
7365 }
7366 ADD_CE020_CYCLES;
7367 return v;
7368 }
7369
mem_access_delay_byte_read_ce020(uaecptr addr)7370 uae_u32 mem_access_delay_byte_read_ce020 (uaecptr addr)
7371 {
7372 uae_u32 v;
7373 RESET_CE020_CYCLES;
7374 STORE_CE020_CYCLES;
7375 switch (ce_banktype[addr >> 16])
7376 {
7377 case CE_MEMBANK_CHIP16:
7378 case CE_MEMBANK_CHIP32:
7379 v = wait_cpu_cycle_read_ce020 (addr, 0);
7380 break;
7381 case CE_MEMBANK_FAST16:
7382 case CE_MEMBANK_FAST32:
7383 v = get_byte (addr);
7384 do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
7385 break;
7386 default:
7387 v = get_byte (addr);
7388 break;
7389 }
7390 ADD_CE020_CYCLES;
7391 return v;
7392 }
7393
mem_access_delay_byte_write_ce020(uaecptr addr,uae_u32 v)7394 void mem_access_delay_byte_write_ce020 (uaecptr addr, uae_u32 v)
7395 {
7396 RESET_CE020_CYCLES;
7397 STORE_CE020_CYCLES;
7398 switch (ce_banktype[addr >> 16])
7399 {
7400 case CE_MEMBANK_CHIP16:
7401 case CE_MEMBANK_CHIP32:
7402 wait_cpu_cycle_write_ce020 (addr, 0, v);
7403 break;
7404 case CE_MEMBANK_FAST16:
7405 case CE_MEMBANK_FAST32:
7406 put_byte (addr, v);
7407 do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
7408 break;
7409 default:
7410 put_byte (addr, v);
7411 break;
7412 }
7413 ADD_CE020_CYCLES;
7414 }
7415
mem_access_delay_word_write_ce020(uaecptr addr,uae_u32 v)7416 void mem_access_delay_word_write_ce020 (uaecptr addr, uae_u32 v)
7417 {
7418 RESET_CE020_CYCLES;
7419 STORE_CE020_CYCLES;
7420 switch (ce_banktype[addr >> 16])
7421 {
7422 case CE_MEMBANK_CHIP16:
7423 case CE_MEMBANK_CHIP32:
7424 if ((addr & 3) == 3) {
7425 wait_cpu_cycle_write_ce020 (addr + 0, 0, (v >> 8) & 0xff);
7426 wait_cpu_cycle_write_ce020 (addr + 1, 0, (v >> 0) & 0xff);
7427 } else {
7428 wait_cpu_cycle_write_ce020 (addr + 0, 1, v);
7429 }
7430 break;
7431 case CE_MEMBANK_FAST16:
7432 case CE_MEMBANK_FAST32:
7433 put_word (addr, v);
7434 if ((addr & 3) == 3)
7435 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7436 else
7437 do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
7438 break;
7439 default:
7440 put_word (addr, v);
7441 break;
7442 }
7443 ADD_CE020_CYCLES;
7444 }
7445
mem_access_delay_long_write_ce020(uaecptr addr,uae_u32 v)7446 void mem_access_delay_long_write_ce020 (uaecptr addr, uae_u32 v)
7447 {
7448 RESET_CE020_CYCLES;
7449 STORE_CE020_CYCLES;
7450 switch (ce_banktype[addr >> 16])
7451 {
7452 case CE_MEMBANK_CHIP16:
7453 wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
7454 wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >> 0) & 0xffff);
7455 break;
7456 case CE_MEMBANK_CHIP32:
7457 if ((addr & 3) == 3) {
7458 wait_cpu_cycle_write_ce020 (addr + 0, 1, (v >> 16) & 0xffff);
7459 wait_cpu_cycle_write_ce020 (addr + 2, 1, (v >> 0) & 0xffff);
7460 } else {
7461 wait_cpu_cycle_write_ce020 (addr + 0, -1, v);
7462 }
7463 break;
7464 case CE_MEMBANK_FAST32:
7465 put_long (addr, v);
7466 if ((addr & 3) != 0)
7467 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7468 else
7469 do_cycles_ce020_mem (1 * CPU020_MEM_CYCLE, v);
7470 break;
7471 case CE_MEMBANK_FAST16:
7472 put_long (addr, v);
7473 do_cycles_ce020_mem (2 * CPU020_MEM_CYCLE, v);
7474 break;
7475 default:
7476 put_long (addr, v);
7477 break;
7478 }
7479 ADD_CE020_CYCLES;
7480 }
7481
7482 #endif /* defined CPUEMU_21 || defined CPUEMU_22 || defined CPUEMU_23 || defined CPUEMU_32 */
7483
7484 // 68030 caches aren't so simple as 68020 cache..
getcache030(struct cache030 * cp,uaecptr addr,uae_u32 * tagp,int * lwsp)7485 STATIC_INLINE struct cache030 *getcache030 (struct cache030 *cp, uaecptr addr, uae_u32 *tagp, int *lwsp)
7486 {
7487 int index, lws;
7488 uae_u32 tag;
7489 struct cache030 *c;
7490
7491 addr &= ~3;
7492 index = (addr >> 4) & (CACHELINES030 - 1);
7493 tag = regs.s | (addr & ~((CACHELINES030 << 4) - 1));
7494 lws = (addr >> 2) & 3;
7495 c = &cp[index];
7496 *tagp = tag;
7497 *lwsp = lws;
7498 return c;
7499 }
7500
update_cache030(struct cache030 * c,uae_u32 val,uae_u32 tag,int lws)7501 STATIC_INLINE void update_cache030 (struct cache030 *c, uae_u32 val, uae_u32 tag, int lws)
7502 {
7503 if (c->tag != tag)
7504 c->valid[0] = c->valid[1] = c->valid[2] = c->valid[3] = false;
7505 c->tag = tag;
7506 c->valid[lws] = true;
7507 c->data[lws] = val;
7508 }
7509
fill_icache030(uae_u32 addr)7510 static void fill_icache030 (uae_u32 addr)
7511 {
7512 int lws;
7513 uae_u32 tag;
7514 uae_u32 data;
7515 struct cache030 *c;
7516
7517 addr &= ~3;
7518 if (regs.cacheholdingaddr020 == addr)
7519 return;
7520 c = getcache030 (icaches030, addr, &tag, &lws);
7521 if (c->valid[lws] && c->tag == tag) {
7522 // cache hit
7523 regs.cacheholdingaddr020 = addr;
7524 regs.cacheholdingdata020 = c->data[lws];
7525 return;
7526 }
7527
7528 // cache miss
7529 if (currprefs.cpu_cycle_exact) {
7530 if (!regs.ce020memcycle_data)
7531 regs.ce020memcycles = 0;
7532 regs.ce020memcycle_data = false;
7533 unsigned long cycs = get_cycles ();
7534 data = mem_access_delay_longi_read_ce020 (addr);
7535 // add as available "free" internal CPU time.
7536 cycs = get_cycles () - cycs;
7537 regs.ce020memcycles += cycs;
7538 } else if (currprefs.cpu_memory_cycle_exact) {
7539 data = mem_access_delay_longi_read_ce020 (addr);
7540 } else {
7541 data = get_longi (addr);
7542 }
7543 if ((regs.cacr & 3) == 1) { // not frozen and enabled
7544 update_cache030 (c, data, tag, lws);
7545 }
7546 if ((regs.cacr & 0x11) == 0x11 && lws == 0 && !c->valid[1] && !c->valid[2] && !c->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
7547 // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
7548 c->data[1] = get_longi (addr + 4);
7549 c->data[2] = get_longi (addr + 8);
7550 c->data[3] = get_longi (addr + 12);
7551 if (currprefs.cpu_cycle_exact)
7552 do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c->data[3]);
7553 c->valid[1] = c->valid[2] = c->valid[3] = true;
7554 }
7555 regs.cacheholdingaddr020 = addr;
7556 regs.cacheholdingdata020 = data;
7557 }
7558
cancache030(uaecptr addr)7559 STATIC_INLINE bool cancache030 (uaecptr addr)
7560 {
7561 return ce_cachable[addr >> 16] != 0;
7562 }
7563
7564 // and finally the worst part, 68030 data cache..
write_dcache030x(uaecptr addr,uae_u32 val,int size)7565 static void write_dcache030x(uaecptr addr, uae_u32 val, int size)
7566 {
7567 struct cache030 *c1, *c2;
7568 int lws1, lws2;
7569 uae_u32 tag1, tag2;
7570 int aligned = addr & 3;
7571 int wa = regs.cacr & 0x2000;
7572 int hit;
7573
7574 if (!(regs.cacr & 0x100)) // data cache disabled?
7575 return;
7576 if (!cancache030(addr))
7577 return;
7578
7579 c1 = getcache030(dcaches030, addr, &tag1, &lws1);
7580
7581 // easy one
7582 if (size == 2 && aligned == 0 && wa == 1) {
7583 update_cache030(c1, val, tag1, lws1);
7584 return;
7585 }
7586
7587 hit = (c1->tag == tag1 && c1->valid[lws1]);
7588 if (hit || wa) {
7589 if (size == 2) {
7590 if (hit) {
7591 c1->data[lws1] &= ~(0xffffffff >> (aligned * 8));
7592 c1->data[lws1] |= val >> (aligned * 8);
7593 } else
7594 c1->valid[lws1] = false;
7595 } else if (size == 1) {
7596 if (hit) {
7597 c1->data[lws1] &= ~(0xffff0000 >> (aligned * 8));
7598 c1->data[lws1] |= (val << 16) >> (aligned * 8);
7599 } else
7600 c1->valid[lws1] = false;
7601 } else if (size == 0) {
7602 if (hit) {
7603 c1->data[lws1] &= ~(0xff000000 >> (aligned * 8));
7604 c1->data[lws1] |= (val << 24) >> (aligned * 8);
7605 } else
7606 c1->valid[lws1] = false;
7607 }
7608 }
7609
7610 // do we need to update a 2nd cache entry ?
7611 if ((size == 0) || (size == 1 && aligned <= 2) || (size == 2 && aligned == 0))
7612 return;
7613
7614 c2 = getcache030(dcaches030, addr + 4, &tag2, &lws2);
7615 hit = (c2->tag == tag2 && c2->valid[lws2]);
7616 if (hit || wa) {
7617 if (size == 2) {
7618 if (hit) {
7619 c2->data[lws2] &= 0xffffffff >> (aligned * 8);
7620 c2->data[lws2] |= val << ((4 - aligned) * 8);
7621 } else
7622 c2->valid[lws2] = false;
7623 } else if (size == 1) {
7624 if (hit) {
7625 c2->data[lws2] &= 0x00ffffff;
7626 c2->data[lws2] |= val << 24;
7627 } else
7628 c2->valid[lws2] = false;
7629 }
7630 }
7631 }
7632
write_dcache030(uaecptr addr,uae_u32 v,int size)7633 void write_dcache030(uaecptr addr, uae_u32 v, int size)
7634 {
7635 write_dcache030x(addr, v, size);
7636 if (currprefs.cpu_memory_cycle_exact) {
7637 if (size == 2)
7638 mem_access_delay_long_write_ce020(addr, v);
7639 else if (size == 1)
7640 mem_access_delay_word_write_ce020(addr, v);
7641 else
7642 mem_access_delay_byte_write_ce020(addr, v);
7643 } else {
7644 if (size == 2)
7645 put_long(addr, v);
7646 else if (size == 1)
7647 put_word(addr, v);
7648 else
7649 put_byte(addr, v);
7650 }
7651 }
7652
read_dcache030(uaecptr addr,int size)7653 uae_u32 read_dcache030 (uaecptr addr, int size)
7654 {
7655 struct cache030 *c1, *c2;
7656 int lws1, lws2;
7657 uae_u32 tag1, tag2;
7658 int aligned = addr & 3;
7659 uae_u32 v1, v2;
7660
7661 if (!(regs.cacr & 0x100) || !cancache030 (addr)) { // data cache disabled?
7662 if (currprefs.cpu_memory_cycle_exact) {
7663 if (size == 2)
7664 return mem_access_delay_long_read_ce020 (addr);
7665 else if (size == 1)
7666 return mem_access_delay_word_read_ce020 (addr);
7667 else
7668 return mem_access_delay_byte_read_ce020 (addr);
7669 } else {
7670 if (size == 2)
7671 return get_long (addr);
7672 else if (size == 1)
7673 return get_word (addr);
7674 else
7675 return get_byte (addr);
7676 }
7677 }
7678 c1 = getcache030 (dcaches030, addr, &tag1, &lws1);
7679 addr &= ~3;
7680 if (!c1->valid[lws1] || c1->tag != tag1) {
7681 v1 = currprefs.cpu_memory_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
7682 update_cache030 (c1, v1, tag1, lws1);
7683 } else {
7684 v1 = c1->data[lws1];
7685 if (uae_boot_rom_type > 0) {
7686 // this check and fix is needed for UAE filesystem handler because it runs in host side and in
7687 // separate thread. No way to access via cache without locking that would cause major slowdown
7688 // and unneeded complexity
7689 uae_u32 tv = get_long(addr);
7690 if (tv != v1) {
7691 write_log(_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
7692 size, aligned, addr, tv, v1, tag1, lws1, M68K_GETPC);
7693 v1 = tv;
7694 }
7695 }
7696 }
7697 // only one long fetch needed?
7698 if (size == 0) {
7699 v1 >>= (3 - aligned) * 8;
7700 return v1;
7701 } else if (size == 1 && aligned <= 2) {
7702 v1 >>= (2 - aligned) * 8;
7703 return v1;
7704 } else if (size == 2 && aligned == 0) {
7705 if ((regs.cacr & 0x1100) == 0x1100 && lws1 == 0 && !c1->valid[1] && !c1->valid[2] && !c1->valid[3] && ce_banktype[addr >> 16] == CE_MEMBANK_FAST32) {
7706 // do burst fetch if cache enabled, not frozen, all slots invalid, no chip ram
7707 c1->data[1] = get_long (addr + 4);
7708 c1->data[2] = get_long (addr + 8);
7709 c1->data[3] = get_long (addr + 12);
7710 do_cycles_ce020_mem (3 * (CPU020_MEM_CYCLE - 1), c1->data[3]);
7711 c1->valid[1] = c1->valid[2] = c1->valid[3] = true;
7712 }
7713 return v1;
7714 }
7715 // no, need another one
7716 addr += 4;
7717 c2 = getcache030 (dcaches030, addr, &tag2, &lws2);
7718 if (!c2->valid[lws2] || c2->tag != tag2) {
7719 v2 = currprefs.cpu_memory_cycle_exact ? mem_access_delay_long_read_ce020 (addr) : get_long (addr);
7720 update_cache030 (c2, v2, tag2, lws2);
7721 } else {
7722 v2 = c2->data[lws2];
7723 if (uae_boot_rom_type > 0) {
7724 uae_u32 tv = get_long(addr);
7725 if (tv != v2) {
7726 write_log (_T("data cache mismatch %d %d %08x %08x != %08x %08x %d PC=%08x\n"),
7727 size, aligned, addr, tv, v2, tag2, lws2, M68K_GETPC);
7728 v2 = tv;
7729 }
7730 }
7731 }
7732 if (size == 1 && aligned == 3)
7733 return (v1 << 8) | (v2 >> 24);
7734 else if (size == 2 && aligned == 1)
7735 return (v1 << 8) | (v2 >> 24);
7736 else if (size == 2 && aligned == 2)
7737 return (v1 << 16) | (v2 >> 16);
7738 else if (size == 2 && aligned == 3)
7739 return (v1 << 24) | (v2 >> 8);
7740
7741 write_log (_T("dcache030 weirdness!?\n"));
7742 return 0;
7743 }
7744
7745 #ifdef CPUEMU_23
get_word_ce030_prefetch(int o)7746 uae_u32 get_word_ce030_prefetch (int o)
7747 {
7748 uae_u32 pc = m68k_getpc () + o;
7749 uae_u32 v;
7750
7751 if (pc & 2) {
7752 v = regs.prefetch020[0] & 0xffff;
7753 #if MORE_ACCURATE_68020_PIPELINE
7754 pipeline_020(regs.prefetch020[1], pc);
7755 #endif
7756 regs.prefetch020[0] = regs.prefetch020[1];
7757 // branch instruction detected in pipeline: stop fetches until branch executed.
7758 if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
7759 fill_icache030 (pc + 2 + 4);
7760 regs.prefetch020[1] = regs.cacheholdingdata020;
7761 }
7762 } else {
7763 v = regs.prefetch020[0] >> 16;
7764 #if MORE_ACCURATE_68020_PIPELINE
7765 pipeline_020(regs.prefetch020[1] >> 16, pc);
7766 #endif
7767 }
7768 do_cycles_ce020_internal (2);
7769 return v;
7770 }
7771 #endif
7772
7773 #ifdef CPUEMU_22
get_word_030_prefetch(int o)7774 uae_u32 get_word_030_prefetch(int o)
7775 {
7776 uae_u32 pc = m68k_getpc() + o;
7777 uae_u32 v;
7778
7779 if (pc & 2) {
7780 v = regs.prefetch020[0] & 0xffff;
7781 #if MORE_ACCURATE_68020_PIPELINE
7782 pipeline_020(regs.prefetch020[1], pc);
7783 #endif
7784 regs.prefetch020[0] = regs.prefetch020[1];
7785 // branch instruction detected in pipeline: stop fetches until branch executed.
7786 if (!MORE_ACCURATE_68020_PIPELINE || regs.pipeline_stop >= 0) {
7787 fill_icache030(pc + 2 + 4);
7788 regs.prefetch020[1] = regs.cacheholdingdata020;
7789 }
7790 } else {
7791 v = regs.prefetch020[0] >> 16;
7792 #if MORE_ACCURATE_68020_PIPELINE
7793 pipeline_020(regs.prefetch020[1] >> 16, pc);
7794 #endif
7795 }
7796 return v;
7797 }
7798 #endif
7799
get_word_icache030(uaecptr addr)7800 uae_u32 get_word_icache030(uaecptr addr)
7801 {
7802 fill_icache030(addr);
7803 return regs.cacheholdingdata020 >> ((addr & 2) ? 0 : 16);
7804 }
get_long_icache030(uaecptr addr)7805 uae_u32 get_long_icache030(uaecptr addr)
7806 {
7807 uae_u32 v;
7808 fill_icache030(addr);
7809 if ((addr & 2) == 0)
7810 return regs.cacheholdingdata020;
7811 v = regs.cacheholdingdata020 << 16;
7812 fill_icache030(addr + 4);
7813 v |= regs.cacheholdingdata020 >> 16;
7814 return v;
7815 }
7816
fill_icache040(uae_u32 addr)7817 uae_u32 fill_icache040(uae_u32 addr)
7818 {
7819 int index, i, lws;
7820 uae_u32 tag;
7821 struct cache040 *c;
7822 int line;
7823
7824 if (!(regs.cacr & 0x8000)) {
7825 uae_u32 addr2 = addr & ~15;
7826 lws = (addr >> 2) & 3;
7827 addr &= ~3;
7828 if (regs.prefetch020addr == addr2)
7829 return regs.prefetch020[lws];
7830 regs.prefetch020addr = addr2;
7831 if (currprefs.cpu_memory_cycle_exact) {
7832 regs.prefetch020[0] = mem_access_delay_longi_read_ce020(addr2 + 0);
7833 regs.prefetch020[1] = mem_access_delay_longi_read_ce020(addr2 + 4);
7834 regs.prefetch020[2] = mem_access_delay_longi_read_ce020(addr2 + 8);
7835 regs.prefetch020[3] = mem_access_delay_longi_read_ce020(addr2 + 12);
7836 } else {
7837 regs.prefetch020[0] = get_longi(addr2 + 0);
7838 regs.prefetch020[1] = get_longi(addr2 + 4);
7839 regs.prefetch020[2] = get_longi(addr2 + 8);
7840 regs.prefetch020[3] = get_longi(addr2 + 12);
7841 x_do_cycles(4 * cpucycleunit);
7842 }
7843 return regs.prefetch020[lws];
7844 }
7845
7846 index = (addr >> 4) & (CACHESETS040 - 1);
7847 tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
7848 lws = (addr >> 2) & 3;
7849 addr &= ~15;
7850 c = &icaches040[index];
7851 for (i = 0; i < CACHELINES040; i++) {
7852 if (c->valid[i] && c->tag[i] == tag) {
7853 // cache hit
7854 icachelinecnt++;
7855 x_do_cycles(1 * cpucycleunit);
7856 return c->data[i][lws];
7857 }
7858 }
7859 // cache miss
7860 if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
7861 line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
7862 }
7863 else {
7864 for (line = 0; line < CACHELINES040; line++) {
7865 if (c->valid[line] == false)
7866 break;
7867 }
7868 }
7869 c->tag[line] = tag;
7870 c->valid[line] = true;
7871 if (currprefs.cpu_memory_cycle_exact) {
7872 c->data[line][0] = mem_access_delay_longi_read_ce020(addr + 0);
7873 c->data[line][1] = mem_access_delay_longi_read_ce020(addr + 4);
7874 c->data[line][2] = mem_access_delay_longi_read_ce020(addr + 8);
7875 c->data[line][3] = mem_access_delay_longi_read_ce020(addr + 12);
7876 } else {
7877 c->data[line][0] = get_longi(addr + 0);
7878 c->data[line][1] = get_longi(addr + 4);
7879 c->data[line][2] = get_longi(addr + 8);
7880 c->data[line][3] = get_longi(addr + 12);
7881 x_do_cycles(4 * cpucycleunit);
7882 }
7883 return c->data[line][lws];
7884 }
7885
7886 #if 0
7887 static bool is_dcache040(uae_u32 addr)
7888 {
7889 int index, i, lws;
7890 uae_u32 tag;
7891 struct cache040 *c;
7892
7893 addr &= ~15;
7894 index = (addr >> 4) & (CACHESETS040 - 1);
7895 tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
7896 lws = (addr >> 2) & 3;
7897 c = &dcaches040[index];
7898 for (i = 0; i < CACHELINES040; i++) {
7899 if (c->valid[i] && c->tag[i] == tag) {
7900 return true;
7901 }
7902 }
7903 return false;
7904 }
7905
7906 uae_u32 read_dcache040(uae_u32 addr)
7907 {
7908 int index, i, lws;
7909 uae_u32 tag;
7910 struct cache040 *c;
7911 int line;
7912
7913 addr &= ~15;
7914 index = (addr >> 4) & (CACHESETS040 - 1);
7915 tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
7916 lws = (addr >> 2) & 3;
7917 c = &dcaches040[index];
7918 for (i = 0; i < CACHELINES040; i++) {
7919 if (c->valid[i] && c->tag[i] == tag) {
7920 // cache hit
7921 dcachelinecnt++;
7922 return c->data[i][lws];
7923 }
7924 }
7925 // cache miss
7926 if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
7927 line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
7928 for (i = 0; i < 4; i++) {
7929 if (c->dirty[line][i]) {
7930 c->dirty[line][i] = false;
7931 mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
7932 }
7933 }
7934 }
7935 else {
7936 for (line = 0; line < CACHELINES040; line++) {
7937 if (c->valid[line] == false)
7938 break;
7939 }
7940 }
7941 c->tag[line] = tag;
7942 c->valid[line] = true;
7943 c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
7944 c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
7945 c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
7946 c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
7947 regs.cacheholdingaddr020 = addr;
7948 }
7949
7950 void write_dcache040(uae_u32 addr, uae_u32 val)
7951 {
7952 int index, i, lws;
7953 uae_u32 tag;
7954 struct cache040 *c;
7955 int line;
7956
7957 addr &= ~15;
7958 index = (addr >> 4) & (CACHESETS040 - 1);
7959 tag = regs.s | (addr & ~((CACHESETS040 << 4) - 1));
7960 lws = (addr >> 2) & 3;
7961 c = &dcaches040[index];
7962 for (i = 0; i < CACHELINES040; i++) {
7963 if (c->valid[i] && c->tag[i] == tag) {
7964 // cache hit
7965 dcachelinecnt++;
7966 c->data[i][lws] = val;
7967 mem_access_delay_long_write_ce020(addr + i * 4, c->data[i][lws]);
7968 //c->dirty[i][lws] = true;
7969 }
7970 }
7971 #if 0
7972 // cache miss
7973 if (c->valid[0] && c->valid[1] && c->valid[2] && c->valid[3]) {
7974 line = (icachelinecnt >> 1) & (CACHELINES040 - 1);
7975 for (i = 0; i < 4; i++) {
7976 if (c->dirty[line][i]) {
7977 c->dirty[line][i] = false;
7978 mem_access_delay_long_write_ce020(addr + i * 4, c->data[line][i]);
7979 }
7980 }
7981 }
7982 else {
7983 for (line = 0; line < CACHELINES040; line++) {
7984 if (c->valid[line] == false)
7985 break;
7986 }
7987 }
7988 c->tag[line] = tag;
7989 c->valid[line] = true;
7990 c->data[line][0] = mem_access_delay_long_read_ce020(addr + 0);
7991 c->data[line][1] = mem_access_delay_long_read_ce020(addr + 4);
7992 c->data[line][2] = mem_access_delay_long_read_ce020(addr + 8);
7993 c->data[line][3] = mem_access_delay_long_read_ce020(addr + 12);
7994 c->data[line][lws] = val;
7995 c->dirty[line][lws] = true;
7996 #endif
7997 }
7998 #endif
7999
8000 // really unoptimized
get_word_icache040(uaecptr addr)8001 uae_u32 get_word_icache040(uaecptr addr)
8002 {
8003 uae_u32 v = fill_icache040(addr);
8004 return v >> ((addr & 2) ? 0 : 16);
8005 }
get_long_icache040(uaecptr addr)8006 uae_u32 get_long_icache040(uaecptr addr)
8007 {
8008 uae_u32 v1, v2;
8009 v1 = fill_icache040(addr);
8010 if ((addr & 2) == 0)
8011 return v1;
8012 v2 = fill_icache040(addr + 4);
8013 return (v2 >> 16) | (v1 << 16);
8014 }
get_ilong_cache_040(int o)8015 uae_u32 get_ilong_cache_040(int o)
8016 {
8017 return get_long_icache040(m68k_getpci() + o);
8018 }
get_iword_cache_040(int o)8019 uae_u32 get_iword_cache_040(int o)
8020 {
8021 return get_word_icache040(m68k_getpci() + o);
8022 }
8023
nocache040(uaecptr addr)8024 STATIC_INLINE bool nocache040(uaecptr addr)
8025 {
8026 if (!currprefs.cpu_memory_cycle_exact)
8027 return false;
8028 if (!(regs.cacr & 0x80000000))
8029 return true;
8030 if (addr >= 0xd80000 && addr < 0xc00000)
8031 return true;
8032 if (addr >= 0xe80000 && addr < 0xf00000)
8033 return true;
8034 return false;
8035 }
8036
put_long_cache_040(uaecptr addr,uae_u32 v)8037 void put_long_cache_040(uaecptr addr, uae_u32 v)
8038 {
8039 #if 1
8040 if (nocache040(addr))
8041 mem_access_delay_long_write_ce020(addr, v);
8042 else
8043 put_long(addr, v);
8044 #else
8045 if ((addr & 2) == 0) {
8046 if (is_dcache040(addr))
8047 write_dcache040(addr, v);
8048 else if (currprefs.cpu_memory_cycle_exact)
8049 mem_access_delay_long_write_ce020(addr, v);
8050 else
8051 put_long(addr, v);
8052 } else {
8053 uae_u32 vp;
8054 if (is_dcache040(addr)) {
8055 vp = read_dcache040(addr);
8056 vp &= 0xffff0000;
8057 vp |= v >> 16;
8058 write_dcache040(addr, vp);
8059 } else if (currprefs.cpu_memory_cycle_exact) {
8060 mem_access_delay_word_write_ce020(addr + 0, v >> 16);
8061 } else {
8062 put_word(addr + 0, v >> 16);
8063 }
8064 if (is_dcache040(addr + 4)) {
8065 vp = read_dcache040(addr + 4);
8066 vp &= 0x0000ffff;
8067 vp |= v << 16;
8068 write_dcache040(addr + 4, vp);
8069 } else if (currprefs.cpu_memory_cycle_exact) {
8070 mem_access_delay_word_write_ce020(addr + 2, v);
8071 } else {
8072 put_word(addr + 2, v);
8073 }
8074 }
8075 #endif
8076 }
put_word_cache_040(uaecptr addr,uae_u32 v)8077 void put_word_cache_040(uaecptr addr, uae_u32 v)
8078 {
8079 #if 1
8080 if (nocache040(addr))
8081 mem_access_delay_word_write_ce020(addr, v);
8082 else
8083 put_word(addr, v);
8084 #else
8085 if (is_dcache040(addr)) {
8086 uae_u32 vp;
8087 vp = read_dcache040(addr);
8088 if (addr & 2) {
8089 vp &= 0xffff0000;
8090 vp |= v & 0xffff;
8091 } else {
8092 vp &= 0x0000ffff;
8093 vp |= v << 16;
8094 }
8095 write_dcache040(addr, vp);
8096 } else if (currprefs.cpu_memory_cycle_exact) {
8097 mem_access_delay_word_write_ce020(addr, v);
8098 } else {
8099 put_word(addr, v);
8100 }
8101 #endif
8102 }
put_byte_cache_040(uaecptr addr,uae_u32 v)8103 void put_byte_cache_040(uaecptr addr, uae_u32 v)
8104 {
8105 #if 1
8106 if (nocache040(addr))
8107 mem_access_delay_byte_write_ce020(addr, v);
8108 else
8109 put_byte(addr, v);
8110 #else
8111 if (is_dcache040(addr)) {
8112 uae_u32 vp;
8113 uae_u32 mask = 0xff000000 >> (addr & 3);
8114 vp = read_dcache040(addr);
8115 vp &= ~mask;
8116 vp |= (v << (3 - (addr & 3))) & mask;
8117 write_dcache040(addr, vp);
8118 } else if (currprefs.cpu_memory_cycle_exact) {
8119 mem_access_delay_byte_write_ce020(addr, v);
8120 } else {
8121 put_byte(addr, v);
8122 }
8123 #endif
8124 }
8125
get_long_cache_040(uaecptr addr)8126 uae_u32 get_long_cache_040(uaecptr addr)
8127 {
8128 #if 1
8129 if (nocache040(addr))
8130 return mem_access_delay_long_read_ce020(addr);
8131 else
8132 return get_long(addr);
8133 #else
8134 uae_u32 v1, v2;
8135 v1 = read_dcache040(addr);
8136 if ((addr & 2) == 0)
8137 return v1;
8138 v2 = read_dcache040(addr + 4);
8139 return (v2 >> 16) | (v1 << 16);
8140 #endif
8141 }
get_word_cache_040(uaecptr addr)8142 uae_u32 get_word_cache_040(uaecptr addr)
8143 {
8144 #if 1
8145 if (nocache040(addr))
8146 return mem_access_delay_word_read_ce020(addr);
8147 else
8148 return get_word(addr);
8149 #else
8150 uae_u32 v = read_dcache040(addr);
8151 return v >> ((addr & 2) ? 0 : 16);
8152 #endif
8153 }
get_byte_cache_040(uaecptr addr)8154 uae_u32 get_byte_cache_040(uaecptr addr)
8155 {
8156 #if 1
8157 if (nocache040(addr))
8158 return mem_access_delay_byte_read_ce020(addr);
8159 else
8160 return get_byte(addr);
8161 #else
8162 uae_u32 v = read_dcache040(addr);
8163 return v >> (8 * (3 - (addr & 3)));
8164 #endif
8165 }
next_iword_cache040(void)8166 uae_u32 next_iword_cache040(void)
8167 {
8168 uae_u32 r = get_word_icache040(m68k_getpci());
8169 m68k_incpci(2);
8170 return r;
8171 }
next_ilong_cache040(void)8172 uae_u32 next_ilong_cache040(void)
8173 {
8174 uae_u32 r = get_long_icache040(m68k_getpci());
8175 m68k_incpci(4);
8176 return r;
8177 }
8178
flush_dcache(uaecptr addr,int size)8179 void flush_dcache (uaecptr addr, int size)
8180 {
8181 if (!currprefs.cpu_memory_cycle_exact && !currprefs.cpu_compatible)
8182 return;
8183 if (currprefs.cpu_model >= 68030) {
8184 for (int i = 0; i < CACHELINES030; i++) {
8185 dcaches030[i].valid[0] = 0;
8186 dcaches030[i].valid[1] = 0;
8187 dcaches030[i].valid[2] = 0;
8188 dcaches030[i].valid[3] = 0;
8189 }
8190 }
8191 }
8192
fill_prefetch_030(void)8193 void fill_prefetch_030 (void)
8194 {
8195 uaecptr pc = m68k_getpc ();
8196 uaecptr pc2 = pc;
8197 pc &= ~3;
8198 regs.pipeline_pos = 0;
8199 regs.pipeline_stop = 0;
8200
8201 fill_icache030 (pc);
8202 if (currprefs.cpu_cycle_exact)
8203 do_cycles_ce020_internal(2);
8204 regs.prefetch020[0] = regs.cacheholdingdata020;
8205
8206 fill_icache030 (pc + 4);
8207 if (currprefs.cpu_cycle_exact)
8208 do_cycles_ce020_internal(2);
8209 regs.prefetch020[1] = regs.cacheholdingdata020;
8210
8211 #if MORE_ACCURATE_68020_PIPELINE
8212 if (pc2 & 2) {
8213 pipeline_020(regs.prefetch020[0], pc);
8214 pipeline_020(regs.prefetch020[1] >> 16, pc);
8215 } else {
8216 pipeline_020(regs.prefetch020[0] >> 16, pc);
8217 pipeline_020(regs.prefetch020[0], pc);
8218 }
8219 #endif
8220
8221 #ifdef CPUEMU_23
8222 if (currprefs.cpu_cycle_exact)
8223 regs.irc = get_word_ce030_prefetch (0);
8224 else
8225 #endif
8226 #ifdef CPUEMU_22
8227 regs.irc = get_word_030_prefetch(0);
8228 #endif
8229 }
8230
fill_prefetch_020(void)8231 void fill_prefetch_020 (void)
8232 {
8233 uaecptr pc = m68k_getpc ();
8234 uaecptr pc2 = pc;
8235 pc &= ~3;
8236 uae_u32 (*fetch)(uaecptr) = currprefs.cpu_memory_cycle_exact ? mem_access_delay_longi_read_ce020 : get_longi;
8237 regs.pipeline_pos = 0;
8238 regs.pipeline_stop = 0;
8239 regs.pipeline_r8[0] = regs.pipeline_r8[1] = -1;
8240
8241 fill_icache020 (pc, fetch);
8242 if (currprefs.cpu_cycle_exact)
8243 do_cycles_ce020_internal(2);
8244 regs.prefetch020[0] = regs.cacheholdingdata020;
8245
8246 fill_icache020 (pc + 4, fetch);
8247 if (currprefs.cpu_cycle_exact)
8248 do_cycles_ce020_internal(2);
8249 regs.prefetch020[1] = regs.cacheholdingdata020;
8250
8251 #if MORE_ACCURATE_68020_PIPELINE
8252 if (pc2 & 2) {
8253 pipeline_020(regs.prefetch020[0], pc);
8254 pipeline_020(regs.prefetch020[1] >> 16, pc);
8255 } else {
8256 pipeline_020(regs.prefetch020[0] >> 16, pc);
8257 pipeline_020(regs.prefetch020[0], pc);
8258 }
8259 #endif
8260
8261 if (currprefs.cpu_cycle_exact)
8262 regs.irc = get_word_ce020_prefetch (0);
8263 else
8264 regs.irc = get_word_020_prefetch (0);
8265 }
8266
fill_prefetch(void)8267 void fill_prefetch (void)
8268 {
8269 regs.pipeline_pos = 0;
8270 if (currprefs.cachesize)
8271 return;
8272 if (!currprefs.cpu_compatible)
8273 return;
8274 if (currprefs.cpu_model >= 68040) {
8275 if (currprefs.cpu_compatible || currprefs.cpu_memory_cycle_exact) {
8276 fill_icache040(m68k_getpc() + 16);
8277 fill_icache040(m68k_getpc());
8278 }
8279 } else if (currprefs.cpu_model == 68020) {
8280 fill_prefetch_020 ();
8281 } else if (currprefs.cpu_model == 68030) {
8282 fill_prefetch_030 ();
8283 } else if (currprefs.cpu_model <= 68010) {
8284 uaecptr pc = m68k_getpc ();
8285 regs.ir = x_get_word (pc);
8286 regs.irc = x_get_word (pc + 2);
8287 }
8288 }
8289