|
|
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.