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