2
* UAE - The Un*x Amiga Emulator
6
* (c) 1995 Bernd Schmidt
18
#include "cpu_prefetch.h"
24
#include "savestate.h"
30
extern uae_u8* compiled_code;
35
#define console_out printf
37
/* Opcode of faulting instruction */
38
static uae_u16 last_op_for_exception_3;
39
/* PC at fault time */
40
static uaecptr last_addr_for_exception_3;
41
/* Address that generated the exception */
42
static uaecptr last_fault_for_exception_3;
43
/* read (0) or write (1) access */
44
static int last_writeaccess_for_exception_3;
45
/* instruction (1) or data (0) access */
46
static int last_instructionaccess_for_exception_3;
48
const int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
49
const int imm8_table[] = { 8,1,2,3,4,5,6,7 };
51
int movem_index1[256];
52
int movem_index2[256];
56
int fpp_movem_index1[256];
57
int fpp_movem_index2[256];
58
int fpp_movem_next[256];
61
cpuop_func *cpufunctbl[65536];
63
static int warned_cpu68020;
66
#define COUNT_INSTRS 0
69
static unsigned long int instrcount[65536];
70
static uae_u16 opcodenums[65536];
72
static int compfn (const void *el1, const void *el2)
74
return instrcount[*(const uae_u16 *)el1] < instrcount[*(const uae_u16 *)el2];
77
static char *icountfilename (void)
79
char *name = getenv ("INSNCOUNT");
82
return COUNT_INSTRS == 2 ? "frequent.68k" : "insncount";
85
void dump_counts (void)
87
FILE *f = fopen (icountfilename (), "w");
88
unsigned long int total;
91
write_log ("Writing instruction count file...\n");
92
for (i = 0; i < 65536; i++) {
94
total += instrcount[i];
96
qsort (opcodenums, 65536, sizeof(uae_u16), compfn);
98
fprintf (f, "Total: %lu\n", total);
99
for (i=0; i < 65536; i++) {
100
unsigned long int cnt = instrcount[opcodenums[i]];
102
struct mnemolookup *lookup;
105
dp = table68k + opcodenums[i];
106
for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
108
fprintf (f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
113
void dump_counts (void)
118
STATIC_INLINE void count_instr (unsigned int opcode)
120
#if COUNT_INSTRS == 2
121
if (table68k[opcode].handler != -1)
122
instrcount[table68k[opcode].handler]++;
123
#elif COUNT_INSTRS == 1
124
instrcount[opcode]++;
128
static unsigned long op_illg_1 (uae_u32 opcode, struct regstruct *regs) REGPARAM;
130
static unsigned long REGPARAM2 op_illg_1 (uae_u32 opcode, struct regstruct *regs)
132
op_illg (opcode, regs);
136
static void build_cpufunctbl (void)
139
unsigned long opcode;
140
const struct cputbl *tbl = 0;
142
switch (currprefs.cpu_level) {
144
#ifndef CPUEMU_68000_ONLY
147
tbl = op_smalltbl_0_ff;
150
tbl = op_smalltbl_1_ff;
153
tbl = op_smalltbl_2_ff;
156
tbl = op_smalltbl_3_ff;
161
tbl = op_smalltbl_4_ff;
163
if (currprefs.cpu_compatible)
164
tbl = op_smalltbl_5_ff; /* prefetch */
167
if (currprefs.cpu_cycle_exact)
168
tbl = op_smalltbl_6_ff; /* prefetch and cycle-exact */
174
write_log ("no CPU emulation cores available!");
178
for (opcode = 0; opcode < 65536; opcode++)
179
cpufunctbl[opcode] = op_illg_1;
180
for (i = 0; tbl[i].handler != NULL; i++)
181
cpufunctbl[tbl[i].opcode] = tbl[i].handler;
184
for (opcode = 0; opcode < 65536; opcode++) {
187
if (table68k[opcode].mnemo == i_ILLG || table68k[opcode].clev > currprefs.cpu_level)
190
if (table68k[opcode].handler != -1) {
191
f = cpufunctbl[table68k[opcode].handler];
194
cpufunctbl[opcode] = f;
198
write_log ("Building CPU function table, %d opcodes (%d %d %d).\n",
199
opcnt, currprefs.cpu_level,
200
currprefs.cpu_cycle_exact ? -1 : currprefs.cpu_compatible ? 1 : 0,
201
currprefs.address_space_24);
207
void fill_prefetch_slow (struct regstruct *regs)
210
if (currprefs.cpu_cycle_exact) {
211
regs->ir = get_word_ce (m68k_getpc (regs));
212
regs->irc = get_word_ce (m68k_getpc (regs) + 2);
215
regs->ir = get_word (m68k_getpc (regs));
216
regs->irc = get_word (m68k_getpc (regs) + 2);
222
unsigned long cycles_mask, cycles_val;
224
static void update_68k_cycles (void)
227
cycles_val = currprefs.m68k_speed;
228
if (currprefs.m68k_speed < 1) {
229
cycles_mask = 0xFFFFFFFF;
234
void check_prefs_changed_cpu (void)
236
if (currprefs.cpu_level != changed_prefs.cpu_level
237
|| currprefs.cpu_compatible != changed_prefs.cpu_compatible
238
|| currprefs.cpu_cycle_exact != changed_prefs.cpu_cycle_exact) {
240
if (!currprefs.cpu_compatible && changed_prefs.cpu_compatible)
241
fill_prefetch_slow (®s);
243
currprefs.cpu_level = changed_prefs.cpu_level;
244
currprefs.cpu_compatible = changed_prefs.cpu_compatible;
245
currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
246
currprefs.blitter_cycle_exact = changed_prefs.cpu_cycle_exact;
249
/* Force opcode handler loop to exit. We don't want it to
250
* carry on running with the old opcode handler table. */
251
set_special (®s, SPCFLAG_MODE_CHANGE);
253
if (currprefs.m68k_speed != changed_prefs.m68k_speed) {
254
currprefs.m68k_speed = changed_prefs.m68k_speed;
255
reset_frame_rate_hack ();
256
update_68k_cycles ();
257
/* Force opcode handler loop to exit. We don't want it to
258
* carry on running with cached values of cycles_mask and
261
set_special (®s, SPCFLAG_MODE_CHANGE);
263
if (currprefs.cpu_idle != changed_prefs.cpu_idle) {
264
currprefs.cpu_idle = changed_prefs.cpu_idle;
268
void init_m68k (void)
272
update_68k_cycles ();
274
for (i = 0 ; i < 256 ; i++) {
276
for (j = 0 ; j < 8 ; j++) {
277
if (i & (1 << j)) break;
280
movem_index2[i] = 7-j;
281
movem_next[i] = i & (~(1 << j));
284
for (i = 0 ; i < 256 ; i++) {
286
for (j = 7 ; j >= 0 ; j--) {
287
if (i & (1 << j)) break;
289
fpp_movem_index1[i] = 7-j;
290
fpp_movem_index2[i] = j;
291
fpp_movem_next[i] = i & (~(1 << j));
296
FILE *f = fopen (icountfilename (), "r");
297
memset (instrcount, 0, sizeof instrcount);
299
uae_u32 opcode, count, total;
301
write_log ("Reading instruction count file...\n");
302
fscanf (f, "Total: %lu\n", &total);
303
while (fscanf (f, "%lx: %lu %s\n", &opcode, &count, name) == 3) {
304
instrcount[opcode] = count;
310
write_log ("Building CPU table for configuration: 68");
311
regs.address_space_mask = 0xffffffff;
312
if (currprefs.cpu_compatible > 0) {
313
if (currprefs.address_space_24 && currprefs.cpu_level > 3)
314
currprefs.address_space_24 = 0;
315
if (currprefs.address_space_24 && currprefs.cpu_level > 1)
318
switch (currprefs.cpu_level) {
326
write_log ("020/881");
329
/* Who is going to miss the MMU anyway...? :-) */
333
/* Who is going to miss the MMU anyway...? :-) */
340
if (currprefs.cpu_cycle_exact) {
341
if (currprefs.cpu_level == 0)
342
write_log (" prefetch and cycle-exact");
344
write_log (" ~cycle-exact");
345
} else if (currprefs.cpu_compatible)
346
write_log (" prefetch");
347
if (currprefs.address_space_24) {
348
regs.address_space_mask = 0x00ffffff;
349
write_log (" 24-bit addressing");
356
write_log ("%d CPU functions\n", nr_cpuop_funcs);
361
/* We need to check whether NATMEM settings have changed
362
* before starting the CPU */
363
check_prefs_changed_comp ();
366
reset_frame_rate_hack ();
367
update_68k_cycles ();
370
struct regstruct regs;
371
static uae_s32 m68kpc_offset;
373
#define get_ibyte_1(regs, o) get_byte((regs)->pc + ((regs)->pc_p - (regs)->pc_oldp) + (o) + 1)
374
#define get_iword_1(regs, o) get_word((regs)->pc + ((regs)->pc_p - (regs)->pc_oldp) + (o))
375
#define get_ilong_1(regs, o) get_long((regs)->pc + ((regs)->pc_p - (regs)->pc_oldp) + (o))
377
static uae_s32 ShowEA (void *f, uae_u16 opcode, int reg, amodes mode, wordsizes size, char *buf, uae_u32 *eaddr, int safemode)
390
sprintf (buffer, "D%d", reg);
393
sprintf (buffer, "A%d", reg);
396
sprintf (buffer, "(A%d)", reg);
397
addr = regs.regs[reg + 8];
400
sprintf (buffer, "(A%d)+", reg);
401
addr = regs.regs[reg + 8];
404
sprintf (buffer, "-(A%d)", reg);
405
addr = regs.regs[reg + 8];
410
disp16 = get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2;
412
sprintf (offtxt, "-$%04x", -disp16);
414
sprintf (offtxt, "$%04x", disp16);
415
addr = m68k_areg (®s,reg) + disp16;
416
sprintf (buffer, "(A%d,%s) == $%08x", reg, offtxt, (unsigned long)addr);
420
dp = get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2;
422
r = (dp & 0x7000) >> 12;
423
dispreg = dp & 0x8000 ? m68k_areg (®s,r) : m68k_dreg (®s,r);
424
if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
425
dispreg <<= (dp >> 9) & 3;
428
uae_s32 outer = 0, disp = 0;
429
uae_s32 base = m68k_areg (®s,reg);
431
sprintf (name, "A%d, ", reg);
432
if (dp & 0x80) { base = 0; name[0] = 0; }
433
if (dp & 0x40) dispreg = 0;
434
if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2; }
435
if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (®s, m68kpc_offset); m68kpc_offset += 4; }
438
if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2; }
439
if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (®s, m68kpc_offset); m68kpc_offset += 4; }
441
if (!(dp & 4)) base += dispreg;
442
if ((dp & 3) && !safemode) base = get_long (base);
443
if (dp & 4) base += dispreg;
446
sprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08x", name,
447
dp & 0x8000 ? 'A' : 'D', r, dp & 0x800 ? 'L' : 'W',
448
1 << ((dp >> 9) & 3),
451
addr = m68k_areg (®s,reg) + (uae_s32)((uae_s8)disp8) + dispreg;
452
sprintf (buffer, "(A%d, %c%d.%c*%d, $%02x) == $%08x", reg,
453
dp & 0x8000 ? 'A' : 'D', r, dp & 0x800 ? 'L' : 'W',
454
1 << ((dp >> 9) & 3), disp8, addr);
458
addr = m68k_getpc (®s) + m68kpc_offset;
459
disp16 = get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2;
460
addr += (uae_s16)disp16;
461
sprintf (buffer, "(PC,$%04x) == $%08x", disp16 & 0xffff, addr);
464
addr = m68k_getpc (®s) + m68kpc_offset;
465
dp = get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2;
467
r = (dp & 0x7000) >> 12;
468
dispreg = dp & 0x8000 ? m68k_areg (®s,r) : m68k_dreg (®s,r);
469
if (!(dp & 0x800)) dispreg = (uae_s32)(uae_s16)(dispreg);
470
dispreg <<= (dp >> 9) & 3;
473
uae_s32 outer = 0,disp = 0;
476
sprintf (name, "PC, ");
477
if (dp & 0x80) { base = 0; name[0] = 0; }
478
if (dp & 0x40) dispreg = 0;
479
if ((dp & 0x30) == 0x20) { disp = (uae_s32)(uae_s16)get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2; }
480
if ((dp & 0x30) == 0x30) { disp = get_ilong_1 (®s, m68kpc_offset); m68kpc_offset += 4; }
483
if ((dp & 0x3) == 0x2) { outer = (uae_s32)(uae_s16)get_iword_1 (®s, m68kpc_offset); m68kpc_offset += 2; }
484
if ((dp & 0x3) == 0x3) { outer = get_ilong_1 (®s, m68kpc_offset); m68kpc_offset += 4; }
486
if (!(dp & 4)) base += dispreg;
487
if ((dp & 3) && !safemode) base = get_long (base);
488
if (dp & 4) base += dispreg;
491
sprintf (buffer, "(%s%c%d.%c*%d+%d)+%d == $%08x", name,
492
dp & 0x8000 ? 'A' : 'D', r, dp & 0x800 ? 'L' : 'W',
493
1 << ((dp >> 9) & 3),
496
addr += (uae_s32)((uae_s8)disp8) + dispreg;
497
sprintf (buffer, "(PC, %c%d.%c*%d, $%02x) == $%08x", dp & 0x8000 ? 'A' : 'D',
498
r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
503
addr = (uae_s32)(uae_s16)get_iword_1 (®s, m68kpc_offset);
504
sprintf (buffer,"$%08x", (unsigned long)addr);
508
addr = get_ilong_1 (®s, m68kpc_offset);
509
sprintf (buffer,"$%0lx", (unsigned long)addr);
515
sprintf (buffer, "#$%02x", (unsigned int)(get_iword_1 (®s, m68kpc_offset) & 0xff));
519
sprintf (buffer, "#$%04x", (unsigned int)(get_iword_1 (®s, m68kpc_offset) & 0xffff));
523
sprintf (buffer, "#$%08x", (unsigned int)(get_ilong_1 (®s, m68kpc_offset) & 0xffffffff));
531
offset = (uae_s32)(uae_s8)get_iword_1 (®s, m68kpc_offset);
533
sprintf (buffer, "#$%02x", (unsigned int)(offset & 0xff));
536
offset = (uae_s32)(uae_s16)get_iword_1 (®s, m68kpc_offset);
539
sprintf (buffer,"#$%04x", (unsigned int)(offset & 0xffff));
542
offset = (uae_s32)get_ilong_1 (®s, m68kpc_offset);
544
sprintf (buffer, "#$%08x", (unsigned int)offset);
547
offset = (uae_s32)(uae_s8)(reg & 0xff);
548
sprintf (buffer, "#$%08x", (unsigned int)offset);
554
f_out (f, "%s", buffer);
556
strcat (buf, buffer);
563
uae_u32 REGPARAM2 get_disp_ea_020 (struct regstruct *regs, uae_u32 base, uae_u32 dp)
565
int reg = (dp >> 12) & 15;
566
uae_s32 regd = regs->regs[reg];
567
if ((dp & 0x800) == 0)
568
regd = (uae_s32)(uae_s16)regd;
569
regd <<= (dp >> 9) & 3;
572
if (dp & 0x80) base = 0;
573
if (dp & 0x40) regd = 0;
575
if ((dp & 0x30) == 0x20) base += (uae_s32)(uae_s16) next_iword (regs);
576
if ((dp & 0x30) == 0x30) base += next_ilong (regs);
578
if ((dp & 0x3) == 0x2) outer = (uae_s32)(uae_s16) next_iword (regs);
579
if ((dp & 0x3) == 0x3) outer = next_ilong (regs);
581
if ((dp & 0x4) == 0) base += regd;
582
if (dp & 0x3) base = get_long (base);
583
if (dp & 0x4) base += regd;
587
return base + (uae_s32)((uae_s8)dp) + regd;
591
uae_u32 REGPARAM2 get_disp_ea_000 (struct regstruct *regs, uae_u32 base, uae_u32 dp)
593
int reg = (dp >> 12) & 15;
594
uae_s32 regd = regs->regs[reg];
596
if ((dp & 0x800) == 0)
597
regd = (uae_s32)(uae_s16)regd;
598
return base + (uae_s8)dp + regd;
600
/* Branch-free code... benchmark this again now that
601
* things are no longer inline. */
604
mask = ((dp & 0x800) >> 11) - 1;
605
regd16 = (uae_s32)(uae_s16)regd;
615
void REGPARAM2 MakeSR (struct regstruct *regs)
618
assert((regs.t1 & 1) == regs->t1);
619
assert((regs.t0 & 1) == regs->t0);
620
assert((regs.s & 1) == regs->s);
621
assert((regs.m & 1) == regs->m);
622
assert((XFLG & 1) == XFLG);
623
assert((NFLG & 1) == NFLG);
624
assert((ZFLG & 1) == ZFLG);
625
assert((VFLG & 1) == VFLG);
626
assert((CFLG & 1) == CFLG);
628
regs->sr = ((regs->t1 << 15) | (regs->t0 << 14)
629
| (regs->s << 13) | (regs->m << 12) | (regs->intmask << 8)
630
| (GET_XFLG(®s->ccrflags) << 4) | (GET_NFLG(®s->ccrflags) << 3)
631
| (GET_ZFLG(®s->ccrflags) << 2) | (GET_VFLG(®s->ccrflags) << 1)
632
| GET_CFLG(®s->ccrflags));
635
void REGPARAM2 MakeFromSR (struct regstruct *regs)
640
SET_XFLG (®s->ccrflags, (regs->sr >> 4) & 1);
641
SET_NFLG (®s->ccrflags, (regs->sr >> 3) & 1);
642
SET_ZFLG (®s->ccrflags, (regs->sr >> 2) & 1);
643
SET_VFLG (®s->ccrflags, (regs->sr >> 1) & 1);
644
SET_CFLG (®s->ccrflags, regs->sr & 1);
645
if (regs->t1 == ((regs->sr >> 15) & 1) &&
646
regs->t0 == ((regs->sr >> 14) & 1) &&
647
regs->s == ((regs->sr >> 13) & 1) &&
648
regs->m == ((regs->sr >> 12) & 1) &&
649
regs->intmask == ((regs->sr >> 8) & 7))
651
regs->t1 = (regs->sr >> 15) & 1;
652
regs->t0 = (regs->sr >> 14) & 1;
653
regs->s = (regs->sr >> 13) & 1;
654
regs->m = (regs->sr >> 12) & 1;
655
regs->intmask = (regs->sr >> 8) & 7;
656
if (currprefs.cpu_level >= 2) {
657
if (olds != regs->s) {
660
regs->msp = m68k_areg (regs, 7);
662
regs->isp = m68k_areg (regs, 7);
663
m68k_areg (regs, 7) = regs->usp;
665
regs->usp = m68k_areg (regs, 7);
666
m68k_areg (regs, 7) = regs->m ? regs->msp : regs->isp;
668
} else if (olds && oldm != regs->m) {
670
regs->msp = m68k_areg (regs, 7);
671
m68k_areg (regs, 7) = regs->isp;
673
regs->isp = m68k_areg (regs, 7);
674
m68k_areg (regs, 7) = regs->msp;
678
regs->t0 = regs->m = 0;
679
if (olds != regs->s) {
681
regs->isp = m68k_areg (regs, 7);
682
m68k_areg (regs, 7) = regs->usp;
684
regs->usp = m68k_areg (regs, 7);
685
m68k_areg (regs, 7) = regs->isp;
690
set_special (regs, SPCFLAG_INT);
691
if (regs->t1 || regs->t0)
692
set_special (regs, SPCFLAG_TRACE);
694
/* Keep SPCFLAG_DOTRACE, we still want a trace exception for
695
SR-modifying instructions (including STOP). */
696
unset_special (regs, SPCFLAG_TRACE);
699
STATIC_INLINE void trace_exception (struct regstruct *regs, unsigned int nr)
701
unset_special (regs, SPCFLAG_TRACE | SPCFLAG_DOTRACE);
702
if (regs->t1 && !regs->t0) {
703
/* Trace stays pending if exception is div by zero, chk,
706
if (nr == 5 || nr == 6 || nr == 7 || (nr >= 32 && nr <= 47))
707
set_special (regs, SPCFLAG_DOTRACE);
709
regs->t1 = regs->t0 = regs->m = 0;
712
static void exception_debug (int nr)
715
if (!exception_debugging)
717
console_out ("Exception %d, PC=%08x\n", nr, m68k_getpc (®s));
723
/* cycle-exact exception handler, 68000 only */
725
STATIC_INLINE void Exception_ce (int nr, struct regstruct *regs, uaecptr oldpc)
727
uae_u32 currpc = m68k_getpc (regs), newpc;
731
exception_debug (nr);
738
case 3: /* address */
741
case 4: /* illegal instruction */
744
case 5: /* divide by zero */
753
case 8: /* privilege */
759
case 25: /* interrupts */
787
/* some delays are interleaved with stack pushes, not bothered yet..
790
do_cycles (c * CYCLE_UNIT / 2);
793
regs->usp = m68k_areg (regs, 7);
794
m68k_areg (regs, 7) = regs->isp;
797
if (nr == 2 || nr == 3) { /* 2=bus error,3=address error */
798
uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
799
mode |= last_writeaccess_for_exception_3 ? 0 : 16;
800
m68k_areg (regs, 7) -= 14;
801
/* fixme: bit3=I/N */
802
put_word_ce (m68k_areg (regs, 7) + 12, last_addr_for_exception_3);
803
put_word_ce (m68k_areg (regs, 7) + 8, regs->sr);
804
put_word_ce (m68k_areg (regs, 7) + 10, last_addr_for_exception_3 >> 16);
805
put_word_ce (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
806
put_word_ce (m68k_areg (regs, 7) + 4, last_fault_for_exception_3);
807
put_word_ce (m68k_areg (regs, 7) + 0, mode);
808
put_word_ce (m68k_areg (regs, 7) + 2, last_fault_for_exception_3 >> 16);
810
write_log ("Exception %d at %08x -> %08x!\n", nr, currpc, get_long (4 * nr));
814
m68k_areg (regs, 7) -= 6;
815
put_word_ce (m68k_areg (regs, 7) + 4, currpc);
816
put_word_ce (m68k_areg (regs, 7) + 0, regs->sr);
817
put_word_ce (m68k_areg (regs, 7) + 2, currpc >> 16);
819
newpc = get_word_ce (4 * nr) << 16;
820
newpc |= get_word_ce (4 * nr + 2);
822
if (nr == 2 || nr == 3)
823
uae_reset (1); /* there is nothing else we can do.. */
825
exception3 (regs->ir, m68k_getpc (regs), newpc);
828
m68k_setpc (regs, newpc);
829
fill_prefetch_slow (regs);
830
set_special (regs, SPCFLAG_END_COMPILE);
831
trace_exception (regs, nr);
835
STATIC_INLINE void Exception_normal (int nr, struct regstruct *regs, uaecptr oldpc)
837
uae_u32 currpc = m68k_getpc (regs), newpc;
840
exception_debug (nr);
844
regs->usp = m68k_areg (regs, 7);
845
if (currprefs.cpu_level >= 2)
846
m68k_areg (regs, 7) = regs->m ? regs->msp : regs->isp;
848
m68k_areg (regs, 7) = regs->isp;
851
if (currprefs.cpu_level > 0) {
852
if (nr == 2 || nr == 3) {
854
if (currprefs.cpu_level >= 4) { /* 68040 */
856
for (i = 0 ; i < 18 ; i++) {
857
m68k_areg (regs, 7) -= 2;
858
put_word (m68k_areg (regs, 7), 0);
860
m68k_areg (regs, 7) -= 4;
861
put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
862
m68k_areg (regs, 7) -= 2;
863
put_word (m68k_areg (regs, 7), 0);
864
m68k_areg (regs, 7) -= 2;
865
put_word (m68k_areg (regs, 7), 0);
866
m68k_areg (regs, 7) -= 2;
867
put_word (m68k_areg (regs, 7), 0);
868
m68k_areg (regs, 7) -= 2;
869
put_word (m68k_areg (regs, 7), 0x0140 | (sv ? 6 : 2)); /* SSW */
870
m68k_areg (regs, 7) -= 4;
871
put_long (m68k_areg (regs, 7), last_addr_for_exception_3);
872
m68k_areg (regs, 7) -= 2;
873
put_word (m68k_areg (regs, 7), 0x7000 + nr * 4);
875
m68k_areg (regs, 7) -= 4;
876
put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
877
m68k_areg (regs, 7) -= 2;
878
put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
881
uae_u16 ssw = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
882
ssw |= last_writeaccess_for_exception_3 ? 0 : 0x40;
884
for (i = 0 ; i < 36; i++) {
885
m68k_areg (regs, 7) -= 2;
886
put_word (m68k_areg (regs, 7), 0);
888
m68k_areg (regs, 7) -= 4;
889
put_long (m68k_areg (regs, 7), last_fault_for_exception_3);
890
m68k_areg (regs, 7) -= 2;
891
put_word (m68k_areg (regs, 7), 0);
892
m68k_areg (regs, 7) -= 2;
893
put_word (m68k_areg (regs, 7), 0);
894
m68k_areg (regs, 7) -= 2;
895
put_word (m68k_areg (regs, 7), 0);
896
m68k_areg (regs, 7) -= 2;
897
put_word (m68k_areg (regs, 7), ssw);
898
m68k_areg (regs, 7) -= 2;
899
put_word (m68k_areg (regs, 7), 0xb000 + nr * 4);
902
write_log ("Exception %d (%08x) at %08x -> %08x!\n", nr, oldpc, currpc, get_long (regs->vbr + 4*nr));
904
} else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
905
m68k_areg (regs, 7) -= 4;
906
put_long (m68k_areg (regs, 7), oldpc);
907
m68k_areg (regs, 7) -= 2;
908
put_word (m68k_areg (regs, 7), 0x2000 + nr * 4);
909
} else if (regs->m && nr >= 24 && nr < 32) { /* M + Interrupt */
910
m68k_areg (regs, 7) -= 2;
911
put_word (m68k_areg (regs, 7), nr * 4);
912
m68k_areg (regs, 7) -= 4;
913
put_long (m68k_areg (regs, 7), currpc);
914
m68k_areg (regs, 7) -= 2;
915
put_word (m68k_areg (regs, 7), regs->sr);
916
regs->sr |= (1 << 13);
917
regs->msp = m68k_areg (regs, 7);
918
m68k_areg (regs, 7) = regs->isp;
919
m68k_areg (regs, 7) -= 2;
920
put_word (m68k_areg (regs, 7), 0x1000 + nr * 4);
922
m68k_areg (regs, 7) -= 2;
923
put_word (m68k_areg (regs, 7), nr * 4);
925
} else if (nr == 2 || nr == 3) {
926
uae_u16 mode = (sv ? 4 : 0) | (last_instructionaccess_for_exception_3 ? 2 : 1);
927
mode |= last_writeaccess_for_exception_3 ? 0 : 16;
928
m68k_areg (regs, 7) -= 14;
929
/* fixme: bit3=I/N */
930
put_word (m68k_areg (regs, 7) + 0, mode);
931
put_long (m68k_areg (regs, 7) + 2, last_fault_for_exception_3);
932
put_word (m68k_areg (regs, 7) + 6, last_op_for_exception_3);
933
put_word (m68k_areg (regs, 7) + 8, regs->sr);
934
put_long (m68k_areg (regs, 7) + 10, last_addr_for_exception_3);
936
write_log ("Exception %d (%08x) at %08x -> %08x!\n", nr, oldpc, currpc, get_long (regs->vbr + 4*nr));
940
m68k_areg (regs, 7) -= 4;
941
put_long (m68k_areg (regs, 7), currpc);
942
m68k_areg (regs, 7) -= 2;
943
put_word (m68k_areg (regs, 7), regs->sr);
945
newpc = get_long (regs->vbr + 4 * nr);
947
if (nr == 2 || nr == 3)
948
uae_reset (1); /* there is nothing else we can do.. */
950
exception3 (regs->ir, m68k_getpc (regs), newpc);
953
m68k_setpc (regs, newpc);
954
set_special (regs, SPCFLAG_END_COMPILE);
955
fill_prefetch_slow (regs);
956
trace_exception (regs, nr);
959
void REGPARAM2 Exception (int nr, struct regstruct *regs, uaecptr oldpc)
963
write_log ("exception %2d %08x %08x (%04x %04x)\n",
964
nr, oldpc, m68k_getpc (regs), intena, intreq);
967
if (currprefs.cpu_cycle_exact && currprefs.cpu_level == 0)
968
Exception_ce (nr, regs, oldpc);
971
Exception_normal (nr, regs, oldpc);
974
STATIC_INLINE void service_interrupt (unsigned int level, struct regstruct *regs)
976
if (level > regs->intmask) {
979
unset_special (regs, SPCFLAG_STOP);
981
Exception (level + 24, regs, 0);
983
regs->intmask = level;
988
* Directly cause an interrupt to occur.
990
* This probably ain't a great idea, because this could allow an interrupt
991
* to be forced before an opcode is completed and the PC updated.
993
void Interrupt (unsigned int level)
996
service_interrupt (level, ®s);
999
static uae_u32 caar, cacr, itt0, itt1, dtt0, dtt1, tc, mmusr, urp, srp, buscr, pcr;
1001
#ifndef CPUEMU_68000_ONLY
1003
static int movec_illg (int regno)
1005
int regno2 = regno & 0x7ff;
1006
if (currprefs.cpu_level == 1) { /* 68010 */
1011
if (currprefs.cpu_level == 2 || currprefs.cpu_level == 3) { /* 68020 */
1012
if (regno == 3) return 1; /* 68040 only */
1013
/* 4 is >=68040, but 0x804 is in 68020 */
1014
if (regno2 < 4 || regno == 0x804)
1018
if (currprefs.cpu_level >= 4) { /* 68040 */
1019
if (regno == 0x802) return 1; /* 68020 only */
1020
if (regno2 < 8) return 0;
1021
if (currprefs.cpu_level == 6 && regno2 == 8) /* 68060 only */
1028
int m68k_move2c (int regno, uae_u32 *regp)
1030
// write_log ("move2c %04x <- %08x\n", regno, *regp);
1031
if (movec_illg (regno)) {
1032
op_illg (0x4E7B, ®s);
1036
case 0: regs.sfc = *regp & 7; break;
1037
case 1: regs.dfc = *regp & 7; break;
1039
cacr = *regp & (currprefs.cpu_level < 4 ? 0x3 : (currprefs.cpu_level == 4 ? 0x80008000 : 0xf8800e00));
1041
if (currprefs.cpu_level < 4) {
1042
set_cache_state (cacr & 1);
1047
set_cache_state ((cacr & 0x8000) || 0);
1048
if (*regp & 0x08) { /* Just to be on the safe side */
1054
case 3: tc = *regp & 0xc000; break;
1055
/* Mask out fields that should be zero. */
1056
case 4: itt0 = *regp & 0xffffe364; break;
1057
case 5: itt1 = *regp & 0xffffe364; break;
1058
case 6: dtt0 = *regp & 0xffffe364; break;
1059
case 7: dtt1 = *regp & 0xffffe364; break;
1060
case 8: buscr = *regp & 0xf0000000; break;
1062
case 0x800: regs.usp = *regp; break;
1063
case 0x801: regs.vbr = *regp; break;
1064
case 0x802: caar = *regp & 0xfc; break;
1065
case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg (®s, 7) = regs.msp; break;
1066
case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg (®s, 7) = regs.isp; break;
1067
case 0x805: mmusr = *regp; break;
1068
case 0x806: urp = *regp; break;
1069
case 0x807: srp = *regp; break;
1070
case 0x808: pcr = *regp & (0x40 | 2 | 1); break;
1072
op_illg (0x4E7B, ®s);
1079
int m68k_movec2 (int regno, uae_u32 *regp)
1081
// write_log ("movec2 %04x ", regno);
1082
if (movec_illg (regno)) {
1083
op_illg (0x4E7A, ®s);
1087
case 0: *regp = regs.sfc; break;
1088
case 1: *regp = regs.dfc; break;
1089
case 2: *regp = cacr; break;
1090
case 3: *regp = tc; break;
1091
case 4: *regp = itt0; break;
1092
case 5: *regp = itt1; break;
1093
case 6: *regp = dtt0; break;
1094
case 7: *regp = dtt1; break;
1095
case 8: *regp = buscr; break;
1097
case 0x800: *regp = regs.usp; break;
1098
case 0x801: *regp = regs.vbr; break;
1099
case 0x802: *regp = caar; break;
1100
case 0x803: *regp = regs.m == 1 ? m68k_areg (®s, 7) : regs.msp; break;
1101
case 0x804: *regp = regs.m == 0 ? m68k_areg (®s, 7) : regs.isp; break;
1102
case 0x805: *regp = mmusr; break;
1103
case 0x806: *regp = urp; break;
1104
case 0x807: *regp = srp; break;
1105
case 0x808: *regp = 0x04300100 | pcr; break;
1108
op_illg (0x4E7A, ®s);
1112
// write_log ("-> %08x\n", *regp);
1117
div_unsigned(uae_u32 src_hi, uae_u32 src_lo, uae_u32 div, uae_u32 *quot, uae_u32 *rem)
1119
uae_u32 q = 0, cbit = 0;
1122
if (div <= src_hi) {
1125
for (i = 0 ; i < 32 ; i++) {
1126
cbit = src_hi & 0x80000000ul;
1128
if (src_lo & 0x80000000ul) src_hi++;
1131
if (cbit || div <= src_hi) {
1141
void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
1143
#if defined(uae_s64)
1145
Exception (5, ®s, oldpc);
1148
if (extra & 0x800) {
1149
/* signed variant */
1150
uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (®s, (extra >> 12) & 7);
1153
if (extra & 0x400) {
1155
a |= (uae_s64)m68k_dreg (®s, extra & 7) << 32;
1157
rem = a % (uae_s64)(uae_s32)src;
1158
quot = a / (uae_s64)(uae_s32)src;
1159
if ((quot & UVAL64(0xffffffff80000000)) != 0
1160
&& (quot & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
1162
SET_VFLG (®s.ccrflags, 1);
1163
SET_NFLG (®s.ccrflags, 1);
1164
SET_CFLG (®s.ccrflags, 0);
1166
if (((uae_s32)rem < 0) != ((uae_s64)a < 0)) rem = -rem;
1167
SET_VFLG (®s.ccrflags, 0);
1168
SET_CFLG (®s.ccrflags, 0);
1169
SET_ZFLG (®s.ccrflags, ((uae_s32)quot) == 0);
1170
SET_NFLG (®s.ccrflags, ((uae_s32)quot) < 0);
1171
m68k_dreg (®s, extra & 7) = (uae_u32)rem;
1172
m68k_dreg (®s, (extra >> 12) & 7) = (uae_u32)quot;
1176
uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (®s, (extra >> 12) & 7);
1179
if (extra & 0x400) {
1181
a |= (uae_u64)m68k_dreg (®s, extra & 7) << 32;
1183
rem = a % (uae_u64)src;
1184
quot = a / (uae_u64)src;
1185
if (quot > 0xffffffffu) {
1186
SET_VFLG (®s.ccrflags, 1);
1187
SET_NFLG (®s.ccrflags, 1);
1188
SET_CFLG (®s.ccrflags, 0);
1190
SET_VFLG (®s.ccrflags, 0);
1191
SET_CFLG (®s.ccrflags, 0);
1192
SET_ZFLG (®s.ccrflags, ((uae_s32)quot) == 0);
1193
SET_NFLG (®s.ccrflags, ((uae_s32)quot) < 0);
1194
m68k_dreg (®s, extra & 7) = (uae_u32)rem;
1195
m68k_dreg (®s, (extra >> 12) & 7) = (uae_u32)quot;
1200
Exception (5, ®s, oldpc);
1203
if (extra & 0x800) {
1204
/* signed variant */
1205
uae_s32 lo = (uae_s32)m68k_dreg (®s, (extra >> 12) & 7);
1206
uae_s32 hi = lo < 0 ? -1 : 0;
1211
if (extra & 0x400) {
1212
hi = (uae_s32)m68k_dreg (®s, extra & 7);
1221
if ((uae_s32)src < 0) src = -src;
1222
if (div_unsigned(hi, lo, src, ", &rem) ||
1223
(sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
1224
SET_VFLG (®s.ccrflags, 1);
1225
SET_NFLG (®s.ccrflags, 1);
1226
SET_CFLG (®s.ccrflags, 0);
1228
if (sign & 0x80000000) quot = -quot;
1229
if (((uae_s32)rem < 0) != (save_high < 0)) rem = -rem;
1230
SET_VFLG (®s.ccrflags, 0);
1231
SET_CFLG (®s.ccrflags, 0);
1232
SET_ZFLG (®s.ccrflags, ((uae_s32)quot) == 0);
1233
SET_NFLG (®s.ccrflags, ((uae_s32)quot) < 0);
1234
m68k_dreg (®s, extra & 7) = rem;
1235
m68k_dreg (®s, (extra >> 12) & 7) = quot;
1239
uae_u32 lo = (uae_u32)m68k_dreg (®s, (extra >> 12) & 7);
1243
if (extra & 0x400) {
1244
hi = (uae_u32)m68k_dreg (®s, extra & 7);
1246
if (div_unsigned(hi, lo, src, ", &rem)) {
1247
SET_VFLG (®s.ccrflags, 1);
1248
SET_NFLG (®s.ccrflags, 1);
1249
SET_CFLG (®s.ccrflags, 0);
1251
SET_VFLG (®s.ccrflags, 0);
1252
SET_CFLG (®s.ccrflags, 0);
1253
SET_ZFLG (®s.ccrflags, ((uae_s32)quot) == 0);
1254
SET_NFLG (®s.ccrflags, ((uae_s32)quot) < 0);
1255
m68k_dreg (®s, extra & 7) = rem;
1256
m68k_dreg (®s, (extra >> 12) & 7) = quot;
1263
mul_unsigned (uae_u32 src1, uae_u32 src2, uae_u32 *dst_hi, uae_u32 *dst_lo)
1265
uae_u32 r0 = (src1 & 0xffff) * (src2 & 0xffff);
1266
uae_u32 r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
1267
uae_u32 r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
1268
uae_u32 r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
1271
lo = r0 + ((r1 << 16) & 0xffff0000ul);
1274
lo = r0 + ((r2 << 16) & 0xffff0000ul);
1276
r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
1281
void m68k_mull (uae_u32 opcode, uae_u32 src, uae_u16 extra)
1283
#if defined(uae_s64)
1284
if (extra & 0x800) {
1285
/* signed variant */
1286
uae_s64 a = (uae_s64)(uae_s32)m68k_dreg (®s, (extra >> 12) & 7);
1288
a *= (uae_s64)(uae_s32)src;
1289
SET_VFLG (®s.ccrflags, 0);
1290
SET_CFLG (®s.ccrflags, 0);
1291
SET_ZFLG (®s.ccrflags, a == 0);
1292
SET_NFLG (®s.ccrflags, a < 0);
1294
m68k_dreg (®s, extra & 7) = (uae_u32)(a >> 32);
1295
else if ((a & UVAL64(0xffffffff80000000)) != 0
1296
&& (a & UVAL64(0xffffffff80000000)) != UVAL64(0xffffffff80000000))
1298
SET_VFLG (®s.ccrflags, 1);
1300
m68k_dreg (®s, (extra >> 12) & 7) = (uae_u32)a;
1303
uae_u64 a = (uae_u64)(uae_u32)m68k_dreg (®s, (extra >> 12) & 7);
1306
SET_VFLG (®s.ccrflags, 0);
1307
SET_CFLG (®s.ccrflags, 0);
1308
SET_ZFLG (®s.ccrflags, a == 0);
1309
SET_NFLG (®s.ccrflags, ((uae_s64)a) < 0);
1311
m68k_dreg (®s, extra & 7) = (uae_u32)(a >> 32);
1312
else if ((a & UVAL64(0xffffffff00000000)) != 0) {
1313
SET_VFLG (®s.ccrflags, 1);
1315
m68k_dreg (®s, (extra >> 12) & 7) = (uae_u32)a;
1318
if (extra & 0x800) {
1319
/* signed variant */
1321
uae_u32 dst_lo,dst_hi;
1324
src1 = (uae_s32)src;
1325
src2 = (uae_s32)m68k_dreg (®s, (extra >> 12) & 7);
1326
sign = (src1 ^ src2);
1327
if (src1 < 0) src1 = -src1;
1328
if (src2 < 0) src2 = -src2;
1329
mul_unsigned((uae_u32)src1,(uae_u32)src2,&dst_hi,&dst_lo);
1330
if (sign & 0x80000000) {
1333
if (dst_lo == 0) dst_hi++;
1335
SET_VFLG (®s.ccrflags, 0);
1336
SET_CFLG (®s.ccrflags, 0);
1337
SET_ZFLG (®s.ccrflags, dst_hi == 0 && dst_lo == 0);
1338
SET_NFLG (®s.ccrflags, ((uae_s32)dst_hi) < 0);
1340
m68k_dreg (®s, extra & 7) = dst_hi;
1341
else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0)
1342
&& ((dst_hi & 0xffffffff) != 0xffffffff
1343
|| (dst_lo & 0x80000000) != 0x80000000))
1345
SET_VFLG (®s.ccrflags, 1);
1347
m68k_dreg (®s, (extra >> 12) & 7) = dst_lo;
1350
uae_u32 dst_lo,dst_hi;
1352
mul_unsigned(src,(uae_u32)m68k_dreg (®s, (extra >> 12) & 7),&dst_hi,&dst_lo);
1354
SET_VFLG (®s.ccrflags, 0);
1355
SET_CFLG (®s.ccrflags, 0);
1356
SET_ZFLG (®s.ccrflags, dst_hi == 0 && dst_lo == 0);
1357
SET_NFLG (®s.ccrflags, ((uae_s32)dst_hi) < 0);
1359
m68k_dreg (®s, extra & 7) = dst_hi;
1360
else if (dst_hi != 0) {
1361
SET_VFLG (®s.ccrflags, 1);
1363
m68k_dreg (®s, (extra >> 12) & 7) = dst_lo;
1371
void m68k_reset (void)
1373
regs.kick_mask = 0x00F80000;
1377
if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) {
1378
m68k_setpc (®s, regs.pc);
1379
/* MakeFromSR() must not swap stack pointer */
1380
regs.s = (regs.sr >> 13) & 1;
1382
/* set stack pointer */
1384
m68k_areg (®s, 7) = regs.isp;
1386
m68k_areg (®s, 7) = regs.usp;
1391
m68k_areg (®s, 7) = get_long (0x00f80000);
1392
m68k_setpc (®s, get_long (0x00f80004));
1398
SET_ZFLG (®s.ccrflags, 0);
1399
SET_XFLG (®s.ccrflags, 0);
1400
SET_CFLG (®s.ccrflags, 0);
1401
SET_VFLG (®s.ccrflags, 0);
1402
SET_NFLG (®s.ccrflags, 0);
1404
regs.vbr = regs.sfc = regs.dfc = 0;
1406
regs.fpcr = regs.fpsr = regs.fpiar = 0;
1410
fill_prefetch_slow (®s);
1412
warned_cpu68020 = 0;
1415
STATIC_INLINE int in_rom (uaecptr pc)
1417
return (munge24 (pc) & 0xFFF80000) == 0xF80000;
1420
STATIC_INLINE int in_rtarea (uaecptr pc)
1422
return (munge24 (pc) & 0xFFFF0000) == RTAREA_BASE;
1425
unsigned long REGPARAM2 op_illg (uae_u32 opcode, struct regstruct *regs)
1427
uaecptr pc = m68k_getpc (regs);
1429
int inrom = in_rom (pc);
1430
int inrt = in_rtarea (pc);
1432
if (cloanto_rom && (opcode & 0xF100) == 0x7100) {
1433
m68k_dreg (regs, (opcode >> 9) & 7) = (uae_s8)(opcode & 0xFF);
1434
m68k_incpc (regs, 2);
1435
fill_prefetch_slow (regs);
1439
if (opcode == 0x4E7B && get_long (0x10) == 0 && inrom && !warned_cpu68020) {
1440
gui_message ("Your Kickstart requires a 68020 CPU");
1441
warned_cpu68020 = 1;
1442
uae_restart (-1, NULL);
1446
if (opcode == 0xFF0D) {
1448
/* This is from the dummy Kickstart replacement */
1449
uae_u16 arg = get_iword (regs, 2);
1450
m68k_incpc (regs, 4);
1451
ersatz_perform (arg);
1452
fill_prefetch_slow (regs);
1455
/* User-mode STOP replacement */
1456
m68k_setstopped (regs, 1);
1461
if ((opcode & 0xF000) == 0xA000 && inrt) {
1463
m68k_incpc (regs, 2);
1464
m68k_handle_trap (opcode & 0xFFF, regs);
1465
fill_prefetch_slow (regs);
1470
if ((opcode & 0xF000) == 0xF000) {
1472
write_log ("B-Trap %04x at %08x (%p)\n", opcode, m68k_getpc (regs) + m68kpc_offset, regs->pc_p);
1475
Exception (0xB, regs, 0);
1478
if ((opcode & 0xF000) == 0xA000) {
1482
m68k_handle_trap (opcode & 0xFFF, regs);
1485
Exception (0xA, regs, 0);
1489
write_log ("Illegal instruction: %04x at %08x -> %08x\n", opcode, pc, get_long (regs->vbr + 0x10));
1493
Exception (4, regs, 0);
1499
void mmu_op(uae_u32 opcode, struct regstruct *regs, uae_u16 extra)
1501
if ((opcode & 0xFE0) == 0x0500) {
1504
write_log ("PFLUSH @ %08x\n", m68k_getpc (regs));
1505
} else if ((opcode & 0x0FD8) == 0x548) {
1507
write_log ("PTEST @ %08x\n", m68k_getpc (regs));
1509
op_illg (opcode, regs);
1514
static uaecptr last_trace_ad = 0;
1516
static NOINLINE void do_trace (struct regstruct *regs)
1518
if (regs->t0 && currprefs.cpu_level >= 2) {
1520
/* should also include TRAP, CHK, SR modification FPcc */
1521
/* probably never used so why bother */
1522
/* We can afford this to be inefficient... */
1523
m68k_setpc (regs, m68k_getpc (regs));
1524
fill_prefetch_slow (regs);
1525
opcode = get_word (regs->pc);
1526
if ( opcode == 0x4e72 /* RTE */
1527
|| opcode == 0x4e74 /* RTD */
1528
|| opcode == 0x4e75 /* RTS */
1529
|| opcode == 0x4e77 /* RTR */
1530
|| opcode == 0x4e76 /* TRAPV */
1531
|| (opcode & 0xffc0) == 0x4e80 /* JSR */
1532
|| (opcode & 0xffc0) == 0x4ec0 /* JMP */
1533
|| (opcode & 0xff00) == 0x6100 /* BSR */
1534
|| ((opcode & 0xf000) == 0x6000 /* Bcc */
1535
&& cctrue (®s->ccrflags, (opcode >> 8) & 0xf))
1536
|| ((opcode & 0xf0f0) == 0x5050 /* DBcc */
1537
&& !cctrue (®s->ccrflags, (opcode >> 8) & 0xf)
1538
&& (uae_s16) m68k_dreg (regs, opcode & 7) != 0))
1540
last_trace_ad = m68k_getpc (regs);
1541
unset_special (regs, SPCFLAG_TRACE);
1542
set_special (regs, SPCFLAG_DOTRACE);
1544
} else if (regs->t1) {
1545
last_trace_ad = m68k_getpc (regs);
1546
unset_special (regs, SPCFLAG_TRACE);
1547
set_special (regs, SPCFLAG_DOTRACE);
1552
* Handle the STOP opcode.
1554
* The 68k CPU stays in stopped state, essentially doing
1555
* nothing, until an IRQ arrives,
1557
static NOINLINE void do_stop (struct regstruct *regs)
1559
unsigned int stop_count = 0;
1562
/* An IRQ breaks the STOP state. */
1563
if (regs->spcflags & (SPCFLAG_INT | SPCFLAG_DOINT))
1566
/* E-UAE wants us to stop interpeting opcodes for some reason -
1567
* perhaps to handle changes in settings - and this will
1568
* implicitly break the STOP state.
1570
if ((regs->spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)))
1573
if (currprefs.cpu_idle && currprefs.m68k_speed != 0) {
1574
/* The CPU idle thang. We attempt to stop hogging the host
1575
* CPU when the emulated 68k ain't doing nothing.
1577
static int sleep_countdown;
1578
static unsigned int lvpos;
1580
/* Check that we are not passed the end a frame. If
1581
* we are passed, then no IRQs will occur to get us out
1582
* of the STOP state, so we don't want to sleep.
1584
* We could have used !is_lastline here, but the JIT mucks
1585
* around with that for its own evil purposes.
1587
if (lvpos != vpos) {
1590
stop_count++; /* Count of STOP cycles for this execution of STOP. */
1593
if (sleep_countdown < 0) {
1595
sleep_countdown = currprefs.cpu_idle;
1597
/* Avoid small numbers of STOP cycles. Arbitrary number here. */
1598
if (stop_count > 32) {
1600
frame_time_t curr_time = uae_gethrtime ();
1604
idletime += uae_gethrtime() - curr_time;
1610
do_cycles (4 * CYCLE_UNIT);
1612
if (regs->spcflags & SPCFLAG_COPPER)
1615
} while (regs->spcflags & SPCFLAG_STOP);
1619
STATIC_INLINE int do_specialties (int cycles, struct regstruct *regs)
1621
#ifdef ACTION_REPLAY
1622
#ifdef ACTION_REPLAY_HRTMON
1623
if ((regs->spcflags & SPCFLAG_ACTION_REPLAY) && hrtmon_flag != ACTION_REPLAY_INACTIVE) {
1624
int isinhrt = (m68k_getpc (regs) >= hrtmem_start && m68k_getpc (regs) < hrtmem_start + hrtmem_size);
1625
/* exit from HRTMon? */
1626
if(hrtmon_flag == ACTION_REPLAY_HIDE && !isinhrt) hrtmon_hide();
1627
/* HRTMon breakpoint? (not via IRQ7) */
1628
if(hrtmon_flag == ACTION_REPLAY_IDLE && isinhrt) hrtmon_breakenter();
1629
if(hrtmon_flag == ACTION_REPLAY_ACTIVE && isinhrt) hrtmon_flag = ACTION_REPLAY_HIDE;
1630
if(hrtmon_flag == ACTION_REPLAY_ACTIVATE) hrtmon_enter();
1631
if(!(regs->spcflags & ~SPCFLAG_ACTION_REPLAY)) return 0;
1634
if ((regs->spcflags & SPCFLAG_ACTION_REPLAY) && action_replay_flag != ACTION_REPLAY_INACTIVE )
1636
/*if(action_replay_flag == ACTION_REPLAY_ACTIVE && !is_ar_pc_in_rom())*/
1637
/* write_log ("PC:%p\n", m68k_getpc (regs));*/
1639
if(action_replay_flag == ACTION_REPLAY_ACTIVATE || action_replay_flag == ACTION_REPLAY_DORESET)
1640
action_replay_enter();
1641
if(action_replay_flag == ACTION_REPLAY_HIDE && !is_ar_pc_in_rom())
1643
action_replay_hide();
1644
unset_special (regs, SPCFLAG_ACTION_REPLAY);
1646
if (action_replay_flag == ACTION_REPLAY_WAIT_PC )
1648
/*write_log ("Waiting for PC: %p, current PC= %p\n", wait_for_pc, m68k_getpc (regs));*/
1649
if (m68k_getpc (regs) == wait_for_pc)
1651
action_replay_flag = ACTION_REPLAY_ACTIVATE; /* Activate after next instruction. */
1657
if (regs->spcflags & SPCFLAG_COPPER)
1662
unset_special (regs, SPCFLAG_END_COMPILE); /* has done its job */
1665
while ((regs->spcflags & SPCFLAG_BLTNASTY) && dmaen (DMA_BLITTER) && cycles > 0 && !currprefs.blitter_cycle_exact) {
1666
unsigned int c = blitnasty ();
1668
cycles -= c * CYCLE_UNIT * 2;
1669
if (cycles < CYCLE_UNIT)
1673
do_cycles (c * CYCLE_UNIT);
1674
if (regs->spcflags & SPCFLAG_COPPER)
1678
if (regs->spcflags & SPCFLAG_DOTRACE)
1679
Exception (9, regs, last_trace_ad);
1680
if (regs->spcflags & SPCFLAG_TRAP) {
1681
unset_special (regs, SPCFLAG_TRAP);
1682
Exception (3, regs, 0);
1685
if (regs->spcflags & SPCFLAG_STOP)
1688
if (regs->spcflags & SPCFLAG_TRACE)
1691
/* An interrupt request takes at least 2 cycles (maybe 4) to reach the CPU, and
1692
* there are programs that require this delay - which is not too surprising...
1694
* In non-cycle-exact mode we handle this by separating the interrupt request
1695
* pending (SPCFLAG_INT) and interrupt request arrived (SPCFLAG_DOINT) events.
1696
* This ensures that there's always a delay of one opcode (and so at least 2
1697
* machine cycles) between the interrupt controller requesting an interrupt
1698
* and us servicing it here.
1700
* In cycle-exact mode, there's just one event (SPCFLAG_INT) and the delay is
1701
* handled internally by the interrupt controller code in custom.c - intlev()
1704
if ((regs->spcflags & SPCFLAG_DOINT) ||
1705
(currprefs.cpu_cycle_exact && (regs->spcflags & SPCFLAG_INT))) {
1707
int intr = intlev ();
1709
unset_special (regs, SPCFLAG_DOINT);
1712
service_interrupt (intr, regs);
1715
if ((regs->spcflags & SPCFLAG_INT) && !currprefs.cpu_cycle_exact) {
1716
unset_special (regs, SPCFLAG_INT);
1717
set_special (regs, SPCFLAG_DOINT);
1720
if ((regs->spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) {
1721
unset_special (regs, SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
1730
static void m68k_run_1 (void)
1736
/* It's really sad to have two almost identical functions for this, but we
1737
do it all for performance... :(
1738
This version emulates 68000's prefetch "cache" */
1739
static void m68k_run_1 (void)
1741
struct regstruct *r = ®s;
1742
unsigned long cycles_mask_local = cycles_mask;
1743
unsigned long cycles_val_local = cycles_val;
1746
unsigned long cycles;
1747
uae_u32 opcode = r->ir;
1748
count_instr (opcode);
1750
cycles = (*cpufunctbl[opcode])(opcode, r);
1752
cycles &= cycles_mask_local;
1753
cycles |= cycles_val_local;
1756
if (do_specialties (cycles, r))
1762
#endif /* CPUEMU_5 */
1766
static void m68k_run_1_ce (void)
1772
/* cycle-exact m68k_run() */
1774
static void m68k_run_1_ce (void)
1776
struct regstruct *r = ®s;
1779
uae_u32 opcode = r->ir;
1781
(*cpufunctbl[opcode])(opcode, r);
1783
if (do_specialties (0, r))
1788
#endif /* CPUEMU_6 */
1790
#ifdef JIT /* Completely different run_2 replacement */
1792
void do_nothing(void)
1794
/* What did you expect this to do? */
1796
/* I bet you didn't expect *that* ;-) */
1799
void exec_nostats(void)
1801
struct regstruct *r = ®s;
1802
unsigned long cycles_mask_local = cycles_mask;
1803
unsigned long cycles_val_local = cycles_val;
1808
uae_u32 opcode = get_iword (r, 0);
1810
new_cycles = (*cpufunctbl[opcode])(opcode, r);
1812
new_cycles &= cycles_mask_local;
1813
new_cycles |= cycles_val_local;
1814
do_cycles (new_cycles);
1816
if (end_block(opcode) || r->spcflags)
1817
return; /* We will deal with the spcflags in the caller */
1821
static int triggered;
1823
void execute_normal(void)
1825
struct regstruct *r = ®s;
1826
unsigned long cycles_mask_local = cycles_mask;
1827
unsigned long cycles_val_local = cycles_val;
1829
cpu_history pc_hist[MAXRUN];
1833
if (check_for_cache_miss())
1838
start_pc_p = r->pc_oldp;
1842
/* Take note: This is the do-it-normal loop */
1843
uae_u32 opcode = get_iword (r, 0);
1845
special_mem = DISTRUST_CONSISTENT_MEM;
1846
pc_hist[blocklen].location = (uae_u16*)r->pc_p;
1848
new_cycles = (*cpufunctbl[opcode])(opcode, r);
1850
new_cycles &= cycles_mask_local;
1851
new_cycles |= cycles_val_local;
1852
do_cycles (new_cycles);
1853
total_cycles += new_cycles;
1854
pc_hist[blocklen].specmem = special_mem;
1856
if (end_block(opcode) || blocklen >= MAXRUN || r->spcflags) {
1857
compile_block(pc_hist,blocklen,total_cycles);
1858
return; /* We will deal with the spcflags in the caller */
1860
/* No need to check regs.spcflags, because if they were set,
1861
we'd have ended up inside that "if" */
1865
typedef void compiled_handler(void);
1867
static void m68k_run_2a (void)
1870
#if defined X86_ASSEMBLY
1871
__asm__ __volatile__(
1872
"\tpush %%ebp\n\tcall *%0\n\tpop %%ebp" /* FIXME */
1873
:: "m" (cache_tags[cacheline(regs.pc_p)].handler)
1874
: "%edx", "%ecx", "%eax",
1875
"%esi", "%ebx", "%edi", "%ebp", "memory", "cc");
1877
((compiled_handler*)(pushall_call_handler))();
1879
/* Whenever we return from that, we should check spcflags */
1880
if (regs.spcflags) {
1881
if (do_specialties (0, ®s)) {
1891
static void m68k_run_2 (void)
1895
static void m68k_run_2p (void)
1901
/* emulate simple prefetch */
1902
static void m68k_run_2p (void)
1904
uae_u32 prefetch, prefetch_pc;
1905
struct regstruct *r = ®s;
1906
unsigned long cycles_mask_local = cycles_mask;
1907
unsigned long cycles_val_local = cycles_val;
1909
prefetch_pc = m68k_getpc (r);
1910
prefetch = get_long (prefetch_pc);
1912
unsigned long cycles;
1914
uae_u32 pc = m68k_getpc (r);
1915
if (pc == prefetch_pc)
1916
opcode = prefetch >> 16;
1917
else if (pc == prefetch_pc + 2)
1918
opcode = prefetch & 0xffff;
1920
opcode = get_word (pc);
1922
count_instr (opcode);
1924
prefetch_pc = m68k_getpc (r) + 2;
1925
prefetch = get_long (prefetch_pc);
1926
cycles = (*cpufunctbl[opcode])(opcode, r);
1927
cycles &= cycles_mask_local;
1928
cycles |= cycles_val_local;
1931
if (do_specialties (cycles, r))
1937
/* Same thing, but don't use prefetch to get opcode. */
1938
static void m68k_run_2 (void)
1940
struct regstruct *r = ®s;
1941
unsigned long cycles_mask_local = cycles_mask;
1942
unsigned long cycles_val_local = cycles_val;
1945
unsigned long cycles;
1946
uae_u32 opcode = get_iword (r, 0);
1947
count_instr (opcode);
1949
cycles = (*cpufunctbl[opcode])(opcode, r);
1951
cycles &= cycles_mask_local;
1952
cycles |= cycles_val_local;
1955
if (do_specialties (cycles, r))
1961
#endif /* CPUEMU_0 */
1964
static void exception2_handle (uaecptr addr, uaecptr fault)
1966
last_addr_for_exception_3 = addr;
1967
last_fault_for_exception_3 = fault;
1968
last_writeaccess_for_exception_3 = 0;
1969
last_instructionaccess_for_exception_3 = 0;
1970
Exception (2, ®s, addr);
1973
void m68k_go (int may_quit)
1976
void (*run_func)(void);
1985
/* program jumped to non-existing memory and cpu was >= 68020 */
1986
get_real_address (regs.isp); /* stack in no one's land? -> reboot */
1990
exception2_handle (regs.panic_pc, regs.panic_addr);
1992
/* system is very badly confused */
1993
write_log ("double bus error or corrupted stack, forcing reboot..\n");
2000
run_func = (currprefs.cpu_level == 0 && currprefs.cpu_cycle_exact ? m68k_run_1_ce :
2001
currprefs.cpu_level == 0 && currprefs.cpu_compatible ? m68k_run_1 :
2002
currprefs.cpu_compatible ? m68k_run_2p :
2005
run_func = (currprefs.cpu_cycle_exact && currprefs.cpu_level == 0 ? m68k_run_1_ce :
2006
currprefs.cpu_compatible > 0 && currprefs.cpu_level == 0 ? m68k_run_1 :
2007
currprefs.cpu_level >= 2 && currprefs.cachesize ? m68k_run_2a :
2008
currprefs.cpu_compatible ? m68k_run_2p :
2013
if (uae_state_change_pending ())
2019
#if defined(DEBUGGER) || defined (ENFORCER)
2021
static const char * const ccnames[] =
2022
{ "T","F","HI","LS","CC","CS","NE","EQ",
2023
"VC","VS","PL","MI","GE","LT","GT","LE" };
2025
static void m68k_disasm_2 (void *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr, int safemode)
2028
m68kpc_offset = addr - m68k_getpc (®s);
2031
char instrname[100], *ccpt;
2034
struct mnemolookup *lookup;
2038
oldpc = m68kpc_offset;
2039
opcode = get_iword_1 (®s, m68kpc_offset);
2040
if (cpufunctbl[opcode] == op_illg_1) {
2043
dp = table68k + opcode;
2044
for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
2047
f_out (f, "%08x ", m68k_getpc (®s) + m68kpc_offset);
2050
strcpy (instrname, lookup->name);
2051
ccpt = strstr (instrname, "cc");
2053
strncpy (ccpt, ccnames[dp->cc], 2);
2056
case sz_byte: strcat (instrname, ".B "); break;
2057
case sz_word: strcat (instrname, ".W "); break;
2058
case sz_long: strcat (instrname, ".L "); break;
2059
default: strcat (instrname, " "); break;
2063
newpc = m68k_getpc (®s) + m68kpc_offset;
2064
newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, seaddr, safemode);
2066
if (dp->suse && dp->duse)
2067
strcat (instrname, ",");
2069
newpc = m68k_getpc (®s) + m68kpc_offset;
2070
newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, deaddr, safemode);
2073
for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++) {
2074
f_out (f, "%04x ", get_iword_1 (®s, oldpc + i * 2));
2078
f_out (f, instrname);
2083
if (cctrue (®s.ccrflags, dp->cc))
2084
f_out (f, " == %08x (TRUE)", newpc);
2086
f_out (f, " == %08x (FALSE)", newpc);
2087
} else if ((opcode & 0xff00) == 0x6100) { /* BSR */
2090
f_out (f, " == %08x", newpc);
2095
*nextpc = m68k_getpc (®s) + m68kpc_offset;
2098
void m68k_disasm_ea (void *f, uaecptr addr, uaecptr *nextpc, int cnt, uae_u32 *seaddr, uae_u32 *deaddr)
2100
m68k_disasm_2 (f, addr, nextpc, cnt, seaddr, deaddr, 1);
2102
void m68k_disasm (void *f, uaecptr addr, uaecptr *nextpc, int cnt)
2104
m68k_disasm_2 (f, addr, nextpc, cnt, NULL, NULL, 0);
2107
/*************************************************************
2108
Disasm the m68kcode at the given address into instrname
2110
*************************************************************/
2111
void sm68k_disasm (char *instrname, char *instrcode, uaecptr addr, uaecptr *nextpc)
2115
struct mnemolookup *lookup;
2121
m68kpc_offset = addr - m68k_getpc (®s);
2123
oldpc = m68kpc_offset;
2124
opcode = get_iword_1 (®s, m68kpc_offset);
2125
if (cpufunctbl[opcode] == op_illg_1) {
2128
dp = table68k + opcode;
2129
for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++);
2133
strcpy (instrname, lookup->name);
2134
ccpt = strstr (instrname, "cc");
2136
strncpy (ccpt, ccnames[dp->cc], 2);
2139
case sz_byte: strcat (instrname, ".B "); break;
2140
case sz_word: strcat (instrname, ".W "); break;
2141
case sz_long: strcat (instrname, ".L "); break;
2142
default: strcat (instrname, " "); break;
2146
newpc = m68k_getpc (®s) + m68kpc_offset;
2147
newpc += ShowEA (0, opcode, dp->sreg, dp->smode, dp->size, instrname, NULL, 0);
2149
if (dp->suse && dp->duse)
2150
strcat (instrname, ",");
2152
newpc = m68k_getpc (®s) + m68kpc_offset;
2153
newpc += ShowEA (0, opcode, dp->dreg, dp->dmode, dp->size, instrname, NULL, 0);
2159
for (i = 0; i < (m68kpc_offset - oldpc) / 2; i++)
2161
sprintf (instrcode, "%04x ", get_iword_1 (®s, oldpc + i * 2));
2162
instrcode += strlen(instrcode);
2167
*nextpc = m68k_getpc (®s) + m68kpc_offset;
2170
void m68k_dumpstate (void *f, uaecptr *nextpc)
2179
for (i = 0; i < 8; i++){
2180
f_out (f, "D%d: %08x ", i, m68k_dreg (®s, i));
2181
if ((i & 3) == 3) f_out (f, "\n");
2183
for (i = 0; i < 8; i++){
2184
f_out (f, "A%d: %08x ", i, m68k_areg (®s, i));
2185
if ((i & 3) == 3) f_out (f, "\n");
2187
if (regs.s == 0) regs.usp = m68k_areg (®s, 7);
2188
if (regs.s && regs.m) regs.msp = m68k_areg (®s, 7);
2189
if (regs.s && regs.m == 0) regs.isp = m68k_areg (®s, 7);
2190
f_out (f, "USP=%08x ISP=%08x MSP=%08x VBR=%08x\n",
2191
regs.usp,regs.isp,regs.msp,regs.vbr);
2192
f_out (f, "T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
2193
regs.t1, regs.t0, regs.s, regs.m,
2194
GET_XFLG(®s.ccrflags), GET_NFLG(®s.ccrflags),
2195
GET_ZFLG(®s.ccrflags), GET_VFLG(®s.ccrflags),
2196
GET_CFLG(®s.ccrflags), regs.intmask);
2198
if (currprefs.cpu_level >= 2) {
2200
for (i = 0; i < 8; i++){
2201
f_out (f, "FP%d: %g ", i, regs.fp[i]);
2202
if ((i & 3) == 3) f_out (f, "\n");
2204
fpsr = fpp_get_fpsr (®s);
2205
f_out (f, "N=%d Z=%d I=%d NAN=%d\n",
2206
(fpsr & 0x8000000) != 0,
2207
(fpsr & 0x4000000) != 0,
2208
(fpsr & 0x2000000) != 0,
2209
(fpsr & 0x1000000) != 0);
2212
if (currprefs.cpu_compatible) {
2214
struct mnemolookup *lookup1, *lookup2;
2215
dp = table68k + regs.irc;
2216
for (lookup1 = lookuptab; lookup1->mnemo != dp->mnemo; lookup1++);
2217
dp = table68k + regs.ir;
2218
for (lookup2 = lookuptab; lookup2->mnemo != dp->mnemo; lookup2++);
2219
f_out (f, "prefetch %04x (%s) %04x (%s)\n", regs.irc, lookup1->name, regs.ir, lookup2->name);
2222
m68k_disasm (f, m68k_getpc (®s), nextpc, 1);
2224
f_out (f, "next PC: %08x\n", *nextpc);
2229
void m68k_dumpstate (void *f, uaecptr *nextpc)
2238
/* CPU save/restore code */
2240
#define CPUTYPE_EC 1
2241
#define CPUMODE_HALT 1
2243
const uae_u8 *restore_cpu (const uae_u8 *src)
2245
unsigned int i, model, flags;
2248
model = restore_u32 ();
2251
changed_prefs.cpu_level = 0;
2254
changed_prefs.cpu_level = 1;
2257
changed_prefs.cpu_level = 2;
2260
changed_prefs.cpu_level = 4;
2263
changed_prefs.cpu_level = 6;
2266
write_log ("Unknown cpu type %d\n", model);
2270
flags = restore_u32 ();
2271
changed_prefs.address_space_24 = 0;
2272
if (flags & CPUTYPE_EC)
2273
changed_prefs.address_space_24 = 1;
2275
changed_prefs.cpu_compatible = 0;
2276
currprefs.cpu_level = changed_prefs.cpu_level;
2277
currprefs.address_space_24 = changed_prefs.address_space_24;
2278
currprefs.cpu_compatible = changed_prefs.cpu_compatible;
2279
currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact;
2280
currprefs.blitter_cycle_exact = changed_prefs.blitter_cycle_exact;
2281
for (i = 0; i < 15; i++)
2282
regs.regs[i] = restore_u32 ();
2283
regs.pc = restore_u32 ();
2284
regs.irc = restore_u16 ();
2285
regs.ir = restore_u16 ();
2286
regs.usp = restore_u32 ();
2287
regs.isp = restore_u32 ();
2288
regs.sr = restore_u16 ();
2290
if (l & CPUMODE_HALT) {
2292
set_special (®s, SPCFLAG_STOP);
2295
if (model >= 68010) {
2296
regs.dfc = restore_u32 ();
2297
regs.sfc = restore_u32 ();
2298
regs.vbr = restore_u32 ();
2300
if (model >= 68020) {
2301
caar = restore_u32 ();
2302
cacr = restore_u32 ();
2303
regs.msp = restore_u32 ();
2304
/* A500 speed in 68020 mode isn't too logical.. */
2305
if (changed_prefs.m68k_speed == 0)
2306
currprefs.m68k_speed = changed_prefs.m68k_speed = -1;
2308
write_log ("CPU %d%s%03d, PC=%08x\n",
2309
model / 1000, flags & 1 ? "EC" : "", model % 1000, regs.pc);
2314
void restore_cpu_finish (void)
2317
m68k_setpc (®s, regs.pc);
2320
static const int cpumodel[] = { 68000, 68010, 68020, 68020, 68040, 68060 };
2322
uae_u8 *save_cpu (uae_u32 *len, uae_u8 *dstptr)
2324
uae_u8 *dstbak, *dst;
2325
unsigned int model, i;
2328
dstbak = dst = dstptr;
2330
dstbak = dst = malloc(4+4+15*4+4+4+4+4+2+4+4+4+4+4+4+4);
2331
model = cpumodel[currprefs.cpu_level];
2332
save_u32 (model); /* MODEL */
2333
save_u32 (currprefs.address_space_24 ? 1 : 0); /* FLAGS */
2334
for (i = 0; i < 15; i++) save_u32 (regs.regs[i]); /* D0-D7 A0-A6 */
2335
save_u32 (m68k_getpc (®s)); /* PC */
2336
save_u16 (regs.irc); /* prefetch */
2337
save_u16 (regs.ir); /* instruction prefetch */
2339
save_u32 (!regs.s ? regs.regs[15] : regs.usp); /* USP */
2340
save_u32 (regs.s ? regs.regs[15] : regs.isp); /* ISP */
2341
save_u16 (regs.sr); /* SR/CCR */
2342
save_u32 (regs.stopped ? CPUMODE_HALT : 0); /* flags */
2343
if (model >= 68010) {
2344
save_u32 (regs.dfc); /* DFC */
2345
save_u32 (regs.sfc); /* SFC */
2346
save_u32 (regs.vbr); /* VBR */
2348
if (model >= 68020) {
2349
save_u32 (caar); /* CAAR */
2350
save_u32 (cacr); /* CACR */
2351
save_u32 (regs.msp); /* MSP */
2353
*len = dst - dstbak;
2357
#endif /* SAVESTATE */
2359
static void exception3f (uae_u32 opcode, uaecptr addr, uaecptr fault, int writeaccess, int instructionaccess)
2361
last_addr_for_exception_3 = addr;
2362
last_fault_for_exception_3 = fault;
2363
last_op_for_exception_3 = opcode;
2364
last_writeaccess_for_exception_3 = writeaccess;
2365
last_instructionaccess_for_exception_3 = instructionaccess;
2366
Exception (3, ®s, fault);
2369
void exception3 (uae_u32 opcode, uaecptr addr, uaecptr fault)
2371
exception3f (opcode, addr, fault, 0, 0);
2374
void exception3i (uae_u32 opcode, uaecptr addr, uaecptr fault)
2376
exception3f (opcode, addr, fault, 0, 1);
2379
void exception2 (uaecptr addr, uaecptr fault)
2381
write_log ("delayed exception2!\n");
2382
regs.panic_pc = m68k_getpc (®s);
2383
regs.panic_addr = addr;
2385
set_special (®s, SPCFLAG_BRK);
2386
m68k_setpc (®s, 0xf80000);
2388
set_special (®s, SPCFLAG_END_COMPILE);
2390
fill_prefetch_slow (®s);
2393
void cpureset (void)
2398
if (currprefs.cpu_level == 0 && (currprefs.cpu_compatible || currprefs.cpu_cycle_exact)) {
2402
ins = get_word (m68k_getpc (®s) + 2);
2403
if ((ins & ~7) == 0x4ed0) {
2405
uae_u32 addr = m68k_areg (regs, reg);
2406
write_log ("reset/jmp (ax) combination emulated\n");
2410
m68k_setpc (®s, addr);
2418
The routines below take dividend and divisor as parameters.
2419
They return 0 if division by zero, or exact number of cycles otherwise.
2421
The number of cycles returned assumes a register operand.
2422
Effective address time must be added if memory operand.
2424
For 68000 only (not 68010, 68012, 68020, etc).
2425
Probably valid for 68008 after adding the extra prefetch cycle.
2428
Best and worst cases are for register operand:
2429
(Note the difference with the documented range.)
2434
Overflow (always): 10 cycles.
2435
Worst case: 136 cycles.
2436
Best case: 76 cycles.
2441
Absolute overflow: 16-18 cycles.
2442
Signed overflow is not detected prematurely.
2444
Worst case: 156 cycles.
2445
Best case without signed overflow: 122 cycles.
2446
Best case with signed overflow: 120 cycles
2454
// Unsigned division
2457
STATIC_INLINE int getDivu68kCycles_2(uae_u32 dividend, uae_u16 divisor)
2467
if((dividend >> 16) >= divisor)
2468
return (mcycles = 5) * 2;
2471
hdivisor = divisor << 16;
2473
for( i = 0; i < 15; i++)
2480
// If carry from shift
2481
if((uae_s32)temp < 0)
2483
dividend -= hdivisor;
2488
if(dividend >= hdivisor)
2490
dividend -= hdivisor;
2497
int getDivu68kCycles(uae_u32 dividend, uae_u16 divisor)
2499
int v = getDivu68kCycles_2(dividend, divisor) - 4;
2500
// write_log ("U%d ", v);
2509
STATIC_INLINE int getDivs68kCycles_2(uae_s32 dividend, uae_s16 divisor)
2523
// Check for absolute overflow
2524
if(((uae_u32)abs(dividend) >> 16) >= (uae_u16)abs(divisor))
2526
return (mcycles + 2) * 2;
2529
// Absolute quotient
2530
aquot = (uae_u32) abs(dividend) / (uae_u16)abs(divisor);
2542
// Count 15 msbits in absolute of quotient
2544
for( i = 0; i < 15; i++)
2546
if((uae_s16)aquot >= 0)
2553
int getDivs68kCycles(uae_s32 dividend, uae_s16 divisor)
2555
int v = getDivs68kCycles_2(dividend, divisor) - 4;
2556
// write_log ("S%d ", v);