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, 1 month 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

# User Rev Content
1 cebix 1.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 gbeauche 1.16 #include "compiler/compemu.h"
26 gbeauche 1.15 #include "fpu/fpu.h"
27 cebix 1.1
28 gbeauche 1.14 #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
29     B2_mutex *spcflags_lock = NULL;
30 gbeauche 1.13 #endif
31    
32 gbeauche 1.10 #if ENABLE_MON
33     #include "mon.h"
34     #include "mon_disass.h"
35     #endif
36    
37 gbeauche 1.17 bool quit_program = false;
38 cebix 1.1 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 gbeauche 1.10 #if FLIGHT_RECORDER
57     struct rec_step {
58 gbeauche 1.20 uae_u32 pc;
59     #if FLIGHT_RECORDER >= 2
60 gbeauche 1.10 uae_u32 d[8];
61     uae_u32 a[8];
62 gbeauche 1.20 #endif
63 gbeauche 1.10 };
64    
65 gbeauche 1.20 const int LOG_SIZE = 32768;
66 gbeauche 1.10 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 gbeauche 1.16 void m68k_record_step(uaecptr pc)
76 gbeauche 1.10 {
77 gbeauche 1.20 #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 gbeauche 1.10 }
86 gbeauche 1.20 #endif
87 gbeauche 1.10 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 gbeauche 1.20 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 gbeauche 1.10 #if ENABLE_MON
112 gbeauche 1.20 disass_68k(f, pc);
113 gbeauche 1.10 #endif
114     }
115 gbeauche 1.11 fclose(f);
116 gbeauche 1.10 }
117     #endif
118    
119 gbeauche 1.20 #if ENABLE_MON
120     static void dump_regs(void)
121     {
122     m68k_dumpstate(NULL);
123     }
124     #endif
125    
126 cebix 1.1 #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 gbeauche 1.18 void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM;
190 cebix 1.1
191 gbeauche 1.18 void REGPARAM2 op_illg_1 (uae_u32 opcode)
192 cebix 1.1 {
193 gbeauche 1.18 op_illg (cft_map (opcode));
194 cebix 1.1 }
195    
196     static void build_cpufunctbl (void)
197     {
198     int i;
199     unsigned long opcode;
200 cebix 1.2 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 gbeauche 1.13 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 cebix 1.1
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 gbeauche 1.14
277     #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
278     spcflags_lock = B2_create_mutex();
279     #endif
280 gbeauche 1.15 fpu_init(CPUType == 4);
281 gbeauche 1.6 }
282    
283     void exit_m68k (void)
284     {
285     fpu_exit ();
286 gbeauche 1.14 #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
287     B2_delete_mutex(spcflags_lock);
288     #endif
289 cebix 1.1 }
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 gbeauche 1.7 #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 cebix 1.1 #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 gbeauche 1.7 #endif
306 cebix 1.1
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 cebix 1.5 (unsigned long)addr);
339 cebix 1.1 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 cebix 1.5 (unsigned long)addr);
372 cebix 1.1 } 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 cebix 1.5 (unsigned long)addr);
378 cebix 1.1 }
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 cebix 1.5 sprintf (buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(unsigned long)addr);
385 cebix 1.1 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 cebix 1.5 (unsigned long)addr);
419 cebix 1.1 } 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 cebix 1.5 disp8, (unsigned long)addr);
424 cebix 1.1 }
425     break;
426     case absw:
427 cebix 1.5 sprintf (buffer,"$%08lx", (unsigned long)(uae_s32)(uae_s16)get_iword_1 (m68kpc_offset));
428 cebix 1.1 m68kpc_offset += 2;
429     break;
430     case absl:
431 cebix 1.5 sprintf (buffer,"$%08lx", (unsigned long)get_ilong_1 (m68kpc_offset));
432 cebix 1.1 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 cebix 1.5 sprintf (buffer,"#$%08lx", (unsigned long)(get_ilong_1 (m68kpc_offset)));
446 cebix 1.1 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 cebix 1.5 sprintf (buffer,"#$%08lx", (unsigned long)offset);
466 cebix 1.1 break;
467     case immi:
468     offset = (uae_s32)(uae_s8)(reg & 0xff);
469 cebix 1.5 sprintf (buffer,"#$%08lx", (unsigned long)offset);
470 cebix 1.1 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 gbeauche 1.13 SPCFLAGS_SET( SPCFLAG_INT );
725 cebix 1.1 if (regs.t1 || regs.t0)
726 gbeauche 1.13 SPCFLAGS_SET( SPCFLAG_TRACE );
727 cebix 1.1 else
728 gbeauche 1.12 /* Keep SPCFLAG_DOTRACE, we still want a trace exception for
729     SR-modifying instructions (including STOP). */
730 gbeauche 1.13 SPCFLAGS_CLEAR( SPCFLAG_TRACE );
731 cebix 1.1 }
732    
733     void Exception(int nr, uaecptr oldpc)
734     {
735 gbeauche 1.9 uae_u32 currpc = m68k_getpc ();
736 cebix 1.1 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 gbeauche 1.9 put_long (m68k_areg(regs, 7), currpc);
765 cebix 1.1 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 gbeauche 1.9 put_long (m68k_areg(regs, 7), currpc);
791 cebix 1.1 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 gbeauche 1.13 SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE );
796 cebix 1.1 fill_prefetch_0 ();
797     regs.t1 = regs.t0 = regs.m = 0;
798 gbeauche 1.13 SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE );
799 cebix 1.1 }
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 gbeauche 1.13 SPCFLAGS_SET( SPCFLAG_INT );
810 cebix 1.1 }
811    
812 gbeauche 1.12 static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp;
813 cebix 1.1
814 gbeauche 1.9 int m68k_move2c (int regno, uae_u32 *regp)
815 cebix 1.1 {
816 gbeauche 1.9 if ((CPUType == 1 && (regno & 0x7FF) > 1)
817 gbeauche 1.12 || (CPUType < 4 && (regno & 0x7FF) > 2)
818     || (CPUType == 4 && regno == 0x802))
819 gbeauche 1.9 {
820 cebix 1.1 op_illg (0x4E7B);
821 gbeauche 1.9 return 0;
822     } else {
823 cebix 1.1 switch (regno) {
824     case 0: regs.sfc = *regp & 7; break;
825     case 1: regs.dfc = *regp & 7; break;
826 gbeauche 1.16 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 cebix 1.2 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 cebix 1.1 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 gbeauche 1.12 case 0x805: mmusr = *regp; break;
853     case 0x806: urp = *regp; break;
854     case 0x807: srp = *regp; break;
855 cebix 1.1 default:
856     op_illg (0x4E7B);
857 gbeauche 1.9 return 0;
858 cebix 1.1 }
859 gbeauche 1.9 }
860     return 1;
861 cebix 1.1 }
862    
863 gbeauche 1.9 int m68k_movec2 (int regno, uae_u32 *regp)
864 cebix 1.1 {
865 gbeauche 1.9 if ((CPUType == 1 && (regno & 0x7FF) > 1)
866 gbeauche 1.12 || (CPUType < 4 && (regno & 0x7FF) > 2)
867     || (CPUType == 4 && regno == 0x802))
868 gbeauche 1.9 {
869 cebix 1.1 op_illg (0x4E7A);
870 gbeauche 1.9 return 0;
871     } else {
872 cebix 1.1 switch (regno) {
873     case 0: *regp = regs.sfc; break;
874     case 1: *regp = regs.dfc; break;
875     case 2: *regp = cacr; break;
876 cebix 1.2 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 cebix 1.1 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 gbeauche 1.12 case 0x805: *regp = mmusr; break;
887     case 0x806: *regp = urp; break;
888     case 0x807: *regp = srp; break;
889 cebix 1.1 default:
890     op_illg (0x4E7A);
891 gbeauche 1.9 return 0;
892     }
893 cebix 1.1 }
894 gbeauche 1.9 return 1;
895 cebix 1.1 }
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 gbeauche 1.13 // 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 cebix 1.1 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 gbeauche 1.13 SPCFLAGS_INIT( 0 );
1173 cebix 1.1 regs.intmask = 7;
1174     regs.vbr = regs.sfc = regs.dfc = 0;
1175 gbeauche 1.6 fpu_reset();
1176 gbeauche 1.10
1177     #if FLIGHT_RECORDER
1178 gbeauche 1.20 log_ptr = 0;
1179     memset(log, 0, sizeof(log));
1180     #endif
1181    
1182 gbeauche 1.10 #if ENABLE_MON
1183 gbeauche 1.20 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 gbeauche 1.10 // Install "log" command in mon
1189     mon_add_command("log", dump_log, "log Dump m68k emulation log\n");
1190 gbeauche 1.20 #endif
1191 gbeauche 1.10 }
1192     #endif
1193 cebix 1.1 }
1194    
1195 gbeauche 1.13 void m68k_emulop_return(void)
1196 cebix 1.1 {
1197 gbeauche 1.13 SPCFLAGS_SET( SPCFLAG_BRK );
1198 gbeauche 1.17 quit_program = true;
1199 gbeauche 1.13 }
1200 cebix 1.1
1201 gbeauche 1.13 void m68k_emulop(uae_u32 opcode)
1202     {
1203 cebix 1.1 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 gbeauche 1.13 }
1220    
1221 gbeauche 1.18 void REGPARAM2 op_illg (uae_u32 opcode)
1222 gbeauche 1.13 {
1223     uaecptr pc = m68k_getpc ();
1224 cebix 1.1
1225     if ((opcode & 0xF000) == 0xA000) {
1226     Exception(0xA,0);
1227 gbeauche 1.18 return;
1228 cebix 1.1 }
1229    
1230     if ((opcode & 0xF000) == 0xF000) {
1231     Exception(0xB,0);
1232 gbeauche 1.18 return;
1233 cebix 1.1 }
1234    
1235 cebix 1.4 write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc);
1236 gbeauche 1.16 #if USE_JIT && JIT_DEBUG
1237     compiler_dumpstate();
1238     #endif
1239 cebix 1.4
1240 cebix 1.1 Exception (4,0);
1241 gbeauche 1.18 return;
1242 cebix 1.1 }
1243    
1244     void mmu_op(uae_u32 opcode, uae_u16 extra)
1245     {
1246 gbeauche 1.12 if ((opcode & 0xFE0) == 0x0500) {
1247     /* PFLUSH */
1248     mmusr = 0;
1249     } else if ((opcode & 0x0FD8) == 0x548) {
1250     /* PTEST */
1251 cebix 1.1 } else
1252 gbeauche 1.12 op_illg (opcode);
1253 cebix 1.1 }
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 gbeauche 1.9 if (regs.t0 && CPUType >= 2) {
1262 cebix 1.1 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 gbeauche 1.13 opcode = get_word(m68k_getpc());
1269 cebix 1.1 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 gbeauche 1.13 SPCFLAGS_CLEAR( SPCFLAG_TRACE );
1285     SPCFLAGS_SET( SPCFLAG_DOTRACE );
1286 cebix 1.1 }
1287     } else if (regs.t1) {
1288     last_trace_ad = m68k_getpc ();
1289 gbeauche 1.13 SPCFLAGS_CLEAR( SPCFLAG_TRACE );
1290     SPCFLAGS_SET( SPCFLAG_DOTRACE );
1291 cebix 1.1 }
1292     }
1293    
1294 gbeauche 1.13 int m68k_do_specialties (void)
1295 cebix 1.1 {
1296 gbeauche 1.16 #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 gbeauche 1.13 if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) {
1309 cebix 1.1 Exception (9,last_trace_ad);
1310     }
1311 gbeauche 1.13 while (SPCFLAGS_TEST( SPCFLAG_STOP )) {
1312     if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){
1313     SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT );
1314 cebix 1.1 int intr = intlev ();
1315     if (intr != -1 && intr > regs.intmask) {
1316     Interrupt (intr);
1317     regs.stopped = 0;
1318 gbeauche 1.13 SPCFLAGS_CLEAR( SPCFLAG_STOP );
1319 cebix 1.1 }
1320     }
1321     }
1322 gbeauche 1.13 if (SPCFLAGS_TEST( SPCFLAG_TRACE ))
1323 cebix 1.1 do_trace ();
1324    
1325 gbeauche 1.13 if (SPCFLAGS_TEST( SPCFLAG_DOINT )) {
1326     SPCFLAGS_CLEAR( SPCFLAG_DOINT );
1327 cebix 1.1 int intr = intlev ();
1328     if (intr != -1 && intr > regs.intmask) {
1329     Interrupt (intr);
1330     regs.stopped = 0;
1331     }
1332     }
1333 gbeauche 1.13 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 gbeauche 1.18 return 1;
1340 cebix 1.1 }
1341     return 0;
1342     }
1343    
1344 gbeauche 1.13 void m68k_do_execute (void)
1345 cebix 1.1 {
1346 cebix 1.4 for (;;) {
1347     uae_u32 opcode = GET_OPCODE;
1348 gbeauche 1.10 #if FLIGHT_RECORDER
1349 gbeauche 1.16 m68k_record_step(m68k_getpc());
1350 gbeauche 1.10 #endif
1351 cebix 1.4 (*cpufunctbl[opcode])(opcode);
1352 gbeauche 1.21 cpu_check_ticks();
1353 gbeauche 1.17 if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
1354     if (m68k_do_specialties())
1355 cebix 1.4 return;
1356     }
1357 cebix 1.1 }
1358     }
1359    
1360 gbeauche 1.19 #if USE_JIT && !(defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY))
1361 gbeauche 1.16 void m68k_compile_execute (void)
1362     {
1363     for (;;) {
1364 gbeauche 1.17 if (quit_program)
1365 gbeauche 1.16 break;
1366 gbeauche 1.17 m68k_do_compile_execute();
1367 gbeauche 1.16 }
1368     }
1369     #endif
1370    
1371 gbeauche 1.13 void m68k_execute (void)
1372 cebix 1.1 {
1373 gbeauche 1.16 #if USE_JIT
1374     ++m68k_execute_depth;
1375     #endif
1376 cebix 1.1 for (;;) {
1377 gbeauche 1.17 if (quit_program)
1378 cebix 1.1 break;
1379 gbeauche 1.17 m68k_do_execute();
1380 cebix 1.1 }
1381 gbeauche 1.16 #if USE_JIT
1382     --m68k_execute_depth;
1383     #endif
1384 cebix 1.1 }
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 gbeauche 1.15
1493     fpu_dump_registers();
1494     fpu_dump_flags();
1495    
1496 cebix 1.1 m68k_disasm(m68k_getpc (), nextpc, 1);
1497     if (nextpc)
1498     printf ("next PC: %08lx\n", *nextpc);
1499     }