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 = &regs;
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 = &regs;
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 = &regs;
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 = &regs;
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 = &regs;
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 = &regs;
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 = &regs;
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 = &regs;
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 = &regs;
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 = &regs;
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