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