1  /*
2   * UAE - The Un*x Amiga Emulator - CPU core
3   *
4   * MC68000 emulation
5   *
6   * (c) 1995 Bernd Schmidt
7   *
8   * Adaptation to Hatari by Thomas Huth
9   *
10   * This file is distributed under the GNU General Public License, version 2
11   * or at your option any later version. Read the file gpl.txt for details.
12   */
13 
14 
15 /* 2007/11/12	[NP]	Add HATARI_TRACE_CPU_DISASM.							*/
16 /* 2007/11/15	[NP]	In MakeFromSR, writes to m and t0 should be ignored and set to 0 if cpu < 68020 */
17 /* 2007/11/26	[NP]	We set BusErrorPC in m68k_run_1 instead of M68000_BusError, else the BusErrorPC	*/
18 /*			will not point to the opcode that generated the bus error.			*/
19 /*			Huge debug/work on Exceptions 2/3 stack frames, result is more accurate and	*/
20 /*			allow to pass the very tricky Transbeauce 2 Demo's protection.			*/
21 /* 2007/11/28	[NP]	Backport DIVS/DIVU cycles exact routines from WinUAE (original work by Jorge	*/
22 /*			Cwik, pasti@fxatari.com).							*/
23 /* 2007/12/06	[NP]	The PC stored in the stack frame for the bus error is complex to emulate,	*/
24 /*			because it doesn't necessarily point to the next instruction after the one that	*/
25 /*			triggered the bus error. In the case of the Transbeauce 2 Demo, after 		*/
26 /*			'move.l $0.w,$24.w', PC is incremented of 4 bytes, not 6, and stored in the	*/
27 /*			stack. Special case to decrement PC of 2 bytes if opcode is '21f8'.		*/
28 /*			This should be fixed with a real model.						*/
29 /* 2007/12/07	[NP]	If Trace is enabled and a group 2 exception occurs (such as CHK), the trace	*/
30 /*			handler should be called after the group 2's handler. If a bus error, address	*/
31 /*			error or illegal occurs while Trace is enabled, the trace handler should not be	*/
32 /*			called after this instruction (Transbeauce 2 Demo, Phaleon Demo).		*/
33 /*			This means that if a CHK is executed while trace bit was set, we must set PC	*/
34 /*			to CHK handler, turn trace off in the internal SR, but we must still call the	*/
35 /*			trace handler one last time with the PC set to the CHK's handler (even if	*/
36 /*			trace mode is internally turned off while processing an exception). Once trace	*/
37 /*			handler is finished (RTE), we return to the CHK's handler.			*/
38 /*			This is true for DIV BY 0, CHK, TRAPV and TRAP.					*/
39 /*			Backport exception_trace() from WinUAE to handle this behaviour	(used in	*/
40 /*			Transbeauce 2 demo).								*/
41 /* 2007/12/09	[NP]	'dc.w $a' should not be used to call 'OpCode_SysInit' but should give an illegal*/
42 /*			instruction (Transbeauce 2 demo).						*/
43 /*			Instead of always replacing the illegal instructions $8, $a and $c by the	*/
44 /*			3 functions required for HD emulation, we now do it in cart.c only if the	*/
45 /*			built-in cartridge image is loaded.						*/
46 /*			YEAH! Hatari is now the first emulator to pass the Transbeauce 2 protection :)	*/
47 /* 2007/12/18	[NP]	More precise timings for HBL, VBL and MFP interrupts. On ST, these interrupts	*/
48 /*			are taking 56 cycles instead of the 44 cycles in the 68000's documentation.	*/
49 /* 2007/12/24	[NP]	If an interrupt (HBL, VBL) is pending after instruction 'n' was processed, the	*/
50 /*			exception should be called before instr. 'n+1' is processed, not after (else the*/
51 /*			interrupt's handler is delayed by one 68000's instruction, which could break	*/
52 /*			some demos with too strict timings) (ACF's Demo Main Menu).			*/
53 /*			We call the interrupt if ( SPCFLAG_INT | SPCFLAG_DOINT ) is set, not only if	*/
54 /*			SPCFLAG_DOINT is set (as it was already the case when handling 'STOP').		*/
55 /* 2007/12/25	[NP]	FIXME When handling exceptions' cycles, using nr >= 64 to determine if this is	*/
56 /*			an MFP exception could be wrong if the MFP VR was set to another value than the	*/
57 /*			default $40 (this could be a problem with programs requiring a precise cycles	*/
58 /*			calculation while changing VR, but no such programs were encountered so far).	*/
59 /*			-> FIXED, see 2008/10/05							*/
60 /* 2008/04/17	[NP]	In m68k_run_1/m68k_run_2, add the wait state cycles before testing if content	*/
61 /*			of PendingInterruptCount is <= 0 (else the int could happen a few cycles earlier*/
62 /*			than expected in some rare cases (reading $fffa21 in BIG Demo Screen 1)).	*/
63 /* 2008/09/14	[NP]	Add the value of the new PC in the exception's log.				*/
64 /* 2008/09/14	[NP]	Correct cycles for TRAP are 34 not 38 (4 more cycles were counted because cpuemu*/
65 /*			returns 4 and Exception() adds 34) (Phaleon / Illusion Demo by Next).		*/
66 /*			FIXME : Others exception cycles may be wrong too.				*/
67 /* 2008/10/05	[NP]	Add a parameter 'ExceptionSource' to Exception(). This allows to know the source*/
68 /*			of the exception (video, mfp, cpu) and properly handle MFP interrupts. Since	*/
69 /*			it's possible to change the vector base in $fffa17, MFP int vectors can overlap	*/
70 /*			the 'normal' 68000 ones and the exception number is not enough to decide.	*/
71 /*			We need ExceptionSource to remove the ambiguity.				*/
72 /*			Fix High Fidelity Dreams by Aura which sets MFP vector base to $c0 instead of	*/
73 /*			$100. In that case, timer B int becomes exception nr 56 and conflicts with the	*/
74 /*			'MMU config error' exception, which takes 4 cycles instead of 56 cycles for MFP.*/
75 /* 2008/11/18	[NP]	In 'do_specialties()', when the cpu is in the STOP state, we must test all	*/
76 /*			possible int handlers while PendingInterruptCount <= 0 without increasing the	*/
77 /*			cpu cycle counter. In the case where both an MFP int and an HBL occur at the	*/
78 /*			same time for example, the HBL was delayed by 4 cycles if no MFP exception	*/
79 /*			was triggered, which was wrong (this happened mainly with the TOS timer D that	*/
80 /*			expires very often). Such precision is required for very recent hardscroll	*/
81 /*			techniques that use 'stop' to stay in sync with the video shifter.		*/
82 /* 2008/11/23	[NP]	In 'do_specialties()', when in STOP state, we must first test for a pending	*/
83 /*			interrupt that would exit the STOP state immediately, without doing a 'while'	*/
84 /*			loop until 'SPCFLAG_INT' or 'SPCFLAG_DOINT' are set.				*/
85 /* 2008/11/29	[NP]	Call 'InterruptAddJitter()' when a video interrupt happens to precisely emulate */
86 /*			the jitter happening on the Atari (see video.c for the jitter patterns).	*/
87 /*			FIXME : Pattern is not always correct when handling pending interrupt in STOP	*/
88 /*			state, but this should be harmless as no program has been found using this.	*/
89 /* 2008/12/05	[NP]	On Atari it takes 56 cycles to process an interrupt. During that time, a higher	*/
90 /*			level interrupt could happen and we must execute it before the previous int	*/
91 /*			(see m68k_run_1()).								*/
92 /*			This is the case for the VBL which can interrupt the last HBL of a screen	*/
93 /*			(end of line 312) at various point (from 0 to 8 cycles).			*/
94 /*			This fixes the fullscreen tunnel in Suretrip 49% by Checkpoint, which uses a	*/
95 /*			really buggy vbl/hbl combination, even on a real ST. Also fixes sample sound	*/
96 /*			in Swedish New Year's TCB screen.						*/
97 /* 2008/12/11	[NP]	Extract interrupt handling from do_specialties() in do_specialties_interrupt()	*/
98 /*			and factorize some code. In m68k_run_1 when testing for multiple interrupts at	*/
99 /*			the same time, call do_specialties_interrupt() to check only the special flags	*/
100 /*			related to interrupts (MFP and video) (else, this caused problem when the TRACE	*/
101 /*			flag was set).									*/
102 /* 2008/12/14	[NP]	In m68k_run_1(), we should check for simultaneous ints only if the cpu is not	*/
103 /*			in the STOP state after the last instruction was executed. Else, the call to	*/
104 /*			do_specialties_interrupt() could acknowledge the interrupt and we would never	*/
105 /*			exit the STOP state in do_specialties() just after (the problem can happen if	*/
106 /*			the TOS timer D expires just at the same time as the STOP instruction).		*/
107 /*			Fix regression since 2008/12/11 in the hidden screen from ULM in Oh Crickey...	*/
108 /* 2008/12/20	[NP]	In m68k_run_1(), when checking interrupts and STOP mode, we should test		*/
109 /*			PendingInterruptCount before regs.spcflags to have a faster evaluation of the	*/
110 /*			'while' condition (PendingInterruptCount <= 0 is true less often than STOP==0)	*/
111 /* 2011/04/29	[NP]	In Exception(), check the new PC is not on odd address ; raise an address error	*/
112 /*			exception if it's the case.							*/
113 /* 2012/09/01	[NP]	Add a special case to correct the stacked PC when a bus error happens during	*/
114 /*			a movem (fix the game Blood Money).						*/
115 /* 2013/03/16	[NP]	In refill_prefetch(), reload only one new word in regs.prefetch if low word is	*/
116 /*			still valid : low word goes to high word and we reload only low word		*/
117 /*			(fix EOR/ADD self modified code in the protection for the game Damocles).	*/
118 /* 2013/04/11	[NP]	In Exception(), call MFP_ProcessIACK after 12 cycles to update the MFP's vector	*/
119 /*			number used for the exception (see mfp.c).					*/
120 /* 2013/05/03	[NP]	In Exception(), handle IACK for HBL and VBL interrupts too, allowing pending bit*/
121 /*			to be set twice during an active video interrupt (correct fix for Super Monaco	*/
122 /*			GP, Super Hang On, Monster Business, European Demo's Intro, BBC Menu 52).	*/
123 /* 2014/02/22	[NP]	In Exception(), call valid_address() before reading the opcode at BusErrorPC,	*/
124 /*			else this will cause an unwanted "double bus error" ("Union Demo" loader).	*/
125 /* 2014/02/22	[NP]	In refill_prefetch(), use get_word() instead of do_get_mem_word() to generate	*/
126 /*			a bus error when trying to read from an invalid region.				*/
127 /* 2014/03/18	[NP]	In Exception(), add a specific case to restore the dest part of a "move" after	*/
128 /*			it was overwritten during a bus error (fix the game Dragon Flight).		*/
129 /* 2014/04/06	[NP]	In Exception(), add a special case for last_addr_for_exception_3 stored in the	*/
130 /*			stack after a bus error (fix the game Batman The Movie).			*/
131 /* 2014/09/07	[NP]	In m68k_run_1(), if get_iword_prefetch() triggers a bus error, we must call the	*/
132 /*			bus error immediately and fetch the correct opcode for the bus error handler	*/
133 /*			(fix Blood Money on Superior 65, PC=4e664e66 after RTS).			*/
134 /* 2014/09/07	[NP]	For address error, store if the access was in cpu space or data space and fix	*/
135 /*			the exception stack frame accordingly (fix Blood Money on Superior 65,		*/
136 /*			PC=4e664e66 after RTS)								*/
137 
138 const char NewCpu_fileid[] = "Hatari newcpu.c : " __DATE__ " " __TIME__;
139 
140 #include "sysdeps.h"
141 #include "hatari-glue.h"
142 #include "maccess.h"
143 #include "memory.h"
144 #include "newcpu.h"
145 #include "main.h"
146 #include "m68000.h"
147 #include "cycInt.h"
148 #include "mfp.h"
149 #include "tos.h"
150 #include "vdi.h"
151 #include "cart.h"
152 #include "dialog.h"
153 #include "bios.h"
154 #include "xbios.h"
155 #include "screen.h"
156 #include "video.h"
157 #include "options.h"
158 #include "dsp.h"
159 #include "log.h"
160 #include "debugui.h"
161 #include "debugcpu.h"
162 #include "68kDisass.h"
163 
164 #ifdef HAVE_CAPSIMAGE
165 #if CAPSIMAGE_VERSION == 5
166 #include <caps5/CapsLibAll.h>
167 #endif
168 #endif
169 
170 //#define DEBUG_PREFETCH
171 
172 struct flag_struct regflags;
173 
174 /* Opcode of faulting instruction */
175 uae_u16 last_op_for_exception_3;
176 /* PC at fault time */
177 uaecptr last_addr_for_exception_3;
178 /* Address that generated the exception */
179 uaecptr last_fault_for_exception_3;
180 /* instruction (1) or data (0) access */
181 int last_instructionaccess_for_exception_3;
182 
183 const int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
184 const int imm8_table[] = { 8,1,2,3,4,5,6,7 };
185 
186 int movem_index1[256];
187 int movem_index2[256];
188 int movem_next[256];
189 
190 int fpp_movem_index1[256];
191 int fpp_movem_index2[256];
192 int fpp_movem_next[256];
193 
194 cpuop_func *cpufunctbl[65536];
195 
196 int OpcodeFamily;
197 int BusCyclePenalty = 0;
198 
199 #define COUNT_INSTRS 0
200 
201 #if COUNT_INSTRS
202 static unsigned long int instrcount[65536];
203 static uae_u16 opcodenums[65536];
204 
compfn(const void * el1,const void * el2)205 static int compfn (const void *el1, const void *el2)
206 {
207     return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
208 }
209 
icountfilename(void)210 static char *icountfilename (void)
211 {
212     char *name = getenv ("INSNCOUNT");
213     if (name)
214 	return name;
215     return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
216 }
217 
dump_counts(void)218 void dump_counts (void)
219 {
220     FILE *f = fopen (icountfilename (), "w");
221     unsigned long int total;
222     int i;
223 
224     write_log ("Writing instruction count file...\n");
225     for (i = 0; i < 65536; i++) {
226 	opcodenums[i] = i;
227 	total += instrcount[i];
228     }
229     qsort (opcodenums, 65536, sizeof(uae_u16), compfn);
230 
231     fprintf (f, "Total: %lu\n", total);
232     for (i=0; i < 65536; i++) {
233 	unsigned long int cnt = instrcount[opcodenums[i]];
234 	struct instr *dp;
235 	struct mnemolookup *lookup;
236 	if (!cnt)
237 	    break;
238 	dp = table68k + opcodenums[i];
239 	for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
240 	    ;
241 	fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
242     }
243     fclose (f);
244 }
245 #else
dump_counts(void)246 void dump_counts (void)
247 {
248 }
249 #endif
250 
251 
252 static unsigned long op_illg_1 (uae_u32 opcode) REGPARAM;
253 
op_illg_1(uae_u32 opcode)254 static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode)
255 {
256     op_illg (opcode);
257     return 4;
258 }
259 
260 
build_cpufunctbl(void)261 void build_cpufunctbl(void)
262 {
263     int i;
264     unsigned long opcode;
265     const struct cputbl *tbl = (currprefs.cpu_level == 4 ? op_smalltbl_0_ff
266 			      : currprefs.cpu_level == 3 ? op_smalltbl_1_ff
267 			      : currprefs.cpu_level == 2 ? op_smalltbl_2_ff
268 			      : currprefs.cpu_level == 1 ? op_smalltbl_3_ff
269 			      : ! currprefs.cpu_compatible ? op_smalltbl_4_ff
270 			      : op_smalltbl_5_ff);
271 
272     Log_Printf(LOG_DEBUG, "Building CPU function table (%d %d %d).\n",
273 	           currprefs.cpu_level, currprefs.cpu_compatible, currprefs.address_space_24);
274 
275     for (opcode = 0; opcode < 65536; opcode++)
276 	cpufunctbl[opcode] = op_illg_1;
277     for (i = 0; tbl[i].handler != NULL; i++) {
278 	if (! tbl[i].specific)
279 	    cpufunctbl[tbl[i].opcode] = tbl[i].handler;
280     }
281     for (opcode = 0; opcode < 65536; opcode++) {
282 	cpuop_func *f;
283 
284 	if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > currprefs.cpu_level)
285 	    continue;
286 
287 	if (table68k[opcode].handler != -1) {
288 	    f = cpufunctbl[table68k[opcode].handler];
289 	    if (f == op_illg_1)
290 		abort();
291 	    cpufunctbl[opcode] = f;
292 	}
293     }
294     for (i = 0; tbl[i].handler != NULL; i++) {
295 	if (tbl[i].specific)
296 	    cpufunctbl[tbl[i].opcode] = tbl[i].handler;
297     }
298 }
299 
300 
301 
init_m68k(void)302 void init_m68k (void)
303 {
304     int i;
305 
306     for (i = 0 ; i < 256 ; i++) {
307 	int j;
308 	for (j = 0 ; j < 8 ; j++) {
309 		if (i & (1 << j)) break;
310 	}
311 	movem_index1[i] = j;
312 	movem_index2[i] = 7-j;
313 	movem_next[i] = i & (~(1 << j));
314     }
315     for (i = 0 ; i < 256 ; i++) {
316 	int j;
317 	for (j = 7 ; j >= 0 ; j--) {
318 		if (i & (1 << j)) break;
319 	}
320 	fpp_movem_index1[i] = 7-j;
321 	fpp_movem_index2[i] = j;
322 	fpp_movem_next[i] = i & (~(1 << j));
323     }
324 #if COUNT_INSTRS
325     {
326 	FILE *f = fopen (icountfilename (), "r");
327 	memset (instrcount, 0, sizeof instrcount);
328 	if (f) {
329 	    uae_u32 opcode, count, total;
330 	    char name[20];
331 	    write_log ("Reading instruction count file...\n");
332 	    fscanf (f, "Total: %lu\n", &total);
333 	    while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
334 		instrcount[opcode] = count;
335 	    }
336 	    fclose(f);
337 	}
338     }
339 #endif
340     write_log ("Building CPU table for configuration: 68");
341     if (currprefs.address_space_24 && currprefs.cpu_level > 1)
342         write_log ("EC");
343     switch (currprefs.cpu_level) {
344     case 1:
345         write_log ("010");
346         break;
347     case 2:
348         write_log ("020");
349         break;
350     case 3:
351         write_log ("020/881");
352         break;
353     case 4:
354         /* Who is going to miss the MMU anyway...? :-)  */
355         write_log ("040");
356         break;
357     default:
358         write_log ("000");
359         break;
360     }
361     if (currprefs.cpu_compatible)
362         write_log (" (compatible mode)");
363     write_log ("\n");
364 
365     read_table68k ();
366     do_merges ();
367 
368     Log_Printf(LOG_DEBUG, "%d CPU functions\n", nr_cpuop_funcs);
369 
370     build_cpufunctbl ();
371 }
372 
373 
374 /* not used ATM:
375 static struct regstruct regs_backup[16];
376 static int backup_pointer = 0;
377 struct regstruct lastint_regs;
378 int lastint_no;
379 */
380 struct regstruct regs;
381 static long int m68kpc_offset;
382 
383 
384 #define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
385 #define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
386 #define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
387 
ShowEA(FILE * f,int reg,amodes mode,wordsizes size,char * buf)388 uae_s32 ShowEA (FILE *f, int reg, amodes mode, wordsizes size, char *buf)
389 {
390     uae_u16 dp;
391     uae_s8 disp8;
392     uae_s16 disp16;
393     int r;
394     uae_u32 dispreg;
395     uaecptr addr;
396     uae_s32 offset = 0;
397     char buffer[80];
398 
399     switch (mode){
400      case Dreg:
401 	sprintf (buffer,"D%d", reg);
402 	break;
403      case Areg:
404 	sprintf (buffer,"A%d", reg);
405 	break;
406      case Aind:
407 	sprintf (buffer,"(A%d)", reg);
408 	break;
409      case Aipi:
410 	sprintf (buffer,"(A%d)+", reg);
411 	break;
412      case Apdi:
413 	sprintf (buffer,"-(A%d)", reg);
414 	break;
415      case Ad16:
416 	disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
417 	addr = m68k_areg(regs,reg) + (uae_s16)disp16;
418 	sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff,
419 					(unsigned long)addr);
420 	break;
421      case Ad8r:
422 	dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
423 	disp8 = dp & 0xFF;
424 	r = (dp & 0x7000) >> 12;
425 	dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
426 	if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
427 	dispreg <<= (dp >> 9) & 3;
428 
429 	if (dp & 0x100) {
430 	    uae_s32 outer = 0, disp = 0;
431 	    uae_s32 base = m68k_areg(regs,reg);
432 	    char name[10];
433 	    sprintf (name,"A%d, ",reg);
434 	    if (dp & 0x80) { base = 0; name[0] = 0; }
435 	    if (dp & 0x40) dispreg = 0;
436 	    if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
437 	    if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
438 	    base += disp;
439 
440 	    if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
441 	    if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
442 
443 	    if (!(dp & 4)) base += dispreg;
444 	    if (dp & 3) base = get_long (base);
445 	    if (dp & 4) base += dispreg;
446 
447 	    addr = base + outer;
448 	    sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
449 		    dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
450 		    1 << ((dp >> 9) & 3),
451 		    (long)disp, (long)outer, (unsigned long)addr);
452 	} else {
453 	  addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg;
454 	  sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg,
455 	       dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
456 	       1 << ((dp >> 9) & 3), disp8,
457 	       (unsigned long)addr);
458 	}
459 	break;
460      case PC16:
461 	addr = m68k_getpc () + m68kpc_offset;
462 	disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
463 	addr += (uae_s16)disp16;
464 	sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr);
465 	break;
466      case PC8r:
467 	addr = m68k_getpc () + m68kpc_offset;
468 	dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
469 	disp8 = dp & 0xFF;
470 	r = (dp & 0x7000) >> 12;
471 	dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
472 	if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
473 	dispreg <<= (dp >> 9) & 3;
474 
475 	if (dp & 0x100) {
476 	    uae_s32 outer = 0,disp = 0;
477 	    uae_s32 base = addr;
478 	    char name[10];
479 	    sprintf (name,"PC, ");
480 	    if (dp & 0x80) { base = 0; name[0] = 0; }
481 	    if (dp & 0x40) dispreg = 0;
482 	    if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
483 	    if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
484 	    base += disp;
485 
486 	    if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
487 	    if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
488 
489 	    if (!(dp & 4)) base += dispreg;
490 	    if (dp & 3) base = get_long (base);
491 	    if (dp & 4) base += dispreg;
492 
493 	    addr = base + outer;
494 	    sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
495 		    dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
496 		    1 << ((dp >> 9) & 3),
497 		    (long)disp, (long)outer, (unsigned long)addr);
498 	} else {
499 	  addr += (uae_s32)((uae_s8)disp8) + dispreg;
500 	  sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D',
501 		(int)r, dp & 0x800 ? 'L' : 'W',  1 << ((dp >> 9) & 3),
502 		disp8, (unsigned long)addr);
503 	}
504 	break;
505      case absw:
506 	sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset));
507 	m68kpc_offset += 2;
508 	break;
509      case absl:
510 	sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset));
511 	m68kpc_offset += 4;
512 	break;
513      case imm:
514 	switch (size){
515 	 case sz_byte:
516 	    sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff));
517 	    m68kpc_offset += 2;
518 	    break;
519 	 case sz_word:
520 	    sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff));
521 	    m68kpc_offset += 2;
522 	    break;
523 	 case sz_long:
524 	    sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset)));
525 	    m68kpc_offset += 4;
526 	    break;
527 	 default:
528 	    break;
529 	}
530 	break;
531      case imm0:
532 	offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
533 	m68kpc_offset += 2;
534 	sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff));
535 	break;
536      case imm1:
537 	offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
538 	m68kpc_offset += 2;
539 	sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff));
540 	break;
541      case imm2:
542 	offset = (uae_s32)get_ilong_1 (m68kpc_offset);
543 	m68kpc_offset += 4;
544 	sprintf (buffer,"#$%08lx", (unsigned long)offset);
545 	break;
546      case immi:
547 	offset = (uae_s32)(uae_s8)(reg & 0xff);
548 	sprintf (buffer,"#$%08lx", (unsigned long)offset);
549 	break;
550      default:
551 	break;
552     }
553     if (buf == 0)
554 	fprintf (f, "%s", buffer);
555     else
556 	strcat (buf, buffer);
557     return offset;
558 }
559 
560 
561 /* The plan is that this will take over the job of exception 3 handling -
562  * the CPU emulation functions will just do a longjmp to m68k_go whenever
563  * they hit an odd address. */
564 #if 0
565 static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
566 {
567     uae_u16 dp;
568     uae_s8 disp8;
569     uae_s16 disp16;
570     int r;
571     uae_u32 dispreg;
572     uaecptr addr;
573     /*uae_s32 offset = 0;*/
574 
575     switch (mode){
576      case Dreg:
577 	*val = m68k_dreg (regs, reg);
578 	return 1;
579      case Areg:
580 	*val = m68k_areg (regs, reg);
581 	return 1;
582 
583      case Aind:
584      case Aipi:
585 	addr = m68k_areg (regs, reg);
586 	break;
587      case Apdi:
588 	addr = m68k_areg (regs, reg);
589 	break;
590      case Ad16:
591 	disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
592 	addr = m68k_areg(regs,reg) + (uae_s16)disp16;
593 	break;
594      case Ad8r:
595 	addr = m68k_areg (regs, reg);
596      d8r_common:
597 	dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
598 	disp8 = dp & 0xFF;
599 	r = (dp & 0x7000) >> 12;
600 	dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
601 	if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
602 	dispreg <<= (dp >> 9) & 3;
603 
604 	if (dp & 0x100) {
605 	    uae_s32 outer = 0, disp = 0;
606 	    uae_s32 base = addr;
607 	    if (dp & 0x80) base = 0;
608 	    if (dp & 0x40) dispreg = 0;
609 	    if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
610 	    if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
611 	    base += disp;
612 
613 	    if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
614 	    if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
615 
616 	    if (!(dp & 4)) base += dispreg;
617 	    if (dp & 3) base = get_long (base);
618 	    if (dp & 4) base += dispreg;
619 
620 	    addr = base + outer;
621 	} else {
622 	  addr += (uae_s32)((uae_s8)disp8) + dispreg;
623 	}
624 	break;
625      case PC16:
626 	addr = m68k_getpc () + m68kpc_offset;
627 	disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
628 	addr += (uae_s16)disp16;
629 	break;
630      case PC8r:
631 	addr = m68k_getpc () + m68kpc_offset;
632 	goto d8r_common;
633      case absw:
634 	addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
635 	m68kpc_offset += 2;
636 	break;
637      case absl:
638 	addr = get_ilong_1 (m68kpc_offset);
639 	m68kpc_offset += 4;
640 	break;
641      case imm:
642 	switch (size){
643 	 case sz_byte:
644 	    *val = get_iword_1 (m68kpc_offset) & 0xff;
645 	    m68kpc_offset += 2;
646 	    break;
647 	 case sz_word:
648 	    *val = get_iword_1 (m68kpc_offset) & 0xffff;
649 	    m68kpc_offset += 2;
650 	    break;
651 	 case sz_long:
652 	    *val = get_ilong_1 (m68kpc_offset);
653 	    m68kpc_offset += 4;
654 	    break;
655 	 default:
656 	    break;
657 	}
658 	return 1;
659      case imm0:
660 	*val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
661 	m68kpc_offset += 2;
662 	return 1;
663      case imm1:
664 	*val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
665 	m68kpc_offset += 2;
666 	return 1;
667      case imm2:
668 	*val = get_ilong_1 (m68kpc_offset);
669 	m68kpc_offset += 4;
670 	return 1;
671      case immi:
672 	*val = (uae_s32)(uae_s8)(reg & 0xff);
673 	return 1;
674      default:
675 	addr = 0;
676 	break;
677     }
678     if ((addr & 1) == 0)
679 	return 1;
680 
681     last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
682     last_fault_for_exception_3 = addr;
683     return 0;
684 }
685 #endif
686 
687 
get_disp_ea_020(uae_u32 base,uae_u32 dp)688 uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp)
689 {
690     int reg = (dp >> 12) & 15;
691     uae_s32 regd = regs.regs[reg];
692     if ((dp & 0x800) == 0)
693 	regd = (uae_s32)(uae_s16)regd;
694     regd <<= (dp >> 9) & 3;
695     if (dp & 0x100) {
696 	uae_s32 outer = 0;
697 	if (dp & 0x80) base = 0;
698 	if (dp & 0x40) regd = 0;
699 
700 	if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword();
701 	if ((dp & 0x30) == 0x30) base += next_ilong();
702 
703 	if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword();
704 	if ((dp & 0x3) == 0x3) outer = next_ilong();
705 
706 	if ((dp & 0x4) == 0) base += regd;
707 	if (dp & 0x3) base = get_long (base);
708 	if (dp & 0x4) base += regd;
709 
710 	return base + outer;
711     } else {
712 	return base + (uae_s32)((uae_s8)dp) + regd;
713     }
714 }
715 
get_disp_ea_000(uae_u32 base,uae_u32 dp)716 uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
717 {
718     int reg = (dp >> 12) & 15;
719     uae_s32 regd = regs.regs[reg];
720 #if 1
721     if ((dp & 0x800) == 0)
722 	regd = (uae_s32)(uae_s16)regd;
723     return base + (uae_s8)dp + regd;
724 #else
725     /* Branch-free code... benchmark this again now that
726      * things are no longer inline.  */
727     uae_s32 regd16;
728     uae_u32 mask;
729     mask = ((dp & 0x800) >> 11) - 1;
730     regd16 = (uae_s32)(uae_s16)regd;
731     regd16 &= mask;
732     mask = ~mask;
733     base += (uae_s8)dp;
734     regd &= mask;
735     regd |= regd16;
736     return base + regd;
737 #endif
738 }
739 
740 
741 /* Create the Status Register from the flags */
MakeSR(void)742 void MakeSR (void)
743 {
744 #if 0
745     assert((regs.t1 & 1) == regs.t1);
746     assert((regs.t0 & 1) == regs.t0);
747     assert((regs.s & 1) == regs.s);
748     assert((regs.m & 1) == regs.m);
749     assert((XFLG & 1) == XFLG);
750     assert((NFLG & 1) == NFLG);
751     assert((ZFLG & 1) == ZFLG);
752     assert((VFLG & 1) == VFLG);
753     assert((CFLG & 1) == CFLG);
754 #endif
755     regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
756 	       | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
757 	       | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1)
758 	       | GET_CFLG);
759 }
760 
761 
762 /* Set up the flags from Status Register */
MakeFromSR(void)763 void MakeFromSR (void)
764 {
765     int oldm = regs.m;
766     int olds = regs.s;
767 
768     regs.t1 = (regs.sr >> 15) & 1;
769     regs.t0 = (regs.sr >> 14) & 1;
770     regs.s = (regs.sr >> 13) & 1;
771     regs.m = (regs.sr >> 12) & 1;
772     regs.intmask = (regs.sr >> 8) & 7;
773     SET_XFLG ((regs.sr >> 4) & 1);
774     SET_NFLG ((regs.sr >> 3) & 1);
775     SET_ZFLG ((regs.sr >> 2) & 1);
776     SET_VFLG ((regs.sr >> 1) & 1);
777     SET_CFLG (regs.sr & 1);
778     if (currprefs.cpu_level >= 2) {
779 	if (olds != regs.s) {
780 	    if (olds) {
781 		if (oldm)
782 		    regs.msp = m68k_areg(regs, 7);
783 		else
784 		    regs.isp = m68k_areg(regs, 7);
785 		m68k_areg(regs, 7) = regs.usp;
786 	    } else {
787 		regs.usp = m68k_areg(regs, 7);
788 		m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
789 	    }
790 	} else if (olds && oldm != regs.m) {
791 	    if (oldm) {
792 		regs.msp = m68k_areg(regs, 7);
793 		m68k_areg(regs, 7) = regs.isp;
794 	    } else {
795 		regs.isp = m68k_areg(regs, 7);
796 		m68k_areg(regs, 7) = regs.msp;
797 	    }
798 	}
799     } else {
800 	/* [NP] If cpu < 68020, m and t0 are ignored and should be set to 0 */
801 	regs.t0 = 0;
802 	regs.m = 0;
803 
804 	if (olds != regs.s) {
805 	    if (olds) {
806 		regs.isp = m68k_areg(regs, 7);
807 		m68k_areg(regs, 7) = regs.usp;
808 	    } else {
809 		regs.usp = m68k_areg(regs, 7);
810 		m68k_areg(regs, 7) = regs.isp;
811 	    }
812 	}
813     }
814 
815     /* Pending interrupts can occur again after a write to the SR: */
816     set_special (SPCFLAG_DOINT);
817     if (regs.t1 || regs.t0)
818 	set_special (SPCFLAG_TRACE);
819     else
820 	/* Keep SPCFLAG_DOTRACE, we still want a trace exception for
821 	   SR-modifying instructions (including STOP).  */
822 	unset_special (SPCFLAG_TRACE);
823 }
824 
825 
exception_trace(int nr)826 static void exception_trace (int nr)
827 {
828     unset_special (SPCFLAG_TRACE | SPCFLAG_DOTRACE);
829     if (regs.t1 && !regs.t0) {
830         /* trace stays pending if exception is div by zero, chk,
831          * trapv or trap #x
832          */
833         if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
834             set_special (SPCFLAG_DOTRACE);
835     }
836     regs.t1 = regs.t0 = regs.m = 0;
837 }
838 
839 
840 /*
841  * Compute the number of jitter cycles to add when a video interrupt occurs
842  * (this is specific to the Atari ST)
843  */
InterruptAddJitter(int Level,int Pending)844 static void InterruptAddJitter (int Level , int Pending)
845 {
846     int cycles = 0;
847 
848     if ( Level == 2 )				/* HBL */
849       {
850         if ( Pending )
851 	  cycles = HblJitterArrayPending[ HblJitterIndex ];
852 	else
853 	  cycles = HblJitterArray[ HblJitterIndex ];
854       }
855 
856     else if ( Level == 4 )			/* VBL */
857       {
858         if ( Pending )
859 	  cycles = VblJitterArrayPending[ VblJitterIndex ];
860 	else
861 	  cycles = VblJitterArray[ VblJitterIndex ];
862       }
863 
864 //fprintf ( stderr , "jitter %d\n" , cycles );
865 //cycles=0;
866     if ( cycles > 0 )				/* no need to call M68000_AddCycles if cycles == 0 */
867       M68000_AddCycles ( cycles );
868 }
869 
870 
871 /* Handle exceptions. We need a special case to handle MFP exceptions */
872 /* on Atari ST, because it's possible to change the MFP's vector base */
873 /* and get a conflict with 'normal' cpu exceptions. */
Exception(int nr,uaecptr oldpc,int ExceptionSource)874 void Exception(int nr, uaecptr oldpc, int ExceptionSource)
875 {
876     uae_u32 currpc = m68k_getpc () , newpc;
877 
878     /*if( nr>=2 && nr<10 )  fprintf(stderr,"Exception (-> %i bombs)!\n",nr);*/
879 
880     /* Pending bits / vector number can change before the end of the IACK sequence. */
881     /* We need to handle MFP and HBL/VBL cases for this. */
882     if ( ExceptionSource == M68000_EXC_SRC_INT_MFP )
883     {
884         M68000_AddCycles ( CPU_IACK_CYCLES_MFP );
885 	CPU_IACK = true;
886         while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
887             CALL_VAR(PendingInterruptFunction);
888         nr = MFP_ProcessIACK ( nr );
889 	CPU_IACK = false;
890     }
891     else if ( ( ExceptionSource == M68000_EXC_SRC_AUTOVEC ) && ( ( nr == 26 ) || ( nr == 28 ) ) )
892     {
893         M68000_AddCycles ( CPU_IACK_CYCLES_VIDEO );
894 	CPU_IACK = true;
895         while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
896             CALL_VAR(PendingInterruptFunction);
897         if ( MFP_UpdateNeeded == true )
898             MFP_UpdateIRQ ( 0 );					/* update MFP's state if some internal timers related to MFP expired */
899         pendingInterrupts &= ~( 1 << ( nr - 24 ) );			/* clear HBL or VBL pending bit */
900 	CPU_IACK = false;
901     }
902 
903 
904     if (ExceptionSource == M68000_EXC_SRC_CPU)
905       {
906         if (nr == 0x22)
907         {
908           /* Intercept VDI & AES exceptions (Trap #2) */
909           if(bVdiAesIntercept && VDI_AES_Entry())
910           {
911             /* Set 'PC' to address of 'VDI_OPCODE' illegal instruction.
912              * This will call OpCode_VDI() after completion of Trap call!
913              * This is used to modify specific VDI return vectors contents.
914 	     */
915             VDI_OldPC = currpc;
916             currpc = CART_VDI_OPCODE_ADDR;
917           }
918         }
919         else if (nr == 0x2d)
920         {
921           /* Intercept BIOS (Trap #13) calls */
922           if (Bios())  return;
923         }
924         else if (nr == 0x2e)
925         {
926           /* Intercept XBIOS (Trap #14) calls */
927           if (XBios())  return;
928         }
929       }
930 
931     MakeSR();
932 
933     /* Change to supervisor mode if necessary */
934     if (!regs.s) {
935 	regs.usp = m68k_areg(regs, 7);
936 	if (currprefs.cpu_level >= 2)
937 	    m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
938 	else
939 	    m68k_areg(regs, 7) = regs.isp;
940 	regs.s = 1;
941     }
942 
943     /* Build additional exception stack frame for 68010 and higher */
944     /* (special case for MFP) */
945     if (currprefs.cpu_level > 0) {
946         if (ExceptionSource == M68000_EXC_SRC_INT_MFP
947 		    || ExceptionSource == M68000_EXC_SRC_INT_DSP) {
948 	    m68k_areg(regs, 7) -= 2;
949 	    put_word (m68k_areg(regs, 7), nr * 4);	/* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
950         }
951         else if (nr == 2 || nr == 3) {
952 	    int i;
953 	    /* @@@ this is probably wrong (?) */
954 	    for (i = 0 ; i < 12 ; i++) {
955 		m68k_areg(regs, 7) -= 2;
956 		put_word (m68k_areg(regs, 7), 0);
957 	    }
958 	    m68k_areg(regs, 7) -= 2;
959 	    put_word (m68k_areg(regs, 7), 0xa000 + nr * 4);
960 	} else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
961 	    m68k_areg(regs, 7) -= 4;
962 	    put_long (m68k_areg(regs, 7), oldpc);
963 	    m68k_areg(regs, 7) -= 2;
964 	    put_word (m68k_areg(regs, 7), 0x2000 + nr * 4);
965 	} else if (regs.m && nr >= 24 && nr < 32) {
966 	    m68k_areg(regs, 7) -= 2;
967 	    put_word (m68k_areg(regs, 7), nr * 4);
968 	    m68k_areg(regs, 7) -= 4;
969 	    put_long (m68k_areg(regs, 7), currpc);
970 	    m68k_areg(regs, 7) -= 2;
971 	    put_word (m68k_areg(regs, 7), regs.sr);
972 	    regs.sr |= (1 << 13);
973 	    regs.msp = m68k_areg(regs, 7);
974 	    m68k_areg(regs, 7) = regs.isp;
975 	    m68k_areg(regs, 7) -= 2;
976 	    put_word (m68k_areg(regs, 7), 0x1000 + nr * 4);
977 	} else {
978 	    m68k_areg(regs, 7) -= 2;
979 	    put_word (m68k_areg(regs, 7), nr * 4);
980 	}
981     }
982 
983     /* Push PC on stack: */
984     m68k_areg(regs, 7) -= 4;
985     put_long (m68k_areg(regs, 7), currpc);
986     /* Push SR on stack: */
987     m68k_areg(regs, 7) -= 2;
988     put_word (m68k_areg(regs, 7), regs.sr);
989 
990     LOG_TRACE(TRACE_CPU_EXCEPTION, "cpu exception %d currpc %x buspc %x newpc %x fault_e3 %x op_e3 %hx addr_e3 %x\n",
991 	nr, currpc, BusErrorPC, get_long (regs.vbr + 4*nr), last_fault_for_exception_3, last_op_for_exception_3, last_addr_for_exception_3);
992 
993     /* 68000 bus/address errors: */
994     if (currprefs.cpu_level==0 && (nr==2 || nr==3) && ExceptionSource == M68000_EXC_SRC_CPU) {
995 	uae_u16 specialstatus = last_instructionaccess_for_exception_3 ? 2 : 1;
996 	uae_u16 BusError_opcode;
997 
998 	/* Special status word emulation isn't perfect yet... :-( */
999 	if (regs.sr & 0x2000)
1000 	    specialstatus |= 0x4;
1001 	m68k_areg(regs, 7) -= 8;
1002 	if (nr == 3) {    /* Address error */
1003 	    specialstatus |= ( last_op_for_exception_3 & (~0x1f) );	/* [NP] unused bits of specialstatus are those of the last opcode ! */
1004 	    put_word (m68k_areg(regs, 7), specialstatus);
1005 	    put_long (m68k_areg(regs, 7)+2, last_fault_for_exception_3);
1006 	    put_word (m68k_areg(regs, 7)+6, last_op_for_exception_3);
1007 	    put_long (m68k_areg(regs, 7)+10, last_addr_for_exception_3);
1008 	    if (ExceptionDebugMask & EXCEPT_ADDRESS) {
1009 	      fprintf(stderr,"Address Error at address $%x, PC=$%x\n",last_fault_for_exception_3,currpc);
1010 	      DebugUI(REASON_CPU_EXCEPTION);
1011 	    }
1012 	}
1013 	else {    /* Bus error */
1014 	    /* Get the opcode that caused the bus error, to adapt the stack frame in some cases */
1015 	    /* (we must call get_word() only on valid region, else this will cause a double bus error) */
1016 	    if ( valid_address ( BusErrorPC , 2 ) )
1017 	      BusError_opcode = get_word(BusErrorPC);
1018 	    else
1019 	      BusError_opcode = 0;
1020 
1021 	    specialstatus |= ( BusError_opcode & (~0x1f) );		/* [NP] unused bits of special status are those of the last opcode ! */
1022 	    if (bBusErrorReadWrite)
1023 	      specialstatus |= 0x10;
1024 	    put_word (m68k_areg(regs, 7), specialstatus);
1025 	    put_long (m68k_areg(regs, 7)+2, BusErrorAddress);
1026 	    put_word (m68k_areg(regs, 7)+6, BusError_opcode);		/* Opcode */
1027 
1028 	    /* [NP] PC stored in the stack frame is not necessarily pointing to the next instruction ! */
1029 	    /* FIXME : we should have a proper model for this, in the meantime we handle specific cases */
1030 	    if ( BusError_opcode == 0x21f8 )						/* move.l $0.w,$24.w (Transbeauce 2 loader) */
1031 	      put_long (m68k_areg(regs, 7)+10, currpc-2);				/* correct PC is 2 bytes less than usual value */
1032 
1033 	    else if ( ( BusErrorPC == 0xccc ) && ( BusError_opcode == 0x48d6 ) )	/* 48d6 3f00 movem.l a0-a5,(a6) (Blood Money) */
1034 	      put_long (m68k_areg(regs, 7)+10, currpc+2);				/* correct PC is 2 bytes more than usual value */
1035 
1036 	    else if ( ( BusErrorPC == 0x1fece ) && ( BusError_opcode == 0x33d4 ) )	/* 1fece : 33d4 0001 fdca move.w (a4),$1fdca (Batman The Movie) */
1037 	      put_long (m68k_areg(regs, 7)+10, currpc-4);				/* correct PC is 4 bytes less than usual value */
1038 
1039 	    /* [NP] In case of a move with a bus error on the read part, uae cpu is writing to the dest part */
1040 	    /* then process the bus error ; on a real CPU, the bus error occurs after the read and before the */
1041 	    /* write, so the dest part doesn't change. For now, we restore the dest part on some specific cases */
1042 	    /* FIXME : the bus error should be processed just after the read, not at the end of the instruction */
1043 	    else if ( ( BusErrorPC == 0x62a ) && ( BusError_opcode == 0x3079 ) )	/* 3079 4ef9 0000 move.l $4ef90000,a0 (Dragon Flight) */
1044 	      m68k_areg(regs, 0) = 8;							/* A0 should not be changed to "0" but keep its value "8" */
1045 
1046 	    else if ( get_long(BusErrorPC) == 0x13f88e21 )				/* 13f8 8e21 move.b $ffff8e21.w,$xxxxx (Tymewarp) */
1047 	      put_byte ( get_long(BusErrorPC+4) , 0x00 );				/* dest content should not be changed to "ff" but keep its value "00" */
1048 
1049 	    fprintf(stderr,"Bus Error at address $%x, PC=$%lx %x %x\n", BusErrorAddress, (long)currpc, BusErrorPC , BusError_opcode);
1050 
1051 	    /* Check for double bus errors: */
1052 	    if (regs.spcflags & SPCFLAG_BUSERROR) {
1053 	      fprintf(stderr, "Detected double bus error at address $%x, PC=$%lx => CPU halted!\n",
1054 	              BusErrorAddress, (long)currpc);
1055 	      unset_special(SPCFLAG_BUSERROR);
1056 	      if (ExceptionDebugMask & EXCEPT_BUS)
1057 	        DebugUI(REASON_CPU_EXCEPTION);
1058 	      else
1059 		DlgAlert_Notice("Detected double bus error => CPU halted!\nEmulation needs to be reset.\n");
1060 	      regs.intmask = 7;
1061 	      m68k_setstopped(true);
1062 	      return;
1063 	    }
1064 	    if ((ExceptionDebugMask & EXCEPT_BUS) && BusErrorAddress!=0xff8a00) {
1065 	      fprintf(stderr,"Bus Error at address $%x, PC=$%lx\n", BusErrorAddress, (long)currpc);
1066 	      DebugUI(REASON_CPU_EXCEPTION);
1067 	    }
1068 	}
1069     }
1070 
1071     /* Set PC and flags */
1072     if ((ExceptionDebugMask & EXCEPT_NOHANDLER) && (regs.vbr + 4*nr) == 0) {
1073         fprintf(stderr,"Uninitialized exception handler #%i!\n", nr);
1074 	DebugUI(REASON_CPU_EXCEPTION);
1075     }
1076     newpc = get_long (regs.vbr + 4*nr);
1077     if ( newpc & 1)				/* check new pc is even */
1078       {
1079         if ( nr==2 || nr==3 )			/* address error during bus/address error -> stop emulation */
1080             {
1081 	      fprintf(stderr,"Address Error during exception 2/3, aborting new PC=$%x\n",newpc);
1082 	      if (ExceptionDebugMask & (EXCEPT_BUS|EXCEPT_ADDRESS))
1083 	        DebugUI(REASON_CPU_EXCEPTION);
1084 	      else
1085 		DlgAlert_Notice("Address Error during exception 2/3 => CPU halted!\nEmulation needs to be reset.\n");
1086             }
1087         else
1088             {
1089 		fprintf(stderr,"Address Error during exception, new PC=$%x\n",newpc);
1090 		Exception ( 3 , m68k_getpc() , M68000_EXC_SRC_CPU );
1091             }
1092         return;
1093       }
1094     /* handle debugger invocation for rest of exceptions */
1095     if (ExceptionDebugMask && nr > 3 && nr < 9)
1096       DebugUI_Exceptions(nr, currpc);
1097 
1098     m68k_setpc (get_long (regs.vbr + 4*nr));
1099     fill_prefetch_0 ();
1100     /* Handle trace flags depending on current state */
1101     exception_trace (nr);
1102 
1103     /* Handle exception cycles (special case for MFP) */
1104     if (ExceptionSource == M68000_EXC_SRC_INT_MFP)
1105     {
1106       M68000_AddCycles(44+12-CPU_IACK_CYCLES_MFP);	/* MFP interrupt, 'nr' can be in a different range depending on $fffa17 */
1107     }
1108     else if (nr >= 24 && nr <= 31)
1109     {
1110       if ( nr == 26 )					/* HBL */
1111         M68000_AddCycles(44+12-CPU_IACK_CYCLES_VIDEO);	/* Video Interrupt */
1112       else if ( nr == 28 ) 				/* VBL */
1113         M68000_AddCycles(44+12-CPU_IACK_CYCLES_VIDEO);	/* Video Interrupt */
1114       else
1115         M68000_AddCycles(44+4);				/* Other Interrupts */
1116     }
1117     else if(nr >= 32 && nr <= 47)
1118     {
1119       M68000_AddCycles(34-4);			/* Trap (total is 34, but cpuemu.c already adds 4) */
1120     }
1121     else switch(nr)
1122     {
1123       case 2: M68000_AddCycles(50); break;	/* Bus error */
1124       case 3: M68000_AddCycles(50); break;	/* Address error */
1125       case 4: M68000_AddCycles(34); break;	/* Illegal instruction */
1126       case 5: M68000_AddCycles(38); break;	/* Div by zero */
1127       case 6: M68000_AddCycles(40); break;	/* CHK */
1128       case 7: M68000_AddCycles(34); break;	/* TRAPV */
1129       case 8: M68000_AddCycles(34); break;	/* Privilege violation */
1130       case 9: M68000_AddCycles(34); break;	/* Trace */
1131       case 10: M68000_AddCycles(34); break;	/* Line-A - probably wrong */
1132       case 11: M68000_AddCycles(34); break;	/* Line-F - probably wrong */
1133       default:
1134         /* FIXME: Add right cycles value for MFP interrupts and copro exceptions ... */
1135         if(nr < 64)
1136           M68000_AddCycles(4);			/* Coprocessor and unassigned exceptions (???) */
1137         else
1138           M68000_AddCycles(44+12);		/* Must be a MFP or DSP interrupt */
1139         break;
1140     }
1141 
1142 }
1143 
1144 
Interrupt(int nr,int Pending)1145 static void Interrupt(int nr , int Pending)
1146 {
1147     assert(nr < 8 && nr >= 0);
1148     /*lastint_regs = regs;*/
1149     /*lastint_no = nr;*/
1150 
1151     /* On Hatari, only video ints are using SPCFLAG_INT (see m68000.c) */
1152     Exception(nr+24, 0, M68000_EXC_SRC_AUTOVEC);
1153 
1154     regs.intmask = nr;
1155     set_special (SPCFLAG_INT);
1156 
1157     /* Handle Atari ST's specific jitter for hbl/vbl */
1158     InterruptAddJitter ( nr , Pending );
1159 }
1160 
1161 
1162 uae_u32 caar, cacr;
1163 static uae_u32 itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp;
1164 
1165 
movec_illg(int regno)1166 static int movec_illg (int regno)
1167 {
1168     int regno2 = regno & 0x7ff;
1169     if (currprefs.cpu_level == 1) { /* 68010 */
1170 	if (regno2 < 2)
1171 	    return 0;
1172 	return 1;
1173     }
1174     if (currprefs.cpu_level == 2 || currprefs.cpu_level == 3) { /* 68020 */
1175 	if (regno == 3) return 1; /* 68040 only */
1176 	 /* 4 is >=68040, but 0x804 is in 68020 */
1177 	 if (regno2 < 4 || regno == 0x804)
1178 	    return 0;
1179 	return 1;
1180     }
1181     if (currprefs.cpu_level >= 4) { /* 68040 */
1182 	if (regno == 0x802) return 1; /* 68020 only */
1183 	if (regno2 < 8) return 0;
1184 	if (currprefs.cpu_level == 6 && regno2 == 8) /* 68060 only */
1185 	    return 0;
1186 	return 1;
1187     }
1188     return 1;
1189 }
1190 
m68k_move2c(int regno,uae_u32 * regp)1191 int m68k_move2c (int regno, uae_u32 *regp)
1192 {
1193     if (movec_illg (regno)) {
1194 	op_illg (0x4E7B);
1195 	return 0;
1196     } else {
1197 	switch (regno) {
1198 	case 0: regs.sfc = *regp & 7; break;
1199 	case 1: regs.dfc = *regp & 7; break;
1200 	case 2:
1201 	{
1202 	    uae_u32 cacr_mask = 0;
1203 	    if (currprefs.cpu_level == 2)	// 68020
1204 		cacr_mask = 0x0000000f;
1205 	    else if (currprefs.cpu_level == 3)	// Fake 68030
1206 		cacr_mask = 0x00003f1f;
1207 	    else if (currprefs.cpu_level == 4)	// 68040
1208 		cacr_mask = 0x80008000;
1209 	    cacr = *regp & cacr_mask;
1210 	}
1211 	case 3: tc = *regp & 0xc000; break;
1212 	  /* Mask out fields that should be zero.  */
1213 	case 4: itt0 = *regp & 0xffffe364; break;
1214 	case 5: itt1 = *regp & 0xffffe364; break;
1215 	case 6: dtt0 = *regp & 0xffffe364; break;
1216 	case 7: dtt1 = *regp & 0xffffe364; break;
1217 
1218 	case 0x800: regs.usp = *regp; break;
1219 	case 0x801: regs.vbr = *regp; break;
1220 	case 0x802: caar = *regp; break;
1221 	case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
1222 	case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
1223 	case 0x805: mmusr = *regp; break;
1224 	case 0x806: urp = *regp; break;
1225 	case 0x807: srp = *regp; break;
1226 	default:
1227 	    op_illg (0x4E7B);
1228 	    return 0;
1229 	}
1230     }
1231     return 1;
1232 }
1233 
m68k_movec2(int regno,uae_u32 * regp)1234 int m68k_movec2 (int regno, uae_u32 *regp)
1235 {
1236     if (movec_illg (regno)) {
1237 	op_illg (0x4E7A);
1238 	return 0;
1239     } else {
1240 	switch (regno) {
1241 	case 0: *regp = regs.sfc; break;
1242 	case 1: *regp = regs.dfc; break;
1243 	case 2: *regp = cacr; break;
1244 	case 3: *regp = tc; break;
1245 	case 4: *regp = itt0; break;
1246 	case 5: *regp = itt1; break;
1247 	case 6: *regp = dtt0; break;
1248 	case 7: *regp = dtt1; break;
1249 	case 0x800: *regp = regs.usp; break;
1250 	case 0x801: *regp = regs.vbr; break;
1251 	case 0x802: *regp = caar; break;
1252 	case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
1253 	case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
1254 	case 0x805: *regp = mmusr; break;
1255 	case 0x806: *regp = urp; break;
1256 	case 0x807: *regp = srp; break;
1257 	default:
1258 	    op_illg (0x4E7A);
1259 	    return 0;
1260 	}
1261     }
1262     return 1;
1263 }
1264 
1265 STATIC_INLINE int
div_unsigned(uae_u32 src_hi,uae_u32 src_lo,uae_u32 ndiv,uae_u32 * quot,uae_u32 * rem)1266 div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 ndiv, uae_u32 *quot, uae_u32 *rem)
1267 {
1268 	uae_u32 q = 0, cbit = 0;
1269 	int i;
1270 
1271 	if (ndiv <= src_hi) {
1272 	    return 1;
1273 	}
1274 	for (i = 0 ; i < 32 ; i++) {
1275 		cbit = src_hi & 0x80000000ul;
1276 		src_hi <<= 1;
1277 		if (src_lo & 0x80000000ul) src_hi++;
1278 		src_lo <<= 1;
1279 		q = q << 1;
1280 		if (cbit || ndiv <= src_hi) {
1281 			q |= 1;
1282 			src_hi -= ndiv;
1283 		}
1284 	}
1285 	*quot = q;
1286 	*rem = src_hi;
1287 	return 0;
1288 }
1289 
m68k_divl(uae_u32 opcode,uae_u32 src,uae_u16 extra,uaecptr oldpc)1290 void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
1291 {
1292 #if defined(uae_s64)
1293     if (src == 0) {
1294 	Exception (5, oldpc,M68000_EXC_SRC_CPU);
1295 	return;
1296     }
1297     if (extra & 0x800) {
1298 	/* signed variant */
1299 	uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
1300 	uae_s64 quot, rem;
1301 
1302 	if (extra & 0x400) {
1303 	    a &= 0xffffffffu;
1304 	    a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32;
1305 	}
1306 	rem = a % (uae_s64)(uae_s32)src;
1307 	quot = a / (uae_s64)(uae_s32)src;
1308 	if ((quot & UVAL64(0xffffffff80000000)) != 0
1309 	    && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
1310 	{
1311 	    SET_VFLG (1);
1312 	    SET_NFLG (1);
1313 	    SET_CFLG (0);
1314 	} else {
1315 	    if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
1316 	    SET_VFLG (0);
1317 	    SET_CFLG (0);
1318 	    SET_ZFLG (((uae_s32)quot) == 0);
1319 	    SET_NFLG (((uae_s32)quot) < 0);
1320 	    m68k_dreg(regs, extra & 7) = rem;
1321 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
1322 	}
1323     } else {
1324 	/* unsigned */
1325 	uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
1326 	uae_u64 quot, rem;
1327 
1328 	if (extra & 0x400) {
1329 	    a &= 0xffffffffu;
1330 	    a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32;
1331 	}
1332 	rem = a % (uae_u64)src;
1333 	quot = a / (uae_u64)src;
1334 	if (quot > 0xffffffffu) {
1335 	    SET_VFLG (1);
1336 	    SET_NFLG (1);
1337 	    SET_CFLG (0);
1338 	} else {
1339 	    SET_VFLG (0);
1340 	    SET_CFLG (0);
1341 	    SET_ZFLG (((uae_s32)quot) == 0);
1342 	    SET_NFLG (((uae_s32)quot) < 0);
1343 	    m68k_dreg(regs, extra & 7) = rem;
1344 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
1345 	}
1346     }
1347 #else
1348     if (src == 0) {
1349 	Exception (5, oldpc,M68000_EXC_SRC_CPU);
1350 	return;
1351     }
1352     if (extra & 0x800) {
1353 	/* signed variant */
1354 	uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
1355 	uae_s32 hi = lo < 0 ? -1 : 0;
1356 	uae_s32 save_high;
1357 	uae_u32 quot, rem;
1358 	uae_u32 sign;
1359 
1360 	if (extra & 0x400) {
1361 	    hi = (uae_s32)m68k_dreg(regs, extra & 7);
1362 	}
1363 	save_high = hi;
1364 	sign = (hi ^ src);
1365 	if (hi < 0) {
1366 	    hi = ~hi;
1367 	    lo = -lo;
1368 	    if (lo == 0) hi++;
1369 	}
1370 	if ((uae_s32)src < 0) src = -src;
1371 	if (div_unsigned(hi, lo, src, &quot, &rem) ||
1372 	    (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
1373 	    SET_VFLG (1);
1374 	    SET_NFLG (1);
1375 	    SET_CFLG (0);
1376 	} else {
1377 	    if (sign & 0x80000000) quot = -quot;
1378 	    if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
1379 	    SET_VFLG (0);
1380 	    SET_CFLG (0);
1381 	    SET_ZFLG (((uae_s32)quot) == 0);
1382 	    SET_NFLG (((uae_s32)quot) < 0);
1383 	    m68k_dreg(regs, extra & 7) = rem;
1384 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
1385 	}
1386     } else {
1387 	/* unsigned */
1388 	uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
1389 	uae_u32 hi = 0;
1390 	uae_u32 quot, rem;
1391 
1392 	if (extra & 0x400) {
1393 	    hi = (uae_u32)m68k_dreg(regs, extra & 7);
1394 	}
1395 	if (div_unsigned(hi, lo, src, &quot, &rem)) {
1396 	    SET_VFLG (1);
1397 	    SET_NFLG (1);
1398 	    SET_CFLG (0);
1399 	} else {
1400 	    SET_VFLG (0);
1401 	    SET_CFLG (0);
1402 	    SET_ZFLG (((uae_s32)quot) == 0);
1403 	    SET_NFLG (((uae_s32)quot) < 0);
1404 	    m68k_dreg(regs, extra & 7) = rem;
1405 	    m68k_dreg(regs, (extra >> 12) & 7) = quot;
1406 	}
1407     }
1408 #endif
1409 }
1410 
1411 STATIC_INLINE void
mul_unsigned(uae_u32 src1,uae_u32 src2,uae_u32 * dst_hi,uae_u32 * dst_lo)1412 mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
1413 {
1414 	uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
1415 	uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
1416 	uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
1417 	uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
1418 	uae_u32 lo;
1419 
1420 	lo = r0 + ((r1 << 16) & 0xffff0000ul);
1421 	if (lo < r0) r3++;
1422 	r0 = lo;
1423 	lo = r0 + ((r2 << 16) & 0xffff0000ul);
1424 	if (lo < r0) r3++;
1425 	r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
1426 	*dst_lo = lo;
1427 	*dst_hi = r3;
1428 }
1429 
m68k_mull(uae_u32 opcode,uae_u32 src,uae_u16 extra)1430 void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
1431 {
1432 #if defined(uae_s64)
1433     if (extra & 0x800) {
1434 	/* signed variant */
1435 	uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
1436 
1437 	a *= (uae_s64)(uae_s32)src;
1438 	SET_VFLG (0);
1439 	SET_CFLG (0);
1440 	SET_ZFLG (a == 0);
1441 	SET_NFLG (a < 0);
1442 	if (extra & 0x400)
1443 	    m68k_dreg(regs, extra & 7) = a >> 32;
1444 	else if ((a & UVAL64(0xffffffff80000000)) != 0
1445 		 && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
1446 	{
1447 	    SET_VFLG (1);
1448 	}
1449 	m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
1450     } else {
1451 	/* unsigned */
1452 	uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
1453 
1454 	a *= (uae_u64)src;
1455 	SET_VFLG (0);
1456 	SET_CFLG (0);
1457 	SET_ZFLG (a == 0);
1458 	SET_NFLG (((uae_s64)a) < 0);
1459 	if (extra & 0x400)
1460 	    m68k_dreg(regs, extra & 7) = a >> 32;
1461 	else if ((a & UVAL64(0xffffffff00000000)) != 0) {
1462 	    SET_VFLG (1);
1463 	}
1464 	m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
1465     }
1466 #else
1467     if (extra & 0x800) {
1468 	/* signed variant */
1469 	uae_s32 src1,src2;
1470 	uae_u32 dst_lo,dst_hi;
1471 	uae_u32 sign;
1472 
1473 	src1 = (uae_s32)src;
1474 	src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
1475 	sign = (src1 ^ src2);
1476 	if (src1 < 0) src1 = -src1;
1477 	if (src2 < 0) src2 = -src2;
1478 	mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
1479 	if (sign & 0x80000000) {
1480 		dst_hi = ~dst_hi;
1481 		dst_lo = -dst_lo;
1482 		if (dst_lo == 0) dst_hi++;
1483 	}
1484 	SET_VFLG (0);
1485 	SET_CFLG (0);
1486 	SET_ZFLG (dst_hi == 0 && dst_lo == 0);
1487 	SET_NFLG (((uae_s32)dst_hi) < 0);
1488 	if (extra & 0x400)
1489 	    m68k_dreg(regs, extra & 7) = dst_hi;
1490 	else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
1491 		 && ((dst_hi & 0xffffffff) != 0xffffffff
1492 		     || (dst_lo & 0x80000000) != 0x80000000))
1493 	{
1494 	    SET_VFLG (1);
1495 	}
1496 	m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1497     } else {
1498 	/* unsigned */
1499 	uae_u32 dst_lo,dst_hi;
1500 
1501 	mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
1502 
1503 	SET_VFLG (0);
1504 	SET_CFLG (0);
1505 	SET_ZFLG (dst_hi == 0 && dst_lo == 0);
1506 	SET_NFLG (((uae_s32)dst_hi) < 0);
1507 	if (extra & 0x400)
1508 	    m68k_dreg(regs, extra & 7) = dst_hi;
1509 	else if (dst_hi != 0) {
1510 	    SET_VFLG (1);
1511 	}
1512 	m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1513     }
1514 #endif
1515 }
1516 
1517 
m68k_reset(void)1518 void m68k_reset (void)
1519 {
1520     regs.s = 1;
1521     regs.m = 0;
1522     regs.stopped = 0;
1523     regs.t1 = 0;
1524     regs.t0 = 0;
1525     SET_ZFLG (0);
1526     SET_XFLG (0);
1527     SET_CFLG (0);
1528     SET_VFLG (0);
1529     SET_NFLG (0);
1530     regs.spcflags &= ( SPCFLAG_MODE_CHANGE | SPCFLAG_DEBUGGER );	/* Clear specialflags except mode-change and debugger */
1531     regs.intmask = 7;
1532     regs.vbr = regs.sfc = regs.dfc = 0;
1533     regs.fpcr = regs.fpsr = regs.fpiar = 0;
1534 
1535     m68k_areg(regs, 7) = get_long(0);
1536     m68k_setpc(get_long(4));
1537     refill_prefetch (m68k_getpc(), 0);
1538 }
1539 
1540 
op_illg(uae_u32 opcode)1541 unsigned long REGPARAM2 op_illg (uae_u32 opcode)
1542 {
1543 #if 0
1544     uaecptr pc = m68k_getpc ();
1545 #endif
1546     if ((opcode & 0xF000) == 0xF000) {
1547 	Exception(0xB,0,M68000_EXC_SRC_CPU);
1548 	return 4;
1549     }
1550     if ((opcode & 0xF000) == 0xA000) {
1551 	Exception(0xA,0,M68000_EXC_SRC_CPU);
1552 	return 4;
1553     }
1554 #if 0
1555     write_log ("Illegal instruction: %04x at %08lx\n", opcode, (long)pc);
1556 #endif
1557     Exception (4,0,M68000_EXC_SRC_CPU);
1558     return 4;
1559 }
1560 
1561 
mmu_op(uae_u32 opcode,uae_u16 extra)1562 void mmu_op(uae_u32 opcode, uae_u16 extra)
1563 {
1564     if ((opcode & 0xFE0) == 0x0500) {
1565 	/* PFLUSH */
1566 	mmusr = 0;
1567 	write_log ("PFLUSH\n");
1568     } else if ((opcode & 0x0FD8) == 0x548) {
1569 	/* PTEST */
1570 	write_log ("PTEST\n");
1571     } else
1572 	op_illg (opcode);
1573 }
1574 
1575 
1576 static uaecptr last_trace_ad = 0;
1577 
do_trace(void)1578 static void do_trace (void)
1579 {
1580     if (regs.t0 && currprefs.cpu_level >= 2) {
1581 	uae_u16 opcode;
1582 	/* should also include TRAP, CHK, SR modification FPcc */
1583 	/* probably never used so why bother */
1584 	/* We can afford this to be inefficient... */
1585 	m68k_setpc (m68k_getpc ());
1586 	fill_prefetch_0 ();
1587 	opcode = get_word (regs.pc);
1588 	if (opcode == 0x4e73 		/* RTE */
1589 	    || opcode == 0x4e74 		/* RTD */
1590 	    || opcode == 0x4e75 		/* RTS */
1591 	    || opcode == 0x4e77 		/* RTR */
1592 	    || opcode == 0x4e76 		/* TRAPV */
1593 	    || (opcode & 0xffc0) == 0x4e80 	/* JSR */
1594 	    || (opcode & 0xffc0) == 0x4ec0 	/* JMP */
1595 	    || (opcode & 0xff00) == 0x6100  /* BSR */
1596 	    || ((opcode & 0xf000) == 0x6000	/* Bcc */
1597 		&& cctrue((opcode >> 8) & 0xf))
1598 	    || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
1599 		&& !cctrue((opcode >> 8) & 0xf)
1600 		&& (uae_s16)m68k_dreg(regs, opcode & 7) != 0))
1601 	{
1602 	    last_trace_ad = m68k_getpc ();
1603 	    unset_special (SPCFLAG_TRACE);
1604 	    set_special (SPCFLAG_DOTRACE);
1605 	}
1606     } else if (regs.t1) {
1607 	last_trace_ad = m68k_getpc ();
1608 	unset_special (SPCFLAG_TRACE);
1609 	set_special (SPCFLAG_DOTRACE);
1610     }
1611 }
1612 
1613 
1614 /*
1615  * Handle special flags
1616  */
1617 
do_specialties_interrupt(int Pending)1618 static bool do_specialties_interrupt (int Pending)
1619 {
1620 #if ENABLE_DSP_EMU
1621     /* Check for DSP int first (if enabled) (level 6) */
1622     if (regs.spcflags & SPCFLAG_DSP) {
1623        if (DSP_ProcessIRQ() == true)
1624          return true;
1625     }
1626 #endif
1627 
1628     /* Check for MFP ints (level 6) */
1629     if (regs.spcflags & SPCFLAG_MFP) {
1630        if (MFP_ProcessIRQ() == true)
1631          return true;					/* MFP exception was generated, no higher interrupt can happen */
1632     }
1633 
1634     /* No MFP int, check for VBL/HBL ints (levels 4/2) */
1635     if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)) {
1636 	int intr = intlev ();
1637 	/* SPCFLAG_DOINT will be enabled again in MakeFromSR to handle pending interrupts! */
1638 //	unset_special (SPCFLAG_DOINT);
1639 	unset_special (SPCFLAG_INT | SPCFLAG_DOINT);
1640 	if (intr != -1 && intr > regs.intmask) {
1641 	    Interrupt (intr , Pending);			/* process the interrupt and add pending jitter if necessary */
1642 	    return true;
1643 	}
1644     }
1645 
1646     return false;					/* no interrupt was found */
1647 }
1648 
1649 
do_specialties(void)1650 static int do_specialties (void)
1651 {
1652     if(regs.spcflags & SPCFLAG_BUSERROR) {
1653 	/* We can not execute bus errors directly in the memory handler
1654 	 * functions since the PC should point to the address of the next
1655 	 * instruction, so we're executing the bus errors here: */
1656 	unset_special(SPCFLAG_BUSERROR);
1657 	Exception(2,0,M68000_EXC_SRC_CPU);
1658     }
1659 
1660     if(regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
1661 	/* Add some extra cycles to simulate a wait state */
1662 	unset_special(SPCFLAG_EXTRA_CYCLES);
1663 	M68000_AddCycles(nWaitStateCycles);
1664 	nWaitStateCycles = 0;
1665     }
1666 
1667     if (regs.spcflags & SPCFLAG_DOTRACE) {
1668 	Exception (9,last_trace_ad,M68000_EXC_SRC_CPU);
1669     }
1670 
1671 
1672     /* Handle the STOP instruction */
1673     if ( regs.spcflags & SPCFLAG_STOP ) {
1674 //fprintf ( stderr , "test stop %d\n" , nCyclesMainCounter );
1675         /* We first test if there's a pending interrupt that would */
1676         /* allow to immediately leave the STOP state */
1677         if ( do_specialties_interrupt(true) ) {		/* test if there's an interrupt and add pending jitter */
1678             regs.stopped = 0;
1679             unset_special (SPCFLAG_STOP);
1680 //fprintf ( stderr , "exit stop %d\n" , nCyclesMainCounter );
1681         }
1682 
1683 	/* No pending int, we have to wait for the next matching int */
1684 	while (regs.spcflags & SPCFLAG_STOP) {
1685 
1686 	    /* Take care of quit event if needed */
1687 	    if (regs.spcflags & SPCFLAG_BRK)
1688 		return 1;
1689 
1690 	    M68000_AddCycles(4);
1691 
1692 	    /* It is possible one or more ints happen at the same time */
1693 	    /* We must process them during the same cpu cycle then choose the highest priority one */
1694 	    while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
1695 		CALL_VAR(PendingInterruptFunction);
1696 	    if ( MFP_UpdateNeeded == true )
1697 	        MFP_UpdateIRQ ( 0 );
1698 
1699 	    /* Check is there's an interrupt to process (could be a delayed MFP interrupt) */
1700 	    if ( do_specialties_interrupt(false) ) {	/* test if there's an interrupt and add non pending jitter */
1701 		regs.stopped = 0;
1702 		unset_special (SPCFLAG_STOP);
1703 	    }
1704 	}
1705     }
1706 
1707 
1708     if (regs.spcflags & SPCFLAG_TRACE)
1709 	do_trace ();
1710 
1711 //    if (regs.spcflags & SPCFLAG_DOINT) {
1712     /* [NP] pending int should be processed now, not after the current instr */
1713     /* so we check for (SPCFLAG_INT | SPCFLAG_DOINT), not just for SPCFLAG_DOINT */
1714 
1715     if ( do_specialties_interrupt(false) ) {	/* test if there's an interrupt and add non pending jitter */
1716         regs.stopped = 0;			/* [NP] useless ? */
1717     }
1718     if (regs.spcflags & SPCFLAG_INT) {
1719 	unset_special (SPCFLAG_INT);
1720 	set_special (SPCFLAG_DOINT);
1721     }
1722 
1723     if (regs.spcflags & SPCFLAG_DEBUGGER)
1724 	DebugCpu_Check();
1725 
1726     if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
1727 	unset_special(SPCFLAG_MODE_CHANGE);
1728 	return 1;
1729     }
1730 
1731     return 0;
1732 }
1733 
1734 
1735 /* It's really sad to have two almost identical functions for this, but we
1736    do it all for performance... :( */
m68k_run_1(void)1737 static void m68k_run_1 (void)
1738 {
1739 #ifdef DEBUG_PREFETCH
1740     uae_u8 saved_bytes[20];
1741     uae_u8 *oldpcp;
1742 #endif
1743 
1744     for (;;) {
1745 	int cycles;
1746 //fprintf (stderr, "ir in  %x %x\n",do_get_mem_long(&regs.prefetch) , regs.prefetch_pc);
1747 	uae_u32 opcode = get_iword_prefetch (0);
1748 
1749 	if (regs.spcflags & SPCFLAG_BUSERROR)
1750 	{
1751 	    unset_special(SPCFLAG_BUSERROR);
1752 	    Exception(2,0,M68000_EXC_SRC_CPU);
1753 
1754 	    /* Get opcode for bus error handler and check other special bits */
1755 	    opcode = get_iword_prefetch (0);
1756 	    if (regs.spcflags) {
1757 		if (do_specialties ())
1758 		    return;
1759 	    }
1760 	}
1761 
1762 #ifdef DEBUG_PREFETCH
1763 //	if (get_ilong (0) != do_get_mem_long (&regs.prefetch)) {
1764 //	    fprintf (stderr, "Prefetch differs from memory.\n");
1765 //	    debugging = 1;
1766 //	    return;
1767 //	}
1768 	oldpcp = regs.pc_p;
1769 	memcpy (saved_bytes, regs.pc_p, 20);
1770 #endif
1771 
1772 	/*m68k_dumpstate(stderr, NULL);*/
1773 	if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
1774 	{
1775 	    int FrameCycles, HblCounterVideo, LineCycles;
1776 
1777 	    Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1778 
1779 	    LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1780 	    Disasm(stderr, m68k_getpc (), NULL, 1);
1781 	}
1782 
1783 	/* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
1784 /*	regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
1785 #if COUNT_INSTRS == 2
1786 	if (table68k[opcode].handler != -1)
1787 	    instrcount[table68k[opcode].handler]++;
1788 #elif COUNT_INSTRS == 1
1789 	instrcount[opcode]++;
1790 #endif
1791 
1792 	/* In case of a Bus Error, we need the PC of the instruction that caused */
1793 	/* the error to build the exception stack frame */
1794 	BusErrorPC = m68k_getpc();
1795 
1796 	if (bDspEnabled)
1797 	    Cycles_SetCounter(CYCLES_COUNTER_CPU, 0);	/* to measure the total number of cycles spent in the cpu */
1798 
1799 	/* Uncomment following lines to call capslib's debugger after each instruction */
1800 	//if ( CAPSGetDebugRequest() )
1801 	//  DebugUI(REASON_CPU_BREAKPOINT);
1802 
1803 	cycles = (*cpufunctbl[opcode])(opcode);
1804 //fprintf (stderr, "ir out %x %x\n",do_get_mem_long(&regs.prefetch) , regs.prefetch_pc);
1805 
1806 #ifdef DEBUG_PREFETCH
1807 	if (memcmp (saved_bytes, oldpcp, 20) != 0) {
1808 	    fprintf (stderr, "Self-modifying code detected %x.\n" , m68k_getpc() );
1809 //	    set_special (SPCFLAG_BRK);
1810 //	    debugging = 1;
1811 	}
1812 #endif
1813 
1814 	M68000_AddCyclesWithPairing(cycles);
1815 	if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
1816 	  /* Add some extra cycles to simulate a wait state */
1817 	  unset_special(SPCFLAG_EXTRA_CYCLES);
1818 	  M68000_AddCycles(nWaitStateCycles);
1819 	  nWaitStateCycles = 0;
1820 	}
1821 
1822 	/* We can have several interrupts at the same time before the next CPU instruction */
1823 	/* We must check for pending interrupt and call do_specialties_interrupt() only */
1824 	/* if the cpu is not in the STOP state. Else, the int could be acknowledged now */
1825 	/* and prevent exiting the STOP state when calling do_specialties() after. */
1826 	/* For performance, we first test PendingInterruptCount, then regs.spcflags */
1827 	if ( PendingInterruptCount <= 0 )
1828 	{
1829 	    while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) && ( ( regs.spcflags & SPCFLAG_STOP ) == 0 ) )
1830 		CALL_VAR ( PendingInterruptFunction );		/* call the interrupt's handler */
1831 	    if ( MFP_UpdateNeeded == true )
1832 		MFP_UpdateIRQ ( 0 );				/* update MFP's state if some internal timers related to MFP expired */
1833 	}
1834 
1835 	if (regs.spcflags) {
1836 	    if (do_specialties ())
1837 		return;
1838 	}
1839 
1840 	/* Run DSP 56k code if necessary */
1841 	if (bDspEnabled) {
1842 	    DSP_Run( Cycles_GetCounter(CYCLES_COUNTER_CPU) * 2);
1843 	}
1844     }
1845 }
1846 
1847 
1848 /* Same thing, but don't use prefetch to get opcode.  */
m68k_run_2(void)1849 static void m68k_run_2 (void)
1850 {
1851     for (;;) {
1852 	int cycles;
1853 	uae_u32 opcode = get_iword (0);
1854 
1855 	/*m68k_dumpstate(stderr, NULL);*/
1856 	if (LOG_TRACE_LEVEL(TRACE_CPU_DISASM))
1857 	{
1858 	    int FrameCycles, HblCounterVideo, LineCycles;
1859 
1860 	    Video_GetPosition ( &FrameCycles , &HblCounterVideo , &LineCycles );
1861 
1862 	    LOG_TRACE_PRINT ( "cpu video_cyc=%6d %3d@%3d : " , FrameCycles, LineCycles, HblCounterVideo );
1863 	    Disasm(stderr, m68k_getpc (), NULL, 1);
1864 	}
1865 
1866 	/* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
1867 /*	regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
1868 #if COUNT_INSTRS == 2
1869 	if (table68k[opcode].handler != -1)
1870 	    instrcount[table68k[opcode].handler]++;
1871 #elif COUNT_INSTRS == 1
1872 	instrcount[opcode]++;
1873 #endif
1874 
1875 	/* In case of a Bus Error, we need the PC of the instruction that caused */
1876 	/* the error to build the exception stack frame */
1877 	BusErrorPC = m68k_getpc();
1878 
1879 	cycles = (*cpufunctbl[opcode])(opcode);
1880 
1881 	if (bDspEnabled)
1882 	    Cycles_SetCounter(CYCLES_COUNTER_CPU, 0);	/* to measure the total number of cycles spent in the cpu */
1883 
1884 	M68000_AddCycles(cycles);
1885 	if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
1886 	  /* Add some extra cycles to simulate a wait state */
1887 	  unset_special(SPCFLAG_EXTRA_CYCLES);
1888 	  M68000_AddCycles(nWaitStateCycles);
1889 	  nWaitStateCycles = 0;
1890 	}
1891 
1892         if ( PendingInterruptCount <= 0 )
1893 	{
1894 	    while ( ( PendingInterruptCount <= 0 ) && ( PendingInterruptFunction ) )
1895 		CALL_VAR(PendingInterruptFunction);
1896 	    if ( MFP_UpdateNeeded == true )
1897 		MFP_UpdateIRQ ( 0 );
1898 	}
1899 
1900 	if (regs.spcflags) {
1901 	    if (do_specialties ())
1902 		return;
1903 	}
1904 
1905 	/* Run DSP 56k code if necessary */
1906 	if (bDspEnabled) {
1907 	    DSP_Run( Cycles_GetCounter(CYCLES_COUNTER_CPU) );
1908 	}
1909     }
1910 }
1911 
1912 
m68k_go(int may_quit)1913 void m68k_go (int may_quit)
1914 {
1915     static int in_m68k_go = 0;
1916 
1917     if (in_m68k_go || !may_quit) {
1918 	write_log ("Bug! m68k_go is not reentrant.\n");
1919 	abort ();
1920     }
1921 
1922     in_m68k_go++;
1923     while (!(regs.spcflags & SPCFLAG_BRK)) {
1924         if(currprefs.cpu_compatible)
1925           m68k_run_1();
1926          else
1927           m68k_run_2();
1928     }
1929     unset_special(SPCFLAG_BRK);
1930     in_m68k_go--;
1931 }
1932 
1933 
1934 /*
1935 static void m68k_verify (uaecptr addr, uaecptr *nextpc)
1936 {
1937     uae_u32 opcode, val;
1938     struct instr *dp;
1939 
1940     opcode = get_iword_1(0);
1941     last_op_for_exception_3 = opcode;
1942     m68kpc_offset = 2;
1943 
1944     if (cpufunctbl[opcode] == op_illg_1) {
1945 	opcode = 0x4AFC;
1946     }
1947     dp = table68k + opcode;
1948 
1949     if (dp->suse) {
1950 	if (!verify_ea (dp->sreg, dp->smode, dp->size, &val)) {
1951 	    Exception (3, 0,M68000_EXC_SRC_CPU);
1952 	    return;
1953 	}
1954     }
1955     if (dp->duse) {
1956 	if (!verify_ea (dp->dreg, dp->dmode, dp->size, &val)) {
1957 	    Exception (3, 0,M68000_EXC_SRC_CPU);
1958 	    return;
1959 	}
1960     }
1961 }
1962 */
1963 
1964 
m68k_disasm(FILE * f,uaecptr addr,uaecptr * nextpc,int cnt)1965 void m68k_disasm (FILE *f, uaecptr addr, uaecptr *nextpc, int cnt)
1966 {
1967     static const char * const ccnames[] =
1968         { "T ","F ","HI","LS","CC","CS","NE","EQ",
1969           "VC","VS","PL","MI","GE","LT","GT","LE" };
1970 
1971     uaecptr newpc = 0;
1972     m68kpc_offset = addr - m68k_getpc ();
1973     while (cnt-- > 0) {
1974 	char instrname[20],*ccpt;
1975 	int opwords;
1976 	uae_u32 opcode;
1977 	const struct mnemolookup *lookup;
1978 	struct instr *dp;
1979 	fprintf (f, "%08lx: ", m68k_getpc () + m68kpc_offset);
1980 	for (opwords = 0; opwords < 5; opwords++){
1981 	    if ( valid_address ( m68k_getpc () + m68kpc_offset + opwords*2 , 2 ) )
1982 	        fprintf (f, "%04x ", get_iword_1 (m68kpc_offset + opwords*2));
1983 	    else
1984 	        fprintf (f, "**** " );
1985 	}
1986 	if ( ! valid_address ( m68k_getpc () + m68kpc_offset , 2 ) ) {
1987 	    fprintf (f , "BUS ERROR\n" );			/* If region is not valid (bus error region) */
1988 	    m68kpc_offset += 2;
1989 	    continue;
1990 	}
1991 
1992 	opcode = get_iword_1 (m68kpc_offset);
1993 	m68kpc_offset += 2;
1994 	if (cpufunctbl[opcode] == op_illg_1) {
1995 	    opcode = 0x4AFC;
1996 	}
1997 	dp = table68k + opcode;
1998 	for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
1999 	    ;
2000 
2001 	strcpy (instrname, lookup->name);
2002 	ccpt = strstr (instrname, "cc");
2003 	if (ccpt != 0) {
2004 	    strncpy (ccpt, ccnames[dp->cc], 2);
2005 	}
2006 	fprintf (f, "%s", instrname);
2007 	switch (dp->size){
2008 	 case sz_byte: fprintf (f, ".B "); break;
2009 	 case sz_word: fprintf (f, ".W "); break;
2010 	 case sz_long: fprintf (f, ".L "); break;
2011 	 default: fprintf (f, "   "); break;
2012 	}
2013 
2014 	if (dp->suse) {
2015 	    newpc = m68k_getpc () + m68kpc_offset;
2016 	    newpc += ShowEA (f, dp->sreg, dp->smode, dp->size, 0);
2017 	}
2018 	if (dp->suse && dp->duse)
2019 	    fprintf (f, ",");
2020 	if (dp->duse) {
2021 	    newpc = m68k_getpc () + m68kpc_offset;
2022 	    newpc += ShowEA (f, dp->dreg, dp->dmode, dp->size, 0);
2023 	}
2024 	if (ccpt != 0) {
2025 	    if (cctrue(dp->cc))
2026 		fprintf (f, " == %08lx (TRUE)", (long)newpc);
2027 	    else
2028 		fprintf (f, " == %08lx (FALSE)", (long)newpc);
2029 	} else if ((opcode & 0xff00) == 0x6100) /* BSR */
2030 	    fprintf (f, " == %08lx", (long)newpc);
2031 	fprintf (f, "\n");
2032     }
2033     if (nextpc)
2034 	*nextpc = m68k_getpc () + m68kpc_offset;
2035 }
2036 
m68k_dumpstate(FILE * f,uaecptr * nextpc)2037 void m68k_dumpstate (FILE *f, uaecptr *nextpc)
2038 {
2039     int i;
2040     for (i = 0; i < 8; i++){
2041 	fprintf (f, "D%d: %08lx ", i, (long)m68k_dreg(regs, i));
2042 	if ((i & 3) == 3) fprintf (f, "\n");
2043     }
2044     for (i = 0; i < 8; i++){
2045 	fprintf (f, "A%d: %08lx ", i, (long)m68k_areg(regs, i));
2046 	if ((i & 3) == 3) fprintf (f, "\n");
2047     }
2048     if (regs.s == 0) regs.usp = m68k_areg(regs, 7);
2049     if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7);
2050     if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7);
2051     fprintf (f, "USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n",
2052 	     (long)regs.usp,(long)regs.isp,(long)regs.msp,(long)regs.vbr);
2053     fprintf (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
2054 	     regs.t1, regs.t0, regs.s, regs.m,
2055 	     GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask);
2056     for (i = 0; i < 8; i++){
2057 	fprintf (f, "FP%d: %g ", i, regs.fp[i]);
2058 	if ((i & 3) == 3) fprintf (f, "\n");
2059     }
2060     fprintf (f, "N=%d Z=%d I=%d NAN=%d\n",
2061 	     (regs.fpsr & 0x8000000) != 0,
2062 	     (regs.fpsr & 0x4000000) != 0,
2063 	     (regs.fpsr & 0x2000000) != 0,
2064 	     (regs.fpsr & 0x1000000) != 0);
2065     if (currprefs.cpu_compatible)
2066 	fprintf (f, "prefetch %08lx\n", (unsigned long)do_get_mem_long(&regs.prefetch));
2067 
2068     m68k_disasm (f, m68k_getpc (), nextpc, 1);
2069     if (nextpc)
2070 	fprintf (f, "next PC: %08lx\n", (long)*nextpc);
2071 }
2072 
2073 
2074 /*
2075 
2076  The routines below take dividend and divisor as parameters.
2077  They return 0 if division by zero, or exact number of cycles otherwise.
2078 
2079  The number of cycles returned assumes a register operand.
2080  Effective address time must be added if memory operand.
2081 
2082  For 68000 only (not 68010, 68012, 68020, etc).
2083  Probably valid for 68008 after adding the extra prefetch cycle.
2084 
2085 
2086  Best and worst cases are for register operand:
2087  (Note the difference with the documented range.)
2088 
2089 
2090  DIVU:
2091 
2092  Overflow (always): 10 cycles.
2093  Worst case: 136 cycles.
2094  Best case: 76 cycles.
2095 
2096 
2097  DIVS:
2098 
2099  Absolute overflow: 16-18 cycles.
2100  Signed overflow is not detected prematurely.
2101 
2102  Worst case: 156 cycles.
2103  Best case without signed overflow: 122 cycles.
2104  Best case with signed overflow: 120 cycles
2105 
2106 
2107  */
2108 
2109 
2110 //
2111 // DIVU
2112 // Unsigned division
2113 //
2114 
getDivu68kCycles_2(uae_u32 dividend,uae_u16 divisor)2115 STATIC_INLINE int getDivu68kCycles_2 (uae_u32 dividend, uae_u16 divisor)
2116 {
2117     int mcycles;
2118     uae_u32 hdivisor;
2119     int i;
2120 
2121     if (divisor == 0)
2122 	return 0;
2123 
2124     // Overflow
2125     if ((dividend >> 16) >= divisor)
2126 	return (mcycles = 5) * 2;
2127 
2128     mcycles = 38;
2129     hdivisor = divisor << 16;
2130 
2131     for (i = 0; i < 15; i++) {
2132 	uae_u32 temp;
2133 	temp = dividend;
2134 
2135 	dividend <<= 1;
2136 
2137 	// If carry from shift
2138 	if ((uae_s32)temp < 0)
2139 	    dividend -= hdivisor;
2140 	else {
2141 	    mcycles += 2;
2142 	    if (dividend >= hdivisor) {
2143 		dividend -= hdivisor;
2144 		mcycles--;
2145 	    }
2146 	}
2147     }
2148     return mcycles * 2;
2149 }
getDivu68kCycles(uae_u32 dividend,uae_u16 divisor)2150 int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor)
2151 {
2152     int v = getDivu68kCycles_2 (dividend, divisor) - 4;
2153 //    write_log ("U%d ", v);
2154     return v;
2155 }
2156 
2157 //
2158 // DIVS
2159 // Signed division
2160 //
2161 
getDivs68kCycles_2(uae_s32 dividend,uae_s16 divisor)2162 STATIC_INLINE int getDivs68kCycles_2 (uae_s32 dividend, uae_s16 divisor)
2163 {
2164     int mcycles;
2165     uae_u32 aquot;
2166     int i;
2167 
2168     if (divisor == 0)
2169 	return 0;
2170 
2171     mcycles = 6;
2172 
2173     if (dividend < 0)
2174 	mcycles++;
2175 
2176     // Check for absolute overflow
2177     if (((uae_u32)abs (dividend) >> 16) >= (uae_u16)abs (divisor))
2178 	return (mcycles + 2) * 2;
2179 
2180     // Absolute quotient
2181     aquot = (uae_u32) abs (dividend) / (uae_u16)abs (divisor);
2182 
2183     mcycles += 55;
2184 
2185     if (divisor >= 0) {
2186 	if (dividend >= 0)
2187 	    mcycles--;
2188 	else
2189 	    mcycles++;
2190     }
2191 
2192     // Count 15 msbits in absolute of quotient
2193 
2194     for (i = 0; i < 15; i++) {
2195 	if ((uae_s16)aquot >= 0)
2196 	    mcycles++;
2197 	aquot <<= 1;
2198     }
2199 
2200     return mcycles * 2;
2201 }
getDivs68kCycles(uae_s32 dividend,uae_s16 divisor)2202 int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor)
2203 {
2204     int v = getDivs68kCycles_2 (dividend, divisor) - 4;
2205 //    write_log ("S%d ", v);
2206     return v;
2207 }
2208