|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * Read 68000 CPU specs from file "table68k" ! 5: * ! 6: * Copyright 1995,1996 Bernd Schmidt ! 7: */ ! 8: ! 9: #include "sysconfig.h" ! 10: #include "sysdeps.h" ! 11: #include <ctype.h> ! 12: #include <string.h> ! 13: ! 14: #include "readcpu.h" ! 15: ! 16: int nr_cpuop_funcs; ! 17: ! 18: struct mnemolookup lookuptab[] = { ! 19: { i_ILLG, "ILLEGAL" , ""}, ! 20: { i_OR, "OR" , "" }, ! 21: { i_CHK, "CHK" , "" }, ! 22: { i_CHK2, "CHK2" , "" }, ! 23: { i_AND, "AND" , "" }, ! 24: { i_EOR, "EOR" , "" }, ! 25: { i_ORSR, "ORSR" , "" }, ! 26: { i_ANDSR, "ANDSR" , "" }, ! 27: { i_EORSR, "EORSR" , "" }, ! 28: { i_SUB, "SUB" , "" }, ! 29: { i_SUBA, "SUBA" , "" }, ! 30: { i_SUBX, "SUBX" , "" }, ! 31: { i_SBCD, "SBCD" , "" }, ! 32: { i_ADD, "ADD" , "" }, ! 33: { i_ADDA, "ADDA" , "" }, ! 34: { i_ADDX, "ADDX" , "" }, ! 35: { i_ABCD, "ABCD" , "" }, ! 36: { i_NEG, "NEG" , ""}, ! 37: { i_NEGX, "NEGX" , "" }, ! 38: { i_NBCD, "NBCD" , "" }, ! 39: { i_CLR, "CLR" , "" }, ! 40: { i_NOT, "NOT" , "" }, ! 41: { i_TST, "TST" , "" }, ! 42: { i_BTST, "BTST" , "" }, ! 43: { i_BCHG, "BCHG" , "" }, ! 44: { i_BCLR, "BCLR" , ""}, ! 45: { i_BSET, "BSET" , ""}, ! 46: { i_CMP, "CMP" , "" }, ! 47: { i_CMPM, "CMPM" , ""}, ! 48: { i_CMPA, "CMPA" , ""}, ! 49: { i_MVPRM, "MVPRM" , "" }, ! 50: { i_MVPMR, "MVPMR" , "" }, ! 51: { i_MOVE, "MOVE" , "" }, ! 52: { i_MOVEA, "MOVEA" , "" }, ! 53: { i_MVSR2, "MVSR2" , "" }, ! 54: { i_MV2SR, "MV2SR" , "" }, ! 55: { i_SWAP, "SWAP" , "" }, ! 56: { i_EXG, "EXG" , "" }, ! 57: { i_EXT, "EXT" , ""}, ! 58: { i_MVMEL, "MVMEL", "MOVEM" }, ! 59: { i_MVMLE, "MVMLE", "MOVEM" }, ! 60: { i_TRAP, "TRAP" , "" }, ! 61: { i_MVR2USP, "MVR2USP" , "" }, ! 62: { i_MVUSP2R, "MVUSP2R" , ""}, ! 63: { i_NOP, "NOP" , "" }, ! 64: { i_RESET, "RESET" , "" }, ! 65: { i_RTE, "RTE" , "" }, ! 66: { i_RTD, "RTD" , "" }, ! 67: { i_LINK, "LINK" , "" }, ! 68: { i_UNLK, "UNLK" , "" }, ! 69: { i_RTS, "RTS" , "" }, ! 70: { i_STOP, "STOP" , "" }, ! 71: { i_TRAPV, "TRAPV" , ""}, ! 72: { i_RTR, "RTR" , "" }, ! 73: { i_JSR, "JSR" , "" }, ! 74: { i_JMP, "JMP" , ""}, ! 75: { i_BSR, "BSR" , ""}, ! 76: { i_Bcc, "Bcc" , ""}, ! 77: { i_LEA, "LEA" , ""}, ! 78: { i_PEA, "PEA" , ""}, ! 79: { i_DBcc, "DBcc" , "" }, ! 80: { i_Scc, "Scc" , "" }, ! 81: { i_DIVU, "DIVU" , "" }, ! 82: { i_DIVS, "DIVS" , ""}, ! 83: { i_MULU, "MULU" , "" }, ! 84: { i_MULS, "MULS" , "" }, ! 85: { i_ASR, "ASR" , "" }, ! 86: { i_ASL, "ASL" , ""}, ! 87: { i_LSR, "LSR" , ""}, ! 88: { i_LSL, "LSL" , ""}, ! 89: { i_ROL, "ROL" , ""}, ! 90: { i_ROR, "ROR" , ""}, ! 91: { i_ROXL, "ROXL" , "" }, ! 92: { i_ROXR, "ROXR" , ""}, ! 93: { i_ASRW, "ASRW" , "" }, ! 94: { i_ASLW, "ASLW" , ""}, ! 95: { i_LSRW, "LSRW" , "" }, ! 96: { i_LSLW, "LSLW" , ""}, ! 97: { i_ROLW, "ROLW" , ""}, ! 98: { i_RORW, "RORW" , ""}, ! 99: { i_ROXLW, "ROXLW" , "" }, ! 100: { i_ROXRW, "ROXRW" , ""}, ! 101: ! 102: { i_MOVE2C, "MOVE2C", "MOVEC" }, ! 103: { i_MOVEC2, "MOVEC2", "MOVEC" }, ! 104: { i_CAS, "CAS" , "" }, ! 105: { i_CAS2, "CAS2" , "" }, ! 106: { i_MULL, "MULL" , "" }, ! 107: { i_DIVL, "DIVL" , ""}, ! 108: { i_BFTST, "BFTST" , ""}, ! 109: { i_BFEXTU, "BFEXTU" , ""}, ! 110: { i_BFCHG, "BFCHG" , "" }, ! 111: { i_BFEXTS, "BFEXTS" , "" }, ! 112: { i_BFCLR, "BFCLR" , ""}, ! 113: { i_BFFFO, "BFFFO" , "" }, ! 114: { i_BFSET, "BFSET" , ""}, ! 115: { i_BFINS, "BFINS" , ""}, ! 116: { i_PACK, "PACK" , ""}, ! 117: { i_UNPK, "UNPK" , ""}, ! 118: { i_TAS, "TAS" , ""}, ! 119: { i_BKPT, "BKPT" , ""}, ! 120: { i_CALLM, "CALLM" , ""}, ! 121: { i_RTM, "RTM" , ""}, ! 122: { i_TRAPcc, "TRAPcc" , ""}, ! 123: { i_MOVES, "MOVES" , ""}, ! 124: { i_FPP, "FPP" , ""}, ! 125: { i_FDBcc, "FDBcc" , ""}, ! 126: { i_FScc, "FScc" , ""}, ! 127: { i_FTRAPcc, "FTRAPcc" , "" }, ! 128: { i_FBcc, "FBcc" , ""}, ! 129: { i_FBcc, "FBcc" , ""}, ! 130: { i_FSAVE, "FSAVE" , ""}, ! 131: { i_FRESTORE, "FRESTORE" , ""}, ! 132: ! 133: { i_CINVL, "CINVL" , ""}, ! 134: { i_CINVP, "CINVP" , "" }, ! 135: { i_CINVA, "CINVA" , ""}, ! 136: { i_CPUSHL, "CPUSHL" , ""}, ! 137: { i_CPUSHP, "CPUSHP" , "" }, ! 138: { i_CPUSHA, "CPUSHA" , "" }, ! 139: { i_MOVE16, "MOVE16" , ""}, ! 140: ! 141: { i_MMUOP030, "MMUOP030" , "" }, ! 142: { i_PFLUSHN, "PFLUSHN" , "" }, ! 143: { i_PFLUSH, "PFLUSH" , ""}, ! 144: { i_PFLUSHAN, "PFLUSHAN" , ""}, ! 145: { i_PFLUSHA, "PFLUSHA" , ""}, ! 146: ! 147: { i_PLPAR, "PLPAR" , ""}, ! 148: { i_PLPAW, "PLPAW" , ""}, ! 149: { i_PTESTR, "PTESTR" , ""}, ! 150: { i_PTESTW, "PTESTW" , ""}, ! 151: ! 152: { i_LPSTOP, "LPSTOP" , ""}, ! 153: { i_ILLG, "" , ""}, ! 154: }; ! 155: ! 156: struct instr *table68k; ! 157: ! 158: static int specialcase (uae_u16 opcode, int cpu_lev) ! 159: { ! 160: int mode = (opcode >> 3) & 7; ! 161: int reg = opcode & 7; ! 162: ! 163: if (cpu_lev >= 2) ! 164: return cpu_lev; ! 165: /* TST.W A0, TST.L A0, TST.x (d16,PC) and TST.x (d8,PC,Xn) are 68020+ only */ ! 166: if ((opcode & 0xff00) == 0x4a00) { ! 167: if (mode == 7 && (reg == 4 || reg == 2 || reg == 3)) ! 168: return 2; ! 169: if (mode == 1) /* Ax */ ! 170: return 2; ! 171: } ! 172: /* CMPI.W #x,(d16,PC) and CMPI.W #x,(d8,PC,Xn) are 68020+ only */ ! 173: if ((opcode & 0xff00) == 0x0c00) { ! 174: if (mode == 7 && (reg == 2 || reg == 3)) ! 175: return 2; ! 176: } ! 177: return cpu_lev; ! 178: } ! 179: ! 180: static amodes mode_from_str (const TCHAR *str) ! 181: { ! 182: if (_tcsncmp (str, "Dreg", 4) == 0) return Dreg; ! 183: if (_tcsncmp (str, "Areg", 4) == 0) return Areg; ! 184: if (_tcsncmp (str, "Aind", 4) == 0) return Aind; ! 185: if (_tcsncmp (str, "Apdi", 4) == 0) return Apdi; ! 186: if (_tcsncmp (str, "Aipi", 4) == 0) return Aipi; ! 187: if (_tcsncmp (str, "Ad16", 4) == 0) return Ad16; ! 188: if (_tcsncmp (str, "Ad8r", 4) == 0) return Ad8r; ! 189: if (_tcsncmp (str, "absw", 4) == 0) return absw; ! 190: if (_tcsncmp (str, "absl", 4) == 0) return absl; ! 191: if (_tcsncmp (str, "PC16", 4) == 0) return PC16; ! 192: if (_tcsncmp (str, "PC8r", 4) == 0) return PC8r; ! 193: if (_tcsncmp (str, "Immd", 4) == 0) return imm; ! 194: abort (); ! 195: return 0; ! 196: } ! 197: ! 198: STATIC_INLINE amodes mode_from_mr (int mode, int reg) ! 199: { ! 200: switch (mode) { ! 201: case 0: return Dreg; ! 202: case 1: return Areg; ! 203: case 2: return Aind; ! 204: case 3: return Aipi; ! 205: case 4: return Apdi; ! 206: case 5: return Ad16; ! 207: case 6: return Ad8r; ! 208: case 7: ! 209: switch (reg) { ! 210: case 0: return absw; ! 211: case 1: return absl; ! 212: case 2: return PC16; ! 213: case 3: return PC8r; ! 214: case 4: return imm; ! 215: case 5: ! 216: case 6: ! 217: case 7: return am_illg; ! 218: } ! 219: } ! 220: abort (); ! 221: return 0; ! 222: } ! 223: ! 224: static void build_insn (int insn) ! 225: { ! 226: int find = -1; ! 227: int variants; ! 228: int isjmp = 0; ! 229: struct instr_def id; ! 230: const TCHAR *opcstr; ! 231: int i; ! 232: ! 233: int flaglive = 0, flagdead = 0; ! 234: ! 235: id = defs68k[insn]; ! 236: ! 237: /* Note: We treat anything with unknown flags as a jump. That ! 238: is overkill, but "the programmer" was lazy quite often, and ! 239: *this* programmer can't be bothered to work out what can and ! 240: can't trap. Usually, this will be overwritten with the gencomp ! 241: based information, anyway. */ ! 242: ! 243: for (i = 0; i < 5; i++) { ! 244: switch (id.flaginfo[i].flagset){ ! 245: case fa_unset: break; ! 246: case fa_isjmp: isjmp = 1; break; ! 247: case fa_isbranch: isjmp = 1; break; ! 248: case fa_zero: flagdead |= 1 << i; break; ! 249: case fa_one: flagdead |= 1 << i; break; ! 250: case fa_dontcare: flagdead |= 1 << i; break; ! 251: case fa_unknown: isjmp = 1; flagdead = -1; goto out1; ! 252: case fa_set: flagdead |= 1 << i; break; ! 253: } ! 254: } ! 255: ! 256: out1: ! 257: for (i = 0; i < 5; i++) { ! 258: switch (id.flaginfo[i].flaguse) { ! 259: case fu_unused: break; ! 260: case fu_isjmp: isjmp = 1; flaglive |= 1 << i; break; ! 261: case fu_maybecc: isjmp = 1; flaglive |= 1 << i; break; ! 262: case fu_unknown: isjmp = 1; flaglive |= 1 << i; break; ! 263: case fu_used: flaglive |= 1 << i; break; ! 264: } ! 265: } ! 266: ! 267: opcstr = id.opcstr; ! 268: for (variants = 0; variants < (1 << id.n_variable); variants++) { ! 269: int bitcnt[lastbit]; ! 270: int bitval[lastbit]; ! 271: int bitpos[lastbit]; ! 272: int i; ! 273: uae_u16 opc = id.bits; ! 274: uae_u16 msk, vmsk; ! 275: int pos = 0; ! 276: int mnp = 0; ! 277: int bitno = 0; ! 278: TCHAR mnemonic[10]; ! 279: ! 280: wordsizes sz = sz_long; ! 281: int srcgather = 0, dstgather = 0; ! 282: int usesrc = 0, usedst = 0; ! 283: int srctype = 0; ! 284: int srcpos = -1, dstpos = -1; ! 285: ! 286: amodes srcmode = am_unknown, destmode = am_unknown; ! 287: int srcreg = -1, destreg = -1; ! 288: ! 289: for (i = 0; i < lastbit; i++) ! 290: bitcnt[i] = bitval[i] = 0; ! 291: ! 292: vmsk = 1 << id.n_variable; ! 293: ! 294: for (i = 0, msk = 0x8000; i < 16; i++, msk >>= 1) { ! 295: if (!(msk & id.mask)) { ! 296: int currbit = id.bitpos[bitno++]; ! 297: int bit_set; ! 298: vmsk >>= 1; ! 299: bit_set = variants & vmsk ? 1 : 0; ! 300: if (bit_set) ! 301: opc |= msk; ! 302: bitpos[currbit] = 15 - i; ! 303: bitcnt[currbit]++; ! 304: bitval[currbit] <<= 1; ! 305: bitval[currbit] |= bit_set; ! 306: } ! 307: } ! 308: ! 309: if (bitval[bitj] == 0) bitval[bitj] = 8; ! 310: /* first check whether this one does not match after all */ ! 311: if (bitval[bitz] == 3 || bitval[bitC] == 1) ! 312: continue; ! 313: if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff)) ! 314: continue; ! 315: ! 316: /* bitI and bitC get copied to biti and bitc */ ! 317: if (bitcnt[bitI]) { ! 318: bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI]; ! 319: } ! 320: if (bitcnt[bitC]) ! 321: bitval[bitc] = bitval[bitC]; ! 322: ! 323: pos = 0; ! 324: while (opcstr[pos] && !_istspace(opcstr[pos])) { ! 325: if (opcstr[pos] == '.') { ! 326: pos++; ! 327: switch (opcstr[pos]) { ! 328: ! 329: case 'B': sz = sz_byte; break; ! 330: case 'W': sz = sz_word; break; ! 331: case 'L': sz = sz_long; break; ! 332: case 'z': ! 333: switch (bitval[bitz]) { ! 334: case 0: sz = sz_byte; break; ! 335: case 1: sz = sz_word; break; ! 336: case 2: sz = sz_long; break; ! 337: default: abort(); ! 338: } ! 339: break; ! 340: default: abort(); ! 341: } ! 342: } else { ! 343: mnemonic[mnp] = opcstr[pos]; ! 344: if (mnemonic[mnp] == 'f') { ! 345: find = -1; ! 346: switch (bitval[bitf]) { ! 347: case 0: mnemonic[mnp] = 'R'; break; ! 348: case 1: mnemonic[mnp] = 'L'; break; ! 349: default: abort(); ! 350: } ! 351: } ! 352: mnp++; ! 353: } ! 354: pos++; ! 355: } ! 356: mnemonic[mnp] = 0; ! 357: ! 358: /* now, we have read the mnemonic and the size */ ! 359: while (opcstr[pos] && _istspace(opcstr[pos])) ! 360: pos++; ! 361: ! 362: /* A goto a day keeps the D******a away. */ ! 363: if (opcstr[pos] == 0) ! 364: goto endofline; ! 365: ! 366: /* parse the source address */ ! 367: usesrc = 1; ! 368: switch (opcstr[pos++]) { ! 369: case 'D': ! 370: srcmode = Dreg; ! 371: switch (opcstr[pos++]) { ! 372: case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break; ! 373: case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break; ! 374: default: abort(); ! 375: } ! 376: break; ! 377: case 'A': ! 378: srcmode = Areg; ! 379: switch (opcstr[pos++]) { ! 380: case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break; ! 381: case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break; ! 382: default: abort(); ! 383: } ! 384: switch (opcstr[pos]) { ! 385: case 'p': srcmode = Apdi; pos++; break; ! 386: case 'P': srcmode = Aipi; pos++; break; ! 387: case 'a': srcmode = Aind; pos++; break; ! 388: } ! 389: break; ! 390: case 'L': ! 391: srcmode = absl; ! 392: break; ! 393: case '#': ! 394: switch (opcstr[pos++]) { ! 395: case 'z': srcmode = imm; break; ! 396: case '0': srcmode = imm0; break; ! 397: case '1': srcmode = imm1; break; ! 398: case '2': srcmode = imm2; break; ! 399: case 'i': srcmode = immi; srcreg = (uae_s32)(uae_s8)bitval[biti]; ! 400: if (CPU_EMU_SIZE < 4) { ! 401: /* Used for branch instructions */ ! 402: srctype = 1; ! 403: srcgather = 1; ! 404: srcpos = bitpos[biti]; ! 405: } ! 406: break; ! 407: case 'j': srcmode = immi; srcreg = bitval[bitj]; ! 408: if (CPU_EMU_SIZE < 3) { ! 409: /* 1..8 for ADDQ/SUBQ and rotshi insns */ ! 410: srcgather = 1; ! 411: srctype = 3; ! 412: srcpos = bitpos[bitj]; ! 413: } ! 414: break; ! 415: case 'J': srcmode = immi; srcreg = bitval[bitJ]; ! 416: if (CPU_EMU_SIZE < 5) { ! 417: /* 0..15 */ ! 418: srcgather = 1; ! 419: srctype = 2; ! 420: srcpos = bitpos[bitJ]; ! 421: } ! 422: break; ! 423: case 'k': srcmode = immi; srcreg = bitval[bitk]; ! 424: if (CPU_EMU_SIZE < 3) { ! 425: srcgather = 1; ! 426: srctype = 4; ! 427: srcpos = bitpos[bitk]; ! 428: } ! 429: break; ! 430: case 'K': srcmode = immi; srcreg = bitval[bitK]; ! 431: if (CPU_EMU_SIZE < 5) { ! 432: /* 0..15 */ ! 433: srcgather = 1; ! 434: srctype = 5; ! 435: srcpos = bitpos[bitK]; ! 436: } ! 437: break; ! 438: case 'p': srcmode = immi; srcreg = bitval[bitK]; ! 439: if (CPU_EMU_SIZE < 5) { ! 440: /* 0..3 */ ! 441: srcgather = 1; ! 442: srctype = 7; ! 443: srcpos = bitpos[bitp]; ! 444: } ! 445: break; ! 446: default: abort(); ! 447: } ! 448: break; ! 449: case 'd': ! 450: srcreg = bitval[bitD]; ! 451: srcmode = mode_from_mr(bitval[bitd],bitval[bitD]); ! 452: if (srcmode == am_illg) ! 453: continue; ! 454: if (CPU_EMU_SIZE < 2 && ! 455: (srcmode == Areg || srcmode == Dreg || srcmode == Aind ! 456: || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi ! 457: || srcmode == Apdi)) ! 458: { ! 459: srcgather = 1; srcpos = bitpos[bitD]; ! 460: } ! 461: if (opcstr[pos] == '[') { ! 462: pos++; ! 463: if (opcstr[pos] == '!') { ! 464: /* exclusion */ ! 465: do { ! 466: pos++; ! 467: if (mode_from_str(opcstr+pos) == srcmode) ! 468: goto nomatch; ! 469: pos += 4; ! 470: } while (opcstr[pos] == ','); ! 471: pos++; ! 472: } else { ! 473: if (opcstr[pos+4] == '-') { ! 474: /* replacement */ ! 475: if (mode_from_str(opcstr+pos) == srcmode) ! 476: srcmode = mode_from_str(opcstr+pos+5); ! 477: else ! 478: goto nomatch; ! 479: pos += 10; ! 480: } else { ! 481: /* normal */ ! 482: while(mode_from_str(opcstr+pos) != srcmode) { ! 483: pos += 4; ! 484: if (opcstr[pos] == ']') ! 485: goto nomatch; ! 486: pos++; ! 487: } ! 488: while(opcstr[pos] != ']') pos++; ! 489: pos++; ! 490: break; ! 491: } ! 492: } ! 493: } ! 494: /* Some addressing modes are invalid as destination */ ! 495: if (srcmode == imm || srcmode == PC16 || srcmode == PC8r) ! 496: goto nomatch; ! 497: break; ! 498: case 's': ! 499: srcreg = bitval[bitS]; ! 500: srcmode = mode_from_mr(bitval[bits],bitval[bitS]); ! 501: ! 502: if (srcmode == am_illg) ! 503: continue; ! 504: if (CPU_EMU_SIZE < 2 && ! 505: (srcmode == Areg || srcmode == Dreg || srcmode == Aind ! 506: || srcmode == Ad16 || srcmode == Ad8r || srcmode == Aipi ! 507: || srcmode == Apdi)) ! 508: { ! 509: srcgather = 1; srcpos = bitpos[bitS]; ! 510: } ! 511: if (opcstr[pos] == '[') { ! 512: pos++; ! 513: if (opcstr[pos] == '!') { ! 514: /* exclusion */ ! 515: do { ! 516: pos++; ! 517: if (mode_from_str(opcstr+pos) == srcmode) ! 518: goto nomatch; ! 519: pos += 4; ! 520: } while (opcstr[pos] == ','); ! 521: pos++; ! 522: } else { ! 523: if (opcstr[pos+4] == '-') { ! 524: /* replacement */ ! 525: if (mode_from_str(opcstr+pos) == srcmode) ! 526: srcmode = mode_from_str(opcstr+pos+5); ! 527: else ! 528: goto nomatch; ! 529: pos += 10; ! 530: } else { ! 531: /* normal */ ! 532: while(mode_from_str(opcstr+pos) != srcmode) { ! 533: pos += 4; ! 534: if (opcstr[pos] == ']') ! 535: goto nomatch; ! 536: pos++; ! 537: } ! 538: while(opcstr[pos] != ']') pos++; ! 539: pos++; ! 540: } ! 541: } ! 542: } ! 543: break; ! 544: default: abort(); ! 545: } ! 546: /* safety check - might have changed */ ! 547: if (srcmode != Areg && srcmode != Dreg && srcmode != Aind ! 548: && srcmode != Ad16 && srcmode != Ad8r && srcmode != Aipi ! 549: && srcmode != Apdi && srcmode != immi) ! 550: { ! 551: srcgather = 0; ! 552: } ! 553: if (srcmode == Areg && sz == sz_byte) ! 554: goto nomatch; ! 555: ! 556: if (opcstr[pos] != ',') ! 557: goto endofline; ! 558: pos++; ! 559: ! 560: /* parse the destination address */ ! 561: usedst = 1; ! 562: switch (opcstr[pos++]) { ! 563: case 'D': ! 564: destmode = Dreg; ! 565: switch (opcstr[pos++]) { ! 566: case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; ! 567: case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; ! 568: default: abort(); ! 569: } ! 570: if (dstpos < 0 || dstpos >= 32) ! 571: abort (); ! 572: break; ! 573: case 'A': ! 574: destmode = Areg; ! 575: switch (opcstr[pos++]) { ! 576: case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break; ! 577: case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break; ! 578: case 'x': destreg = 0; dstgather = 0; dstpos = 0; break; ! 579: default: abort(); ! 580: } ! 581: if (dstpos < 0 || dstpos >= 32) ! 582: abort (); ! 583: switch (opcstr[pos]) { ! 584: case 'p': destmode = Apdi; pos++; break; ! 585: case 'P': destmode = Aipi; pos++; break; ! 586: } ! 587: break; ! 588: case 'L': ! 589: destmode = absl; ! 590: break; ! 591: case '#': ! 592: switch (opcstr[pos++]) { ! 593: case 'z': destmode = imm; break; ! 594: case '0': destmode = imm0; break; ! 595: case '1': destmode = imm1; break; ! 596: case '2': destmode = imm2; break; ! 597: case 'i': destmode = immi; destreg = (uae_s32)(uae_s8)bitval[biti]; break; ! 598: case 'j': destmode = immi; destreg = bitval[bitj]; break; ! 599: case 'J': destmode = immi; destreg = bitval[bitJ]; break; ! 600: case 'k': destmode = immi; destreg = bitval[bitk]; break; ! 601: case 'K': destmode = immi; destreg = bitval[bitK]; break; ! 602: default: abort(); ! 603: } ! 604: break; ! 605: case 'd': ! 606: destreg = bitval[bitD]; ! 607: destmode = mode_from_mr(bitval[bitd],bitval[bitD]); ! 608: if (destmode == am_illg) ! 609: continue; ! 610: if (CPU_EMU_SIZE < 1 && ! 611: (destmode == Areg || destmode == Dreg || destmode == Aind ! 612: || destmode == Ad16 || destmode == Ad8r || destmode == Aipi ! 613: || destmode == Apdi)) ! 614: { ! 615: dstgather = 1; dstpos = bitpos[bitD]; ! 616: } ! 617: ! 618: if (opcstr[pos] == '[') { ! 619: pos++; ! 620: if (opcstr[pos] == '!') { ! 621: /* exclusion */ ! 622: do { ! 623: pos++; ! 624: if (mode_from_str(opcstr+pos) == destmode) ! 625: goto nomatch; ! 626: pos += 4; ! 627: } while (opcstr[pos] == ','); ! 628: pos++; ! 629: } else { ! 630: if (opcstr[pos+4] == '-') { ! 631: /* replacement */ ! 632: if (mode_from_str(opcstr+pos) == destmode) ! 633: destmode = mode_from_str(opcstr+pos+5); ! 634: else ! 635: goto nomatch; ! 636: pos += 10; ! 637: } else { ! 638: /* normal */ ! 639: while(mode_from_str(opcstr+pos) != destmode) { ! 640: pos += 4; ! 641: if (opcstr[pos] == ']') ! 642: goto nomatch; ! 643: pos++; ! 644: } ! 645: while(opcstr[pos] != ']') pos++; ! 646: pos++; ! 647: break; ! 648: } ! 649: } ! 650: } ! 651: /* Some addressing modes are invalid as destination */ ! 652: if (destmode == imm || destmode == PC16 || destmode == PC8r) ! 653: goto nomatch; ! 654: break; ! 655: case 's': ! 656: destreg = bitval[bitS]; ! 657: destmode = mode_from_mr(bitval[bits],bitval[bitS]); ! 658: ! 659: if (destmode == am_illg) ! 660: continue; ! 661: if (CPU_EMU_SIZE < 1 && ! 662: (destmode == Areg || destmode == Dreg || destmode == Aind ! 663: || destmode == Ad16 || destmode == Ad8r || destmode == Aipi ! 664: || destmode == Apdi)) ! 665: { ! 666: dstgather = 1; dstpos = bitpos[bitS]; ! 667: } ! 668: ! 669: if (opcstr[pos] == '[') { ! 670: pos++; ! 671: if (opcstr[pos] == '!') { ! 672: /* exclusion */ ! 673: do { ! 674: pos++; ! 675: if (mode_from_str(opcstr+pos) == destmode) ! 676: goto nomatch; ! 677: pos += 4; ! 678: } while (opcstr[pos] == ','); ! 679: pos++; ! 680: } else { ! 681: if (opcstr[pos+4] == '-') { ! 682: /* replacement */ ! 683: if (mode_from_str(opcstr+pos) == destmode) ! 684: destmode = mode_from_str(opcstr+pos+5); ! 685: else ! 686: goto nomatch; ! 687: pos += 10; ! 688: } else { ! 689: /* normal */ ! 690: while(mode_from_str(opcstr+pos) != destmode) { ! 691: pos += 4; ! 692: if (opcstr[pos] == ']') ! 693: goto nomatch; ! 694: pos++; ! 695: } ! 696: while(opcstr[pos] != ']') pos++; ! 697: pos++; ! 698: } ! 699: } ! 700: } ! 701: break; ! 702: default: abort(); ! 703: } ! 704: /* safety check - might have changed */ ! 705: if (destmode != Areg && destmode != Dreg && destmode != Aind ! 706: && destmode != Ad16 && destmode != Ad8r && destmode != Aipi ! 707: && destmode != Apdi) ! 708: { ! 709: dstgather = 0; ! 710: } ! 711: ! 712: if (destmode == Areg && sz == sz_byte) ! 713: goto nomatch; ! 714: #if 0 ! 715: if (sz == sz_byte && (destmode == Aipi || destmode == Apdi)) { ! 716: dstgather = 0; ! 717: } ! 718: #endif ! 719: endofline: ! 720: /* now, we have a match */ ! 721: if (table68k[opc].mnemo != i_ILLG) ! 722: ;//write_log (L"Double match: %x: %s\n", opc, opcstr); ! 723: if (find == -1) { ! 724: for (find = 0;; find++) { ! 725: if (_tcscmp (mnemonic, lookuptab[find].name) == 0) { ! 726: table68k[opc].mnemo = lookuptab[find].mnemo; ! 727: break; ! 728: } ! 729: if (_tcslen (lookuptab[find].name) == 0) ! 730: abort(); ! 731: } ! 732: } ! 733: else { ! 734: table68k[opc].mnemo = lookuptab[find].mnemo; ! 735: } ! 736: table68k[opc].cc = bitval[bitc]; ! 737: if (table68k[opc].mnemo == i_BTST ! 738: || table68k[opc].mnemo == i_BSET ! 739: || table68k[opc].mnemo == i_BCLR ! 740: || table68k[opc].mnemo == i_BCHG) ! 741: { ! 742: sz = destmode == Dreg ? sz_long : sz_byte; ! 743: } ! 744: table68k[opc].size = sz; ! 745: table68k[opc].sreg = srcreg; ! 746: table68k[opc].dreg = destreg; ! 747: table68k[opc].smode = srcmode; ! 748: table68k[opc].dmode = destmode; ! 749: table68k[opc].spos = srcgather ? srcpos : -1; ! 750: table68k[opc].dpos = dstgather ? dstpos : -1; ! 751: table68k[opc].suse = usesrc; ! 752: table68k[opc].duse = usedst; ! 753: table68k[opc].stype = srctype; ! 754: table68k[opc].plev = id.plevel; ! 755: table68k[opc].clev = specialcase(opc, id.cpulevel); ! 756: ! 757: #if 0 ! 758: for (i = 0; i < 5; i++) { ! 759: table68k[opc].flaginfo[i].flagset = id.flaginfo[i].flagset; ! 760: table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse; ! 761: } ! 762: #endif ! 763: table68k[opc].flagdead = flagdead; ! 764: table68k[opc].flaglive = flaglive; ! 765: table68k[opc].isjmp = isjmp; ! 766: nomatch: ! 767: /* FOO! */; ! 768: } ! 769: } ! 770: ! 771: ! 772: void read_table68k (void) ! 773: { ! 774: int i; ! 775: ! 776: free (table68k); ! 777: table68k = xmalloc (struct instr, 65536); ! 778: for (i = 0; i < 65536; i++) { ! 779: table68k[i].mnemo = i_ILLG; ! 780: table68k[i].handler = -1; ! 781: } ! 782: for (i = 0; i < n_defs68k; i++) { ! 783: build_insn (i); ! 784: } ! 785: } ! 786: ! 787: static int imismatch; ! 788: ! 789: static void handle_merges (long int opcode) ! 790: { ! 791: uae_u16 smsk; ! 792: uae_u16 dmsk; ! 793: int sbitdst, dstend; ! 794: int srcreg, dstreg; ! 795: ! 796: if (table68k[opcode].spos == -1) { ! 797: sbitdst = 1; smsk = 0; ! 798: } else { ! 799: switch (table68k[opcode].stype) { ! 800: case 0: ! 801: smsk = 7; sbitdst = 8; break; ! 802: case 1: ! 803: smsk = 255; sbitdst = 256; break; ! 804: case 2: ! 805: smsk = 15; sbitdst = 16; break; ! 806: case 3: ! 807: smsk = 7; sbitdst = 8; break; ! 808: case 4: ! 809: smsk = 7; sbitdst = 8; break; ! 810: case 5: ! 811: smsk = 63; sbitdst = 64; break; ! 812: case 7: ! 813: smsk = 3; sbitdst = 4; break; ! 814: default: ! 815: smsk = 0; sbitdst = 0; ! 816: abort(); ! 817: break; ! 818: } ! 819: smsk <<= table68k[opcode].spos; ! 820: } ! 821: if (table68k[opcode].dpos == -1) { ! 822: dstend = 1; dmsk = 0; ! 823: } else { ! 824: dmsk = 7 << table68k[opcode].dpos; ! 825: dstend = 8; ! 826: } ! 827: for (srcreg=0; srcreg < sbitdst; srcreg++) { ! 828: for (dstreg=0; dstreg < dstend; dstreg++) { ! 829: uae_u16 code = (uae_u16)opcode; ! 830: ! 831: code = (code & ~smsk) | (srcreg << table68k[opcode].spos); ! 832: code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos); ! 833: ! 834: /* Check whether this is in fact the same instruction. ! 835: * The instructions should never differ, except for the ! 836: * Bcc.(BW) case. */ ! 837: if (table68k[code].mnemo != table68k[opcode].mnemo ! 838: || table68k[code].size != table68k[opcode].size ! 839: || table68k[code].suse != table68k[opcode].suse ! 840: || table68k[code].duse != table68k[opcode].duse) ! 841: { ! 842: imismatch++; continue; ! 843: } ! 844: if (table68k[opcode].suse ! 845: && (table68k[opcode].spos != table68k[code].spos ! 846: || table68k[opcode].smode != table68k[code].smode ! 847: || table68k[opcode].stype != table68k[code].stype)) ! 848: { ! 849: imismatch++; continue; ! 850: } ! 851: if (table68k[opcode].duse ! 852: && (table68k[opcode].dpos != table68k[code].dpos ! 853: || table68k[opcode].dmode != table68k[code].dmode)) ! 854: { ! 855: imismatch++; continue; ! 856: } ! 857: ! 858: if (code != opcode) ! 859: table68k[code].handler = opcode; ! 860: } ! 861: } ! 862: } ! 863: ! 864: void do_merges (void) ! 865: { ! 866: long int opcode; ! 867: int nr = 0; ! 868: imismatch = 0; ! 869: for (opcode = 0; opcode < 65536; opcode++) { ! 870: if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG) ! 871: continue; ! 872: nr++; ! 873: handle_merges (opcode); ! 874: } ! 875: nr_cpuop_funcs = nr; ! 876: } ! 877: ! 878: int get_no_mismatches (void) ! 879: { ! 880: return imismatch; ! 881: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.