|
|
1.1 ! root 1: ! 2: #include <stdio.h> ! 3: #include <stdlib.h> ! 4: #include <string.h> ! 5: #include <stdarg.h> ! 6: ! 7: static int end; ! 8: static int base = 0x1c; ! 9: static unsigned char *buffer; ! 10: static int buf_pos = 0; ! 11: static unsigned short *labels; ! 12: static int pass = 1; ! 13: static unsigned char *probs; ! 14: static enum GUESSMODE { ! 15: GUESS_NONE, ! 16: GUESS_SIMPLE, ! 17: GUESS_WALK ! 18: } guessmode; ! 19: ! 20: static int walk_stack[1024]; ! 21: static int *ws_top = &walk_stack[0]; ! 22: ! 23: #define PUSH_WS(pos) do { ws_top++; *ws_top = (pos); } while (0); ! 24: #define POP_WS() (*(ws_top--)) ! 25: ! 26: /* label flags */ ! 27: #define F_LABEL (1<<0) ! 28: #define F_USELAB (1<<1) ! 29: #define F_DUNNO (1<<2) ! 30: #define F_GUESS_DATA (1<<3) ! 31: #define F_GUESS_STRING (1<<4) ! 32: #define F_WALKED_CODE (1<<5) ! 33: #define F_CODE_STOP (1<<6) ! 34: #define F_LABEL_TABLE (1<<7) ! 35: #define F_LABEL_MAJOR (1<<8) ! 36: ! 37: static void output (const char *format, ...) ! 38: { ! 39: va_list argptr; ! 40: ! 41: if (pass == 1) return; ! 42: va_start (argptr, format); ! 43: vprintf (format, argptr); ! 44: va_end (argptr); ! 45: } ! 46: ! 47: static void output_lab (int adr) ! 48: { ! 49: if (labels[adr] & F_LABEL_MAJOR) output ("L%x", adr); ! 50: else output ("l%x", adr); ! 51: } ! 52: ! 53: unsigned char rd_byte(void) ! 54: { ! 55: return buffer[buf_pos++]; ! 56: } ! 57: ! 58: short rd_short(void) ! 59: { ! 60: short t1, t2; ! 61: t1 = rd_byte(); ! 62: t2 = rd_byte(); ! 63: return ((t1 << 8) | t2); ! 64: } ! 65: ! 66: int rd_int(void) ! 67: { ! 68: short t1, t2, t3, t4; ! 69: t1 = rd_byte(); ! 70: t2 = rd_byte(); ! 71: t3 = rd_byte(); ! 72: t4 = rd_byte(); ! 73: return ((t1 << 24) | (t2 << 16) | (t3 << 8) | t4); ! 74: } ! 75: ! 76: void wr_byte(unsigned char x) ! 77: { ! 78: buffer [buf_pos++] = x; ! 79: } ! 80: ! 81: void wr_short(short x) ! 82: { ! 83: wr_byte((unsigned char)((x>>8) & 0xff)); ! 84: wr_byte((unsigned char)(x & 0xff)); ! 85: } ! 86: ! 87: void wr_int(int x) ! 88: { ! 89: wr_byte((unsigned char)((x>>24) & 0xff)); ! 90: wr_byte((unsigned char)((x>>16) & 0xff)); ! 91: wr_byte((unsigned char)((x>>8) & 0xff)); ! 92: wr_byte((unsigned char)(x & 0xff)); ! 93: } ! 94: ! 95: const char *size_str[4] = { ".b", ".w", ".l", ".?" }; ! 96: /* to convert weird move sizes to standard sizes */ ! 97: const int move_size[4] = { 3, 0, 2, 1 }; ! 98: const char *Bcc_str[16] = { ! 99: NULL,NULL,"hi","ls","cc","cs","ne","eq", ! 100: "vc","vs","pl","mi","ge","lt","gt","le" ! 101: }; ! 102: ! 103: const char *DBcc_str[16] = { ! 104: "t","ra","hi","ls","cc","cs","ne","eq", ! 105: "vc","vs","pl","mi","ge","lt","gt","le" ! 106: }; ! 107: ! 108: const char *Scc_str[16] = { ! 109: "t","f","hi","ls","cc","cs","ne","eq", ! 110: "vc","vs","pl","mi","ge","lt","gt","le" ! 111: }; ! 112: ! 113: typedef union Opcode { ! 114: unsigned short code; ! 115: struct move { ! 116: uint src_reg : 3; ! 117: uint src_mode : 3; ! 118: uint dest_mode : 3; ! 119: uint dest_reg : 3; ! 120: uint size : 2; ! 121: uint op : 2; ! 122: } move; ! 123: struct adr_index { ! 124: int displacement : 8; ! 125: uint zeros : 3; ! 126: uint ind_size : 1; ! 127: uint reg : 3; ! 128: uint reg_type : 1; ! 129: } adr_index; ! 130: struct addq { ! 131: uint dest_reg : 3; ! 132: uint dest_mode : 3; ! 133: uint size : 2; ! 134: uint issub : 1; ! 135: uint data : 3; ! 136: uint op : 4; ! 137: } addq; ! 138: struct jmp { ! 139: uint dest_reg : 3; ! 140: uint dest_mode : 3; ! 141: uint op : 10; ! 142: } jmp; ! 143: struct addi { ! 144: uint dest_reg : 3; ! 145: uint dest_mode : 3; ! 146: uint size : 2; ! 147: uint OP6 : 8; ! 148: } addi; ! 149: /* size and effective address */ ! 150: struct type1 { ! 151: uint ea_reg : 3; ! 152: uint ea_mode : 3; ! 153: uint size : 2; ! 154: uint op : 8; ! 155: } type1; ! 156: /* reg, opmode, ea */ ! 157: struct type2 { ! 158: uint ea_reg : 3; ! 159: uint ea_mode : 3; ! 160: uint op_mode : 3; ! 161: uint reg : 3; ! 162: uint op : 4; ! 163: } type2; ! 164: struct MemShift { ! 165: uint ea_reg : 3; ! 166: uint ea_mode : 3; ! 167: uint OP3 : 2; ! 168: uint dr : 1; ! 169: uint type : 2; ! 170: uint OP0x1c : 5; ! 171: } MemShift; ! 172: struct ASx { ! 173: uint reg : 3; ! 174: uint OP0 : 2; ! 175: uint ir : 1; ! 176: uint size : 2; ! 177: uint dr : 1; ! 178: uint count_reg : 3; ! 179: uint OP0xe : 4; ! 180: } ASx; ! 181: struct abcd { ! 182: uint src_reg : 3; ! 183: uint rm : 1; ! 184: uint OP16 : 5; ! 185: uint dest_reg : 3; ! 186: uint OP12 : 4; ! 187: } abcd; ! 188: struct addx { ! 189: uint src_reg : 3; ! 190: uint rm : 1; ! 191: uint OP0 : 2; ! 192: uint size : 2; ! 193: uint OP1 : 1; ! 194: uint dest_reg : 3; ! 195: uint op : 4; ! 196: } addx; ! 197: struct cmpm { ! 198: uint src_reg : 3; ! 199: uint OP1_1 : 3; ! 200: uint size : 2; ! 201: uint OP2_1 : 1; ! 202: uint dest_reg : 3; ! 203: uint OP0xb : 4; ! 204: } cmpm; ! 205: /* branches */ ! 206: struct DBcc { ! 207: uint reg : 3; ! 208: uint OP25 : 5; ! 209: uint cond : 4; ! 210: uint OP5 : 4; ! 211: } DBcc; ! 212: struct Bcc { ! 213: int displacement : 8; ! 214: uint cond : 4; ! 215: uint op : 4; ! 216: } Bcc; ! 217: struct bra { ! 218: int displacement : 8; ! 219: uint op : 8; ! 220: } bra; ! 221: struct movem { ! 222: uint dest_reg : 3; ! 223: uint dest_mode : 3; ! 224: uint sz : 1; ! 225: uint ONE : 3; ! 226: uint dr : 1; ! 227: uint NINE : 5; ! 228: } movem; ! 229: struct lea { ! 230: uint dest_reg : 3; ! 231: uint dest_mode : 3; ! 232: uint SEVEN : 3; ! 233: uint reg : 3; ! 234: uint FOUR : 4; ! 235: } lea; ! 236: struct moveq { ! 237: int data : 8; ! 238: uint ZERO : 1; ! 239: uint reg : 3; ! 240: uint SEVEN : 4; ! 241: } moveq; ! 242: struct exg { ! 243: uint dest_reg : 3; ! 244: uint op_mode : 5; ! 245: uint OP1 : 1; ! 246: uint src_reg : 3; ! 247: uint OP0xc : 4; ! 248: } exg; ! 249: } Opcode; ! 250: ! 251: /* ! 252: * Skip size is used when there is immediate data, for addressing ! 253: * modes $addr(Ax,Dy.s), and the PC flavoured version of that. ! 254: * The immediate data comes first and must be skipped ! 255: */ ! 256: int is_adrmod (int mode, int reg, int op_size, int skip_size) ! 257: { ! 258: Opcode ext; ! 259: switch (skip_size) { ! 260: case -1: skip_size = 0; break; ! 261: case 0: case 1: skip_size = 2; break; ! 262: default: skip_size = 4; break; ! 263: } ! 264: switch (mode) { ! 265: case 0: case 1: case 2: case 3: case 4: ! 266: return 1; ! 267: case 5: return 1; ! 268: case 6: buf_pos += skip_size; ! 269: ext.code = rd_short (); ! 270: buf_pos -= 2 + skip_size; ! 271: if (ext.adr_index.zeros != 0) return 0; ! 272: else return 1; ! 273: case 7: ! 274: switch (reg) { ! 275: case 0: return 1; ! 276: case 1: return 1; ! 277: case 4: ! 278: if (op_size == 0) { ! 279: if (rd_byte () != 0) { ! 280: buf_pos--; ! 281: return 0; ! 282: } ! 283: buf_pos--; ! 284: return 1; ! 285: } else if (op_size == 2) { ! 286: if (buf_pos <= end-4) return 1; ! 287: else return 0; ! 288: } else if (op_size == 1) { ! 289: if (buf_pos <= end-2) return 1; ! 290: else return 0; ! 291: } else { ! 292: return 0; ! 293: } ! 294: break; ! 295: case 2: ! 296: if (buf_pos <= end-2) return 1; ! 297: else return 0; ! 298: case 3: buf_pos += skip_size; ! 299: ext.code = rd_short (); ! 300: buf_pos -= 2 + skip_size; ! 301: if (ext.adr_index.zeros != 0) return 0; ! 302: else return 1; ! 303: default: ! 304: return 0; ! 305: } ! 306: break; ! 307: default: ! 308: return 0; ! 309: } ! 310: ! 311: } ! 312: ! 313: /* returns abs address if possible or 0xdeadbeef if not */ ! 314: uint put_adrmod (int mode, int reg, int op_size) ! 315: { ! 316: uint temp; ! 317: Opcode ext; ! 318: switch (mode) { ! 319: case 0: output ("d%d", reg); break; ! 320: case 1: output ("a%d", reg); break; ! 321: case 2: output ("(a%d)", reg); break; ! 322: case 3: output ("(a%d)+", reg); break; ! 323: case 4: output ("-(a%d)", reg); break; ! 324: case 5: output ("%hd(a%d)", rd_short(), reg); break; ! 325: case 6: ext.code = rd_short (); ! 326: if (ext.adr_index.zeros != 0) output ("???"); ! 327: output ("%hd(a%d,", ext.adr_index.displacement, reg); ! 328: if (ext.adr_index.reg_type) { ! 329: output ("a%d", ext.adr_index.reg); ! 330: } else { ! 331: output ("d%d", ext.adr_index.reg); ! 332: } ! 333: if (ext.adr_index.ind_size) { ! 334: output (".l)"); ! 335: } else { ! 336: output (".w)"); ! 337: } ! 338: break; ! 339: case 7: ! 340: switch (reg) { ! 341: case 0: output ("$%hx.w", rd_short()); break; ! 342: case 1: temp = rd_int (); ! 343: if (labels[buf_pos-4] & F_USELAB) output_lab (temp); ! 344: else output ("$%x.l", temp); ! 345: return temp; ! 346: case 4: ! 347: if (op_size == 0) { ! 348: if (rd_byte () != 0) output ("???"); ! 349: output ("#$%x", rd_byte ()); ! 350: } else if (op_size == 2) { ! 351: output ("#"); ! 352: if (labels[buf_pos] & F_USELAB) output_lab (rd_int ()); ! 353: else output ("$%x", rd_int ()); ! 354: } else if (op_size == 1) { ! 355: output ("#$%hx", rd_short ()); ! 356: } else { ! 357: output ("#???"); ! 358: } ! 359: break; ! 360: case 2: ! 361: temp = buf_pos; ! 362: temp += rd_short (); ! 363: labels [temp] |= F_LABEL | F_LABEL_MAJOR; ! 364: output_lab (temp); ! 365: output ("(pc)"); ! 366: return temp; ! 367: case 3: temp = buf_pos; ! 368: ext.code = rd_short (); ! 369: if (ext.adr_index.zeros != 0) output ("???"); ! 370: labels [temp + ext.adr_index.displacement] |= F_LABEL | F_LABEL_MAJOR; ! 371: output_lab (temp + ext.adr_index.displacement); ! 372: if (ext.adr_index.reg_type) { ! 373: output ("(pc,a%d", ext.adr_index.reg); ! 374: } else { ! 375: output ("(pc,d%d", ext.adr_index.reg); ! 376: } ! 377: if (ext.adr_index.ind_size) { ! 378: output (".l)"); ! 379: } else { ! 380: output (".w)"); ! 381: } ! 382: break; ! 383: default: ! 384: output ("???"); break; ! 385: } ! 386: break; ! 387: default: ! 388: output ("???"); break; ! 389: } ! 390: return 0xdeadbeef; ! 391: } ! 392: ! 393: void aux_put_movem_regs (int mode, int low, int high) ! 394: { ! 395: if (!mode) { ! 396: /* (Ax)+ and control modes */ ! 397: if (low < 8) { ! 398: if (low == high) { ! 399: output ("d%d", low); ! 400: return; ! 401: } ! 402: if (high >7) { ! 403: if (low == 7) output ("d7/"); ! 404: else output ("d%d-7/", low); ! 405: } else { ! 406: output ("d%d-%d", low, high); ! 407: return; ! 408: } ! 409: } ! 410: if (high > 7) { ! 411: if (low == high) { ! 412: output ("a%d", low-8); ! 413: return; ! 414: } ! 415: if (low > 7) { ! 416: output ("a%d-%d", low-8, high-8); ! 417: } else { ! 418: if (high == 8) output ("a0"); ! 419: else output ("a0-%d", high-8); ! 420: } ! 421: } ! 422: } else { ! 423: /* -(Ax) mode */ ! 424: if (high > 7) { ! 425: if (low == high) { ! 426: output ("d%d", 15-low); ! 427: return; ! 428: } ! 429: if (low > 7) { ! 430: output ("d%d-%d", 15-high, 15-low); ! 431: return; ! 432: } else { ! 433: if (high == 8) output ("d7/"); ! 434: else output ("d%d-7/", 15-high); ! 435: } ! 436: } ! 437: if (low < 8) { ! 438: if (low == high) { ! 439: output ("a%d", 7-low); ! 440: return; ! 441: } ! 442: if (high >7) { ! 443: if (low == 7) output ("a0"); ! 444: else output ("a0-%d", 7-low); ! 445: } else { ! 446: output ("a%d-%d", 7-high, 7-low); ! 447: } ! 448: } ! 449: } ! 450: } ! 451: ! 452: void put_movem_regs (int mask, int mode) ! 453: { ! 454: int start; ! 455: int pos; ! 456: int pixie = 0; ! 457: ! 458: start = -1; ! 459: for (pos=0; pos < 16; pos++) { ! 460: if ((mask & (1<<pos)) && (start == -1)) start = pos; ! 461: else if ((!(mask & (1<<pos))) && (start != -1)) { ! 462: if (pixie) output ("/"); ! 463: else pixie = 1; ! 464: aux_put_movem_regs (mode, start, pos-1); ! 465: start = -1; ! 466: } ! 467: } ! 468: if (mask & (1<<15)) { ! 469: if (pixie) output ("/"); ! 470: else pixie = 1; ! 471: aux_put_movem_regs (mode, start, pos-1); ! 472: start = -1; ! 473: } ! 474: } ! 475: ! 476: void put_imm (int size) ! 477: { ! 478: if (size == 0) { ! 479: rd_byte (); ! 480: output ("#$%x", (int)rd_byte ()); ! 481: } else if (size == 1) { ! 482: output ("#$%hx", (int)rd_short ()); ! 483: } else { ! 484: output ("#$%x", (int)rd_int ()); ! 485: } ! 486: } ! 487: ! 488: #define is_valid_branch(dest) (((dest) >= base) && ((dest < end))) ! 489: ! 490: static void dump_code () ! 491: { ! 492: Opcode op; ! 493: int size; ! 494: int temp; ! 495: const char *str; ! 496: int last_ip; ! 497: ! 498: //output ("\topt\te-\r\n"); ! 499: ! 500: while (buf_pos < end) { ! 501: if ((guessmode == GUESS_WALK) && (pass == 1)) { ! 502: if (labels[buf_pos] & (F_WALKED_CODE | F_CODE_STOP)) { ! 503: buf_pos = POP_WS (); ! 504: continue; ! 505: } ! 506: } ! 507: if (labels[buf_pos] & F_LABEL) { ! 508: if (guessmode == GUESS_SIMPLE) output ("\r\n* data guess rate %d", probs[buf_pos]); ! 509: if (labels[buf_pos] & F_LABEL_MAJOR) { ! 510: output ("\r\n\r\n"); ! 511: output_lab (buf_pos); ! 512: output (":\r\n\t\t"); ! 513: } else { ! 514: output ("\r\n\t"); ! 515: output_lab (buf_pos); ! 516: output (":\t"); ! 517: } ! 518: } else { ! 519: //output ("\r\n_%x:\t\t", buf_pos); ! 520: output ("\r\n\t\t"); ! 521: } ! 522: if (labels[buf_pos] & F_LABEL_TABLE) { ! 523: /* contains fixedup label */ ! 524: temp = rd_int (); ! 525: output ("dc.l\t"); ! 526: output_lab (temp); ! 527: if (!(labels[temp] & F_LABEL)) fprintf (stderr, "Error, Label table entry at 0x%x isn't a label address.\n", buf_pos-4); ! 528: continue; ! 529: } ! 530: if (labels[buf_pos] & F_GUESS_STRING) { ! 531: output ("dc.b\t\""); ! 532: size = 0; ! 533: do { ! 534: temp = rd_byte (); ! 535: if (temp == '"') output ("%c%c", temp, temp); ! 536: else output ("%c", temp); ! 537: if (size++ == 70) break; ! 538: } while ((labels[buf_pos] & F_GUESS_STRING) && (!(labels[buf_pos] & F_LABEL))); ! 539: output ("\""); ! 540: continue; ! 541: } ! 542: if (labels[buf_pos] & F_GUESS_DATA) { ! 543: /* make ds.b if possible */ ! 544: temp = 0; ! 545: last_ip = buf_pos; ! 546: while (rd_byte () == 0) { ! 547: temp++; ! 548: if (labels[buf_pos] & F_LABEL) break; ! 549: else if (labels[buf_pos] & F_WALKED_CODE) break; ! 550: else if (!(labels[buf_pos] & F_GUESS_DATA)) break; ! 551: else if (labels[buf_pos] & F_GUESS_STRING) break; ! 552: } ! 553: if (temp >= 4) { ! 554: output ("ds.b\t%d", temp); ! 555: /* stopped because of an end to zeros */ ! 556: buf_pos--; ! 557: if (rd_byte () != 0) buf_pos--; ! 558: continue; ! 559: } ! 560: buf_pos = last_ip; ! 561: output ("dc.b\t"); ! 562: for (temp = 0; temp<16; temp++) { ! 563: if (temp) output (","); ! 564: output ("$%x", rd_byte ()); ! 565: if (labels[buf_pos] & F_LABEL) break; ! 566: else if (labels[buf_pos] & F_WALKED_CODE) break; ! 567: else if (!(labels[buf_pos] & F_GUESS_DATA)) break; ! 568: else if (labels[buf_pos] & F_GUESS_STRING) break; ! 569: } ! 570: continue; ! 571: } ! 572: last_ip = buf_pos; ! 573: op.code = rd_short (); ! 574: /* ABCD/SBCD */ ! 575: while (op.abcd.OP16 == 16) { ! 576: if (op.abcd.OP12 == 12) output ("abcd\t"); ! 577: else if (op.abcd.OP12 == 8) output ("sbcd\t"); ! 578: else break; ! 579: if (op.abcd.rm) { ! 580: output ("-(a%d),-(a%d)", op.abcd.src_reg, op.abcd.dest_reg); ! 581: } else { ! 582: output ("d%d,d%d", op.abcd.src_reg, op.abcd.dest_reg); ! 583: } ! 584: goto done; ! 585: } ! 586: /* ADD/SUB */ ! 587: while ((op.type2.op == 0xd) || (op.type2.op == 0x9)) { ! 588: if (op.type2.op == 0xd) str = "add"; ! 589: else str = "sub"; ! 590: if (op.type2.op_mode == 3) { ! 591: /* ADDA.W */ ! 592: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break; ! 593: output ("%sa.w\t", str); ! 594: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1); ! 595: output (",a%d", op.type2.reg); ! 596: } ! 597: else if (op.type2.op_mode == 7) { ! 598: /* ADDA.L */ ! 599: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2, -1)) break; ! 600: output ("%sa.l\t", str); ! 601: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2); ! 602: output (",a%d", op.type2.reg); ! 603: } ! 604: else if (op.type2.op_mode < 3) { ! 605: /* dest is reg */ ! 606: /* no .b size Ax sources */ ! 607: if ((op.type2.op_mode == 0) && (op.type2.ea_mode == 0x1)) break; ! 608: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode, -1)) break; ! 609: output ("%s%s\t", str, size_str[op.type2.op_mode]); ! 610: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode); ! 611: output (",d%d", op.type2.reg); ! 612: } else { ! 613: /* dest is ea */ ! 614: if (op.type2.ea_mode == 0x0) break; ! 615: if (op.type2.ea_mode == 0x1) break; ! 616: if (op.type2.ea_mode == 0x7) { ! 617: if ((op.type2.ea_reg == 2) || ! 618: (op.type2.ea_reg == 3) || ! 619: (op.type2.ea_reg == 4)) break; ! 620: } ! 621: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4, -1)) break; ! 622: output ("%s%s\t", str, size_str[op.type2.op_mode-4]); ! 623: output ("d%d,", op.type2.reg); ! 624: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4); ! 625: } ! 626: goto done; ! 627: } ! 628: /* ADDI/SUBI */ ! 629: while ((op.addi.OP6 == 6) || (op.addi.OP6 == 4)) { ! 630: if (op.addi.size == 3) break; ! 631: if (op.addi.dest_mode == 0x1) break; ! 632: if (op.addi.dest_mode == 0x7) { ! 633: if ((op.addi.dest_reg == 2) || ! 634: (op.addi.dest_reg == 3) || ! 635: (op.addi.dest_reg == 4)) break; ! 636: } ! 637: if (!is_adrmod (op.addi.dest_mode, op.addi.dest_reg, op.addi.size, op.addi.size)) break; ! 638: if (op.addi.OP6 == 6) output ("addi%s\t", size_str[op.addi.size]); ! 639: else output ("subi%s\t", size_str[op.addi.size]); ! 640: put_imm (op.addi.size); ! 641: output (","); ! 642: put_adrmod (op.addi.dest_mode, op.addi.dest_reg, op.addi.size); ! 643: goto done; ! 644: } ! 645: /* ADDQ/SUBQ */ ! 646: while (op.addq.op == 0x5) { ! 647: if (op.addq.size == 3) break; ! 648: /* no immediate or pc relative dest */ ! 649: if (op.addq.dest_mode == 0x7) { ! 650: if (op.addq.dest_reg > 0x1) break; ! 651: } ! 652: /* no addq.b to address registers */ ! 653: if ((op.addq.size == 0) && (op.addq.dest_mode == 1)) break; ! 654: if (!is_adrmod (op.addq.dest_mode, op.addq.dest_reg, op.addq.size, -1)) break; ! 655: if (op.addq.issub) output ("subq%s\t", size_str[op.addq.size]); ! 656: else output ("addq%s\t", size_str[op.addq.size]); ! 657: output ("#%d,", (op.addq.data == 0 ? 8 : op.addq.data)); ! 658: put_adrmod (op.addq.dest_mode, op.addq.dest_reg, op.addq.size); ! 659: goto done; ! 660: } ! 661: /* ADDX/SUBX */ ! 662: while (((op.addx.op == 0xd) || (op.addx.op == 0x9)) && (op.addx.OP1 == 1) && (op.addx.OP0 == 0)) { ! 663: if (op.addx.size == 3) break; ! 664: if (op.addx.op == 0xd) output ("addx%s\t", size_str[op.addx.size]); ! 665: else output ("subx%s\t", size_str[op.addx.size]); ! 666: if (op.addx.rm) { ! 667: /* memory to memory */ ! 668: output ("-(a%d),-(a%d)", op.addx.src_reg, op.addx.dest_reg); ! 669: } else { ! 670: output ("d%d,d%d", op.addx.src_reg, op.addx.dest_reg); ! 671: } ! 672: ! 673: goto done; ! 674: } ! 675: /* AND/OR */ ! 676: while ((op.type2.op == 0xc) || (op.type2.op == 0x8)) { ! 677: if (op.type2.op_mode == 3) break; ! 678: if (op.type2.op_mode == 7) break; ! 679: if (op.type2.op == 0xc) str = "and"; ! 680: else str = "or"; ! 681: if (op.type2.op_mode < 3) { ! 682: /* dest is reg */ ! 683: if (op.type2.ea_mode == 0x1) break; ! 684: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode, -1)) break; ! 685: output ("%s%s\t", str, size_str[op.type2.op_mode]); ! 686: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode); ! 687: output (",d%d", op.type2.reg); ! 688: } else { ! 689: /* dest is ea */ ! 690: if (op.type2.ea_mode == 0x0) break; ! 691: if (op.type2.ea_mode == 0x1) break; ! 692: if (op.type2.ea_mode == 0x7) { ! 693: if (op.type2.ea_reg > 1) break; ! 694: } ! 695: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4, -1)) break; ! 696: output ("%s%s\t", str, size_str[op.type2.op_mode-4]); ! 697: output ("d%d,", op.type2.reg); ! 698: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4); ! 699: } ! 700: goto done; ! 701: } ! 702: /* ANDI/EORI/ORI */ ! 703: while ((op.type1.op == 0x02) || (op.type1.op == 0xa) || (op.type1.op == 0x0)) { ! 704: /* ori.b #0,d0 is 0x0 longword and also a nop. it tends to ! 705: * be data rather than code */ ! 706: if (op.code == 0x0) { ! 707: if (rd_short () == 0) { ! 708: buf_pos -= 2; ! 709: labels[buf_pos-2] |= F_DUNNO; ! 710: labels[buf_pos-1] |= F_DUNNO; ! 711: break; ! 712: } else { ! 713: buf_pos -= 2; ! 714: } ! 715: } ! 716: ! 717: if (op.type1.size == 3) break; ! 718: /* no address reg direct */ ! 719: if (op.type1.ea_mode == 0x1) break; ! 720: /* no immediate or pc relative dest */ ! 721: if (op.type1.ea_mode == 0x7) { ! 722: if (op.type1.ea_reg > 0x1) break; ! 723: } ! 724: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, op.type1.size)) break; ! 725: if (op.type1.op == 0x2) output ("andi%s\t", size_str[op.type1.size]); ! 726: else if (op.type1.op == 0xa) output ("eori%s\t", size_str[op.type1.size]); ! 727: else output ("ori%s\t", size_str[op.type1.size]); ! 728: put_imm (op.addi.size); ! 729: output (","); ! 730: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size); ! 731: goto done; ! 732: } ! 733: /* ANDI to CCR */ ! 734: while (op.code == 0x023c) { ! 735: rd_byte (); ! 736: output ("andi\t#$%x,ccr", rd_byte ()); ! 737: goto done; ! 738: } ! 739: /* ANDI to SR */ ! 740: while (op.code == 0x027c) { ! 741: output ("andi\t#$%hx,sr", rd_short ()); ! 742: goto done; ! 743: } ! 744: /* ASx/LSx reg/imm */ ! 745: while (op.ASx.OP0xe == 0xe) { ! 746: if (op.ASx.size == 3) break; ! 747: switch (op.ASx.OP0) { ! 748: case 0: str = "as"; break; ! 749: case 1: str = "ls"; break; ! 750: case 2: str = "rox"; break; ! 751: default: case 3: str = "ro"; break; ! 752: } ! 753: if (op.ASx.ir) { ! 754: /* data register shift */ ! 755: output ("%s%c%s\td%d,d%d", str, ! 756: (op.ASx.dr ? 'l' : 'r'), ! 757: size_str[op.ASx.size], ! 758: op.ASx.count_reg, op.ASx.reg); ! 759: } else { ! 760: /* count shift thingy */ ! 761: output ("%s%c%s\t#%d,d%d", str, ! 762: (op.ASx.dr ? 'l' : 'r'), ! 763: size_str[op.ASx.size], ! 764: (op.ASx.count_reg == 0 ? 8 : op.ASx.count_reg), ! 765: op.ASx.reg); ! 766: } ! 767: goto done; ! 768: } ! 769: /* ASx/LSx memory shift */ ! 770: while ((op.MemShift.OP3 == 3) && (op.MemShift.OP0x1c == 0x1c)) { ! 771: if (op.type1.ea_mode < 0x2) break; ! 772: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break; ! 773: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break; ! 774: switch (op.MemShift.type) { ! 775: case 0: str = "as"; break; ! 776: case 1: str = "ls"; break; ! 777: case 2: str = "rox"; break; ! 778: default: case 3: str = "ro"; break; ! 779: } ! 780: output ("%s%c.w\t", str, (op.ASx.dr ? 'l' : 'r')); ! 781: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1); ! 782: goto done; ! 783: } ! 784: /* Bcc */ ! 785: while (op.Bcc.op == 0x6) { ! 786: if (Bcc_str [op.Bcc.cond] == NULL) break; ! 787: if (op.bra.displacement) { ! 788: temp = buf_pos + op.Bcc.displacement; ! 789: if (!is_valid_branch(temp)) break; ! 790: output ("b%s.s\t", Bcc_str[op.Bcc.cond]); ! 791: output_lab (temp); ! 792: } else { ! 793: temp = buf_pos; ! 794: temp += rd_short (); ! 795: if (!is_valid_branch(temp)) break; ! 796: output ("b%s.w\t", Bcc_str[op.Bcc.cond]); ! 797: output_lab (temp); ! 798: } ! 799: labels [temp] |= F_LABEL; ! 800: if ((guessmode == GUESS_WALK) && (pass == 1)) PUSH_WS (temp); ! 801: goto done; ! 802: } ! 803: /* BRA */ ! 804: while (op.bra.op == 0x60) { ! 805: if (op.bra.displacement) { ! 806: temp = buf_pos + op.bra.displacement; ! 807: if (!is_valid_branch(temp)) break; ! 808: output ("bra.s\t"); ! 809: output_lab (temp); ! 810: labels [temp] |= F_LABEL; ! 811: } else { ! 812: temp = buf_pos; ! 813: temp += rd_short (); ! 814: if (!is_valid_branch(temp)) break; ! 815: output ("bra.w\t"); ! 816: output_lab (temp); ! 817: labels [temp] |= F_LABEL | F_LABEL_MAJOR; ! 818: } ! 819: if ((guessmode == GUESS_WALK) && (pass == 1)) buf_pos = temp; ! 820: goto done; ! 821: } ! 822: /* BSR */ ! 823: while ((op.code & 0xff00) == 0x6100) { ! 824: if (op.bra.displacement) { ! 825: temp = buf_pos + op.bra.displacement; ! 826: if (!is_valid_branch(temp)) break; ! 827: output ("bsr.s\t"); ! 828: output_lab (temp); ! 829: } else { ! 830: temp = buf_pos; ! 831: temp += rd_short (); ! 832: if (!is_valid_branch(temp)) break; ! 833: output ("bsr.w\t"); ! 834: output_lab (temp); ! 835: } ! 836: labels [temp] |= F_LABEL | F_LABEL_MAJOR; ! 837: if ((guessmode == GUESS_WALK) && (pass == 1)) PUSH_WS (temp); ! 838: goto done; ! 839: } ! 840: /* BCHG/BCLR/BSET/BTST (Dn,ea) */ ! 841: while ((op.type2.op == 0) && ((op.type2.op_mode == 0x4) || (op.type2.op_mode == 0x5) || (op.type2.op_mode == 0x6) || (op.type2.op_mode == 0x7))) { ! 842: if (op.type2.ea_mode == 0x1) break; ! 843: if ((op.type2.op_mode != 0x4) && (op.type2.ea_mode == 0x7)) { ! 844: if (op.type2.ea_reg > 1) break; ! 845: } ! 846: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2, -1)) break; ! 847: ! 848: if (op.type2.op_mode == 0x4) output ("btst\t"); ! 849: else if (op.type2.op_mode == 0x5) output ("bchg\t"); ! 850: else if (op.type2.op_mode == 0x6) output ("bclr\t"); ! 851: else output ("bset\t"); ! 852: output ("d%d,", op.type2.reg); ! 853: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2); ! 854: goto done; ! 855: } ! 856: /* BCHG/BCLR/BSET (#<data>,ea) */ ! 857: while ((op.type2.op == 0) && (op.type2.reg == 4) && ! 858: ((op.type2.op_mode == 0) || (op.type2.op_mode == 1) || (op.type2.op_mode == 2) || (op.type2.op_mode == 3))) { ! 859: if (op.type2.ea_mode == 0x1) break; ! 860: if ((op.type2.ea_mode == 0x7) && (op.type2.ea_reg > 1)) break; ! 861: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2, 1)) break; ! 862: temp = rd_byte (); ! 863: if (temp != 0) { ! 864: buf_pos--; ! 865: break; ! 866: } ! 867: if (op.type2.op_mode == 0) { ! 868: output ("btst\t"); ! 869: } else if (op.type2.op_mode == 1) { ! 870: output ("bchg\t"); ! 871: } else if (op.type2.op_mode == 2) { ! 872: output ("bclr\t"); ! 873: } else { ! 874: output ("bset\t"); ! 875: } ! 876: output ("#$%x,", (int)rd_byte ()); ! 877: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2); ! 878: goto done; ! 879: } ! 880: /* BKPT */ ! 881: /*while ((op.code & 0xfff8) == 0x4848) { ! 882: output ("bkpt\t#%d", op.code & 0x7); ! 883: goto done; ! 884: }*/ ! 885: /* CHK */ ! 886: while ((op.type2.op == 0x4) && (op.type2.op_mode == 0x6)) { ! 887: /* no address reg direct */ ! 888: if (op.type2.ea_mode == 0x1) break; ! 889: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break; ! 890: ! 891: output ("chk\t"); ! 892: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1); ! 893: output (",d%d", op.type2.reg); ! 894: ! 895: goto done; ! 896: } ! 897: /* CLR */ ! 898: while (op.type1.op == 0x42) { ! 899: if (op.type1.size == 3) break; ! 900: /* no address reg direct */ ! 901: if (op.type1.ea_mode == 0x1) break; ! 902: /* no immediate or pc relative dest */ ! 903: if (op.type1.ea_mode == 0x7) { ! 904: if (op.type1.ea_reg > 0x1) break; ! 905: } ! 906: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break; ! 907: output ("clr%s\t", size_str[op.type1.size]); ! 908: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size); ! 909: goto done; ! 910: } ! 911: /* CMP */ ! 912: while (op.type2.op == 11) { ! 913: if (op.type2.op_mode > 2) break; ! 914: /* no .b size for adr reg direct */ ! 915: if ((op.type2.op_mode == 0) && (op.type2.ea_mode == 0x1)) break; ! 916: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode, -1)) break; ! 917: output ("cmp%s\t", size_str[op.type2.op_mode]); ! 918: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode); ! 919: output (",d%d", op.type2.reg); ! 920: goto done; ! 921: } ! 922: /* CMPA */ ! 923: while (op.type2.op == 11) { ! 924: if ((op.type2.op_mode != 0x3) && (op.type2.op_mode != 0x7)) break; ! 925: if (op.type2.op_mode == 0x3) size = 1; ! 926: else size = 2; ! 927: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, size, -1)) break; ! 928: output ("cmpa%s\t", size_str [size]); ! 929: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, size); ! 930: output (",a%d", op.type2.reg); ! 931: goto done; ! 932: } ! 933: /* CMPI */ ! 934: while ((op.type1.op == 0x0c) && (op.type1.size != 0x3)) { ! 935: if (op.type1.ea_mode == 0x1) break; ! 936: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break; ! 937: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, op.type1.size)) break; ! 938: output ("cmpi%s\t", size_str [op.type1.size]); ! 939: put_imm (op.type1.size); ! 940: output (","); ! 941: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size); ! 942: goto done; ! 943: } ! 944: /* CMPM */ ! 945: while ((op.cmpm.OP0xb == 0xb) && (op.cmpm.OP2_1 == 0x1) && (op.cmpm.OP1_1 == 0x1)) { ! 946: if (op.cmpm.size == 3) break; ! 947: output ("cmpm%s\t(a%d)+,(a%d)+", size_str [op.cmpm.size], op.cmpm.src_reg, op.cmpm.dest_reg); ! 948: goto done; ! 949: } ! 950: /* DBcc */ ! 951: while ((op.DBcc.OP5 == 5) && (op.DBcc.OP25 == 25)) { ! 952: if (DBcc_str [op.DBcc.cond] == NULL) break; ! 953: temp = buf_pos; ! 954: temp += rd_short (); ! 955: if (!is_valid_branch (temp)) break; ! 956: output ("db%s\td%d,", DBcc_str[op.DBcc.cond], ! 957: op.DBcc.reg); ! 958: output_lab (temp); ! 959: labels [temp] |= F_LABEL; ! 960: if ((guessmode == GUESS_WALK) && (pass == 1)) PUSH_WS (temp); ! 961: goto done; ! 962: } ! 963: /* DIVS/DIVU */ ! 964: while ((op.type2.op == 0x8) && ((op.type2.op_mode == 0x7) || (op.type2.op_mode == 0x3))) { ! 965: if (op.type2.ea_mode == 0x1) break; ! 966: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break; ! 967: if (op.type2.op_mode == 0x7) output ("divs\t"); ! 968: else output ("divu\t"); ! 969: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1); ! 970: output (",d%d", op.type2.reg); ! 971: goto done; ! 972: } ! 973: /* EOR */ ! 974: while (op.type2.op == 0xb) { ! 975: if ((op.type2.op_mode < 4) || (op.type2.op_mode > 6)) break; ! 976: if (op.type2.ea_mode == 0x1) break; ! 977: if ((op.type2.ea_mode == 0x7) && (op.type2.ea_reg > 0x1)) break; ! 978: size = op.type2.op_mode - 4; ! 979: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, size, -1)) break; ! 980: output ("eor%s\t", size_str [size]); ! 981: output ("d%d,", op.type2.reg); ! 982: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, size); ! 983: goto done; ! 984: } ! 985: /* EORI to CCR */ ! 986: while (op.code == 0x0a3c) { ! 987: rd_byte (); ! 988: output ("eori\t#$%x,ccr", rd_byte ()); ! 989: goto done; ! 990: } ! 991: /* EORI to SR */ ! 992: while (op.code == 0x0a7c) { ! 993: output ("eori\t#$%hx,sr", rd_short ()); ! 994: goto done; ! 995: } ! 996: /* EXG */ ! 997: while ((op.exg.OP0xc == 0xc) && (op.exg.OP1 == 1)) { ! 998: if (op.exg.op_mode == 0x8) { ! 999: /* data reg swap */ ! 1000: output ("exg\td%d,d%d", op.exg.src_reg, op.exg.dest_reg); ! 1001: } else if (op.exg.op_mode == 0x9) { ! 1002: /* address reg swap */ ! 1003: output ("exg\ta%d,a%d", op.exg.src_reg, op.exg.dest_reg); ! 1004: } else if (op.exg.op_mode == 0x11) { ! 1005: /* data & adr reg swap */ ! 1006: output ("exg\td%d,a%d", op.exg.src_reg, op.exg.dest_reg); ! 1007: } else { ! 1008: break; ! 1009: } ! 1010: goto done; ! 1011: } ! 1012: /* EXT */ ! 1013: while ((op.code & 0xfe38) == 0x4800) { ! 1014: if (op.type2.op_mode == 0x2) { ! 1015: output ("ext.w\td%d", op.type2.ea_reg); ! 1016: } else if (op.type2.op_mode == 0x3) { ! 1017: output ("ext.l\td%d", op.type2.ea_reg); ! 1018: } else { ! 1019: break; ! 1020: } ! 1021: goto done; ! 1022: } ! 1023: /* HOSTCALL (not 68k) */ ! 1024: while (op.code == 0x000a) { ! 1025: output ("hostcall"); ! 1026: goto done; ! 1027: } ! 1028: /* ILLEGAL */ ! 1029: while (op.code == 0x4afc) { ! 1030: output ("illegal"); ! 1031: goto done; ! 1032: } ! 1033: /* JMP */ ! 1034: while ((op.code & 0xffc0) == 0x4ec0) { ! 1035: if (op.jmp.dest_mode == 0) break; ! 1036: if (op.jmp.dest_mode == 1) break; ! 1037: if (op.jmp.dest_mode == 3) break; ! 1038: if (op.jmp.dest_mode == 4) break; ! 1039: if ((op.jmp.dest_mode == 7) && ! 1040: (op.jmp.dest_reg == 4)) break; ! 1041: if (!is_adrmod (op.jmp.dest_mode, op.jmp.dest_reg, 2, -1)) break; ! 1042: output ("jmp\t"); ! 1043: temp = put_adrmod (op.jmp.dest_mode, op.jmp.dest_reg, 2); ! 1044: if ((guessmode == GUESS_WALK) && (pass == 1)) { ! 1045: if (temp != 0xdeadbeef) buf_pos = temp; ! 1046: else buf_pos = POP_WS (); ! 1047: } ! 1048: goto done; ! 1049: } ! 1050: /* JSR */ ! 1051: while ((op.code & 0xffc0) == 0x4e80) { ! 1052: if (op.type1.ea_mode == 0) break; ! 1053: if (op.type1.ea_mode == 1) break; ! 1054: if (op.type1.ea_mode == 3) break; ! 1055: if (op.type1.ea_mode == 4) break; ! 1056: /* no immediate dest */ ! 1057: if ((op.type1.ea_mode == 7) && (op.type1.ea_reg == 4)) break; ! 1058: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 2, -1)) break; ! 1059: output ("jsr\t"); ! 1060: temp = put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 2); ! 1061: if ((guessmode == GUESS_WALK) && (pass == 1) && (temp != 0xdeadbeef)) { ! 1062: PUSH_WS (temp); ! 1063: } ! 1064: goto done; ! 1065: } ! 1066: /* LEA */ ! 1067: while ((op.lea.SEVEN == 7) && (op.lea.FOUR == 4)) { ! 1068: if (op.lea.dest_mode == 0) break; ! 1069: if (op.lea.dest_mode == 1) break; ! 1070: if (op.lea.dest_mode == 3) break; ! 1071: if (op.lea.dest_mode == 4) break; ! 1072: /* no immediate dest */ ! 1073: if ((op.lea.dest_mode == 7) && (op.lea.dest_reg == 4)) break; ! 1074: if (!is_adrmod (op.lea.dest_mode, op.lea.dest_reg, 2, -1)) break; ! 1075: output ("lea\t"); ! 1076: put_adrmod (op.lea.dest_mode, op.lea.dest_reg, 2); ! 1077: output (",a%d", op.lea.reg); ! 1078: goto done; ! 1079: } ! 1080: /* LINK */ ! 1081: while ((op.code & 0xfff8) == 0x4e50) { ! 1082: output ("link\ta%d,", op.type1.ea_reg); ! 1083: put_imm (1); ! 1084: goto done; ! 1085: } ! 1086: /* MOVE/MOVEA */ ! 1087: while (op.move.op == 0) { ! 1088: if (op.move.size == 0) break; ! 1089: /* byte size and address reg direct is not allowed */ ! 1090: if ((op.move.size == 1) && (op.move.src_mode == 0x1)) break; ! 1091: if ((op.move.size == 1) && (op.move.dest_mode == 0x1)) break; ! 1092: if (op.move.dest_mode == 0x7) { ! 1093: if (op.move.dest_reg > 1) break; ! 1094: } ! 1095: size = move_size [op.move.size]; ! 1096: if (!is_adrmod (op.move.src_mode, op.move.src_reg, size, -1)) break; ! 1097: if ((op.move.src_mode == 0x7) && (op.move.src_reg == 0x4)) { ! 1098: /* immediate crap in the source so we must skip it */ ! 1099: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, size)) break; ! 1100: } else if ((op.move.src_mode == 0x7) && (op.move.src_reg > 0x1)) { ! 1101: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 1)) break; ! 1102: } else if ((op.move.src_mode == 0x7) && (op.move.src_reg == 0x1)) { ! 1103: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 2)) break; ! 1104: } else if ((op.move.src_mode == 0x7) && (op.move.src_reg == 0x0)) { ! 1105: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 1)) break; ! 1106: } else if ((op.move.src_mode == 0x6) || (op.move.src_mode == 0x5)) { ! 1107: /* PC with disp + Dx, (Ax) with disp + Dx */ ! 1108: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 1)) break; ! 1109: } else { ! 1110: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, -1)) break; ! 1111: } ! 1112: if (op.move.dest_mode == 0x1) { ! 1113: output ("movea%s\t", size_str[size]); ! 1114: } else { ! 1115: output ("move%s\t", size_str[size]); ! 1116: } ! 1117: ! 1118: put_adrmod (op.move.src_mode, op.move.src_reg, size); ! 1119: output (","); ! 1120: put_adrmod (op.move.dest_mode, op.move.dest_reg, size); ! 1121: goto done; ! 1122: } ! 1123: /* MOVE to CCR */ ! 1124: while ((op.code & 0xffc0) == 0x44c0) { ! 1125: if (op.type1.ea_mode == 0x1) break; ! 1126: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break; ! 1127: output ("move.w\t"); ! 1128: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1); ! 1129: output (",ccr"); ! 1130: goto done; ! 1131: } ! 1132: /* MOVE from SR */ ! 1133: while ((op.code & 0xffc0) == 0x40c0) { ! 1134: if (op.type1.ea_mode == 0x1) break; ! 1135: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break; ! 1136: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break; ! 1137: output ("move.w\tsr,"); ! 1138: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1); ! 1139: goto done; ! 1140: } ! 1141: /* MOVE to SR */ ! 1142: while ((op.code & 0xffc0) == 0x46c0) { ! 1143: if (op.type1.ea_mode == 0x1) break; ! 1144: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break; ! 1145: output ("move.w\t"); ! 1146: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1); ! 1147: output (",sr"); ! 1148: goto done; ! 1149: } ! 1150: /* MOVE USP */ ! 1151: while ((op.code & 0xfff0) == 0x4e60) { ! 1152: if (op.addx.rm) { ! 1153: /* USP to Ax */ ! 1154: output ("move.l\tusp,a%d", op.addx.src_reg); ! 1155: } else { ! 1156: output ("move.l\ta%d,usp", op.addx.src_reg); ! 1157: } ! 1158: goto done; ! 1159: } ! 1160: /* TODO MOVEC */ ! 1161: /* TODO MOVEP */ ! 1162: /* MOVEM */ ! 1163: while ((op.movem.NINE == 9) && (op.movem.ONE == 1)) { ! 1164: if (op.movem.dr) { ! 1165: /* memory to register */ ! 1166: if (op.movem.dest_mode < 2) break; ! 1167: if (op.movem.dest_mode == 4) break; ! 1168: if ((op.movem.dest_mode == 7) && (op.movem.dest_reg == 4)) break; ! 1169: if (!is_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1, 1)) break; ! 1170: temp = rd_short (); ! 1171: output ("movem%s\t", size_str [op.movem.sz+1]); ! 1172: put_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1); ! 1173: output (","); ! 1174: put_movem_regs (temp, 0); ! 1175: } else { ! 1176: /* register to memory */ ! 1177: if (op.movem.dest_mode < 2) break; ! 1178: if (op.movem.dest_mode == 3) break; ! 1179: if ((op.movem.dest_mode == 7) && (op.movem.dest_reg > 1)) break; ! 1180: if (!is_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1, 1)) break; ! 1181: output ("movem%s\t", size_str [op.movem.sz+1]); ! 1182: put_movem_regs (rd_short (), (op.movem.dest_mode == 4)); ! 1183: output (","); ! 1184: put_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1); ! 1185: } ! 1186: goto done; ! 1187: } ! 1188: /* MOVEQ */ ! 1189: while ((op.moveq.SEVEN == 7) && (op.moveq.ZERO == 0)) { ! 1190: output ("moveq\t#%d,d%d", op.moveq.data, op.moveq.reg); ! 1191: goto done; ! 1192: } ! 1193: /* MULS/MULU */ ! 1194: while ((op.type2.op == 0xc) && ((op.type2.op_mode == 0x7) || (op.type2.op_mode == 0x3))) { ! 1195: if (op.type2.ea_mode == 0x1) break; ! 1196: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break; ! 1197: if (op.type2.op_mode == 0x7) output ("muls\t"); ! 1198: else output ("mulu\t"); ! 1199: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1); ! 1200: output (",d%d", op.type2.reg); ! 1201: goto done; ! 1202: } ! 1203: /* NBCD */ ! 1204: while ((op.code & 0xffc0) == 0x4800) { ! 1205: if (op.type1.ea_mode == 0x1) break; ! 1206: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 1)) break; ! 1207: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0, -1)) break; ! 1208: output ("nbcd\t"); ! 1209: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0); ! 1210: goto done; ! 1211: } ! 1212: /* NEG/NEGX/NOT */ ! 1213: while ((op.type1.op == 0x44) || (op.type1.op == 0x40) || (op.type1.op == 0x46)) { ! 1214: if (op.type1.size == 3) break; ! 1215: if (op.type1.ea_mode == 0x1) break; ! 1216: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 1)) break; ! 1217: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break; ! 1218: if (op.type1.op == 0x44) output ("neg%s\t", size_str [op.type1.size]); ! 1219: else if (op.type1.op == 0x40) output ("negx%s\t", size_str [op.type1.size]); ! 1220: else output ("not%s\t", size_str [op.type1.size]); ! 1221: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size); ! 1222: goto done; ! 1223: } ! 1224: /* NOP */ ! 1225: while (op.code == 0x4e71) { ! 1226: output ("nop"); ! 1227: goto done; ! 1228: } ! 1229: /* ORI to CCR */ ! 1230: while (op.code == 0x003c) { ! 1231: rd_byte (); ! 1232: output ("ori\t#$%x,ccr", rd_byte ()); ! 1233: goto done; ! 1234: } ! 1235: /* ORI to SR */ ! 1236: while (op.code == 0x007c) { ! 1237: output ("ori\t#$%hx,sr", rd_short ()); ! 1238: goto done; ! 1239: } ! 1240: /* PEA */ ! 1241: while ((op.code & 0xffc0) == 0x4840) { ! 1242: if (op.type1.ea_mode < 2) break; ! 1243: if (op.type1.ea_mode == 3) break; ! 1244: if (op.type1.ea_mode == 4) break; ! 1245: if ((op.type1.ea_mode == 7) && (op.type1.ea_reg == 4)) break; ! 1246: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break; ! 1247: output ("pea\t"); ! 1248: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 2); ! 1249: goto done; ! 1250: } ! 1251: /* RESET */ ! 1252: while (op.code == 0x4e70) { ! 1253: output ("reset"); ! 1254: goto done; ! 1255: } ! 1256: /* RTE */ ! 1257: while (op.code == 0x4e73) { ! 1258: output ("rte"); ! 1259: if ((guessmode == GUESS_WALK) && (pass == 1)) buf_pos = POP_WS (); ! 1260: goto done; ! 1261: } ! 1262: /* RTR */ ! 1263: while (op.code == 0x4e77) { ! 1264: output ("rtr"); ! 1265: goto done; ! 1266: } ! 1267: /* RTS */ ! 1268: while (op.code == 0x4e75) { ! 1269: output ("rts"); ! 1270: if ((guessmode == GUESS_WALK) && (pass == 1)) buf_pos = POP_WS (); ! 1271: goto done; ! 1272: } ! 1273: /* Scc */ ! 1274: while ((op.code & 0xf0c0) == 0x50c0) { ! 1275: if (op.type1.ea_mode == 1) break; ! 1276: if ((op.type1.ea_mode == 7) && (op.type1.ea_reg > 1)) break; ! 1277: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0, -1)) break; ! 1278: output ("s%s\t", Scc_str[op.DBcc.cond]); ! 1279: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0); ! 1280: goto done; ! 1281: } ! 1282: /* STOP */ ! 1283: while (op.code == 0x4e72) { ! 1284: output ("stop\t"); ! 1285: put_imm (1); ! 1286: goto done; ! 1287: } ! 1288: /* SWAP */ ! 1289: while ((op.code & 0xfff8) == 0x4840) { ! 1290: output ("swap\td%d", op.code & 0x7); ! 1291: goto done; ! 1292: } ! 1293: /* TAS */ ! 1294: while ((op.code & 0xffc0) == 0x4ac0) { ! 1295: if (op.type1.ea_mode == 0x1) break; ! 1296: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break; ! 1297: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0, -1)) break; ! 1298: output ("tas\t"); ! 1299: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0); ! 1300: goto done; ! 1301: } ! 1302: /* TRAP */ ! 1303: while ((op.code & 0xfff0) == 0x4e40) { ! 1304: output ("trap\t#%d", op.code & 0xf); ! 1305: goto done; ! 1306: } ! 1307: /* TRAPV */ ! 1308: while (op.code == 0x4e76) { ! 1309: output ("trapv"); ! 1310: goto done; ! 1311: } ! 1312: /* TST */ ! 1313: while (op.type1.op == 0x4a) { ! 1314: if (op.type1.size == 3) break; ! 1315: /* no address reg direct */ ! 1316: if (op.type1.ea_mode == 0x1) break; ! 1317: /* no immediate or pc relative dest */ ! 1318: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break; ! 1319: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break; ! 1320: output ("tst%s\t", size_str[op.type1.size]); ! 1321: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size); ! 1322: goto done; ! 1323: } ! 1324: /* UNLK */ ! 1325: while ((op.code & 0xfff8) == 0x4e58) { ! 1326: output ("unlk\ta%d", op.code & 0x7); ! 1327: goto done; ! 1328: } ! 1329: /* fuck knows */ ! 1330: output ("dc.w\t$%hx", op.code); ! 1331: fprintf (stderr, "Eeek. Unknown opcode 0x%hx at 0x%x.\n", op.code, buf_pos-2); ! 1332: labels[buf_pos-2] |= F_DUNNO; ! 1333: labels[buf_pos-1] |= F_DUNNO; ! 1334: if (buf_pos == end) break; ! 1335: else continue; ! 1336: done: ! 1337: /* this isn't data */ ! 1338: if ((guessmode == GUESS_WALK) && (pass == 1)) { ! 1339: labels[last_ip] |= F_WALKED_CODE; ! 1340: labels[last_ip+1] |= F_WALKED_CODE; ! 1341: } ! 1342: continue; ! 1343: } ! 1344: output ("\r\n"); ! 1345: } ! 1346: ! 1347: /* ! 1348: * Pass 0 as reloc for first fixup address, otherwise ! 1349: * pass returned valu. if returned value == 0 you are at the fucking end, man. ! 1350: */ ! 1351: int get_fixup (int reloc) ! 1352: { ! 1353: int old_bufpos; ! 1354: int next; ! 1355: static int reloc_pos; ! 1356: ! 1357: old_bufpos = buf_pos; ! 1358: if (reloc == 0) { ! 1359: buf_pos = end; ! 1360: reloc = rd_int (); ! 1361: reloc_pos = buf_pos; ! 1362: buf_pos = old_bufpos; ! 1363: if (reloc == 0) return 0; ! 1364: else return base + reloc; ! 1365: } else { ! 1366: buf_pos = reloc_pos; ! 1367: again: ! 1368: next = rd_byte (); ! 1369: if (next == 0) { ! 1370: buf_pos = old_bufpos; ! 1371: return 0; ! 1372: } ! 1373: else if (next == 1) { ! 1374: reloc += 254; ! 1375: goto again; ! 1376: } ! 1377: else reloc += next; ! 1378: reloc_pos = buf_pos; ! 1379: buf_pos = old_bufpos; ! 1380: return reloc; ! 1381: } ! 1382: } ! 1383: ! 1384: void do_fixups () ! 1385: { ! 1386: int reloc, next; ! 1387: int pos; ! 1388: ! 1389: reloc = get_fixup (0); ! 1390: fprintf (stderr, "relocs: "); ! 1391: while (reloc) { ! 1392: fprintf (stderr, "0x%x ", reloc); ! 1393: pos = buf_pos; ! 1394: /* address to be modified */ ! 1395: buf_pos = reloc; ! 1396: labels [buf_pos] |= F_USELAB; ! 1397: next = rd_int (); ! 1398: next += base; ! 1399: buf_pos -= 4; ! 1400: wr_int (next); ! 1401: if (next > end) { ! 1402: printf ("Reloc label 0x%x out of range...\n", next); ! 1403: } else { ! 1404: labels [next] |= F_LABEL | F_LABEL_MAJOR; ! 1405: } ! 1406: buf_pos = pos; ! 1407: ! 1408: reloc = get_fixup (reloc); ! 1409: } ! 1410: fprintf (stderr, "\n"); ! 1411: } ! 1412: ! 1413: void guess_datasegs () ! 1414: { ! 1415: //int reloc; ! 1416: int next, dist; ! 1417: int pos, sec_start, num_dunno, prop; ! 1418: ! 1419: if (guessmode == GUESS_WALK) { ! 1420: #if 0 ! 1421: /* 0x4e75 (rts) with label infront is often a function */ ! 1422: for (next = end-3; next >= base; next--) { ! 1423: buf_pos = next; ! 1424: /* rts */ ! 1425: if (rd_short () == 0x4e75) { ! 1426: /* label after */ ! 1427: if (!(labels[buf_pos] & F_LABEL)) continue; ! 1428: /* zoom to label before this rts */ ! 1429: for (; next >= base; next--) { ! 1430: if (labels[next] & F_LABEL) break; ! 1431: if (labels[next] & F_WALKED_CODE) break; ! 1432: } ! 1433: PUSH_WS (end); ! 1434: buf_pos = next; ! 1435: dump_code (); ! 1436: } ! 1437: } ! 1438: /* fixup sections ending in 0x4e75 (rts) are probably functions ! 1439: * not data */ ! 1440: reloc = get_fixup (0); ! 1441: while (reloc) { ! 1442: /* scan to first label and see if the previous word is ! 1443: * an rts */ ! 1444: for (next = reloc; next < end; next++) { ! 1445: if (labels[next] & F_LABEL) break; ! 1446: } ! 1447: buf_pos = next-2; ! 1448: if (rd_short() == 0x4e75) { ! 1449: /* grope section as code (find start label) */ ! 1450: for (next = reloc; next >= base; next--) { ! 1451: if (labels[next] & F_LABEL) break; ! 1452: } ! 1453: PUSH_WS (end); ! 1454: buf_pos = next; ! 1455: dump_code (); ! 1456: } ! 1457: reloc = get_fixup (reloc); ! 1458: } ! 1459: #endif /* 0 */ ! 1460: /* turn everything not F_WALKED_CODE into F_GUESS_DATA */ ! 1461: for (pos=base; pos<end; pos++) { ! 1462: if (!(labels[pos] & F_WALKED_CODE)) { ! 1463: labels[pos] |= F_GUESS_DATA; ! 1464: } ! 1465: } ! 1466: goto skip_simple; ! 1467: } ! 1468: /* if there is a good proportion of F_DUNNOs (unknown opcodes) between ! 1469: * 2 labels then the entire section is probably data */ ! 1470: pos=base; ! 1471: sec_start=base; ! 1472: num_dunno=0; ! 1473: for (;; pos++) { ! 1474: if ((labels [pos] & F_LABEL) || (pos == end)) { ! 1475: /* new section */ ! 1476: if (pos != base) { ! 1477: dist = pos - sec_start; ! 1478: /* proportion of dunnos */ ! 1479: prop = (100*num_dunno)/dist; ! 1480: probs[sec_start] = prop; ! 1481: //printf ("Section prop %d%% (pos 0x%x to 0x%x)\n", prop, sec_start, pos-1); ! 1482: if (prop > 0) { ! 1483: while (sec_start < pos) { ! 1484: labels [sec_start++] |= F_GUESS_DATA; ! 1485: } ! 1486: } ! 1487: } ! 1488: sec_start = pos; ! 1489: num_dunno = 0; ! 1490: } ! 1491: if (pos >= end) break; ! 1492: if (labels [pos] & F_DUNNO) { ! 1493: num_dunno++; ! 1494: } ! 1495: } ! 1496: skip_simple: ! 1497: /* grope for possible text areas */ ! 1498: for (pos=base, dist=0; pos<end; pos++) { ! 1499: buf_pos = pos; ! 1500: next = rd_byte (); ! 1501: /* labels break runs of ascii characters */ ! 1502: if (labels [pos] & F_LABEL) dist = 0; ! 1503: if (!(labels [pos] & F_GUESS_DATA)) dist = 0; ! 1504: if ((next >= ' ') && (next <= 126)) { ! 1505: dist++; ! 1506: } else { ! 1507: dist = 0; ! 1508: } ! 1509: if (dist == 5) { ! 1510: labels [pos-4] |= F_GUESS_STRING; ! 1511: labels [pos-3] |= F_GUESS_STRING; ! 1512: labels [pos-2] |= F_GUESS_STRING; ! 1513: labels [pos-1] |= F_GUESS_STRING; ! 1514: } ! 1515: if (dist >= 5) { ! 1516: labels [pos] |= F_GUESS_STRING; ! 1517: } ! 1518: } ! 1519: } ! 1520: ! 1521: int main (int argc, char **argv) ! 1522: { ! 1523: int i, pos, from, to; ! 1524: FILE *fptr; ! 1525: ! 1526: if (argc < 2) { ! 1527: printf ("Usage: ./thing {-gs|-gw {-codestart addr, addr, ... } {-codestop addr, addr, ... } { -labeltab from,to from2,to2 ... } some.prg\n"); ! 1528: printf (" -gs Simple data section guessing.\n"); ! 1529: printf (" -gw 'Walking' data section guessing.\n"); ! 1530: printf (" -codestart/stop are for -gw mode, when it fucks up its\n"); ! 1531: printf (" walk over the code and misses some code or disassembles\n"); ! 1532: printf (" data.\n"); ! 1533: printf (" -labeltab is for raw reloc thingies. ie dc.l label, which\n"); ! 1534: printf (" have a fixup and must be preserved.\n"); ! 1535: exit (0); ! 1536: } ! 1537: ! 1538: if ((fptr = fopen (argv[argc-1], "r"))==NULL) { ! 1539: fprintf (stderr, "Could not open %s.\n", argv[argc-1]); ! 1540: exit (0); ! 1541: } ! 1542: fseek (fptr, 0, SEEK_END); ! 1543: end = ftell (fptr); ! 1544: fseek (fptr, 0, SEEK_SET); ! 1545: buffer = malloc (end); ! 1546: fread (buffer, 1, end, fptr); ! 1547: fclose (fptr); ! 1548: ! 1549: buf_pos = 2; ! 1550: end = base + rd_int (); ! 1551: ! 1552: labels = malloc (end*sizeof (short)); ! 1553: memset (labels, 0, end*sizeof (short)); ! 1554: ! 1555: guessmode = GUESS_NONE; ! 1556: if (argc > 2) { ! 1557: if (strcmp (argv[1], "-gs")==0) guessmode = GUESS_SIMPLE; ! 1558: else if (strcmp (argv[1], "-gw")==0) { ! 1559: guessmode = GUESS_WALK; ! 1560: PUSH_WS (end); ! 1561: i = 2; ! 1562: if (strcmp (argv[i], "-codestart")==0) { ! 1563: for (i+=1; i<argc-1; i++) { ! 1564: pos = strtol (argv[i], NULL, 0); ! 1565: if (pos == 0) break; ! 1566: PUSH_WS (pos); ! 1567: fprintf (stderr, "Code start 0x%x\n", pos); ! 1568: } ! 1569: } ! 1570: if (strcmp (argv[i], "-codestop")==0) { ! 1571: for (i+=1; i<argc-1; i++) { ! 1572: pos = strtol (argv[i], NULL, 0); ! 1573: if (pos == 0) break; ! 1574: labels[pos] |= F_CODE_STOP; ! 1575: fprintf (stderr, "Code stop 0x%x\n", pos); ! 1576: } ! 1577: } ! 1578: if (strcmp (argv[i], "-labeltab")==0) { ! 1579: for (i+=1; i<argc-1; i++) { ! 1580: if (sscanf (argv[i], "%x,%x", &from, &to) != 2) { ! 1581: fprintf (stderr, "Malformed -labeltab address.\n"); ! 1582: break; ! 1583: } else { ! 1584: fprintf (stderr, "Labeltable 0x%x to 0x%x\n", from, to); ! 1585: for (; from <= to; from++) { ! 1586: labels[from] |= F_LABEL_TABLE; ! 1587: } ! 1588: } ! 1589: } ! 1590: } ! 1591: } ! 1592: } ! 1593: ! 1594: probs = malloc (end); ! 1595: memset (probs, 0, end); ! 1596: do_fixups (); ! 1597: ! 1598: buf_pos = base; ! 1599: dump_code (); ! 1600: ! 1601: if (guessmode) guess_datasegs (); ! 1602: pass = 2; ! 1603: ! 1604: PUSH_WS (end); ! 1605: buf_pos = base; ! 1606: dump_code (); ! 1607: return 0; ! 1608: } ! 1609:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.