ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/newcpu.cpp
Revision: 1.21
Committed: 2005-06-11T06:43:24Z (19 years ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-17
Changes since 1.20: +1 -0 lines
Log Message:
Much improved responsiveness on NetBSD systems.

On those systems, it's really hard to get high resolution timings and the
system oftens fails to honour a timeout in less than 20 ms. The idea here
is to have an average m68k instruction count (countdown quantum) that
triggers real interrupt checks. The quantum is calibrated every 10 ticks
and has a 1000 Hz resolution on average.

File Contents

# Content
1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * MC68000 emulation
5 *
6 * (c) 1995 Bernd Schmidt
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include "sysdeps.h"
14
15 #include "cpu_emulation.h"
16 #include "main.h"
17 #include "emul_op.h"
18
19 extern int intlev(void); // From baisilisk_glue.cpp
20
21 #include "m68k.h"
22 #include "memory.h"
23 #include "readcpu.h"
24 #include "newcpu.h"
25 #include "compiler/compemu.h"
26 #include "fpu/fpu.h"
27
28 #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
29 B2_mutex *spcflags_lock = NULL;
30 #endif
31
32 #if ENABLE_MON
33 #include "mon.h"
34 #include "mon_disass.h"
35 #endif
36
37 bool quit_program = false;
38 struct flag_struct regflags;
39
40 /* Opcode of faulting instruction */
41 uae_u16 last_op_for_exception_3;
42 /* PC at fault time */
43 uaecptr last_addr_for_exception_3;
44 /* Address that generated the exception */
45 uaecptr last_fault_for_exception_3;
46
47 int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
48 int imm8_table[] = { 8,1,2,3,4,5,6,7 };
49
50 int movem_index1[256];
51 int movem_index2[256];
52 int movem_next[256];
53
54 cpuop_func *cpufunctbl[65536];
55
56 #if FLIGHT_RECORDER
57 struct rec_step {
58 uae_u32 pc;
59 #if FLIGHT_RECORDER >= 2
60 uae_u32 d[8];
61 uae_u32 a[8];
62 #endif
63 };
64
65 const int LOG_SIZE = 32768;
66 static rec_step log[LOG_SIZE];
67 static int log_ptr = -1; // First time initialization
68
69 static const char *log_filename(void)
70 {
71 const char *name = getenv("M68K_LOG_FILE");
72 return name ? name : "log.68k";
73 }
74
75 void m68k_record_step(uaecptr pc)
76 {
77 #if FLIGHT_RECORDER >= 2
78 /* XXX: if LSB is set, we are recording from generated code and we
79 don't support registers recording yet. */
80 if ((pc & 1) == 0) {
81 for (int i = 0; i < 8; i++) {
82 log[log_ptr].d[i] = m68k_dreg(regs, i);
83 log[log_ptr].a[i] = m68k_areg(regs, i);
84 }
85 }
86 #endif
87 log[log_ptr].pc = pc;
88 log_ptr = (log_ptr + 1) % LOG_SIZE;
89 }
90
91 static void dump_log(void)
92 {
93 FILE *f = fopen(log_filename(), "w");
94 if (f == NULL)
95 return;
96 for (int i = 0; i < LOG_SIZE; i++) {
97 int j = (i + log_ptr) % LOG_SIZE;
98 uae_u32 pc = log[j].pc & ~1;
99 fprintf(f, "pc %08x", pc);
100 #if FLIGHT_RECORDER >= 2
101 fprintf(f, "\n");
102 if ((log[j].pc & 1) == 0) {
103 fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]);
104 fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]);
105 fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]);
106 fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]);
107 }
108 #else
109 fprintf(f, " | ");
110 #endif
111 #if ENABLE_MON
112 disass_68k(f, pc);
113 #endif
114 }
115 fclose(f);
116 }
117 #endif
118
119 #if ENABLE_MON
120 static void dump_regs(void)
121 {
122 m68k_dumpstate(NULL);
123 }
124 #endif
125
126 #define COUNT_INSTRS 0
127
128 #if COUNT_INSTRS
129 static unsigned long int instrcount[65536];
130 static uae_u16 opcodenums[65536];
131
132 static int compfn (const void *el1, const void *el2)
133 {
134 return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
135 }
136
137 static char *icountfilename (void)
138 {
139 char *name = getenv ("INSNCOUNT");
140 if (name)
141 return name;
142 return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
143 }
144
145 void dump_counts (void)
146 {
147 FILE *f = fopen (icountfilename (), "w");
148 unsigned long int total;
149 int i;
150
151 write_log ("Writing instruction count file...\n");
152 for (i = 0; i < 65536; i++) {
153 opcodenums[i] = i;
154 total += instrcount[i];
155 }
156 qsort (opcodenums, 65536, sizeof(uae_u16), compfn);
157
158 fprintf (f, "Total: %lu\n", total);
159 for (i=0; i < 65536; i++) {
160 unsigned long int cnt = instrcount[opcodenums[i]];
161 struct instr *dp;
162 struct mnemolookup *lookup;
163 if (!cnt)
164 break;
165 dp = table68k + opcodenums[i];
166 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
167 ;
168 fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
169 }
170 fclose (f);
171 }
172 #else
173 void dump_counts (void)
174 {
175 }
176 #endif
177
178 int broken_in;
179
180 static __inline__ unsigned int cft_map (unsigned int f)
181 {
182 #ifndef HAVE_GET_WORD_UNSWAPPED
183 return f;
184 #else
185 return ((f >> 8) & 255) | ((f & 255) << 8);
186 #endif
187 }
188
189 void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM;
190
191 void REGPARAM2 op_illg_1 (uae_u32 opcode)
192 {
193 op_illg (cft_map (opcode));
194 }
195
196 static void build_cpufunctbl (void)
197 {
198 int i;
199 unsigned long opcode;
200 int cpu_level = 0; // 68000 (default)
201 if (CPUType == 4)
202 cpu_level = 4; // 68040 with FPU
203 else {
204 if (FPUType)
205 cpu_level = 3; // 68020 with FPU
206 else if (CPUType >= 2)
207 cpu_level = 2; // 68020
208 else if (CPUType == 1)
209 cpu_level = 1;
210 }
211 struct cputbl *tbl = (
212 cpu_level == 4 ? op_smalltbl_0_ff
213 : cpu_level == 3 ? op_smalltbl_1_ff
214 : cpu_level == 2 ? op_smalltbl_2_ff
215 : cpu_level == 1 ? op_smalltbl_3_ff
216 : op_smalltbl_4_ff);
217
218 for (opcode = 0; opcode < 65536; opcode++)
219 cpufunctbl[cft_map (opcode)] = op_illg_1;
220 for (i = 0; tbl[i].handler != NULL; i++) {
221 if (! tbl[i].specific)
222 cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler;
223 }
224 for (opcode = 0; opcode < 65536; opcode++) {
225 cpuop_func *f;
226
227 if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > cpu_level)
228 continue;
229
230 if (table68k[opcode].handler != -1) {
231 f = cpufunctbl[cft_map (table68k[opcode].handler)];
232 if (f == op_illg_1)
233 abort();
234 cpufunctbl[cft_map (opcode)] = f;
235 }
236 }
237 for (i = 0; tbl[i].handler != NULL; i++) {
238 if (tbl[i].specific)
239 cpufunctbl[cft_map (tbl[i].opcode)] = tbl[i].handler;
240 }
241 }
242
243 void init_m68k (void)
244 {
245 int i;
246
247 for (i = 0 ; i < 256 ; i++) {
248 int j;
249 for (j = 0 ; j < 8 ; j++) {
250 if (i & (1 << j)) break;
251 }
252 movem_index1[i] = j;
253 movem_index2[i] = 7-j;
254 movem_next[i] = i & (~(1 << j));
255 }
256 #if COUNT_INSTRS
257 {
258 FILE *f = fopen (icountfilename (), "r");
259 memset (instrcount, 0, sizeof instrcount);
260 if (f) {
261 uae_u32 opcode, count, total;
262 char name[20];
263 write_log ("Reading instruction count file...\n");
264 fscanf (f, "Total: %lu\n", &total);
265 while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
266 instrcount[opcode] = count;
267 }
268 fclose(f);
269 }
270 }
271 #endif
272 read_table68k ();
273 do_merges ();
274
275 build_cpufunctbl ();
276
277 #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
278 spcflags_lock = B2_create_mutex();
279 #endif
280 fpu_init(CPUType == 4);
281 }
282
283 void exit_m68k (void)
284 {
285 fpu_exit ();
286 #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
287 B2_delete_mutex(spcflags_lock);
288 #endif
289 }
290
291 struct regstruct regs, lastint_regs;
292 static struct regstruct regs_backup[16];
293 static int backup_pointer = 0;
294 static long int m68kpc_offset;
295 int lastint_no;
296
297 #if REAL_ADDRESSING || DIRECT_ADDRESSING
298 #define get_ibyte_1(o) get_byte(get_virtual_address(regs.pc_p) + (o) + 1)
299 #define get_iword_1(o) get_word(get_virtual_address(regs.pc_p) + (o))
300 #define get_ilong_1(o) get_long(get_virtual_address(regs.pc_p) + (o))
301 #else
302 #define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
303 #define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
304 #define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
305 #endif
306
307 uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf)
308 {
309 uae_u16 dp;
310 uae_s8 disp8;
311 uae_s16 disp16;
312 int r;
313 uae_u32 dispreg;
314 uaecptr addr;
315 uae_s32 offset = 0;
316 char buffer[80];
317
318 switch (mode){
319 case Dreg:
320 sprintf (buffer,"D%d", reg);
321 break;
322 case Areg:
323 sprintf (buffer,"A%d", reg);
324 break;
325 case Aind:
326 sprintf (buffer,"(A%d)", reg);
327 break;
328 case Aipi:
329 sprintf (buffer,"(A%d)+", reg);
330 break;
331 case Apdi:
332 sprintf (buffer,"-(A%d)", reg);
333 break;
334 case Ad16:
335 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
336 addr = m68k_areg(regs,reg) + (uae_s16)disp16;
337 sprintf (buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff,
338 (unsigned long)addr);
339 break;
340 case Ad8r:
341 dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
342 disp8 = dp & 0xFF;
343 r = (dp & 0x7000) >> 12;
344 dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
345 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
346 dispreg <<= (dp >> 9) & 3;
347
348 if (dp & 0x100) {
349 uae_s32 outer = 0, disp = 0;
350 uae_s32 base = m68k_areg(regs,reg);
351 char name[10];
352 sprintf (name,"A%d, ",reg);
353 if (dp & 0x80) { base = 0; name[0] = 0; }
354 if (dp & 0x40) dispreg = 0;
355 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
356 if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
357 base += disp;
358
359 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
360 if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
361
362 if (!(dp & 4)) base += dispreg;
363 if (dp & 3) base = get_long (base);
364 if (dp & 4) base += dispreg;
365
366 addr = base + outer;
367 sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
368 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
369 1 << ((dp >> 9) & 3),
370 disp,outer,
371 (unsigned long)addr);
372 } else {
373 addr = m68k_areg(regs,reg) + (uae_s32)((uae_s8)disp8) + dispreg;
374 sprintf (buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg,
375 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
376 1 << ((dp >> 9) & 3), disp8,
377 (unsigned long)addr);
378 }
379 break;
380 case PC16:
381 addr = m68k_getpc () + m68kpc_offset;
382 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
383 addr += (uae_s16)disp16;
384 sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr);
385 break;
386 case PC8r:
387 addr = m68k_getpc () + m68kpc_offset;
388 dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
389 disp8 = dp & 0xFF;
390 r = (dp & 0x7000) >> 12;
391 dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
392 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
393 dispreg <<= (dp >> 9) & 3;
394
395 if (dp & 0x100) {
396 uae_s32 outer = 0,disp = 0;
397 uae_s32 base = addr;
398 char name[10];
399 sprintf (name,"PC, ");
400 if (dp & 0x80) { base = 0; name[0] = 0; }
401 if (dp & 0x40) dispreg = 0;
402 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
403 if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
404 base += disp;
405
406 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
407 if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
408
409 if (!(dp & 4)) base += dispreg;
410 if (dp & 3) base = get_long (base);
411 if (dp & 4) base += dispreg;
412
413 addr = base + outer;
414 sprintf (buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
415 dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
416 1 << ((dp >> 9) & 3),
417 disp,outer,
418 (unsigned long)addr);
419 } else {
420 addr += (uae_s32)((uae_s8)disp8) + dispreg;
421 sprintf (buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D',
422 (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
423 disp8, (unsigned long)addr);
424 }
425 break;
426 case absw:
427 sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset));
428 m68kpc_offset += 2;
429 break;
430 case absl:
431 sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset));
432 m68kpc_offset += 4;
433 break;
434 case imm:
435 switch (size){
436 case sz_byte:
437 sprintf (buffer,"#$%02x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xff));
438 m68kpc_offset += 2;
439 break;
440 case sz_word:
441 sprintf (buffer,"#$%04x", (unsigned int)(get_iword_1 (m68kpc_offset) & 0xffff));
442 m68kpc_offset += 2;
443 break;
444 case sz_long:
445 sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset)));
446 m68kpc_offset += 4;
447 break;
448 default:
449 break;
450 }
451 break;
452 case imm0:
453 offset = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
454 m68kpc_offset += 2;
455 sprintf (buffer,"#$%02x", (unsigned int)(offset & 0xff));
456 break;
457 case imm1:
458 offset = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
459 m68kpc_offset += 2;
460 sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff));
461 break;
462 case imm2:
463 offset = (uae_s32)get_ilong_1 (m68kpc_offset);
464 m68kpc_offset += 4;
465 sprintf (buffer,"#$%08lx", (unsigned long)offset);
466 break;
467 case immi:
468 offset = (uae_s32)(uae_s8)(reg & 0xff);
469 sprintf (buffer,"#$%08lx", (unsigned long)offset);
470 break;
471 default:
472 break;
473 }
474 if (buf == 0)
475 printf ("%s", buffer);
476 else
477 strcat (buf, buffer);
478 return offset;
479 }
480
481 /* The plan is that this will take over the job of exception 3 handling -
482 * the CPU emulation functions will just do a longjmp to m68k_go whenever
483 * they hit an odd address. */
484 static int verify_ea (int reg, amodes mode, wordsizes size, uae_u32 *val)
485 {
486 uae_u16 dp;
487 uae_s8 disp8;
488 uae_s16 disp16;
489 int r;
490 uae_u32 dispreg;
491 uaecptr addr;
492 uae_s32 offset = 0;
493
494 switch (mode){
495 case Dreg:
496 *val = m68k_dreg (regs, reg);
497 return 1;
498 case Areg:
499 *val = m68k_areg (regs, reg);
500 return 1;
501
502 case Aind:
503 case Aipi:
504 addr = m68k_areg (regs, reg);
505 break;
506 case Apdi:
507 addr = m68k_areg (regs, reg);
508 break;
509 case Ad16:
510 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
511 addr = m68k_areg(regs,reg) + (uae_s16)disp16;
512 break;
513 case Ad8r:
514 addr = m68k_areg (regs, reg);
515 d8r_common:
516 dp = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
517 disp8 = dp & 0xFF;
518 r = (dp & 0x7000) >> 12;
519 dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
520 if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
521 dispreg <<= (dp >> 9) & 3;
522
523 if (dp & 0x100) {
524 uae_s32 outer = 0, disp = 0;
525 uae_s32 base = addr;
526 if (dp & 0x80) base = 0;
527 if (dp & 0x40) dispreg = 0;
528 if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
529 if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
530 base += disp;
531
532 if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset); m68kpc_offset += 2; }
533 if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (m68kpc_offset); m68kpc_offset += 4; }
534
535 if (!(dp & 4)) base += dispreg;
536 if (dp & 3) base = get_long (base);
537 if (dp & 4) base += dispreg;
538
539 addr = base + outer;
540 } else {
541 addr += (uae_s32)((uae_s8)disp8) + dispreg;
542 }
543 break;
544 case PC16:
545 addr = m68k_getpc () + m68kpc_offset;
546 disp16 = get_iword_1 (m68kpc_offset); m68kpc_offset += 2;
547 addr += (uae_s16)disp16;
548 break;
549 case PC8r:
550 addr = m68k_getpc () + m68kpc_offset;
551 goto d8r_common;
552 case absw:
553 addr = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
554 m68kpc_offset += 2;
555 break;
556 case absl:
557 addr = get_ilong_1 (m68kpc_offset);
558 m68kpc_offset += 4;
559 break;
560 case imm:
561 switch (size){
562 case sz_byte:
563 *val = get_iword_1 (m68kpc_offset) & 0xff;
564 m68kpc_offset += 2;
565 break;
566 case sz_word:
567 *val = get_iword_1 (m68kpc_offset) & 0xffff;
568 m68kpc_offset += 2;
569 break;
570 case sz_long:
571 *val = get_ilong_1 (m68kpc_offset);
572 m68kpc_offset += 4;
573 break;
574 default:
575 break;
576 }
577 return 1;
578 case imm0:
579 *val = (uae_s32)(uae_s8)get_iword_1 (m68kpc_offset);
580 m68kpc_offset += 2;
581 return 1;
582 case imm1:
583 *val = (uae_s32)(uae_s16)get_iword_1 (m68kpc_offset);
584 m68kpc_offset += 2;
585 return 1;
586 case imm2:
587 *val = get_ilong_1 (m68kpc_offset);
588 m68kpc_offset += 4;
589 return 1;
590 case immi:
591 *val = (uae_s32)(uae_s8)(reg & 0xff);
592 return 1;
593 default:
594 addr = 0;
595 break;
596 }
597 if ((addr & 1) == 0)
598 return 1;
599
600 last_addr_for_exception_3 = m68k_getpc () + m68kpc_offset;
601 last_fault_for_exception_3 = addr;
602 return 0;
603 }
604
605 uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp)
606 {
607 int reg = (dp >> 12) & 15;
608 uae_s32 regd = regs.regs[reg];
609 if ((dp & 0x800) == 0)
610 regd = (uae_s32)(uae_s16)regd;
611 regd <<= (dp >> 9) & 3;
612 if (dp & 0x100) {
613 uae_s32 outer = 0;
614 if (dp & 0x80) base = 0;
615 if (dp & 0x40) regd = 0;
616
617 if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16)next_iword();
618 if ((dp & 0x30) == 0x30) base += next_ilong();
619
620 if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16)next_iword();
621 if ((dp & 0x3) == 0x3) outer = next_ilong();
622
623 if ((dp & 0x4) == 0) base += regd;
624 if (dp & 0x3) base = get_long (base);
625 if (dp & 0x4) base += regd;
626
627 return base + outer;
628 } else {
629 return base + (uae_s32)((uae_s8)dp) + regd;
630 }
631 }
632
633 uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp)
634 {
635 int reg = (dp >> 12) & 15;
636 uae_s32 regd = regs.regs[reg];
637 #if 1
638 if ((dp & 0x800) == 0)
639 regd = (uae_s32)(uae_s16)regd;
640 return base + (uae_s8)dp + regd;
641 #else
642 /* Branch-free code... benchmark this again now that
643 * things are no longer inline. */
644 uae_s32 regd16;
645 uae_u32 mask;
646 mask = ((dp & 0x800) >> 11) - 1;
647 regd16 = (uae_s32)(uae_s16)regd;
648 regd16 &= mask;
649 mask = ~mask;
650 base += (uae_s8)dp;
651 regd &= mask;
652 regd |= regd16;
653 return base + regd;
654 #endif
655 }
656
657 void MakeSR (void)
658 {
659 #if 0
660 assert((regs.t1 & 1) == regs.t1);
661 assert((regs.t0 & 1) == regs.t0);
662 assert((regs.s & 1) == regs.s);
663 assert((regs.m & 1) == regs.m);
664 assert((XFLG & 1) == XFLG);
665 assert((NFLG & 1) == NFLG);
666 assert((ZFLG & 1) == ZFLG);
667 assert((VFLG & 1) == VFLG);
668 assert((CFLG & 1) == CFLG);
669 #endif
670 regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
671 | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
672 | (GET_XFLG << 4) | (GET_NFLG << 3) | (GET_ZFLG << 2) | (GET_VFLG << 1)
673 | GET_CFLG);
674 }
675
676 void MakeFromSR (void)
677 {
678 int oldm = regs.m;
679 int olds = regs.s;
680
681 regs.t1 = (regs.sr >> 15) & 1;
682 regs.t0 = (regs.sr >> 14) & 1;
683 regs.s = (regs.sr >> 13) & 1;
684 regs.m = (regs.sr >> 12) & 1;
685 regs.intmask = (regs.sr >> 8) & 7;
686 SET_XFLG ((regs.sr >> 4) & 1);
687 SET_NFLG ((regs.sr >> 3) & 1);
688 SET_ZFLG ((regs.sr >> 2) & 1);
689 SET_VFLG ((regs.sr >> 1) & 1);
690 SET_CFLG (regs.sr & 1);
691 if (CPUType >= 2) {
692 if (olds != regs.s) {
693 if (olds) {
694 if (oldm)
695 regs.msp = m68k_areg(regs, 7);
696 else
697 regs.isp = m68k_areg(regs, 7);
698 m68k_areg(regs, 7) = regs.usp;
699 } else {
700 regs.usp = m68k_areg(regs, 7);
701 m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
702 }
703 } else if (olds && oldm != regs.m) {
704 if (oldm) {
705 regs.msp = m68k_areg(regs, 7);
706 m68k_areg(regs, 7) = regs.isp;
707 } else {
708 regs.isp = m68k_areg(regs, 7);
709 m68k_areg(regs, 7) = regs.msp;
710 }
711 }
712 } else {
713 if (olds != regs.s) {
714 if (olds) {
715 regs.isp = m68k_areg(regs, 7);
716 m68k_areg(regs, 7) = regs.usp;
717 } else {
718 regs.usp = m68k_areg(regs, 7);
719 m68k_areg(regs, 7) = regs.isp;
720 }
721 }
722 }
723
724 SPCFLAGS_SET( SPCFLAG_INT );
725 if (regs.t1 || regs.t0)
726 SPCFLAGS_SET( SPCFLAG_TRACE );
727 else
728 /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
729 SR-modifying instructions (including STOP). */
730 SPCFLAGS_CLEAR( SPCFLAG_TRACE );
731 }
732
733 void Exception(int nr, uaecptr oldpc)
734 {
735 uae_u32 currpc = m68k_getpc ();
736 MakeSR();
737 if (!regs.s) {
738 regs.usp = m68k_areg(regs, 7);
739 if (CPUType >= 2)
740 m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
741 else
742 m68k_areg(regs, 7) = regs.isp;
743 regs.s = 1;
744 }
745 if (CPUType > 0) {
746 if (nr == 2 || nr == 3) {
747 int i;
748 /* @@@ this is probably wrong (?) */
749 for (i = 0 ; i < 12 ; i++) {
750 m68k_areg(regs, 7) -= 2;
751 put_word (m68k_areg(regs, 7), 0);
752 }
753 m68k_areg(regs, 7) -= 2;
754 put_word (m68k_areg(regs, 7), 0xa000 + nr * 4);
755 } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
756 m68k_areg(regs, 7) -= 4;
757 put_long (m68k_areg(regs, 7), oldpc);
758 m68k_areg(regs, 7) -= 2;
759 put_word (m68k_areg(regs, 7), 0x2000 + nr * 4);
760 } else if (regs.m && nr >= 24 && nr < 32) {
761 m68k_areg(regs, 7) -= 2;
762 put_word (m68k_areg(regs, 7), nr * 4);
763 m68k_areg(regs, 7) -= 4;
764 put_long (m68k_areg(regs, 7), currpc);
765 m68k_areg(regs, 7) -= 2;
766 put_word (m68k_areg(regs, 7), regs.sr);
767 regs.sr |= (1 << 13);
768 regs.msp = m68k_areg(regs, 7);
769 m68k_areg(regs, 7) = regs.isp;
770 m68k_areg(regs, 7) -= 2;
771 put_word (m68k_areg(regs, 7), 0x1000 + nr * 4);
772 } else {
773 m68k_areg(regs, 7) -= 2;
774 put_word (m68k_areg(regs, 7), nr * 4);
775 }
776 } else {
777 if (nr == 2 || nr == 3) {
778 m68k_areg(regs, 7) -= 12;
779 /* ??????? */
780 if (nr == 3) {
781 put_long (m68k_areg(regs, 7), last_fault_for_exception_3);
782 put_word (m68k_areg(regs, 7)+4, last_op_for_exception_3);
783 put_long (m68k_areg(regs, 7)+8, last_addr_for_exception_3);
784 }
785 write_log ("Exception!\n");
786 goto kludge_me_do;
787 }
788 }
789 m68k_areg(regs, 7) -= 4;
790 put_long (m68k_areg(regs, 7), currpc);
791 kludge_me_do:
792 m68k_areg(regs, 7) -= 2;
793 put_word (m68k_areg(regs, 7), regs.sr);
794 m68k_setpc (get_long (regs.vbr + 4*nr));
795 SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE );
796 fill_prefetch_0 ();
797 regs.t1 = regs.t0 = regs.m = 0;
798 SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE );
799 }
800
801 static void Interrupt(int nr)
802 {
803 assert(nr < 8 && nr >= 0);
804 lastint_regs = regs;
805 lastint_no = nr;
806 Exception(nr+24, 0);
807
808 regs.intmask = nr;
809 SPCFLAGS_SET( SPCFLAG_INT );
810 }
811
812 static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp;
813
814 int m68k_move2c (int regno, uae_u32 *regp)
815 {
816 if ((CPUType == 1 && (regno & 0x7FF) > 1)
817 || (CPUType < 4 && (regno & 0x7FF) > 2)
818 || (CPUType == 4 && regno == 0x802))
819 {
820 op_illg (0x4E7B);
821 return 0;
822 } else {
823 switch (regno) {
824 case 0: regs.sfc = *regp & 7; break;
825 case 1: regs.dfc = *regp & 7; break;
826 case 2:
827 cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000);
828 #if USE_JIT
829 if (CPUType < 4) {
830 set_cache_state(cacr&1);
831 if (*regp & 0x08)
832 flush_icache(1);
833 }
834 else {
835 set_cache_state((cacr&0x8000) || 0);
836 // FIXME: The User Manual claims bit 3 of CACR is undefined
837 if (*regp & 0x08)
838 flush_icache(2);
839 }
840 #endif
841 break;
842 case 3: tc = *regp & 0xc000; break;
843 case 4: itt0 = *regp & 0xffffe364; break;
844 case 5: itt1 = *regp & 0xffffe364; break;
845 case 6: dtt0 = *regp & 0xffffe364; break;
846 case 7: dtt1 = *regp & 0xffffe364; break;
847 case 0x800: regs.usp = *regp; break;
848 case 0x801: regs.vbr = *regp; break;
849 case 0x802: caar = *regp &0xfc; break;
850 case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
851 case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
852 case 0x805: mmusr = *regp; break;
853 case 0x806: urp = *regp; break;
854 case 0x807: srp = *regp; break;
855 default:
856 op_illg (0x4E7B);
857 return 0;
858 }
859 }
860 return 1;
861 }
862
863 int m68k_movec2 (int regno, uae_u32 *regp)
864 {
865 if ((CPUType == 1 && (regno & 0x7FF) > 1)
866 || (CPUType < 4 && (regno & 0x7FF) > 2)
867 || (CPUType == 4 && regno == 0x802))
868 {
869 op_illg (0x4E7A);
870 return 0;
871 } else {
872 switch (regno) {
873 case 0: *regp = regs.sfc; break;
874 case 1: *regp = regs.dfc; break;
875 case 2: *regp = cacr; break;
876 case 3: *regp = tc; break;
877 case 4: *regp = itt0; break;
878 case 5: *regp = itt1; break;
879 case 6: *regp = dtt0; break;
880 case 7: *regp = dtt1; break;
881 case 0x800: *regp = regs.usp; break;
882 case 0x801: *regp = regs.vbr; break;
883 case 0x802: *regp = caar; break;
884 case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
885 case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
886 case 0x805: *regp = mmusr; break;
887 case 0x806: *regp = urp; break;
888 case 0x807: *regp = srp; break;
889 default:
890 op_illg (0x4E7A);
891 return 0;
892 }
893 }
894 return 1;
895 }
896
897 static __inline__ int
898 div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
899 {
900 uae_u32 q = 0, cbit = 0;
901 int i;
902
903 if (div <= src_hi) {
904 return 1;
905 }
906 for (i = 0 ; i < 32 ; i++) {
907 cbit = src_hi & 0x80000000ul;
908 src_hi <<= 1;
909 if (src_lo & 0x80000000ul) src_hi++;
910 src_lo <<= 1;
911 q = q << 1;
912 if (cbit || div <= src_hi) {
913 q |= 1;
914 src_hi -= div;
915 }
916 }
917 *quot = q;
918 *rem = src_hi;
919 return 0;
920 }
921
922 void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
923 {
924 #if defined(uae_s64)
925 if (src == 0) {
926 Exception (5, oldpc);
927 return;
928 }
929 if (extra & 0x800) {
930 /* signed variant */
931 uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
932 uae_s64 quot, rem;
933
934 if (extra & 0x400) {
935 a &= 0xffffffffu;
936 a |= (uae_s64)m68k_dreg(regs, extra & 7) << 32;
937 }
938 rem = a % (uae_s64)(uae_s32)src;
939 quot = a / (uae_s64)(uae_s32)src;
940 if ((quot & UVAL64(0xffffffff80000000)) != 0
941 && (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
942 {
943 SET_VFLG (1);
944 SET_NFLG (1);
945 SET_CFLG (0);
946 } else {
947 if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
948 SET_VFLG (0);
949 SET_CFLG (0);
950 SET_ZFLG (((uae_s32)quot) == 0);
951 SET_NFLG (((uae_s32)quot) < 0);
952 m68k_dreg(regs, extra & 7) = rem;
953 m68k_dreg(regs, (extra >> 12) & 7) = quot;
954 }
955 } else {
956 /* unsigned */
957 uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
958 uae_u64 quot, rem;
959
960 if (extra & 0x400) {
961 a &= 0xffffffffu;
962 a |= (uae_u64)m68k_dreg(regs, extra & 7) << 32;
963 }
964 rem = a % (uae_u64)src;
965 quot = a / (uae_u64)src;
966 if (quot > 0xffffffffu) {
967 SET_VFLG (1);
968 SET_NFLG (1);
969 SET_CFLG (0);
970 } else {
971 SET_VFLG (0);
972 SET_CFLG (0);
973 SET_ZFLG (((uae_s32)quot) == 0);
974 SET_NFLG (((uae_s32)quot) < 0);
975 m68k_dreg(regs, extra & 7) = rem;
976 m68k_dreg(regs, (extra >> 12) & 7) = quot;
977 }
978 }
979 #else
980 if (src == 0) {
981 Exception (5, oldpc);
982 return;
983 }
984 if (extra & 0x800) {
985 /* signed variant */
986 uae_s32 lo = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
987 uae_s32 hi = lo < 0 ? -1 : 0;
988 uae_s32 save_high;
989 uae_u32 quot, rem;
990 uae_u32 sign;
991
992 if (extra & 0x400) {
993 hi = (uae_s32)m68k_dreg(regs, extra & 7);
994 }
995 save_high = hi;
996 sign = (hi ^ src);
997 if (hi < 0) {
998 hi = ~hi;
999 lo = -lo;
1000 if (lo == 0) hi++;
1001 }
1002 if ((uae_s32)src < 0) src = -src;
1003 if (div_unsigned(hi, lo, src, &quot, &rem) ||
1004 (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
1005 SET_VFLG (1);
1006 SET_NFLG (1);
1007 SET_CFLG (0);
1008 } else {
1009 if (sign & 0x80000000) quot = -quot;
1010 if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
1011 SET_VFLG (0);
1012 SET_CFLG (0);
1013 SET_ZFLG (((uae_s32)quot) == 0);
1014 SET_NFLG (((uae_s32)quot) < 0);
1015 m68k_dreg(regs, extra & 7) = rem;
1016 m68k_dreg(regs, (extra >> 12) & 7) = quot;
1017 }
1018 } else {
1019 /* unsigned */
1020 uae_u32 lo = (uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
1021 uae_u32 hi = 0;
1022 uae_u32 quot, rem;
1023
1024 if (extra & 0x400) {
1025 hi = (uae_u32)m68k_dreg(regs, extra & 7);
1026 }
1027 if (div_unsigned(hi, lo, src, &quot, &rem)) {
1028 SET_VFLG (1);
1029 SET_NFLG (1);
1030 SET_CFLG (0);
1031 } else {
1032 SET_VFLG (0);
1033 SET_CFLG (0);
1034 SET_ZFLG (((uae_s32)quot) == 0);
1035 SET_NFLG (((uae_s32)quot) < 0);
1036 m68k_dreg(regs, extra & 7) = rem;
1037 m68k_dreg(regs, (extra >> 12) & 7) = quot;
1038 }
1039 }
1040 #endif
1041 }
1042
1043 static __inline__ void
1044 mul_unsigned(uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
1045 {
1046 uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
1047 uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
1048 uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
1049 uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
1050 uae_u32 lo;
1051
1052 lo = r0 + ((r1 << 16) & 0xffff0000ul);
1053 if (lo < r0) r3++;
1054 r0 = lo;
1055 lo = r0 + ((r2 << 16) & 0xffff0000ul);
1056 if (lo < r0) r3++;
1057 r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
1058 *dst_lo = lo;
1059 *dst_hi = r3;
1060 }
1061
1062 void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
1063 {
1064 #if defined(uae_s64)
1065 if (extra & 0x800) {
1066 /* signed variant */
1067 uae_s64 a = (uae_s64)(uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
1068
1069 a *= (uae_s64)(uae_s32)src;
1070 SET_VFLG (0);
1071 SET_CFLG (0);
1072 SET_ZFLG (a == 0);
1073 SET_NFLG (a < 0);
1074 if (extra & 0x400)
1075 m68k_dreg(regs, extra & 7) = a >> 32;
1076 else if ((a & UVAL64(0xffffffff80000000)) != 0
1077 && (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
1078 {
1079 SET_VFLG (1);
1080 }
1081 m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
1082 } else {
1083 /* unsigned */
1084 uae_u64 a = (uae_u64)(uae_u32)m68k_dreg(regs, (extra >> 12) & 7);
1085
1086 a *= (uae_u64)src;
1087 SET_VFLG (0);
1088 SET_CFLG (0);
1089 SET_ZFLG (a == 0);
1090 SET_NFLG (((uae_s64)a) < 0);
1091 if (extra & 0x400)
1092 m68k_dreg(regs, extra & 7) = a >> 32;
1093 else if ((a & UVAL64(0xffffffff00000000)) != 0) {
1094 SET_VFLG (1);
1095 }
1096 m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)a;
1097 }
1098 #else
1099 if (extra & 0x800) {
1100 /* signed variant */
1101 uae_s32 src1,src2;
1102 uae_u32 dst_lo,dst_hi;
1103 uae_u32 sign;
1104
1105 src1 = (uae_s32)src;
1106 src2 = (uae_s32)m68k_dreg(regs, (extra >> 12) & 7);
1107 sign = (src1 ^ src2);
1108 if (src1 < 0) src1 = -src1;
1109 if (src2 < 0) src2 = -src2;
1110 mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
1111 if (sign & 0x80000000) {
1112 dst_hi = ~dst_hi;
1113 dst_lo = -dst_lo;
1114 if (dst_lo == 0) dst_hi++;
1115 }
1116 SET_VFLG (0);
1117 SET_CFLG (0);
1118 SET_ZFLG (dst_hi == 0 && dst_lo == 0);
1119 SET_NFLG (((uae_s32)dst_hi) < 0);
1120 if (extra & 0x400)
1121 m68k_dreg(regs, extra & 7) = dst_hi;
1122 else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
1123 && ((dst_hi & 0xffffffff) != 0xffffffff
1124 || (dst_lo & 0x80000000) != 0x80000000))
1125 {
1126 SET_VFLG (1);
1127 }
1128 m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1129 } else {
1130 /* unsigned */
1131 uae_u32 dst_lo,dst_hi;
1132
1133 mul_unsigned(src,(uae_u32)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
1134
1135 SET_VFLG (0);
1136 SET_CFLG (0);
1137 SET_ZFLG (dst_hi == 0 && dst_lo == 0);
1138 SET_NFLG (((uae_s32)dst_hi) < 0);
1139 if (extra & 0x400)
1140 m68k_dreg(regs, extra & 7) = dst_hi;
1141 else if (dst_hi != 0) {
1142 SET_VFLG (1);
1143 }
1144 m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1145 }
1146 #endif
1147 }
1148 static char* ccnames[] =
1149 { "T ","F ","HI","LS","CC","CS","NE","EQ",
1150 "VC","VS","PL","MI","GE","LT","GT","LE" };
1151
1152 // If value is greater than zero, this means we are still processing an EmulOp
1153 // because the counter is incremented only in m68k_execute(), i.e. interpretive
1154 // execution only
1155 static int m68k_execute_depth = 0;
1156
1157 void m68k_reset (void)
1158 {
1159 m68k_areg (regs, 7) = 0x2000;
1160 m68k_setpc (ROMBaseMac + 0x2a);
1161 fill_prefetch_0 ();
1162 regs.s = 1;
1163 regs.m = 0;
1164 regs.stopped = 0;
1165 regs.t1 = 0;
1166 regs.t0 = 0;
1167 SET_ZFLG (0);
1168 SET_XFLG (0);
1169 SET_CFLG (0);
1170 SET_VFLG (0);
1171 SET_NFLG (0);
1172 SPCFLAGS_INIT( 0 );
1173 regs.intmask = 7;
1174 regs.vbr = regs.sfc = regs.dfc = 0;
1175 fpu_reset();
1176
1177 #if FLIGHT_RECORDER
1178 log_ptr = 0;
1179 memset(log, 0, sizeof(log));
1180 #endif
1181
1182 #if ENABLE_MON
1183 static bool first_time = true;
1184 if (first_time) {
1185 first_time = false;
1186 mon_add_command("regs", dump_regs, "regs Dump m68k emulator registers\n");
1187 #if FLIGHT_RECORDER
1188 // Install "log" command in mon
1189 mon_add_command("log", dump_log, "log Dump m68k emulation log\n");
1190 #endif
1191 }
1192 #endif
1193 }
1194
1195 void m68k_emulop_return(void)
1196 {
1197 SPCFLAGS_SET( SPCFLAG_BRK );
1198 quit_program = true;
1199 }
1200
1201 void m68k_emulop(uae_u32 opcode)
1202 {
1203 struct M68kRegisters r;
1204 int i;
1205
1206 for (i=0; i<8; i++) {
1207 r.d[i] = m68k_dreg(regs, i);
1208 r.a[i] = m68k_areg(regs, i);
1209 }
1210 MakeSR();
1211 r.sr = regs.sr;
1212 EmulOp(opcode, &r);
1213 for (i=0; i<8; i++) {
1214 m68k_dreg(regs, i) = r.d[i];
1215 m68k_areg(regs, i) = r.a[i];
1216 }
1217 regs.sr = r.sr;
1218 MakeFromSR();
1219 }
1220
1221 void REGPARAM2 op_illg (uae_u32 opcode)
1222 {
1223 uaecptr pc = m68k_getpc ();
1224
1225 if ((opcode & 0xF000) == 0xA000) {
1226 Exception(0xA,0);
1227 return;
1228 }
1229
1230 if ((opcode & 0xF000) == 0xF000) {
1231 Exception(0xB,0);
1232 return;
1233 }
1234
1235 write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc);
1236 #if USE_JIT && JIT_DEBUG
1237 compiler_dumpstate();
1238 #endif
1239
1240 Exception (4,0);
1241 return;
1242 }
1243
1244 void mmu_op(uae_u32 opcode, uae_u16 extra)
1245 {
1246 if ((opcode & 0xFE0) == 0x0500) {
1247 /* PFLUSH */
1248 mmusr = 0;
1249 } else if ((opcode & 0x0FD8) == 0x548) {
1250 /* PTEST */
1251 } else
1252 op_illg (opcode);
1253 }
1254
1255 static int n_insns = 0, n_spcinsns = 0;
1256
1257 static uaecptr last_trace_ad = 0;
1258
1259 static void do_trace (void)
1260 {
1261 if (regs.t0 && CPUType >= 2) {
1262 uae_u16 opcode;
1263 /* should also include TRAP, CHK, SR modification FPcc */
1264 /* probably never used so why bother */
1265 /* We can afford this to be inefficient... */
1266 m68k_setpc (m68k_getpc ());
1267 fill_prefetch_0 ();
1268 opcode = get_word(m68k_getpc());
1269 if (opcode == 0x4e72 /* RTE */
1270 || opcode == 0x4e74 /* RTD */
1271 || opcode == 0x4e75 /* RTS */
1272 || opcode == 0x4e77 /* RTR */
1273 || opcode == 0x4e76 /* TRAPV */
1274 || (opcode & 0xffc0) == 0x4e80 /* JSR */
1275 || (opcode & 0xffc0) == 0x4ec0 /* JMP */
1276 || (opcode & 0xff00) == 0x6100 /* BSR */
1277 || ((opcode & 0xf000) == 0x6000 /* Bcc */
1278 && cctrue((opcode >> 8) & 0xf))
1279 || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
1280 && !cctrue((opcode >> 8) & 0xf)
1281 && (uae_s16)m68k_dreg(regs, opcode & 7) != 0))
1282 {
1283 last_trace_ad = m68k_getpc ();
1284 SPCFLAGS_CLEAR( SPCFLAG_TRACE );
1285 SPCFLAGS_SET( SPCFLAG_DOTRACE );
1286 }
1287 } else if (regs.t1) {
1288 last_trace_ad = m68k_getpc ();
1289 SPCFLAGS_CLEAR( SPCFLAG_TRACE );
1290 SPCFLAGS_SET( SPCFLAG_DOTRACE );
1291 }
1292 }
1293
1294 int m68k_do_specialties (void)
1295 {
1296 #if USE_JIT
1297 // Block was compiled
1298 SPCFLAGS_CLEAR( SPCFLAG_JIT_END_COMPILE );
1299
1300 // Retain the request to get out of compiled code until
1301 // we reached the toplevel execution, i.e. the one that
1302 // can compile then run compiled code. This also means
1303 // we processed all (nested) EmulOps
1304 if ((m68k_execute_depth == 0) && SPCFLAGS_TEST( SPCFLAG_JIT_EXEC_RETURN ))
1305 SPCFLAGS_CLEAR( SPCFLAG_JIT_EXEC_RETURN );
1306 #endif
1307
1308 if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) {
1309 Exception (9,last_trace_ad);
1310 }
1311 while (SPCFLAGS_TEST( SPCFLAG_STOP )) {
1312 if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){
1313 SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT );
1314 int intr = intlev ();
1315 if (intr != -1 && intr > regs.intmask) {
1316 Interrupt (intr);
1317 regs.stopped = 0;
1318 SPCFLAGS_CLEAR( SPCFLAG_STOP );
1319 }
1320 }
1321 }
1322 if (SPCFLAGS_TEST( SPCFLAG_TRACE ))
1323 do_trace ();
1324
1325 if (SPCFLAGS_TEST( SPCFLAG_DOINT )) {
1326 SPCFLAGS_CLEAR( SPCFLAG_DOINT );
1327 int intr = intlev ();
1328 if (intr != -1 && intr > regs.intmask) {
1329 Interrupt (intr);
1330 regs.stopped = 0;
1331 }
1332 }
1333 if (SPCFLAGS_TEST( SPCFLAG_INT )) {
1334 SPCFLAGS_CLEAR( SPCFLAG_INT );
1335 SPCFLAGS_SET( SPCFLAG_DOINT );
1336 }
1337 if (SPCFLAGS_TEST( SPCFLAG_BRK )) {
1338 SPCFLAGS_CLEAR( SPCFLAG_BRK );
1339 return 1;
1340 }
1341 return 0;
1342 }
1343
1344 void m68k_do_execute (void)
1345 {
1346 for (;;) {
1347 uae_u32 opcode = GET_OPCODE;
1348 #if FLIGHT_RECORDER
1349 m68k_record_step(m68k_getpc());
1350 #endif
1351 (*cpufunctbl[opcode])(opcode);
1352 cpu_check_ticks();
1353 if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
1354 if (m68k_do_specialties())
1355 return;
1356 }
1357 }
1358 }
1359
1360 #if USE_JIT && !(defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY))
1361 void m68k_compile_execute (void)
1362 {
1363 for (;;) {
1364 if (quit_program)
1365 break;
1366 m68k_do_compile_execute();
1367 }
1368 }
1369 #endif
1370
1371 void m68k_execute (void)
1372 {
1373 #if USE_JIT
1374 ++m68k_execute_depth;
1375 #endif
1376 for (;;) {
1377 if (quit_program)
1378 break;
1379 m68k_do_execute();
1380 }
1381 #if USE_JIT
1382 --m68k_execute_depth;
1383 #endif
1384 }
1385
1386 static void m68k_verify (uaecptr addr, uaecptr *nextpc)
1387 {
1388 uae_u32 opcode, val;
1389 struct instr *dp;
1390
1391 opcode = get_iword_1(0);
1392 last_op_for_exception_3 = opcode;
1393 m68kpc_offset = 2;
1394
1395 if (cpufunctbl[cft_map (opcode)] == op_illg_1) {
1396 opcode = 0x4AFC;
1397 }
1398 dp = table68k + opcode;
1399
1400 if (dp->suse) {
1401 if (!verify_ea (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, &val)) {
1402 Exception (3, 0);
1403 return;
1404 }
1405 }
1406 if (dp->duse) {
1407 if (!verify_ea (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, &val)) {
1408 Exception (3, 0);
1409 return;
1410 }
1411 }
1412 }
1413
1414 void m68k_disasm (uaecptr addr, uaecptr *nextpc, int cnt)
1415 {
1416 uaecptr newpc = 0;
1417 m68kpc_offset = addr - m68k_getpc ();
1418 while (cnt-- > 0) {
1419 char instrname[20],*ccpt;
1420 int opwords;
1421 uae_u32 opcode;
1422 struct mnemolookup *lookup;
1423 struct instr *dp;
1424 printf ("%08lx: ", m68k_getpc () + m68kpc_offset);
1425 for (opwords = 0; opwords < 5; opwords++){
1426 printf ("%04x ", get_iword_1 (m68kpc_offset + opwords*2));
1427 }
1428 opcode = get_iword_1 (m68kpc_offset);
1429 m68kpc_offset += 2;
1430 if (cpufunctbl[cft_map (opcode)] == op_illg_1) {
1431 opcode = 0x4AFC;
1432 }
1433 dp = table68k + opcode;
1434 for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
1435 ;
1436
1437 strcpy (instrname, lookup->name);
1438 ccpt = strstr (instrname, "cc");
1439 if (ccpt != 0) {
1440 strncpy (ccpt, ccnames[dp->cc], 2);
1441 }
1442 printf ("%s", instrname);
1443 switch (dp->size){
1444 case sz_byte: printf (".B "); break;
1445 case sz_word: printf (".W "); break;
1446 case sz_long: printf (".L "); break;
1447 default: printf (" "); break;
1448 }
1449
1450 if (dp->suse) {
1451 newpc = m68k_getpc () + m68kpc_offset;
1452 newpc += ShowEA (dp->sreg, (amodes)dp->smode, (wordsizes)dp->size, 0);
1453 }
1454 if (dp->suse && dp->duse)
1455 printf (",");
1456 if (dp->duse) {
1457 newpc = m68k_getpc () + m68kpc_offset;
1458 newpc += ShowEA (dp->dreg, (amodes)dp->dmode, (wordsizes)dp->size, 0);
1459 }
1460 if (ccpt != 0) {
1461 if (cctrue(dp->cc))
1462 printf (" == %08lx (TRUE)", newpc);
1463 else
1464 printf (" == %08lx (FALSE)", newpc);
1465 } else if ((opcode & 0xff00) == 0x6100) /* BSR */
1466 printf (" == %08lx", newpc);
1467 printf ("\n");
1468 }
1469 if (nextpc)
1470 *nextpc = m68k_getpc () + m68kpc_offset;
1471 }
1472
1473 void m68k_dumpstate (uaecptr *nextpc)
1474 {
1475 int i;
1476 for (i = 0; i < 8; i++){
1477 printf ("D%d: %08lx ", i, m68k_dreg(regs, i));
1478 if ((i & 3) == 3) printf ("\n");
1479 }
1480 for (i = 0; i < 8; i++){
1481 printf ("A%d: %08lx ", i, m68k_areg(regs, i));
1482 if ((i & 3) == 3) printf ("\n");
1483 }
1484 if (regs.s == 0) regs.usp = m68k_areg(regs, 7);
1485 if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7);
1486 if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7);
1487 printf ("USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n",
1488 regs.usp,regs.isp,regs.msp,regs.vbr);
1489 printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
1490 regs.t1, regs.t0, regs.s, regs.m,
1491 GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask);
1492
1493 fpu_dump_registers();
1494 fpu_dump_flags();
1495
1496 m68k_disasm(m68k_getpc (), nextpc, 1);
1497 if (nextpc)
1498 printf ("next PC: %08lx\n", *nextpc);
1499 }