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