|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * MC68000 emulation
5: *
6: * (c) 1995 Bernd Schmidt
7: */
8:
9: #include "sysconfig.h"
10: #include "sysdeps.h"
11:
12: #include "config.h"
13: #include "options.h"
1.1.1.2 ! root 14: #include "machdep/m68k.h"
1.1 root 15: #include "events.h"
16: #include "gui.h"
17: #include "memory.h"
18: #include "custom.h"
1.1.1.2 ! root 19: #include "readcpu.h"
1.1 root 20: #include "newcpu.h"
21: #include "autoconf.h"
22: #include "ersatz.h"
23: #include "blitter.h"
24: #include "debug.h"
25: #include "compiler.h"
26:
27: int areg_byteinc[] = { 1,1,1,1,1,1,1,2 };
28: int imm8_table[] = { 8,1,2,3,4,5,6,7 };
29:
30: int movem_index1[256];
31: int movem_index2[256];
32: int movem_next[256];
33:
34: int fpp_movem_index1[256];
35: int fpp_movem_index2[256];
36: int fpp_movem_next[256];
37:
38: cpuop_func *cpufunctbl[65536];
1.1.1.2 ! root 39: #if USER_PROGRAMS_BEHAVE > 0
! 40: cpuop_func *cpufunctbl_behaved[65536];
1.1 root 41: #endif
42:
43: #define COUNT_INSTRS 0
44:
45: #if COUNT_INSTRS
46: static unsigned long int instrcount[65536];
47: static UWORD opcodenums[65536];
48:
49: static int compfn(const void *el1, const void *el2)
50: {
51: return instrcount[*(const UWORD *)el1] < instrcount[*(const UWORD *)el2];
52: }
53:
54: void dump_counts(void)
55: {
56: FILE *f = fopen(getenv("INSNCOUNT") ? getenv("INSNCOUNT") : "insncount", "w");
57: unsigned long int total = 0;
58: int i;
59:
60: for(i=0; i < 65536; i++) {
61: opcodenums[i] = i;
62: total += instrcount[i];
63: }
64: qsort(opcodenums, 65536, sizeof(UWORD), compfn);
65:
66: fprintf(f, "Total: %lu\n", total);
67: for(i=0; i < 65536; i++) {
68: unsigned long int cnt = instrcount[opcodenums[i]];
69: struct instr *dp;
70: struct mnemolookup *lookup;
71: if (!cnt)
72: break;
73: dp = table68k + opcodenums[i];
74: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++) ;
75: fprintf(f, "%04x: %lu %s\n", opcodenums[i], cnt, lookup->name);
76: }
77: fclose(f);
78: }
79: #else
80: void dump_counts(void)
81: {
82: }
83: #endif
84:
85: int broken_in;
86:
87: void init_m68k (void)
88: {
89: long int opcode;
90: int i,j;
91:
92: for (i = 0 ; i < 256 ; i++) {
93: for (j = 0 ; j < 8 ; j++) {
94: if (i & (1 << j)) break;
95: }
96: movem_index1[i] = j;
97: movem_index2[i] = 7-j;
98: movem_next[i] = i & (~(1 << j));
99: }
100: for (i = 0 ; i < 256 ; i++) {
101: for (j = 7 ; j >= 0 ; j--) {
102: if (i & (1 << j)) break;
103: }
104: fpp_movem_index1[i] = j;
105: fpp_movem_index2[i] = 7-j;
106: fpp_movem_next[i] = i & (~(1 << j));
107: }
108: #if COUNT_INSTRS
109: {
110: FILE *f = fopen("insncount", "r");
111: memset(instrcount, 0, sizeof instrcount);
112: if (f) {
113: ULONG opcode, count, total;
114: char name[20];
115: fscanf(f,"Total: %lu\n",&total);
116: while(fscanf(f,"%lx: %lu %s\n",&opcode,&count,name)==3) {
117: instrcount[opcode] = count;
118: }
119: fclose(f);
120: }
121: }
122: #endif
123: printf("Building CPU table...\n");
124: read_table68k ();
125: do_merges ();
126: for (opcode = 0; opcode < 65536; opcode++)
127: cpufunctbl[opcode] = op_illg;
1.1.1.2 ! root 128: for (i = 0; op_smalltbl[i].handler != NULL; i++) {
! 129: if (!op_smalltbl[i].specific)
! 130: cpufunctbl[op_smalltbl[i].opcode] = op_smalltbl[i].handler;
1.1 root 131: }
132: for (opcode = 0; opcode < 65536; opcode++) {
133: cpuop_func *f;
134:
135: if (table68k[opcode].mnemo == i_ILLG)
136: continue;
137:
138: if (table68k[opcode].handler != -1) {
139: f = cpufunctbl[table68k[opcode].handler];
140: if (f == op_illg)
141: abort();
142: cpufunctbl[opcode] = f;
143: }
144: }
1.1.1.2 ! root 145: for (i = 0; op_smalltbl[i].handler != NULL; i++) {
! 146: if (op_smalltbl[i].specific)
! 147: cpufunctbl[op_smalltbl[i].opcode] = op_smalltbl[i].handler;
! 148: }
! 149: #if USER_PROGRAMS_BEHAVE > 0
! 150: for (opcode = 0; opcode < 65536; opcode++)
! 151: cpufunctbl_behaved[opcode] = op_illg;
! 152:
! 153: for (i = 0; op_direct_smalltbl[i].handler != NULL; i++) {
! 154: if (!op_direct_smalltbl[i].specific)
! 155: cpufunctbl_behaved[op_direct_smalltbl[i].opcode] = op_direct_smalltbl[i].handler;
! 156: }
! 157: for (opcode = 0; opcode < 65536; opcode++) {
! 158: cpuop_func *f;
! 159:
! 160: if (table68k[opcode].mnemo == i_ILLG)
! 161: continue;
! 162:
! 163: if (table68k[opcode].handler != -1) {
! 164: f = cpufunctbl_behaved[table68k[opcode].handler];
! 165: if (f == op_illg)
! 166: abort();
! 167: cpufunctbl_behaved[opcode] = f;
! 168: }
! 169: }
! 170: for (i = 0; op_direct_smalltbl[i].handler != NULL; i++) {
! 171: if (op_direct_smalltbl[i].specific)
! 172: cpufunctbl_behaved[op_direct_smalltbl[i].opcode] = op_direct_smalltbl[i].handler;
1.1 root 173: }
1.1.1.2 ! root 174: #endif
1.1 root 175: }
176:
177: struct regstruct regs, lastint_regs;
178: static struct regstruct regs_backup[16];
179: static int backup_pointer = 0;
180: int lastint_no;
181:
1.1.1.2 ! root 182: LONG ShowEA(int reg, amodes mode, wordsizes size, char *buf)
1.1 root 183: {
184: UWORD dp;
185: BYTE disp8;
186: WORD disp16;
187: int r;
188: ULONG dispreg;
189: CPTR addr;
190: LONG offset = 0;
1.1.1.2 ! root 191: char buffer[80];
1.1 root 192:
193: switch(mode){
194: case Dreg:
1.1.1.2 ! root 195: sprintf(buffer,"D%d", reg);
1.1 root 196: break;
197: case Areg:
1.1.1.2 ! root 198: sprintf(buffer,"A%d", reg);
1.1 root 199: break;
200: case Aind:
1.1.1.2 ! root 201: sprintf(buffer,"(A%d)", reg);
1.1 root 202: break;
203: case Aipi:
1.1.1.2 ! root 204: sprintf(buffer,"(A%d)+", reg);
1.1 root 205: break;
206: case Apdi:
1.1.1.2 ! root 207: sprintf(buffer,"-(A%d)", reg);
1.1 root 208: break;
209: case Ad16:
210: disp16 = nextiword();
1.1.1.2 ! root 211: addr = m68k_areg(regs,reg) + (WORD)disp16;
! 212: sprintf(buffer,"(A%d,$%04x) == $%08lx", reg, disp16 & 0xffff,
1.1 root 213: (long unsigned int)addr);
214: break;
215: case Ad8r:
216: dp = nextiword();
217: disp8 = dp & 0xFF;
218: r = (dp & 0x7000) >> 12;
1.1.1.2 ! root 219: dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
1.1 root 220: if (!(dp & 0x800)) dispreg = (LONG)(WORD)(dispreg);
221: dispreg <<= (dp >> 9) & 3;
222:
223: if (dp & 0x100) {
224: LONG outer = 0, disp = 0;
1.1.1.2 ! root 225: LONG base = m68k_areg(regs,reg);
1.1 root 226: char name[10];
227: sprintf(name,"A%d, ",reg);
228: if (dp & 0x80) { base = 0; name[0] = 0; }
229: if (dp & 0x40) dispreg = 0;
230: if ((dp & 0x30) == 0x20) disp = (LONG)(WORD)nextiword();
231: if ((dp & 0x30) == 0x30) disp = nextilong();
232: base += disp;
233:
234: if ((dp & 0x3) == 0x2) outer = (LONG)(WORD)nextiword();
235: if ((dp & 0x3) == 0x3) outer = nextilong();
236:
237: if (!(dp & 4)) base += dispreg;
238: if (dp & 3) base = get_long (base);
239: if (dp & 4) base += dispreg;
240:
241: addr = base + outer;
1.1.1.2 ! root 242: sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
1.1 root 243: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
244: 1 << ((dp >> 9) & 3),
245: disp,outer,
246: (long unsigned int)addr);
247: }
248: else {
1.1.1.2 ! root 249: addr = m68k_areg(regs,reg) + (LONG)((BYTE)disp8) + dispreg;
! 250: sprintf(buffer,"(A%d, %c%d.%c*%d, $%02x) == $%08lx", reg,
1.1 root 251: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
252: 1 << ((dp >> 9) & 3), disp8,
253: (long unsigned int)addr);
254: }
255: break;
256: case PC16:
257: addr = m68k_getpc();
258: disp16 = nextiword();
259: addr += (WORD)disp16;
1.1.1.2 ! root 260: sprintf(buffer,"(PC,$%04x) == $%08lx", disp16 & 0xffff,(long unsigned int)addr);
1.1 root 261: break;
262: case PC8r:
263: addr = m68k_getpc();
264: dp = nextiword();
265: disp8 = dp & 0xFF;
266: r = (dp & 0x7000) >> 12;
1.1.1.2 ! root 267: dispreg = dp & 0x8000 ? m68k_areg(regs,r) : m68k_dreg(regs,r);
1.1 root 268: if (!(dp & 0x800)) dispreg = (LONG)(WORD)(dispreg);
269: dispreg <<= (dp >> 9) & 3;
270:
271: if (dp & 0x100) {
272: LONG outer = 0,disp = 0;
273: LONG base = addr;
274: char name[10];
275: sprintf(name,"PC, ");
276: if (dp & 0x80) { base = 0; name[0] = 0; }
277: if (dp & 0x80) base = 0;
278: if (dp & 0x40) dispreg = 0;
279: if ((dp & 0x30) == 0x20) disp = (LONG)(WORD)nextiword();
280: if ((dp & 0x30) == 0x30) disp = nextilong();
281: base += disp;
282:
283: if ((dp & 0x3) == 0x2) outer = (LONG)(WORD)nextiword();
284: if ((dp & 0x3) == 0x3) outer = nextilong();
285:
286: if (!(dp & 4)) base += dispreg;
287: if (dp & 3) base = get_long (base);
288: if (dp & 4) base += dispreg;
289:
290: addr = base + outer;
1.1.1.2 ! root 291: sprintf(buffer,"(%s%c%d.%c*%d+%ld)+%ld == $%08lx", name,
1.1 root 292: dp & 0x8000 ? 'A' : 'D', (int)r, dp & 0x800 ? 'L' : 'W',
293: 1 << ((dp >> 9) & 3),
294: disp,outer,
295: (long unsigned int)addr);
1.1.1.2 ! root 296: } else {
1.1 root 297: addr += (LONG)((BYTE)disp8) + dispreg;
1.1.1.2 ! root 298: sprintf(buffer,"(PC, %c%d.%c*%d, $%02x) == $%08lx", dp & 0x8000 ? 'A' : 'D',
1.1 root 299: (int)r, dp & 0x800 ? 'L' : 'W', 1 << ((dp >> 9) & 3),
300: disp8, (long unsigned int)addr);
301: }
302: break;
303: case absw:
1.1.1.2 ! root 304: sprintf(buffer,"$%08lx", (long unsigned int)(LONG)(WORD)nextiword());
1.1 root 305: break;
306: case absl:
1.1.1.2 ! root 307: sprintf(buffer,"$%08lx", (long unsigned int)nextilong());
1.1 root 308: break;
309: case imm:
310: switch(size){
311: case sz_byte:
1.1.1.2 ! root 312: sprintf(buffer,"#$%02x", (unsigned int)(nextiword() & 0xff)); break;
1.1 root 313: case sz_word:
1.1.1.2 ! root 314: sprintf(buffer,"#$%04x", (unsigned int)(nextiword() & 0xffff)); break;
1.1 root 315: case sz_long:
1.1.1.2 ! root 316: sprintf(buffer,"#$%08lx", (long unsigned int)(nextilong())); break;
1.1 root 317: default:
318: break;
319: }
320: break;
321: case imm0:
322: offset = (LONG)(BYTE)nextiword();
1.1.1.2 ! root 323: sprintf(buffer,"#$%02x", (unsigned int)(offset & 0xff));
1.1 root 324: break;
325: case imm1:
326: offset = (LONG)(WORD)nextiword();
1.1.1.2 ! root 327: sprintf(buffer,"#$%04x", (unsigned int)(offset & 0xffff));
1.1 root 328: break;
329: case imm2:
330: offset = (LONG)nextilong();
1.1.1.2 ! root 331: sprintf(buffer,"#$%08lx", (long unsigned int)offset);
1.1 root 332: break;
333: case immi:
334: offset = (LONG)(BYTE)(reg & 0xff);
1.1.1.2 ! root 335: sprintf(buffer,"#$%08lx", (long unsigned int)offset);
1.1 root 336: break;
337: default:
338: break;
339: }
1.1.1.2 ! root 340: if (buf == 0)
! 341: printf("%s", buffer);
! 342: else
! 343: strcat(buf, buffer);
! 344: return offset;
1.1 root 345: }
346:
347: void MakeSR(void)
348: {
349: #if 0
350: assert((regs.t1 & 1) == regs.t1);
351: assert((regs.t0 & 1) == regs.t0);
352: assert((regs.s & 1) == regs.s);
353: assert((regs.m & 1) == regs.m);
354: assert((XFLG & 1) == XFLG);
355: assert((NFLG & 1) == NFLG);
356: assert((ZFLG & 1) == ZFLG);
357: assert((VFLG & 1) == VFLG);
358: assert((CFLG & 1) == CFLG);
359: #endif
360: regs.sr = ((regs.t1 << 15) | (regs.t0 << 14)
361: | (regs.s << 13) | (regs.m << 12) | (regs.intmask << 8)
362: | (XFLG << 4) | (NFLG << 3) | (ZFLG << 2) | (VFLG << 1)
363: | CFLG);
364: }
365:
366: void MakeFromSR(void)
367: {
368: int oldm = regs.m;
369: int olds = regs.s;
370:
371: regs.t1 = (regs.sr >> 15) & 1;
372: regs.t0 = (regs.sr >> 14) & 1;
373: regs.s = (regs.sr >> 13) & 1;
374: regs.m = (regs.sr >> 12) & 1;
375: regs.intmask = (regs.sr >> 8) & 7;
376: XFLG = (regs.sr >> 4) & 1;
377: NFLG = (regs.sr >> 3) & 1;
378: ZFLG = (regs.sr >> 2) & 1;
379: VFLG = (regs.sr >> 1) & 1;
380: CFLG = regs.sr & 1;
381: if (CPU_LEVEL >= 2) {
382: if (olds != regs.s) {
383: if (olds) {
384: if (oldm)
1.1.1.2 ! root 385: regs.msp = m68k_areg(regs, 7);
1.1 root 386: else
1.1.1.2 ! root 387: regs.isp = m68k_areg(regs, 7);
! 388: m68k_areg(regs, 7) = regs.usp;
! 389: } else {
! 390: regs.usp = m68k_areg(regs, 7);
! 391: m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
1.1 root 392: }
393: } else if (olds && oldm != regs.m) {
394: if (oldm) {
1.1.1.2 ! root 395: regs.msp = m68k_areg(regs, 7);
! 396: m68k_areg(regs, 7) = regs.isp;
! 397: } else {
! 398: regs.isp = m68k_areg(regs, 7);
! 399: m68k_areg(regs, 7) = regs.msp;
1.1 root 400: }
401: }
402: } else {
403: if (olds != regs.s) {
404: if (olds) {
1.1.1.2 ! root 405: regs.isp = m68k_areg(regs, 7);
! 406: m68k_areg(regs, 7) = regs.usp;
1.1 root 407: } else {
1.1.1.2 ! root 408: regs.usp = m68k_areg(regs, 7);
! 409: m68k_areg(regs, 7) = regs.isp;
1.1 root 410: }
411: }
412: }
413:
414: regs.spcflags |= SPCFLAG_INT;
415: if (regs.t1 || regs.t0)
416: regs.spcflags |= SPCFLAG_TRACE;
417: else
418: regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
419: }
420:
421: void Exception(int nr, CPTR oldpc)
422: {
1.1.1.2 ! root 423: compiler_flush_jsr_stack();
1.1 root 424: MakeSR();
425: if (!regs.s) {
1.1.1.2 ! root 426: regs.usp = m68k_areg(regs, 7);
1.1 root 427: if (CPU_LEVEL >= 2)
1.1.1.2 ! root 428: m68k_areg(regs, 7) = regs.m ? regs.msp : regs.isp;
1.1 root 429: else
1.1.1.2 ! root 430: m68k_areg(regs, 7) = regs.isp;
1.1 root 431: regs.s = 1;
432: }
433: if (CPU_LEVEL > 0) {
434: if (nr == 2 || nr == 3) {
435: int i;
436: for (i = 0 ; i < 12 ; i++) {
1.1.1.2 ! root 437: m68k_areg(regs, 7) -= 2;
! 438: put_word (m68k_areg(regs, 7), 0);
1.1 root 439: }
1.1.1.2 ! root 440: m68k_areg(regs, 7) -= 2;
! 441: put_word (m68k_areg(regs, 7), 0xa000 + nr * 4);
1.1 root 442: } else if (nr ==5 || nr == 6 || nr == 7 || nr == 9) {
1.1.1.2 ! root 443: m68k_areg(regs, 7) -= 4;
! 444: put_long (m68k_areg(regs, 7), oldpc);
! 445: m68k_areg(regs, 7) -= 2;
! 446: put_word (m68k_areg(regs, 7), 0x2000 + nr * 4);
1.1 root 447: } else if (regs.m && nr >= 24 && nr < 32) {
1.1.1.2 ! root 448: m68k_areg(regs, 7) -= 2;
! 449: put_word (m68k_areg(regs, 7), nr * 4);
! 450: m68k_areg(regs, 7) -= 4;
! 451: put_long (m68k_areg(regs, 7), m68k_getpc ());
! 452: m68k_areg(regs, 7) -= 2;
! 453: put_word (m68k_areg(regs, 7), regs.sr);
1.1 root 454: regs.sr |= (1 << 13);
1.1.1.2 ! root 455: regs.msp = m68k_areg(regs, 7);
! 456: m68k_areg(regs, 7) = regs.isp;
! 457: m68k_areg(regs, 7) -= 2;
! 458: put_word (m68k_areg(regs, 7), 0x1000 + nr * 4);
1.1 root 459: } else {
1.1.1.2 ! root 460: m68k_areg(regs, 7) -= 2;
! 461: put_word (m68k_areg(regs, 7), nr * 4);
1.1 root 462: }
463: }
1.1.1.2 ! root 464: m68k_areg(regs, 7) -= 4;
! 465: put_long (m68k_areg(regs, 7), m68k_getpc ());
! 466: m68k_areg(regs, 7) -= 2;
! 467: put_word (m68k_areg(regs, 7), regs.sr);
1.1 root 468: m68k_setpc(get_long(regs.vbr + 4*nr));
469: regs.t1 = regs.t0 = regs.m = 0;
470: regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
471: }
472:
473: static void Interrupt(int nr)
474: {
475: assert(nr < 8 && nr >= 0);
476: lastint_regs = regs;
477: lastint_no = nr;
478: Exception(nr+24, 0);
479:
480: regs.intmask = nr;
481: regs.spcflags |= SPCFLAG_INT;
482: }
483:
484: static int caar, cacr;
485:
486: void m68k_move2c (int regno, ULONG *regp)
487: {
488: if (CPU_LEVEL == 1 && (regno & 0x7FF) > 1)
489: op_illg (0x4E7B);
490: else
491: switch (regno) {
492: case 0: regs.sfc = *regp & 7; break;
493: case 1: regs.dfc = *regp & 7; break;
494: case 2: cacr = *regp & 0x3; break; /* ignore C and CE */
495: case 0x800: regs.usp = *regp; break;
496: case 0x801: regs.vbr = *regp; break;
497: case 0x802: caar = *regp &0xfc; break;
1.1.1.2 ! root 498: case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
! 499: case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
1.1 root 500: default:
501: op_illg (0x4E7B);
502: break;
503: }
504: }
505:
506: void m68k_movec2 (int regno, ULONG *regp)
507: {
508: if (CPU_LEVEL == 1 && (regno & 0x7FF) > 1)
509: op_illg (0x4E7A);
510: else
511: switch (regno) {
512: case 0: *regp = regs.sfc; break;
513: case 1: *regp = regs.dfc; break;
514: case 2: *regp = cacr; break;
515: case 0x800: *regp = regs.usp; break;
516: case 0x801: *regp = regs.vbr; break;
517: case 0x802: *regp = caar; break;
1.1.1.2 ! root 518: case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
! 519: case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
1.1 root 520: default:
521: op_illg (0x4E7A);
522: break;
523: }
524: }
525:
526: static __inline__ int
527: div_unsigned(ULONG src_hi, ULONG src_lo, ULONG div, ULONG *quot, ULONG *rem)
528: {
529: ULONG q = 0, cbit = 0;
530: int i;
531:
532: if (div <= src_hi) {
533: return(1);
534: }
535: for (i = 0 ; i < 32 ; i++) {
1.1.1.2 ! root 536: cbit = src_hi & 0x80000000ul;
1.1 root 537: src_hi <<= 1;
1.1.1.2 ! root 538: if (src_lo & 0x80000000ul) src_hi++;
1.1 root 539: src_lo <<= 1;
540: q = q << 1;
541: if (cbit || div <= src_hi) {
542: q |= 1;
543: src_hi -= div;
544: }
545: }
546: *quot = q;
547: *rem = src_hi;
548: return(0);
549: }
550:
551: void m68k_divl (ULONG opcode, ULONG src, UWORD extra, CPTR oldpc)
552: {
553: #if defined(INT_64BIT)
554: if (src == 0) {
555: Exception(5,oldpc-2);
556: return;
557: }
558: if (extra & 0x800) {
559: /* signed variant */
1.1.1.2 ! root 560: INT_64BIT a = (INT_64BIT)(LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1 root 561: INT_64BIT quot, rem;
562:
563: if (extra & 0x400) {
564: a &= 0xffffffffLL;
1.1.1.2 ! root 565: a |= (INT_64BIT)m68k_dreg(regs, extra & 7) << 32;
1.1 root 566: }
567: rem = a % (INT_64BIT)(LONG)src;
568: quot = a / (INT_64BIT)(LONG)src;
1.1.1.2 ! root 569: if ((quot & 0xffffffff80000000uLL) != 0 &&
! 570: (quot & 0xffffffff80000000uLL) != 0xffffffff80000000uLL) {
1.1 root 571: VFLG = NFLG = 1;
572: CFLG = 0;
573: }
574: else {
575: if (((LONG)rem < 0) != ((INT_64BIT)a < 0)) rem = -rem;
576: VFLG = CFLG = 0;
577: ZFLG = ((LONG)quot) == 0;
578: NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root 579: m68k_dreg(regs, extra & 7) = rem;
! 580: m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1 root 581: }
582: } else {
583: /* unsigned */
1.1.1.2 ! root 584: unsigned INT_64BIT a = (unsigned INT_64BIT)(ULONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1 root 585: unsigned INT_64BIT quot, rem;
586:
587: if (extra & 0x400) {
588: a &= 0xffffffffLL;
1.1.1.2 ! root 589: a |= (unsigned INT_64BIT)m68k_dreg(regs, extra & 7) << 32;
1.1 root 590: }
591: rem = a % (unsigned INT_64BIT)src;
592: quot = a / (unsigned INT_64BIT)src;
593: if (quot > 0xffffffffLL) {
594: VFLG = NFLG = 1;
595: CFLG = 0;
596: }
597: else {
598: VFLG = CFLG = 0;
599: ZFLG = ((LONG)quot) == 0;
600: NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root 601: m68k_dreg(regs, extra & 7) = rem;
! 602: m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1 root 603: }
604: }
605: #else
606: if (src == 0) {
607: Exception(5,oldpc-2);
608: return;
609: }
610: if (extra & 0x800) {
611: /* signed variant */
1.1.1.2 ! root 612: LONG lo = (LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1 root 613: LONG hi = lo < 0 ? -1 : 0;
614: LONG save_high;
615: ULONG quot, rem;
616: ULONG sign;
617:
618: if (extra & 0x400) {
1.1.1.2 ! root 619: hi = (LONG)m68k_dreg(regs, extra & 7);
1.1 root 620: }
621: save_high = hi;
622: sign = (hi ^ src);
623: if (hi < 0) {
624: hi = ~hi;
625: lo = -lo;
626: if (lo == 0) hi++;
627: }
628: if ((LONG)src < 0) src = -src;
629: if (div_unsigned(hi, lo, src, ", &rem) ||
630: (sign & 0x80000000) ? quot > 0x80000000 : quot > 0x7fffffff) {
631: VFLG = NFLG = 1;
632: CFLG = 0;
633: }
634: else {
635: if (sign & 0x80000000) quot = -quot;
636: if (((LONG)rem < 0) != (save_high < 0)) rem = -rem;
637: VFLG = CFLG = 0;
638: ZFLG = ((LONG)quot) == 0;
639: NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root 640: m68k_dreg(regs, extra & 7) = rem;
! 641: m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1 root 642: }
643: } else {
644: /* unsigned */
1.1.1.2 ! root 645: ULONG lo = (ULONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1 root 646: ULONG hi = 0;
647: ULONG quot, rem;
648:
649: if (extra & 0x400) {
1.1.1.2 ! root 650: hi = (ULONG)m68k_dreg(regs, extra & 7);
1.1 root 651: }
652: if (div_unsigned(hi, lo, src, ", &rem)) {
653: VFLG = NFLG = 1;
654: CFLG = 0;
655: }
656: else {
657: VFLG = CFLG = 0;
658: ZFLG = ((LONG)quot) == 0;
659: NFLG = ((LONG)quot) < 0;
1.1.1.2 ! root 660: m68k_dreg(regs, extra & 7) = rem;
! 661: m68k_dreg(regs, (extra >> 12) & 7) = quot;
1.1 root 662: }
663: }
664: #endif
665: }
666:
667: static __inline__ void
668: mul_unsigned(ULONG src1, ULONG src2, ULONG *dst_hi, ULONG *dst_lo)
669: {
670: ULONG r0 = (src1 & 0xffff) * (src2 & 0xffff);
671: ULONG r1 = ((src1 >> 16) & 0xffff) * (src2 & 0xffff);
672: ULONG r2 = (src1 & 0xffff) * ((src2 >> 16) & 0xffff);
673: ULONG r3 = ((src1 >> 16) & 0xffff) * ((src2 >> 16) & 0xffff);
674: ULONG lo;
675:
1.1.1.2 ! root 676: lo = r0 + ((r1 << 16) & 0xffff0000ul);
1.1 root 677: if (lo < r0) r3++;
678: r0 = lo;
1.1.1.2 ! root 679: lo = r0 + ((r2 << 16) & 0xffff0000ul);
1.1 root 680: if (lo < r0) r3++;
681: r3 += ((r1 >> 16) & 0xffff) + ((r2 >> 16) & 0xffff);
682: *dst_lo = lo;
683: *dst_hi = r3;
684: }
685:
686: void m68k_mull (ULONG opcode, ULONG src, UWORD extra)
687: {
688: #if defined(INT_64BIT)
689: if (extra & 0x800) {
690: /* signed variant */
1.1.1.2 ! root 691: INT_64BIT a = (INT_64BIT)(LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1 root 692:
693: a *= (INT_64BIT)(LONG)src;
694: VFLG = CFLG = 0;
695: ZFLG = a == 0;
696: NFLG = a < 0;
697: if (extra & 0x400)
1.1.1.2 ! root 698: m68k_dreg(regs, extra & 7) = a >> 32;
! 699: else if ((a & 0xffffffff80000000uLL) != 0 &&
! 700: (a & 0xffffffff80000000uLL) != 0xffffffff80000000uLL) {
1.1 root 701: VFLG = 1;
702: }
1.1.1.2 ! root 703: m68k_dreg(regs, (extra >> 12) & 7) = (ULONG)a;
1.1 root 704: } else {
705: /* unsigned */
1.1.1.2 ! root 706: unsigned INT_64BIT a = (unsigned INT_64BIT)(ULONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1 root 707:
708: a *= (unsigned INT_64BIT)src;
709: VFLG = CFLG = 0;
710: ZFLG = a == 0;
711: NFLG = ((INT_64BIT)a) < 0;
712: if (extra & 0x400)
1.1.1.2 ! root 713: m68k_dreg(regs, extra & 7) = a >> 32;
! 714: else if ((a & 0xffffffff00000000uLL) != 0) {
1.1 root 715: VFLG = 1;
716: }
1.1.1.2 ! root 717: m68k_dreg(regs, (extra >> 12) & 7) = (ULONG)a;
1.1 root 718: }
719: #else
720: if (extra & 0x800) {
721: /* signed variant */
722: LONG src1,src2;
723: ULONG dst_lo,dst_hi;
724: ULONG sign;
725:
726: src1 = (LONG)src;
1.1.1.2 ! root 727: src2 = (LONG)m68k_dreg(regs, (extra >> 12) & 7);
1.1 root 728: sign = (src1 ^ src2);
729: if (src1 < 0) src1 = -src1;
730: if (src2 < 0) src2 = -src2;
731: mul_unsigned((ULONG)src1,(ULONG)src2,&dst_hi,&dst_lo);
732: if (sign & 0x80000000) {
733: dst_hi = ~dst_hi;
734: dst_lo = -dst_lo;
735: if (dst_lo == 0) dst_hi++;
736: }
737: VFLG = CFLG = 0;
738: ZFLG = dst_hi == 0 && dst_lo == 0;
739: NFLG = ((LONG)dst_hi) < 0;
740: if (extra & 0x400)
1.1.1.2 ! root 741: m68k_dreg(regs, extra & 7) = dst_hi;
1.1 root 742: else if ((dst_hi != 0 || (dst_lo & 0x80000000) != 0) &&
743: ((dst_hi & 0xffffffff) != 0xffffffff ||
744: (dst_lo & 0x80000000) != 0x80000000)) {
745: VFLG = 1;
746: }
1.1.1.2 ! root 747: m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1.1 root 748: } else {
749: /* unsigned */
750: ULONG dst_lo,dst_hi;
751:
1.1.1.2 ! root 752: mul_unsigned(src,(ULONG)m68k_dreg(regs, (extra >> 12) & 7),&dst_hi,&dst_lo);
1.1 root 753:
754: VFLG = CFLG = 0;
755: ZFLG = dst_hi == 0 && dst_lo == 0;
756: NFLG = ((LONG)dst_hi) < 0;
757: if (extra & 0x400)
1.1.1.2 ! root 758: m68k_dreg(regs, extra & 7) = dst_hi;
1.1 root 759: else if (dst_hi != 0) {
760: VFLG = 1;
761: }
1.1.1.2 ! root 762: m68k_dreg(regs, (extra >> 12) & 7) = dst_lo;
1.1 root 763: }
764: #endif
765: }
766: static char* ccnames[] =
767: { "T ","F ","HI","LS","CC","CS","NE","EQ",
768: "VC","VS","PL","MI","GE","LT","GT","LE" };
769:
770: void m68k_reset(void)
771: {
1.1.1.2 ! root 772: m68k_areg(regs, 7) = get_long(0x00f80000);
1.1 root 773: m68k_setpc(get_long(0x00f80004));
1.1.1.2 ! root 774: regs.kick_mask = 0xF80000;
1.1 root 775: regs.s = 1;
776: regs.m = 0;
777: regs.stopped = 0;
778: regs.t1 = 0;
779: regs.t0 = 0;
780: ZFLG = CFLG = NFLG = VFLG = 0;
781: regs.spcflags = 0;
782: regs.intmask = 7;
783: regs.vbr = regs.sfc = regs.dfc = 0;
784: regs.fpcr = regs.fpsr = regs.fpiar = 0;
785: customreset();
786: }
787:
1.1.1.2 ! root 788: void REGPARAM2 op_illg(ULONG opcode)
1.1 root 789: {
1.1.1.2 ! root 790: compiler_flush_jsr_stack();
1.1 root 791: if (opcode == 0x4E7B && get_long(0x10) == 0
792: && (m68k_getpc() & 0xF80000) == 0xF80000)
793: {
794: fprintf(stderr, "Your Kickstart requires a 68020 CPU. Giving up.\n");
795: broken_in = 1;
796: regs.spcflags |= SPCFLAG_BRK;
797: quit_program = 1;
798: }
1.1.1.2 ! root 799: if (opcode == 0xFF0D) {
! 800: if ((m68k_getpc() & 0xF80000) == 0xF80000) {
! 801: /* This is from the dummy Kickstart replacement */
! 802: ersatz_perform (nextiword ());
! 803: return;
! 804: } else if ((m68k_getpc() & 0xF80000) == 0xF00000) {
! 805: /* User-mode STOP replacement */
! 806: m68k_setstopped(1);
! 807: return;
! 808: }
1.1 root 809: }
810: #ifdef USE_POINTER
811: regs.pc_p -= 2;
812: #else
813: regs.pc -= 2;
814: #endif
815: if ((opcode & 0xF000) == 0xF000) {
816: Exception(0xB,0);
817: return;
818: }
819: if ((opcode & 0xF000) == 0xA000) {
820: Exception(0xA,0);
821: return;
822: }
823: fprintf(stderr, "Illegal instruction: %04x at %08lx\n", opcode, m68k_getpc());
824: Exception(4,0);
825: }
826:
827: void mmu_op(ULONG opcode, UWORD extra)
828: {
829: if ((extra & 0xB000) == 0) { /* PMOVE instruction */
830:
831: } else if ((extra & 0xF000) == 0x2000) { /* PLOAD instruction */
832: } else if ((extra & 0xF000) == 0x8000) { /* PTEST instruction */
833: } else
834: op_illg(opcode);
835: }
836:
837: static int n_insns=0, n_spcinsns=0;
838:
839: static CPTR last_trace_ad = 0;
840:
841: static __inline__ void do_trace(void)
842: {
843: if (regs.spcflags & SPCFLAG_TRACE) { /* 6 */
844: if (regs.t0) {
845: UWORD opcode;
846: /* should also include TRAP, CHK, SR modification FPcc */
847: /* probably never used so why bother */
848: /* We can afford this to be inefficient... */
849: m68k_setpc(m68k_getpc());
850: opcode = get_word(regs.pc);
851: if (opcode == 0x4e72 /* RTE */
852: || opcode == 0x4e74 /* RTD */
853: || opcode == 0x4e75 /* RTS */
854: || opcode == 0x4e77 /* RTR */
855: || opcode == 0x4e76 /* TRAPV */
856: || (opcode & 0xffc0) == 0x4e80 /* JSR */
857: || (opcode & 0xffc0) == 0x4ec0 /* JMP */
858: || (opcode & 0xff00) == 0x6100 /* BSR */
859: || ((opcode & 0xf000) == 0x6000 /* Bcc */
860: && cctrue((opcode >> 8) & 0xf))
861: || ((opcode & 0xf0f0) == 0x5050 /* DBcc */
862: && !cctrue((opcode >> 8) & 0xf)
1.1.1.2 ! root 863: && (WORD)m68k_dreg(regs, opcode & 7) != 0))
1.1 root 864: {
865: last_trace_ad = m68k_getpc();
866: regs.spcflags &= ~SPCFLAG_TRACE;
867: regs.spcflags |= SPCFLAG_DOTRACE;
868: }
869: } else if (regs.t1) {
870: last_trace_ad = m68k_getpc();
871: regs.spcflags &= ~SPCFLAG_TRACE;
872: regs.spcflags |= SPCFLAG_DOTRACE;
873: }
874: }
875: }
876:
1.1.1.2 ! root 877: static void m68k_run_1(void)
1.1 root 878: {
879: regs.spcflags &= ~(SPCFLAG_EMULTRAP);
880: for(;;) {
881:
882: /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
883: /* regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
884: #if COUNT_INSTRS
885: instrcount[opcode]++;
886: #endif
887: #if defined(X86_ASSEMBLY)
1.1.1.2 ! root 888: {
! 889: ULONG opcode = nextiword();
! 890: __asm__ __volatile__("\tcall *%%ebx"
! 891: : : "b" (cpufunctbl[opcode]), "a" (opcode)
! 892: : "%eax", "%ebx", "%edx", "%ecx",
! 893: "%esi", "%edi", "%ebp", "memory", "cc");
! 894: }
1.1 root 895: #else
896: {
1.1.1.2 ! root 897: ULONG opcode = nextiword();
1.1 root 898: (*cpufunctbl[opcode])(opcode);
899: }
900: #endif
901: #ifndef NO_EXCEPTION_3
902: if (buserr) {
903: Exception(3,0);
904: buserr = 0;
905: }
906: #endif
907: if (regs.spcflags & SPCFLAG_EMULTRAP)
908: return;
909: /*n_insns++;*/
910: do_cycles();
911: if (regs.spcflags) {
912: /*n_spcinsns++;*/
1.1.1.2 ! root 913: while (regs.spcflags & SPCFLAG_BLTNASTY) {
! 914: do_cycles();
! 915: if (regs.spcflags & SPCFLAG_DISK)
! 916: do_disk();
! 917: }
! 918: run_compiled_code();
! 919: if (regs.spcflags & SPCFLAG_DOTRACE) {
! 920: Exception(9,last_trace_ad);
! 921: }
! 922: while (regs.spcflags & SPCFLAG_STOP) {
! 923: do_cycles();
! 924: if (regs.spcflags & SPCFLAG_DISK)
! 925: do_disk();
! 926: if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT | SPCFLAG_TIMER)){
! 927: int intr = intlev();
! 928: regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT);
! 929: if (intr != -1 && intr > regs.intmask) {
! 930: Interrupt(intr);
! 931: regs.stopped = 0;
! 932: regs.spcflags &= ~SPCFLAG_STOP;
! 933: }
! 934: }
! 935: }
! 936: do_trace();
! 937: #ifdef WANT_SLOW_MULTIPLY
! 938: /* Kludge for Hardwired demo. The guys who wrote it should be
! 939: * mutilated. */
! 940: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
! 941: do_cycles (); do_cycles (); do_cycles (); do_cycles ();
! 942: regs.spcflags &= ~SPCFLAG_EXTRA_CYCLES;
! 943: }
! 944: #endif
! 945: if (regs.spcflags & SPCFLAG_DISK)
! 946: do_disk();
! 947:
! 948: if (regs.spcflags & (SPCFLAG_DOINT|SPCFLAG_TIMER)) {
! 949: int intr = intlev();
! 950: regs.spcflags &= ~SPCFLAG_DOINT;
! 951: if (intr != -1 && intr > regs.intmask) {
! 952: Interrupt(intr);
! 953: regs.stopped = 0;
! 954: }
! 955: }
! 956: if (regs.spcflags & SPCFLAG_INT) {
! 957: regs.spcflags &= ~SPCFLAG_INT;
! 958: regs.spcflags |= SPCFLAG_DOINT;
! 959: }
! 960: if (regs.spcflags & (SPCFLAG_BRK|SPCFLAG_MODE_CHANGE)) {
! 961: regs.spcflags &= ~(SPCFLAG_BRK|SPCFLAG_MODE_CHANGE);
! 962: return;
! 963: }
! 964: }
! 965: }
! 966: }
! 967:
! 968: #if USER_PROGRAMS_BEHAVE > 0
! 969: static void m68k_run_2(void)
! 970: {
! 971: regs.spcflags &= ~(SPCFLAG_EMULTRAP);
! 972: for(;;) {
! 973:
! 974: /* assert (!regs.stopped && !(regs.spcflags & SPCFLAG_STOP)); */
! 975: /* regs_backup[backup_pointer = (backup_pointer + 1) % 16] = regs;*/
! 976: #if COUNT_INSTRS
! 977: instrcount[opcode]++;
! 978: #endif
! 979: #if defined(X86_ASSEMBLY)
! 980: {
! 981: ULONG opcode = nextiword();
! 982: __asm__ __volatile__("\tcall *%%ebx"
! 983: : : "b" (cpufunctbl_behaved[opcode]), "a" (opcode)
! 984: : "%eax", "%ebx", "%edx", "%ecx",
! 985: "%esi", "%edi", "%ebp", "memory", "cc");
! 986: }
! 987: #else
! 988: {
! 989: ULONG opcode = nextiword();
! 990: (*cpufunctbl_behaved[opcode])(opcode);
! 991: }
! 992: #endif
! 993: #ifndef NO_EXCEPTION_3
! 994: if (buserr) {
! 995: Exception(3,0);
! 996: buserr = 0;
! 997: }
! 998: #endif
! 999: if (regs.spcflags & SPCFLAG_EMULTRAP)
! 1000: return;
! 1001: /*n_insns++;*/
! 1002: do_cycles();
! 1003: if (regs.spcflags) {
! 1004: /*n_spcinsns++;*/
! 1005: while (regs.spcflags & SPCFLAG_BLTNASTY) {
1.1 root 1006: do_cycles();
1.1.1.2 ! root 1007: if (regs.spcflags & SPCFLAG_DISK)
! 1008: do_disk();
1.1 root 1009: }
1010: run_compiled_code();
1.1.1.2 ! root 1011: if (regs.spcflags & SPCFLAG_DOTRACE) {
1.1 root 1012: Exception(9,last_trace_ad);
1013: }
1.1.1.2 ! root 1014: while (regs.spcflags & SPCFLAG_STOP) {
1.1 root 1015: do_cycles();
1.1.1.2 ! root 1016: if (regs.spcflags & SPCFLAG_DISK)
! 1017: do_disk();
! 1018: if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT | SPCFLAG_TIMER)){
1.1 root 1019: int intr = intlev();
1020: regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT);
1021: if (intr != -1 && intr > regs.intmask) {
1022: Interrupt(intr);
1023: regs.stopped = 0;
1024: regs.spcflags &= ~SPCFLAG_STOP;
1025: }
1026: }
1027: }
1028: do_trace();
1029: #ifdef WANT_SLOW_MULTIPLY
1030: /* Kludge for Hardwired demo. The guys who wrote it should be
1031: * mutilated. */
1.1.1.2 ! root 1032: if (regs.spcflags & SPCFLAG_EXTRA_CYCLES) {
1.1 root 1033: do_cycles (); do_cycles (); do_cycles (); do_cycles ();
1034: regs.spcflags &= ~SPCFLAG_EXTRA_CYCLES;
1035: }
1036: #endif
1.1.1.2 ! root 1037: if (regs.spcflags & SPCFLAG_DISK)
! 1038: do_disk();
1.1 root 1039:
1.1.1.2 ! root 1040: if (regs.spcflags & (SPCFLAG_DOINT|SPCFLAG_TIMER)) {
1.1 root 1041: int intr = intlev();
1042: regs.spcflags &= ~SPCFLAG_DOINT;
1043: if (intr != -1 && intr > regs.intmask) {
1044: Interrupt(intr);
1045: regs.stopped = 0;
1046: }
1047: }
1.1.1.2 ! root 1048: if (regs.spcflags & SPCFLAG_INT) {
1.1 root 1049: regs.spcflags &= ~SPCFLAG_INT;
1050: regs.spcflags |= SPCFLAG_DOINT;
1051: }
1.1.1.2 ! root 1052: if (regs.spcflags & (SPCFLAG_BRK|SPCFLAG_MODE_CHANGE)) {
! 1053: regs.spcflags &= ~(SPCFLAG_BRK|SPCFLAG_MODE_CHANGE);
1.1 root 1054: return;
1055: }
1056: }
1057: }
1058: }
1.1.1.2 ! root 1059: #endif
1.1 root 1060:
1061: #ifdef X86_ASSEMBLY
1.1.1.2 ! root 1062: static __inline__ void m68k_run1(void)
1.1 root 1063: {
1064: /* Work around compiler bug: GCC doesn't push %ebp in m68k_run_1. */
1065: __asm__ __volatile__ ("pushl %%ebp\n\tcall *%%eax\n\tpopl %%ebp" : : "a" (m68k_run_1) : "%eax", "%edx", "%ecx", "memory", "cc");
1066: }
1.1.1.2 ! root 1067: #if USER_PROGRAMS_BEHAVE > 0
! 1068: static __inline__ void m68k_run2(void)
1.1 root 1069: {
1.1.1.2 ! root 1070: /* Work around compiler bug: GCC doesn't push %ebp in m68k_run_1. */
! 1071: __asm__ __volatile__ ("pushl %%ebp\n\tcall *%%eax\n\tpopl %%ebp" : : "a" (m68k_run_2) : "%eax", "%edx", "%ecx", "memory", "cc");
1.1 root 1072: }
1073: #endif
1.1.1.2 ! root 1074: #else
! 1075: #define m68k_run1 m68k_run_1
! 1076: #define m68k_run2 m68k_run_2
! 1077: #endif
! 1078:
! 1079: int may_run_compiled;
1.1 root 1080:
1081: void m68k_go(int may_quit)
1082: {
1.1.1.2 ! root 1083: int old_mrc = may_run_compiled;
! 1084:
! 1085: may_run_compiled = may_quit;
1.1 root 1086: for(;;) {
1087: if (may_quit && quit_program)
1088: return;
1089: if (debugging)
1090: debug();
1.1.1.2 ! root 1091: #if USER_PROGRAMS_BEHAVE > 0
! 1092: if ((regs.kick_mask & 0xF00000) != 0xF00000)
! 1093: m68k_run2();
! 1094: else
! 1095: #endif
! 1096: m68k_run1();
! 1097:
1.1 root 1098: /*
1099: * We make sure in the above functions that this is never
1100: * set together with SPCFLAG_INT and similar flags
1101: */
1102: if (regs.spcflags & SPCFLAG_EMULTRAP) {
1103: regs.spcflags &= ~SPCFLAG_EMULTRAP;
1104: if (lasttrap == 0)
1105: break;
1106: do_emultrap(lasttrap);
1107: }
1108: }
1.1.1.2 ! root 1109: may_run_compiled = old_mrc;
1.1 root 1110: }
1111:
1112: void m68k_disasm(CPTR addr, CPTR *nextpc, int cnt)
1113: {
1114: CPTR pc = m68k_getpc();
1115: CPTR newpc = 0;
1116: m68k_setpc(addr);
1117: for (;cnt--;){
1118: char instrname[20],*ccpt;
1119: int opwords;
1120: ULONG opcode;
1121: struct mnemolookup *lookup;
1122: struct instr *dp;
1123: printf("%08lx: ", m68k_getpc());
1124: for(opwords = 0; opwords < 5; opwords++){
1125: printf("%04x ", get_word(m68k_getpc() + opwords*2));
1126: }
1127:
1128: opcode = nextiword();
1129: if (cpufunctbl[opcode] == op_illg) {
1130: opcode = 0x4AFC;
1131: }
1132: dp = table68k + opcode;
1133: for (lookup = lookuptab;lookup->mnemo != dp->mnemo; lookup++)
1134: ;
1135:
1136: strcpy(instrname,lookup->name);
1137: ccpt = strstr(instrname,"cc");
1138: if (ccpt != 0) {
1139: strncpy(ccpt,ccnames[dp->cc],2);
1140: }
1141: printf("%s", instrname);
1142: switch(dp->size){
1143: case sz_byte: printf(".B "); break;
1144: case sz_word: printf(".W "); break;
1145: case sz_long: printf(".L "); break;
1146: default: printf(" ");break;
1147: }
1148:
1149: if (dp->suse) {
1.1.1.2 ! root 1150: newpc = m68k_getpc() + ShowEA(dp->sreg, dp->smode, dp->size, 0);
1.1 root 1151: }
1152: if (dp->suse && dp->duse)
1153: printf(",");
1154: if (dp->duse) {
1.1.1.2 ! root 1155: newpc = m68k_getpc() + ShowEA(dp->dreg, dp->dmode, dp->size, 0);
1.1 root 1156: }
1157: if (ccpt != 0) {
1158: if (cctrue(dp->cc))
1159: printf(" == %08lx (TRUE)",newpc);
1160: else
1161: printf(" == %08lx (FALSE)",newpc);
1162: } else if ((opcode & 0xff00) == 0x6100) /* BSR */
1163: printf(" == %08lx",newpc);
1164: printf("\n");
1165: }
1166: if (nextpc) *nextpc = m68k_getpc();
1167: m68k_setpc(pc);
1168: }
1169:
1170: void m68k_dumpstate(CPTR *nextpc)
1171: {
1172: int i;
1173: for(i = 0; i < 8; i++){
1.1.1.2 ! root 1174: printf("D%d: %08lx ", i, m68k_dreg(regs, i));
1.1 root 1175: if ((i & 3) == 3) printf("\n");
1176: }
1177: for(i = 0; i < 8; i++){
1.1.1.2 ! root 1178: printf("A%d: %08lx ", i, m68k_areg(regs, i));
1.1 root 1179: if ((i & 3) == 3) printf("\n");
1180: }
1.1.1.2 ! root 1181: if (regs.s == 0) regs.usp = m68k_areg(regs, 7);
! 1182: if (regs.s && regs.m) regs.msp = m68k_areg(regs, 7);
! 1183: if (regs.s && regs.m == 0) regs.isp = m68k_areg(regs, 7);
1.1 root 1184: printf("USP=%08lx ISP=%08lx MSP=%08lx VBR=%08lx\n",
1185: regs.usp,regs.isp,regs.msp,regs.vbr);
1186: printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
1187: regs.t1, regs.t0, regs.s, regs.m,
1188: XFLG, NFLG, ZFLG, VFLG, CFLG, regs.intmask);
1189: for(i = 0; i < 8; i++){
1190: printf("FP%d: %g ", i, regs.fp[i]);
1191: if ((i & 3) == 3) printf("\n");
1192: }
1193: printf("N=%d Z=%d I=%d NAN=%d\n",
1194: (regs.fpsr & 0x8000000) != 0,
1195: (regs.fpsr & 0x4000000) != 0,
1196: (regs.fpsr & 0x2000000) != 0,
1197: (regs.fpsr & 0x1000000) != 0);
1198: m68k_disasm(m68k_getpc(), nextpc, 1);
1199: if (nextpc) printf("next PC: %08lx\n", *nextpc);
1200: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.