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