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, ", &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, ", &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(®s.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 (®s.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(®s.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(®s.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