1 /*
2  * newcpu.cpp - CPU emulation
3  *
4  * Copyright (c) 2010 ARAnyM dev team (see AUTHORS)
5  *
6  *
7  * Inspired by Christian Bauer's Basilisk II
8  *
9  * This file is part of the ARAnyM project which builds a new and powerful
10  * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
11  *
12  * ARAnyM is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * ARAnyM is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with ARAnyM; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26  /*
27   * UAE - The Un*x Amiga Emulator
28   *
29   * MC68000 emulation
30   *
31   * (c) 1995 Bernd Schmidt
32   */
33 
34 #include "sysdeps.h"
35 #include <cassert>
36 
37 #include "cpu_emulation.h"
38 #include "main.h"
39 #include "emul_op.h"
40 #include "m68k.h"
41 #include "memory-uae.h"
42 #include "readcpu.h"
43 #include "newcpu.h"
44 #ifdef USE_JIT
45 # include "compiler/compemu.h"
46 #endif
47 #include "fpu/fpu.h"
48 #include "natfeats.h"
49 #include "disasm-glue.h"
50 
51 #include <cstdlib>
52 
53 #define DEBUG 0
54 #include "debug.h"
55 
56 #define SANITY_CHECK_ATC 1
57 
58 struct fixup fixup = {0, 0, 0};
59 
60 int quit_program = 0;
61 int exit_val = 0;
62 
63 // For instruction $7139
64 bool cpu_debugging = false;
65 
66 struct flag_struct regflags;
67 
68 /* LongJump buffers */
69 #ifdef EXCEPTIONS_VIA_LONGJMP
70 JMP_BUF excep_env;
71 #endif
72 /* Opcode of faulting instruction */
73 uae_u16 last_op_for_exception_3;
74 /* PC at fault time */
75 uaecptr last_addr_for_exception_3;
76 /* Address that generated the exception */
77 uaecptr last_fault_for_exception_3;
78 
79 int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
80 int imm8_table[] = { 8,1,2,3,4,5,6,7 };
81 
82 int movem_index1[256];
83 int movem_index2[256];
84 int movem_next[256];
85 
86 #ifdef FLIGHT_RECORDER
87 
88 // feel free to edit the following defines to customize the dump
89 #define FRLOG_HOTKEY	1	/* 1 = dump only when hotkey is held down */
90 #define FRLOG_ALL	1	/* 1 = dump continuously to ever growing log */
91 #define FRLOG_IRQ	0	/* 1 = dump also CPU in interrupts */
92 #define FRLOG_REGS	0	/* 1 = dump also all data/address registers */
93 #define FRLOG_SIZE	8192	/* this many instructions in single dump */
94 
95 struct rec_step {
96 	uae_u32 d[8];
97 	uae_u32 a[8];
98 	uae_u32 pc;
99 	uae_u16 sr;
100 	uae_u32 usp;
101 	uae_u32 msp;
102 	uae_u32 isp;
103 	uae_u16 instr;
104 };
105 
106 bool cpu_flight_recorder_active = false;
107 
108 #if FRLOG_ALL
109 const int LOG_SIZE = 10;
110 #else
111 const int LOG_SIZE = FRLOG_SIZE;
112 #endif
113 static rec_step frlog[LOG_SIZE];
114 static int log_ptr = -1; // First time initialization
115 
log_filename(void)116 static const char *log_filename(void)
117 {
118 	const char *name = getenv("M68K_LOG_FILE");
119 	return name ? name : "log.68k";
120 }
121 
dump_flight_recorder(void)122 void dump_flight_recorder(void)
123 {
124 #if FRLOG_ALL
125 	FILE *f = fopen(log_filename(), "a");
126 #else
127 	FILE *f = fopen(log_filename(), "w");
128 #endif
129 	if (f == NULL)
130 		return;
131 	for (int i = 0; i < LOG_SIZE; i++) {
132 		int j = (i + log_ptr) % LOG_SIZE;
133 		fprintf(f, "pc %08x  instr %04x  sr %04x  usp %08x  msp %08x  isp %08x\n", frlog[j].pc, frlog[j].instr, frlog[j].sr, frlog[j].usp, frlog[j].msp, frlog[j].isp);
134 	// adding a simple opcode -> assembler conversion table would help
135 #if FRLOG_REGS
136 		fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", frlog[j].d[0], frlog[j].d[1], frlog[j].d[2], frlog[j].d[3]);
137 		fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", frlog[j].d[4], frlog[j].d[5], frlog[j].d[6], frlog[j].d[7]);
138 		fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", frlog[j].a[0], frlog[j].a[1], frlog[j].a[2], frlog[j].a[3]);
139 		fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", frlog[j].a[4], frlog[j].a[5], frlog[j].a[6], frlog[j].a[7]);
140 #endif
141 		m68k_disasm(f, frlog[j].pc, NULL, 1);
142 	}
143 	fclose(f);
144 }
145 
m68k_record_step(uaecptr pc,int opcode)146 void m68k_record_step(uaecptr pc, int opcode)
147 {
148 	static bool last_state = false;
149 
150 #if FRLOG_HOTKEY
151 	if (! cpu_flight_recorder_active) {
152 		if (last_state) {
153 			// dump log out
154 		    	dump_flight_recorder();
155 
156 			// remember last state
157 			last_state = false;
158 		}
159 		return;
160 	}
161 #endif
162 
163 	if (! last_state) {
164 		// reset old log
165 		log_ptr = 0;
166 		memset(frlog, 0, sizeof(frlog));
167 		// remember last state
168 		last_state = true;
169 	}
170 
171 #if FRLOG_REGS
172 	for (int i = 0; i < 8; i++) {
173 		frlog[log_ptr].d[i] = m68k_dreg(regs, i);
174 		frlog[log_ptr].a[i] = m68k_areg(regs, i);
175 	}
176 #endif
177 	frlog[log_ptr].pc = pc;
178 
179 	MakeSR();
180 #if ! FRLOG_IRQ
181 	// is CPU in interrupt handler? Quit if should not be logged.
182 	if (regs.s && !regs.m) return;
183 #endif
184 	frlog[log_ptr].sr = regs.sr;
185 	frlog[log_ptr].usp = regs.usp;
186 	frlog[log_ptr].msp = regs.msp;
187 	frlog[log_ptr].isp = regs.isp;
188 	frlog[log_ptr].instr = opcode;
189 
190 	log_ptr = (log_ptr + 1) % LOG_SIZE;
191 #if FRLOG_ALL
192 	if (log_ptr == 0) dump_flight_recorder();
193 #endif
194 }
195 #endif /* FLIGHT_RECORDER */
196 
197 int broken_in;
198 
cft_map(unsigned int f)199 static inline unsigned int cft_map (unsigned int f)
200 {
201 #if !defined(HAVE_GET_WORD_UNSWAPPED) || defined(FULLMMU)
202     return f;
203 #else
204     return do_byteswap_16(f);
205 #endif
206 }
207 
op_illg_1(uae_u32 opcode)208 void REGPARAM2 op_illg_1 (uae_u32 opcode)
209 {
210     op_illg (cft_map (opcode));
211 }
212 
213 
init_m68k(void)214 void init_m68k (void)
215 {
216     int i;
217 
218     for (i = 0 ; i < 256 ; i++) {
219 	int j;
220 	for (j = 0 ; j < 8 ; j++) {
221 		if (i & (1 << j)) break;
222 	}
223 	movem_index1[i] = j;
224 	movem_index2[i] = 7-j;
225 	movem_next[i] = i & (~(1 << j));
226     }
227     fpu_init (CPUType == 4);
228 }
229 
exit_m68k(void)230 void exit_m68k (void)
231 {
232 	fpu_exit ();
233 }
234 
235 struct regstruct regs;
236 // MJ static struct regstruct regs_backup[16];
237 // MJ static int backup_pointer = 0;
238 
239 
240 #ifdef FULLMMU
get_ibyte_1(uae_u32 o)241 static inline uae_u8 get_ibyte_1(uae_u32 o)
242 {
243     return get_ibyte(o);
244 }
get_iword_1(uae_u32 o)245 static inline uae_u16 get_iword_1(uae_u32 o)
246 {
247     return get_iword(o);
248 }
get_ilong_1(uae_u32 o)249 static inline uae_u32 get_ilong_1(uae_u32 o)
250 {
251     return get_ilong(o);
252 }
253 #else
254 # define get_ibyte_1(o) get_byte(m68k_getpc() + (o) + 1)
255 # define get_iword_1(o) get_word(m68k_getpc() + (o))
256 # define get_ilong_1(o) get_long(m68k_getpc() + (o))
257 #endif
258 
259 /*
260  * extract bitfield data from memory and return it in the MSBs
261  * bdata caches the unmodified data for put_bitfield()
262  */
get_bitfield(uae_u32 src,uae_u32 bdata[2],uae_s32 offset,int width)263 uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width)
264 {
265 	uae_u32 tmp, res, mask;
266 
267 	offset &= 7;
268 	mask = 0xffffffffu << (32 - width);
269 	switch ((offset + width + 7) >> 3) {
270 	case 1:
271 		tmp = get_byte(src);
272 		res = tmp << (24 + offset);
273 		bdata[0] = tmp & ~(mask >> (24 + offset));
274 		break;
275 	case 2:
276 		tmp = get_word(src);
277 		res = tmp << (16 + offset);
278 		bdata[0] = tmp & ~(mask >> (16 + offset));
279 		break;
280 	case 3:
281 		tmp = get_word(src);
282 		res = tmp << (16 + offset);
283 		bdata[0] = tmp & ~(mask >> (16 + offset));
284 		tmp = get_byte(src + 2);
285 		res |= tmp << (8 + offset);
286 		bdata[1] = tmp & ~(mask >> (8 + offset));
287 		break;
288 	case 4:
289 		tmp = get_long(src);
290 		res = tmp << offset;
291 		bdata[0] = tmp & ~(mask >> offset);
292 		break;
293 	case 5:
294 		tmp = get_long(src);
295 		res = tmp << offset;
296 		bdata[0] = tmp & ~(mask >> offset);
297 		tmp = get_byte(src + 4);
298 		res |= tmp >> (8 - offset);
299 		bdata[1] = tmp & ~(mask << (8 - offset));
300 		break;
301 	default:
302 		/* Panic? */
303 		res = 0;
304 		break;
305 	}
306 	return res;
307 }
308 
309 /*
310  * write bitfield data (in the LSBs) back to memory, upper bits
311  * must be cleared already.
312  */
put_bitfield(uae_u32 dst,uae_u32 bdata[2],uae_u32 val,uae_s32 offset,int width)313 void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width)
314 {
315 	offset = (offset & 7) + width;
316 	switch ((offset + 7) >> 3) {
317 	case 1:
318 		put_byte(dst, bdata[0] | (val << (8 - offset)));
319 		break;
320 	case 2:
321 		put_word(dst, bdata[0] | (val << (16 - offset)));
322 		break;
323 	case 3:
324 		put_word(dst, bdata[0] | (val >> (offset - 16)));
325 		put_byte(dst + 2, bdata[1] | (val << (24 - offset)));
326 		break;
327 	case 4:
328 		put_long(dst, bdata[0] | (val << (32 - offset)));
329 		break;
330 	case 5:
331 		put_long(dst, bdata[0] | (val >> (offset - 32)));
332 		put_byte(dst + 4, bdata[1] | (val << (40 - offset)));
333 		break;
334 	}
335 }
336 
get_disp_ea_020(uae_u32 base,uae_u32 dp)337 uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp)
338 {
339     int reg = (dp >> 12) & 15;
340     uae_s32 regd = regs.regs[reg];
341     if ((dp & 0x800) == 0)
342 	regd = (uae_s32)(uae_s16)regd;
343     regd <<= (dp >> 9) & 3;
344     if (dp & 0x100) {
345 	uae_s32 outer = 0;
346 	if (dp & 0x80) base = 0;
347 	if (dp & 0x40) regd = 0;
348 
349 	if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword();
350 	if ((dp & 0x30) == 0x30) base += next_ilong();
351 
352 	if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword();
353 	if ((dp & 0x3) == 0x3) outer = next_ilong();
354 
355 	if ((dp & 0x4) == 0) base += regd;
356 	if (dp & 0x3) base = get_long (base);
357 	if (dp & 0x4) base += regd;
358 
359 	return base + outer;
360     } else {
361 	return base + (uae_s32)((uae_s8)dp) + regd;
362     }
363 }
364 
get_disp_ea_000(uae_u32 base,uae_u32 dp)365 uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
366 {
367     int reg = (dp >> 12) & 15;
368     uae_s32 regd = regs.regs[reg];
369 #if 1
370     if ((dp & 0x800) == 0)
371 	regd = (uae_s32)(uae_s16)regd;
372     return base + (uae_s8)dp + regd;
373 #else
374     /* Branch-free code... benchmark this again now that
375      * things are no longer inline.  */
376     uae_s32 regd16;
377     uae_u32 mask;
378     mask = ((dp & 0x800) >> 11) - 1;
379     regd16 = (uae_s32)(uae_s16)regd;
380     regd16 &= mask;
381     mask = ~mask;
382     base += (uae_s8)dp;
383     regd &= mask;
384     regd |= regd16;
385     return base + regd;
386 #endif
387 }
388 
MakeSR(void)389 void MakeSR (void)
390 {
391 #if 0
392     assert((regs.t1 & 1) == regs.t1);
393     assert((regs.t0 & 1) == regs.t0);
394     assert((regs.s & 1) == regs.s);
395     assert((regs.m & 1) == regs.m);
396     assert((XFLG & 1) == XFLG);
397     assert((NFLG & 1) == NFLG);
398     assert((ZFLG & 1) == ZFLG);
399     assert((VFLG & 1) == VFLG);
400     assert((CFLG & 1) == CFLG);
401 #endif
402     regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
403 	       | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
404 	       | (GET_XFLG() << 4) | (GET_NFLG() << 3) | (GET_ZFLG() << 2) | (GET_VFLG() << 1)
405 	       | GET_CFLG());
406 }
407 
MakeFromSR(void)408 void MakeFromSR (void)
409 {
410     int oldm = regs.m;
411     int olds = regs.s;
412 
413     regs.t1 = (regs.sr >> 15) & 1;
414     regs.t0 = (regs.sr >> 14) & 1;
415     regs.s = (regs.sr >> 13) & 1;
416     mmu_set_super(regs.s);
417     regs.m = (regs.sr >> 12) & 1;
418     regs.intmask = (regs.sr >> 8) & 7;
419     SET_XFLG ((regs.sr >> 4) & 1);
420     SET_NFLG ((regs.sr >> 3) & 1);
421     SET_ZFLG ((regs.sr >> 2) & 1);
422     SET_VFLG ((regs.sr >> 1) & 1);
423     SET_CFLG (regs.sr & 1);
424 	if (olds != regs.s) {
425 	    if (olds) {
426 		if (oldm)
427 		    regs.msp = m68k_areg(regs, 7);
428 		else
429 		    regs.isp = m68k_areg(regs, 7);
430 		m68k_areg(regs, 7) = regs.usp;
431 	    } else {
432 		regs.usp = m68k_areg(regs, 7);
433 		m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
434 	    }
435 	} else if (olds && oldm != regs.m) {
436 	    if (oldm) {
437 		regs.msp = m68k_areg(regs, 7);
438 		m68k_areg(regs, 7) = regs.isp;
439 	    } else {
440 		regs.isp = m68k_areg(regs, 7);
441 		m68k_areg(regs, 7) = regs.msp;
442 	    }
443 	}
444 
445     // SPCFLAGS_SET( SPCFLAG_INT );
446     if (regs.t1 || regs.t0)
447 	SPCFLAGS_SET( SPCFLAG_TRACE );
448     else
449 	SPCFLAGS_CLEAR( SPCFLAG_TRACE );
450 }
451 
452 /* for building exception frames */
exc_push_word(uae_u16 w)453 static inline void exc_push_word(uae_u16 w)
454 {
455     m68k_areg(regs, 7) -= 2;
456     put_word(m68k_areg(regs, 7), w);
457 }
exc_push_long(uae_u32 l)458 static inline void exc_push_long(uae_u32 l)
459 {
460     m68k_areg(regs, 7) -= 4;
461     put_long (m68k_areg(regs, 7), l);
462 }
463 
exc_make_frame(int format,uae_u16 sr,uae_u32 currpc,int nr,uae_u32 x0,uae_u32 x1)464 static inline void exc_make_frame(
465 		int format,
466 		uae_u16	sr,
467 		uae_u32 currpc,
468 		int nr,
469 		uae_u32 x0,
470 		uae_u32 x1
471 )
472 {
473     switch(format) {
474      case 4:
475 	exc_push_long(x1);
476 	exc_push_long(x0);
477 	break;
478      case 3:
479      case 2:
480 	exc_push_long(x0);
481 	break;
482     }
483 
484     exc_push_word((format << 12) + (nr * 4));	/* format | vector */
485     exc_push_long(currpc);
486     exc_push_word(sr);
487 }
488 
489 #ifdef EXCEPTIONS_VIA_LONGJMP
490 static int building_bus_fault_stack_frame=0;
491 #endif
492 
Exception(int nr,uaecptr oldpc)493 void Exception(int nr, uaecptr oldpc)
494 {
495     uae_u32 currpc = m68k_getpc ();
496     MakeSR();
497 
498     if (fixup.flag)
499     {
500         m68k_areg(regs, fixup.reg) = fixup.value;
501         fixup.flag = 0;
502     }
503 
504     if (!regs.s) {
505 	regs.usp = m68k_areg(regs, 7);
506 	m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
507 	regs.s = 1;
508 	mmu_set_super(1);
509     }
510 
511     if (nr == 2) {
512     	/* BUS ERROR handler begins */
513 #ifdef ENABLE_EPSLIMITER
514         check_eps_limit(currpc);
515 #endif
516         // panicbug("Exception Nr. %d CPC: %08x NPC: %08x SP=%08x Addr: %08x", nr, currpc, get_long (regs.vbr + 4*nr), m68k_areg(regs, 7), regs.mmu_fault_addr);
517 #ifdef EXCEPTIONS_VIA_LONGJMP
518 	if (!building_bus_fault_stack_frame)
519 #else
520 	try
521 #endif
522 	{
523 #ifdef EXCEPTIONS_VIA_LONGJMP
524             building_bus_fault_stack_frame= 1;
525 #endif
526 	    /* 68040 */
527 	    exc_push_long(0);	/* PD3 */
528 	    exc_push_long(0);	/* PD2 */
529 	    exc_push_long(0);	/* PD1 */
530 	    exc_push_long(0);	/* PD0/WB1D */
531 	    exc_push_long(0);	/* WB1A */
532 	    exc_push_long(0);	/* WB2D */
533 	    exc_push_long(0);	/* WB2A */
534 	    exc_push_long(regs.wb3_data);	/* WB3D */
535 	    exc_push_long(regs.mmu_fault_addr);	/* WB3A */
536 	    exc_push_long(regs.mmu_fault_addr);
537 	    exc_push_word(0);	/* WB1S */
538 	    exc_push_word(0);	/* WB2S */
539 	    exc_push_word(regs.wb3_status);	/* WB3S */
540 	    regs.wb3_status = 0;
541 	    exc_push_word(regs.mmu_ssw);
542 	    exc_push_long(regs.mmu_fault_addr); /* EA */
543 	    exc_make_frame(7, regs.sr, regs.fault_pc, 2, 0, 0);
544 
545 	}
546 #ifdef EXCEPTIONS_VIA_LONGJMP
547 	else
548 #else
549 	catch (m68k_exception)
550 #endif
551 	{
552             report_double_bus_error();
553 #ifdef EXCEPTIONS_VIA_LONGJMP
554             building_bus_fault_stack_frame= 0;
555 #endif
556 	    return;
557         }
558 
559 #ifdef EXCEPTIONS_VIA_LONGJMP
560 	building_bus_fault_stack_frame= 0;
561 #endif
562         /* end of BUS ERROR handler */
563     } else if (nr == 3) {
564 	exc_make_frame(2, regs.sr, last_addr_for_exception_3, nr,
565 			last_fault_for_exception_3 & 0xfffffffe, 0);
566     } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
567 	/* div by zero, CHK, TRAP or TRACE */
568 	exc_make_frame(2, regs.sr, currpc, nr, oldpc, 0);
569     } else if (regs.m && nr >= 24 && nr < 32) {
570 	/* interrupts! */
571 	exc_make_frame(0, regs.sr, currpc, nr, 0, 0);
572 	regs.sr |= (1 << 13);
573 	regs.msp = m68k_areg(regs, 7);
574 	m68k_areg(regs, 7) = regs.isp;
575 
576 	exc_make_frame(1,	/* throwaway */
577 			regs.sr, currpc, nr, 0, 0);
578     } else {
579 	exc_make_frame(0, regs.sr, currpc, nr, 0, 0);
580     }
581     m68k_setpc (get_long (regs.vbr + 4*nr));
582     SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE );
583     fill_prefetch_0 ();
584     regs.t1 = regs.t0 = regs.m = 0;
585     SPCFLAGS_CLEAR(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
586 }
587 
Interrupt(int nr)588 static void Interrupt(int nr)
589 {
590     assert(nr < 8 && nr >= 0);
591     Exception(nr+24, 0);
592 
593     regs.intmask = nr;
594     // why the hell the SPCFLAG_INT is to be set??? (joy)
595     // regs.spcflags |= SPCFLAG_INT; (disabled by joy)
596 }
597 
SCCInterrupt(int nr)598 static void SCCInterrupt(int nr)
599 {
600     // fprintf(stderr, "CPU: in SCCInterrupt\n");
601     Exception(nr, 0);
602 
603     regs.intmask = 5;// ex 5
604 }
605 
MFPInterrupt(int nr)606 static void MFPInterrupt(int nr)
607 {
608     // fprintf(stderr, "CPU: in MFPInterrupt\n");
609     Exception(nr, 0);
610 
611     regs.intmask = 6;
612 }
613 
m68k_move2c(int regno,uae_u32 * regp)614 int m68k_move2c (int regno, uae_u32 *regp)
615 {
616 	switch (regno) {
617 	 case 0: regs.sfc = *regp & 7; break;
618 	 case 1: regs.dfc = *regp & 7; break;
619 	 case 2: regs.cacr = *regp & 0x80008000;
620 #ifdef USE_JIT
621 		 set_cache_state(regs.cacr & 0x8000);
622 		 if (*regp & 0x08) {	/* Just to be on the safe side */
623 			flush_icache(2);
624 		 }
625 #endif
626 		 break;
627 	 case 3: mmu_set_tc(*regp & 0xc000); break;
628 	 case 4:
629 	 case 5:
630 	 case 6:
631 	 case 7: mmu_set_ttr(regno, *regp & 0xffffe364); break;
632 	 case 0x800: regs.usp = *regp; break;
633 	 case 0x801: regs.vbr = *regp; break;
634 	 case 0x802: regs.caar = *regp & 0xfc; break;
635 	 case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
636 	 case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
637 	 case 0x805: mmu_set_mmusr(*regp); break;
638 	 case 0x806: regs.urp = *regp & MMU_ROOT_PTR_ADDR_MASK; break;
639 	 case 0x807: regs.srp = *regp & MMU_ROOT_PTR_ADDR_MASK; break;
640 	 default:
641 	    op_illg (0x4E7B);
642 	    return 0;
643 	}
644     return 1;
645 }
646 
m68k_movec2(int regno,uae_u32 * regp)647 int m68k_movec2 (int regno, uae_u32 *regp)
648 {
649 	switch (regno) {
650 	 case 0: *regp = regs.sfc; break;
651 	 case 1: *regp = regs.dfc; break;
652 	 case 2: *regp = regs.cacr; break;
653 	 case 3: *regp = regs.tc; break;
654 	 case 4: *regp = regs.itt0; break;
655 	 case 5: *regp = regs.itt1; break;
656 	 case 6: *regp = regs.dtt0; break;
657 	 case 7: *regp = regs.dtt1; break;
658 	 case 0x800: *regp = regs.usp; break;
659 	 case 0x801: *regp = regs.vbr; break;
660 	 case 0x802: *regp = regs.caar; break;
661 	 case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
662 	 case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
663 	 case 0x805: *regp = regs.mmusr; break;
664 	 case 0x806: *regp = regs.urp; break;
665 	 case 0x807: *regp = regs.srp; break;
666 	 default:
667 	    op_illg (0x4E7A);
668 	    return 0;
669 	}
670     return 1;
671 }
672 
673 #if !defined(uae_s64)
674 static inline int
div_unsigned(uae_u32 src_hi,uae_u32 src_lo,uae_u32 div,uae_u32 * quot,uae_u32 * rem)675 div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
676 {
677 	uae_u32 q = 0, cbit = 0;
678 	int i;
679 
680 	if (div <= src_hi) {
681 	    return 1;
682 	}
683 	for (i = 0 ; i < 32 ; i++) {
684 		cbit = src_hi & 0x80000000ul;
685 		src_hi <<= 1;
686 		if (src_lo & 0x80000000ul) src_hi++;
687 		src_lo <<= 1;
688 		q = q << 1;
689 		if (cbit || div <= src_hi) {
690 			q |= 1;
691 			src_hi -= div;
692 		}
693 	}
694 	*quot = q;
695 	*rem = src_hi;
696 	return 0;
697 }
698 #endif
699 
m68k_divl(uae_u32,uae_u32 src,uae_u16 extra,uaecptr oldpc)700 void m68k_divl (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra, uaecptr oldpc)
701 {
702 #if defined(uae_s64)
703     if (src == 0) {
704 	Exception (5, oldpc);
705 	return;
706     }
707     if (extra & 0x800) {
708 	/* signed variant */
709 	uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
710 	uae_s64 quot, rem;
711 
712 	if (extra & 0x400) {
713 	    a &= 0xffffffffu;
714 	    a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32;
715 	}
716 	rem = a % (uae_s64)(uae_s32)src;
717 	quot = a / (uae_s64)(uae_s32)src;
718 	if ((quot & UVAL64(0xffffffff80000000)) != 0
719 	    && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
720 	{
721 	    SET_VFLG (1);
722 	    SET_NFLG (1);
723 	    SET_CFLG (0);
724 	} else {
725 	    if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
726 	    SET_VFLG (0);
727 	    SET_CFLG (0);
728 	    SET_ZFLG (((uae_s32)quot) == 0);
729 	    SET_NFLG (((uae_s32)quot) < 0);
730 	    m68k_dreg(regs, extra & 7) = rem;
731 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
732 	}
733     } else {
734 	/* unsigned */
735 	uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
736 	uae_u64 quot, rem;
737 
738 	if (extra & 0x400) {
739 	    a &= 0xffffffffu;
740 	    a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32;
741 	}
742 	rem = a % (uae_u64)src;
743 	quot = a / (uae_u64)src;
744 	if (quot > 0xffffffffu) {
745 	    SET_VFLG (1);
746 	    SET_NFLG (1);
747 	    SET_CFLG (0);
748 	} else {
749 	    SET_VFLG (0);
750 	    SET_CFLG (0);
751 	    SET_ZFLG (((uae_s32)quot) == 0);
752 	    SET_NFLG (((uae_s32)quot) < 0);
753 	    m68k_dreg(regs, extra & 7) = rem;
754 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
755 	}
756     }
757 #else
758     if (src == 0) {
759 	Exception (5, oldpc);
760 	return;
761     }
762     if (extra & 0x800) {
763 	/* signed variant */
764 	uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
765 	uae_s32 hi = lo < 0 ? -1 : 0;
766 	uae_s32 save_high;
767 	uae_u32 quot, rem;
768 	uae_u32 sign;
769 
770 	if (extra & 0x400) {
771 	    hi = (uae_s32)m68k_dreg(regs, extra & 7);
772 	}
773 	save_high = hi;
774 	sign = (hi ^ src);
775 	if (hi < 0) {
776 	    hi = ~hi;
777 	    lo = -lo;
778 	    if (lo == 0) hi++;
779 	}
780 	if ((uae_s32)src < 0) src = -src;
781 	if (div_unsigned(hi, lo, src, &quot, &rem) ||
782 	    (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
783 	    SET_VFLG (1);
784 	    SET_NFLG (1);
785 	    SET_CFLG (0);
786 	} else {
787 	    if (sign & 0x80000000) quot = -quot;
788 	    if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
789 	    SET_VFLG (0);
790 	    SET_CFLG (0);
791 	    SET_ZFLG (((uae_s32)quot) == 0);
792 	    SET_NFLG (((uae_s32)quot) < 0);
793 	    m68k_dreg(regs, extra & 7) = rem;
794 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
795 	}
796     } else {
797 	/* unsigned */
798 	uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
799 	uae_u32 hi = 0;
800 	uae_u32 quot, rem;
801 
802 	if (extra & 0x400) {
803 	    hi = (uae_u32)m68k_dreg(regs, extra & 7);
804 	}
805 	if (div_unsigned(hi, lo, src, &quot, &rem)) {
806 	    SET_VFLG (1);
807 	    SET_NFLG (1);
808 	    SET_CFLG (0);
809 	} else {
810 	    SET_VFLG (0);
811 	    SET_CFLG (0);
812 	    SET_ZFLG (((uae_s32)quot) == 0);
813 	    SET_NFLG (((uae_s32)quot) < 0);
814 	    m68k_dreg(regs, extra & 7) = rem;
815 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
816 	}
817     }
818 #endif
819 }
820 
821 #if !defined(uae_s64)
822 static inline void
mul_unsigned(uae_u32 src1,uae_u32 src2,uae_u32 * dst_hi,uae_u32 * dst_lo)823 mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
824 {
825 	uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
826 	uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
827 	uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
828 	uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
829 	uae_u32 lo;
830 
831 	lo = r0 + ((r1 << 16) & 0xffff0000ul);
832 	if (lo < r0) r3++;
833 	r0 = lo;
834 	lo = r0 + ((r2 << 16) & 0xffff0000ul);
835 	if (lo < r0) r3++;
836 	r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
837 	*dst_lo = lo;
838 	*dst_hi = r3;
839 }
840 #endif
841 
m68k_mull(uae_u32,uae_u32 src,uae_u16 extra)842 void m68k_mull (uae_u32 /*opcode*/, uae_u32 src, uae_u16 extra)
843 {
844 #if defined(uae_s64)
845     if (extra & 0x800) {
846 	/* signed variant */
847 	uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
848 
849 	a *= (uae_s64)(uae_s32)src;
850 	SET_VFLG (0);
851 	SET_CFLG (0);
852 	SET_ZFLG (a == 0);
853 	SET_NFLG (a < 0);
854 	if (extra & 0x400)
855 	    m68k_dreg(regs, extra & 7) = a >> 32;
856 	else if ((a & UVAL64(0xffffffff80000000)) != 0
857 		 && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
858 	{
859 	    SET_VFLG (1);
860 	}
861 	m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
862     } else {
863 	/* unsigned */
864 	uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
865 
866 	a *= (uae_u64)src;
867 	SET_VFLG (0);
868 	SET_CFLG (0);
869 	SET_ZFLG (a == 0);
870 	SET_NFLG (((uae_s64)a) < 0);
871 	if (extra & 0x400)
872 	    m68k_dreg(regs, extra & 7) = a >> 32;
873 	else if ((a & UVAL64(0xffffffff00000000)) != 0) {
874 	    SET_VFLG (1);
875 	}
876 	m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
877     }
878 #else
879     if (extra & 0x800) {
880 	/* signed variant */
881 	uae_s32 src1,src2;
882 	uae_u32 dst_lo,dst_hi;
883 	uae_u32 sign;
884 
885 	src1 = (uae_s32)src;
886 	src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
887 	sign = (src1 ^ src2);
888 	if (src1 < 0) src1 = -src1;
889 	if (src2 < 0) src2 = -src2;
890 	mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
891 	if (sign & 0x80000000) {
892 		dst_hi = ~dst_hi;
893 		dst_lo = -dst_lo;
894 		if (dst_lo == 0) dst_hi++;
895 	}
896 	SET_VFLG (0);
897 	SET_CFLG (0);
898 	SET_ZFLG (dst_hi == 0 && dst_lo == 0);
899 	SET_NFLG (((uae_s32)dst_hi) < 0);
900 	if (extra & 0x400)
901 	    m68k_dreg(regs, extra & 7) = dst_hi;
902 	else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
903 		 && ((dst_hi & 0xffffffff) != 0xffffffff
904 		     || (dst_lo & 0x80000000) != 0x80000000))
905 	{
906 	    SET_VFLG (1);
907 	}
908 	m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
909     } else {
910 	/* unsigned */
911 	uae_u32 dst_lo,dst_hi;
912 
913 	mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
914 
915 	SET_VFLG (0);
916 	SET_CFLG (0);
917 	SET_ZFLG (dst_hi == 0 && dst_lo == 0);
918 	SET_NFLG (((uae_s32)dst_hi) < 0);
919 	if (extra & 0x400)
920 	    m68k_dreg(regs, extra & 7) = dst_hi;
921 	else if (dst_hi != 0) {
922 	    SET_VFLG (1);
923 	}
924 	m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
925     }
926 #endif
927 }
928 
929 // If value is greater than zero, this means we are still processing an EmulOp
930 // because the counter is incremented only in m68k_execute(), i.e. interpretive
931 // execution only
932 #ifdef USE_JIT
933 static int m68k_execute_depth = 0;
934 #endif
935 
m68k_reset(void)936 void m68k_reset (void)
937 {
938     regs.s = 1;
939     regs.m = 0;
940     regs.stopped = 0;
941     regs.t1 = 0;
942     regs.t0 = 0;
943     SET_ZFLG (0);
944     SET_XFLG (0);
945     SET_CFLG (0);
946     SET_VFLG (0);
947     SET_NFLG (0);
948     SPCFLAGS_INIT( 0 );
949     regs.intmask = 7;
950     regs.vbr = regs.sfc = regs.dfc = 0;
951 
952     // need to ensure the following order of initialization is correct
953     // (it is definitely better than what it was before this commit
954     //  since it was reading from 0x00000000 in User mode and with active MMU)
955     mmu_set_tc(regs.tc & ~0x8000); /* disable mmu */
956     m68k_areg (regs, 7) = phys_get_long(0x00000000);
957     m68k_setpc (phys_get_long(0x00000004));
958     fill_prefetch_0 ();
959 
960     /* gb-- moved into {fpp,fpu_x86}.cpp::fpu_init()
961     regs.fpcr = regs.fpsr = regs.fpiar = 0; */
962     fpu_reset();
963     // MMU
964     mmu_reset();
965     mmu_set_super(1);
966     // Cache
967     regs.cacr = 0;
968     regs.caar = 0;
969 #ifdef FLIGHT_RECORDER
970 	log_ptr = 0;
971 	memset(frlog, 0, sizeof(frlog));
972 #endif
973 }
974 
m68k_emulop_return(void)975 void m68k_emulop_return(void)
976 {
977 	SPCFLAGS_SET( SPCFLAG_BRK );
978 	quit_program = 1;
979 }
980 
save_regs(struct M68kRegisters & r)981 static void save_regs(struct M68kRegisters &r)
982 {
983 	int i;
984 
985 	for (i=0; i<8; i++) {
986 		r.d[i] = m68k_dreg(regs, i);
987 		r.a[i] = m68k_areg(regs, i);
988 	}
989 	r.pc = m68k_getpc();
990 	MakeSR();
991 	r.sr = regs.sr;
992 	r.isp = regs.isp;
993 	r.usp = regs.usp;
994 	r.msp = regs.msp;
995 	if ((r.sr & 0x2000) == 0)
996 		r.usp = r.a[7];
997 	else if ((r.sr & 0x1000) != 0)
998 		r.msp = r.a[7];
999 	else
1000 		r.isp = r.a[7];
1001 }
1002 
restore_regs(struct M68kRegisters & r)1003 static void restore_regs(struct M68kRegisters &r)
1004 {
1005 	int i;
1006 
1007 	for (i=0; i<8; i++) {
1008 		m68k_dreg(regs, i) = r.d[i];
1009 		m68k_areg(regs, i) = r.a[i];
1010 	}
1011 	regs.isp = r.isp;
1012 	regs.usp = r.usp;
1013 	regs.msp = r.msp;
1014 	regs.sr = r.sr;
1015 	MakeFromSR();
1016 }
1017 
m68k_emulop(uae_u32 opcode)1018 void m68k_emulop(uae_u32 opcode)
1019 {
1020 	struct M68kRegisters r;
1021 	save_regs(r);
1022 	if (EmulOp(opcode, &r))
1023 		restore_regs(r);
1024 }
1025 
m68k_natfeat_id(void)1026 void m68k_natfeat_id(void)
1027 {
1028 	struct M68kRegisters r;
1029 
1030 	/* is it really necessary to save all registers? */
1031 	save_regs(r);
1032 
1033 	memptr stack = r.a[7] + 4;	/* skip return address */
1034 	r.d[0] = nf_get_id(stack);
1035 
1036 	restore_regs(r);
1037 }
1038 
m68k_natfeat_call(void)1039 void m68k_natfeat_call(void)
1040 {
1041 	struct M68kRegisters r;
1042 
1043 	/* is it really necessary to save all registers? */
1044 	save_regs(r);
1045 
1046 	memptr stack = r.a[7] + 4;	/* skip return address */
1047 	bool isSupervisorMode = ((r.sr & 0x2000) == 0x2000);
1048 	r.d[0] = nf_call(stack, isSupervisorMode);
1049 
1050 	restore_regs(r);
1051 }
1052 
m68k_call(uae_u32 pc)1053 static int m68k_call(uae_u32 pc)
1054 {
1055 	VOLATILE int exc = 0;
1056 	m68k_setpc(pc);
1057     TRY(prb) {
1058 #ifdef USE_JIT
1059 		if (bx_options.jit.jit) {
1060 			exec_nostats();
1061 			//			m68k_do_compile_execute();
1062 			// The above call to m68k_do_compile_execute fails with BadAccess in sigsegv_handler (MAC, if it is executed after the first compile_block)
1063 			// (NULL pointer to addr_instr).
1064 			// Call exec_nostats avoids calling compile_block, because stack modification is only temporary
1065 			// which will fill up compile cache with BOGUS data.
1066 			// we can call exec_nostats directly, do our code, and return back here.
1067 		}
1068 		else
1069 #endif
1070 			m68k_do_execute();
1071     }
1072     CATCH(prb) {
1073     	exc = int(prb);
1074     }
1075     return exc;
1076 }
1077 
m68k_alloca(int size)1078 static uae_u32 m68k_alloca(int size)
1079 {
1080 	uae_u32 sp = (m68k_areg(regs, 7) - size) & ~1;
1081 	m68k_areg(regs, 7) = sp;
1082 	if ((regs.sr & 0x2000) == 0)
1083 		regs.usp = sp;
1084 	else if ((regs.sr & 0x1000) != 0)
1085 		regs.msp = sp;
1086 	else
1087 		regs.isp = sp;
1088 	return sp;
1089 }
1090 
linea68000(volatile uae_u16 opcode)1091 uae_u32 linea68000(volatile uae_u16 opcode)
1092 {
1093 	sigjmp_buf jmp;
1094 	struct M68kRegisters r;
1095 	volatile uae_u32 abase = 0;
1096 
1097 	SAVE_EXCEPTION;
1098 	save_regs(r);
1099 
1100 	const int sz = 8 + sizeof(void *);
1101 	volatile uae_u32 sp = 0;
1102 	uae_u32 backup[(sz + 3) / 4];
1103 
1104 	if (sigsetjmp(jmp, 1) == 0)
1105 	{
1106 		void *p = jmp;
1107 		uae_u8 *sp_p;
1108 		int exc;
1109 
1110 		sp = m68k_alloca(sz);
1111 		memcpy(backup, phys_get_real_address(sp), sz);
1112 
1113 		WriteHWMemInt16(sp, opcode);
1114 		WriteHWMemInt16(sp + 2, 0xa0ff);
1115 		WriteHWMemInt32(sp + 4, 13);
1116 		sp_p = phys_get_real_address(sp + 8);
1117 		*((void **)sp_p) = p;
1118 		if ((exc = m68k_call(sp)) != 0)
1119 		{
1120 			panicbug("exception %d in LINEA", exc);
1121 			m68k_dreg(regs, 0) = 0;
1122 		}
1123 	} else
1124 	{
1125 		abase = m68k_dreg(regs, 0);
1126 	}
1127 
1128 	if (sp)	{
1129 		memcpy(phys_get_real_address(sp), backup, sz);
1130 	}
1131 	restore_regs(r);
1132 	m68k_setpc(r.pc);
1133     RESTORE_EXCEPTION;
1134 	return abase;
1135 }
1136 
1137 
rts68000()1138 static void rts68000()
1139 {
1140 	uae_u32 SP = m68k_getpc() + 6;
1141 	sigjmp_buf *p;
1142 	uae_u8 *sp_p = phys_get_real_address(SP);
1143 
1144 	p = (sigjmp_buf *)(*((void **)sp_p));
1145 	SP += sizeof(void *);
1146 	m68k_areg(regs, 7) = SP;
1147 	siglongjmp(*p, 1);
1148 }
1149 
op_illg(uae_u32 opcode)1150 void REGPARAM2 op_illg (uae_u32 opcode)
1151 {
1152 	uaecptr pc = m68k_getpc ();
1153 
1154 	if ((opcode & 0xF000) == 0xA000) {
1155 		if (opcode == 0xa0ff)
1156 		{
1157 			uae_u32 call = ReadHWMemInt32(pc + 2);
1158 			switch (call)
1159 			{
1160 			case 13:
1161 				rts68000();
1162 				return;
1163 			}
1164 			m68k_setpc(pc + 6);
1165 		}
1166 		Exception(0xA,0);
1167 		return;
1168 	}
1169 
1170 	if ((opcode & 0xF000) == 0xF000) {
1171 		Exception(0xB,0);
1172 		return;
1173 	}
1174 
1175 	D(bug("Illegal instruction: %04x at %08x", opcode, pc));
1176 #if defined(USE_JIT) && defined(JIT_DEBUG)
1177 	compiler_dumpstate();
1178 #endif
1179 
1180 	Exception (4,0);
1181 	return;
1182 }
1183 
1184 static uaecptr last_trace_ad = 0;
1185 
do_trace(void)1186 static void do_trace (void)
1187 {
1188     if (regs.t0) {
1189        uae_u16 opcode;
1190        /* should also include TRAP, CHK, SR modification FPcc */
1191        /* probably never used so why bother */
1192        /* We can afford this to be inefficient... */
1193        m68k_setpc (m68k_getpc ());
1194        fill_prefetch_0 ();
1195        opcode = get_word(m68k_getpc());
1196        if (opcode == 0x4e72            /* RTE */
1197            || opcode == 0x4e74                 /* RTD */
1198            || opcode == 0x4e75                 /* RTS */
1199            || opcode == 0x4e77                 /* RTR */
1200            || opcode == 0x4e76                 /* TRAPV */
1201            || (opcode & 0xffc0) == 0x4e80      /* JSR */
1202            || (opcode & 0xffc0) == 0x4ec0      /* JMP */
1203            || (opcode & 0xff00) == 0x6100  /* BSR */
1204            || ((opcode & 0xf000) == 0x6000     /* Bcc */
1205                && cctrue((opcode >> 8) & 0xf))
1206            || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
1207                && !cctrue((opcode >> 8) & 0xf)
1208                && (uae_s16)m68k_dreg(regs, opcode & 7) != 0))
1209       {
1210  	    last_trace_ad = m68k_getpc ();
1211 	    SPCFLAGS_CLEAR( SPCFLAG_TRACE );
1212 	    SPCFLAGS_SET( SPCFLAG_DOTRACE );
1213 	}
1214     } else if (regs.t1) {
1215        last_trace_ad = m68k_getpc ();
1216        SPCFLAGS_CLEAR( SPCFLAG_TRACE );
1217        SPCFLAGS_SET( SPCFLAG_DOTRACE );
1218     }
1219 }
1220 
1221 #define SERVE_VBL_MFP(resetStop)							\
1222 {															\
1223 	if (SPCFLAGS_TEST( SPCFLAG_INT3|SPCFLAG_VBL|SPCFLAG_INT5|SPCFLAG_SCC|SPCFLAG_MFP )) {		\
1224 		if (SPCFLAGS_TEST( SPCFLAG_INT3 )) {					\
1225 			if (3 > regs.intmask) {							\
1226 				Interrupt(3);								\
1227 				regs.stopped = 0;							\
1228 				SPCFLAGS_CLEAR( SPCFLAG_INT3 );				\
1229 				if (resetStop)								\
1230 					SPCFLAGS_CLEAR( SPCFLAG_STOP );			\
1231 			}												\
1232 		}													\
1233 		if (SPCFLAGS_TEST( SPCFLAG_VBL )) {					\
1234 			if (4 > regs.intmask) {							\
1235 				Interrupt(4);								\
1236 				regs.stopped = 0;							\
1237 				SPCFLAGS_CLEAR( SPCFLAG_VBL );				\
1238 				if (resetStop)								\
1239 					SPCFLAGS_CLEAR( SPCFLAG_STOP );			\
1240 			}												\
1241 		}													\
1242 		if (SPCFLAGS_TEST( SPCFLAG_INT5 )) {					\
1243 			if (5 > regs.intmask) {							\
1244 				Interrupt(5);								\
1245 				regs.stopped = 0;							\
1246 				SPCFLAGS_CLEAR( SPCFLAG_INT5 );				\
1247 				if (resetStop)								\
1248 					SPCFLAGS_CLEAR( SPCFLAG_STOP );			\
1249 			}												\
1250 		}													\
1251 		if (SPCFLAGS_TEST( SPCFLAG_SCC )) {					\
1252 			if (5 > regs.intmask) {						\
1253 				int vector_number=SCCdoInterrupt();			\
1254 				if(vector_number){					\
1255 					 SCCInterrupt(vector_number);	        	\
1256 					regs.stopped = 0;				\
1257 					SPCFLAGS_CLEAR( SPCFLAG_SCC);		\
1258 					if (resetStop)					\
1259 						SPCFLAGS_CLEAR( SPCFLAG_STOP );		\
1260 				}							\
1261 				else							\
1262 					SPCFLAGS_CLEAR( SPCFLAG_SCC );		\
1263 			}								\
1264 		}									\
1265 		if (SPCFLAGS_TEST( SPCFLAG_MFP )) {					\
1266 			if (6 > regs.intmask) {							\
1267 				int vector_number = MFPdoInterrupt();		\
1268 				if (vector_number) {						\
1269 					MFPInterrupt(vector_number);			\
1270 					regs.stopped = 0;						\
1271 					if (resetStop)							\
1272 						SPCFLAGS_CLEAR( SPCFLAG_STOP );		\
1273 				}											\
1274 				else										\
1275 					SPCFLAGS_CLEAR( SPCFLAG_MFP );			\
1276 			}												\
1277 		}													\
1278 	}														\
1279 }
1280 
1281 #define SERVE_INTERNAL_IRQ()								\
1282 {															\
1283 	if (SPCFLAGS_TEST( SPCFLAG_INTERNAL_IRQ )) {			\
1284 		SPCFLAGS_CLEAR( SPCFLAG_INTERNAL_IRQ );				\
1285 		invoke200HzInterrupt();								\
1286 	}														\
1287 }
1288 
m68k_do_specialties(void)1289 int m68k_do_specialties(void)
1290 {
1291 	SERVE_INTERNAL_IRQ();
1292 #ifdef USE_JIT
1293 	// Block was compiled
1294 	SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE );
1295 
1296 	// Retain the request to get out of compiled code until
1297 	// we reached the toplevel execution, i.e. the one that
1298 	// can compile then run compiled code. This also means
1299 	// we processed all (nested) EmulOps
1300 	if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN ))
1301 		SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN );
1302 #endif
1303 	/*n_spcinsns++;*/
1304 	if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) {
1305 		Exception (9,last_trace_ad);
1306 	}
1307 #if 0 /* not for ARAnyM; emulating 040 only */
1308 	if ((regs.spcflags & SPCFLAG_STOP) && regs.s == 0 && currprefs.cpu_model <= 68010) {
1309 		// 68000/68010 undocumented special case:
1310 		// if STOP clears S-bit and T was not set:
1311 		// cause privilege violation exception, PC pointing to following instruction.
1312 		// If T was set before STOP: STOP works as documented.
1313 		m68k_unset_stop();
1314 		Exception(8, 0);
1315 	}
1316 #endif
1317 	while (SPCFLAGS_TEST( SPCFLAG_STOP )) {
1318 		if ((regs.sr & 0x700) == 0x700)
1319 		{
1320 			panicbug("STOPed with interrupts disabled, exiting; pc=$%08x", m68k_getpc());
1321 			m68k_dumpstate (stderr, NULL);
1322 #if 0
1323 			quit_program = 1;
1324 #endif
1325 #ifdef FULL_HISTORY
1326 			ndebug::showHistory(20, false);
1327 			m68k_dumpstate (stderr, NULL);
1328 #endif
1329 			return 1;
1330 		}
1331 		// give unused time slices back to OS
1332 		SleepAndWait();
1333 
1334 		SERVE_INTERNAL_IRQ();
1335 		SERVE_VBL_MFP(true);
1336 		if (SPCFLAGS_TEST( SPCFLAG_BRK ))
1337 			break;
1338 	}
1339 	if (SPCFLAGS_TEST( SPCFLAG_TRACE ))
1340 		do_trace ();
1341 
1342 	SERVE_VBL_MFP(false);
1343 
1344 /*
1345 // do not understand the INT vs DOINT stuff so I disabled it (joy)
1346 	if (regs.spcflags & SPCFLAG_INT) {
1347 		regs.spcflags &= ~SPCFLAG_INT;
1348 		regs.spcflags |= SPCFLAG_DOINT;
1349 	}
1350 */
1351 	if (SPCFLAGS_TEST( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ )) {
1352 		SPCFLAGS_CLEAR( SPCFLAG_BRK /*| SPCFLAG_MODE_CHANGE*/ );
1353 		return 1;
1354 	}
1355 
1356 	return 0;
1357 }
1358 
m68k_do_execute(void)1359 void m68k_do_execute (void)
1360 {
1361     uae_u32 pc;
1362     uae_u32 opcode;
1363     for (;;) {
1364 	regs.fault_pc = pc = m68k_getpc();
1365 #ifdef FULL_HISTORY
1366 #ifdef NEED_TO_DEBUG_BADLY
1367 	history[lasthist] = regs;
1368 	historyf[lasthist] =  regflags;
1369 #else
1370 	history[lasthist] = m68k_getpc();
1371 #endif
1372 	if (++lasthist == MAX_HIST) lasthist = 0;
1373 	if (lasthist == firsthist) {
1374 	    if (++firsthist == MAX_HIST) firsthist = 0;
1375 	}
1376 #endif
1377 
1378 #ifndef FULLMMU
1379 #ifdef ARAM_PAGE_CHECK
1380 	if (((pc ^ pc_page) > ARAM_PAGE_MASK)) {
1381 	    check_ram_boundary(pc, 2, false);
1382 	    pc_page = pc;
1383 	    pc_offset = (uintptr)get_real_address(pc, 0, sz_word) - pc;
1384 	}
1385 #else
1386 	check_ram_boundary(pc, 2, false);
1387 #endif
1388 #endif
1389 	opcode = GET_OPCODE;
1390 #ifdef FLIGHT_RECORDER
1391 	m68k_record_step(m68k_getpc(), cft_map(opcode));
1392 #endif
1393 	(*cpufunctbl[opcode])(opcode);
1394 	cpu_check_ticks();
1395 	regs.fault_pc = m68k_getpc();
1396 
1397 	if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
1398 		if (m68k_do_specialties())
1399 			return;
1400 	}
1401     }
1402 }
1403 
m68k_execute(void)1404 void m68k_execute (void)
1405 {
1406 #ifdef USE_JIT
1407     m68k_execute_depth++;
1408 #endif
1409 #ifdef DEBUGGER
1410     VOLATILE bool after_exception = false;
1411 #endif
1412 
1413 setjmpagain:
1414     TRY(prb) {
1415 	for (;;) {
1416 	    if (quit_program > 0) {
1417 		if (quit_program == 1) {
1418 #ifdef FLIGHT_RECORDER
1419 		    dump_flight_recorder();
1420 #endif
1421 		    break;
1422 		}
1423 		quit_program = 0;
1424 		m68k_reset ();
1425 	    }
1426 #ifdef DEBUGGER
1427 	    if (debugging && !after_exception) debug();
1428 	    after_exception = false;
1429 #endif
1430 	    m68k_do_execute();
1431 	}
1432     }
1433     CATCH(prb) {
1434         Exception(prb, 0);
1435 #ifdef DEBUGGER
1436 	after_exception = true;
1437 #endif
1438     	goto setjmpagain;
1439     }
1440 
1441 #ifdef USE_JIT
1442     m68k_execute_depth--;
1443 #endif
1444 }
1445 
m68k_disasm(FILE * f,uaecptr addr,uaecptr * nextpc,int cnt)1446 void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
1447 {
1448 #ifdef HAVE_DISASM_M68K
1449 	char buf[256];
1450 	int size;
1451 
1452 	disasm_info.memory_vma = addr;
1453     while (cnt-- > 0) {
1454 		size = m68k_disasm_to_buf(&disasm_info, buf, 1);
1455     	fprintf(f, "%s\n", buf);
1456     	if (size < 0)
1457     		break;
1458 	}
1459     if (nextpc)
1460 		*nextpc = disasm_info.memory_vma;
1461 #else
1462     if (nextpc)
1463 		*nextpc = addr;
1464 	(void) f;
1465 	(void) cnt;
1466 #endif
1467 }
1468 
1469 #ifdef DEBUGGER
newm68k_disasm(FILE * f,uaecptr addr,uaecptr * nextpc,unsigned int cnt)1470 void newm68k_disasm(FILE *f, uaecptr addr, uaecptr *nextpc, unsigned int cnt)
1471 {
1472 #ifdef HAVE_DISASM_M68K
1473 	char buf[256];
1474 
1475 	disasm_info.memory_vma = addr;
1476     if (cnt == 0) {
1477 		m68k_disasm_to_buf(&disasm_info, buf, 1);
1478     } else {
1479 	    while (cnt-- > 0) {
1480 		m68k_disasm_to_buf(&disasm_info, buf, 1);
1481     	fprintf(f, "%s\n", buf);
1482     	}
1483     }
1484     if (nextpc)
1485 		*nextpc = disasm_info.memory_vma;
1486 #else
1487     if (nextpc)
1488 		*nextpc = addr;
1489 	(void) cnt;
1490 #endif
1491 }
1492 
1493 #endif /* DEBUGGER */
1494 
1495 #ifdef FULL_HISTORY
showDisasm(uaecptr addr)1496 void showDisasm(uaecptr addr) {
1497 #ifdef HAVE_DISASM_M68K
1498 	char buf[256];
1499 
1500 	disasm_info.memory_vma = addr;
1501 	m68k_disasm_to_buf(&disasm_info, buf, 1);
1502 	bug("%s", buf);
1503 #else
1504 	(void) addr;
1505 #endif
1506 }
1507 #endif /* FULL_HISTORY */
1508 
m68k_dumpstate(FILE * out,uaecptr * nextpc)1509 void m68k_dumpstate (FILE *out, uaecptr *nextpc)
1510 {
1511     int i;
1512     for (i = 0; i < 8; i++){
1513 	fprintf (out, "D%d: %08lx ", i, (unsigned long)m68k_dreg(regs, i));
1514 	if ((i & 3) == 3) fprintf (out, "\n");
1515     }
1516     for (i = 0; i < 8; i++){
1517 	fprintf (out, "A%d: %08lx ", i, (unsigned long)m68k_areg(regs, i));
1518 	if ((i & 3) == 3) fprintf (out, "\n");
1519     }
1520     if (regs.s == 0) regs.usp = m68k_areg(regs, 7);
1521     if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7);
1522     if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7);
1523     fprintf (out, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n",
1524 	    (unsigned long)regs.usp, (unsigned long)regs.isp,
1525 	    (unsigned long)regs.msp, (unsigned long)regs.vbr);
1526     fprintf (out, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d TCE=%d TCP=%d\n",
1527 	    regs.t1, regs.t0, regs.s, regs.m,
1528 	    (int)GET_XFLG(), (int)GET_NFLG(), (int)GET_ZFLG(), (int)GET_VFLG(), (int)GET_CFLG(), regs.intmask,
1529 	    regs.mmu_enabled, regs.mmu_pagesize_8k);
1530     fprintf (out, "CACR=%08lx CAAR=%08lx  URP=%08lx  SRP=%08lx\n",
1531             (unsigned long)regs.cacr,
1532 	    (unsigned long)regs.caar,
1533 	    (unsigned long)regs.urp,
1534 	    (unsigned long)regs.srp);
1535     fprintf (out, "DTT0=%08lx DTT1=%08lx ITT0=%08lx ITT1=%08lx\n",
1536             (unsigned long)regs.dtt0,
1537 	    (unsigned long)regs.dtt1,
1538 	    (unsigned long)regs.itt0,
1539 	    (unsigned long)regs.itt1);
1540     for (i = 0; i < 8; i++){
1541 	fprintf (out, "FP%d: %g ", i, (double)fpu.registers[i]);
1542 	if ((i & 3) == 3) fprintf (out, "\n");
1543     }
1544 #if 0
1545     fprintf (out, "N=%d Z=%d I=%d NAN=%d\n",
1546 		(regs.fpsr & 0x8000000) != 0,
1547 		(regs.fpsr & 0x4000000) != 0,
1548 		(regs.fpsr & 0x2000000) != 0,
1549 		(regs.fpsr & 0x1000000) != 0);
1550 #endif
1551     m68k_disasm(out, m68k_getpc (), nextpc, 1);
1552     if (nextpc)
1553 	fprintf (out, "next PC: %08lx\n", (unsigned long)*nextpc);
1554 }
1555