|
|
1.1 root 1:
2: #include <stdio.h>
3: #include <stdlib.h>
4: #include <string.h>
5: #include <stdarg.h>
6:
7: #include <SDL_types.h>
8:
9: #include "main.h"
10: #include "decode.h"
11: #include "dialog.h"
12: #include "file.h"
13: #include "m68000.h"
14: #include "memAlloc.h"
15: #include "stMemory.h"
16:
17: static int buf_pos = 0;
18:
19: static void output (const char *format, ...)
20: {
21: va_list argptr;
22:
23: va_start (argptr, format);
24: vprintf (format, argptr);
25: va_end (argptr);
26: }
27:
28: static void output_lab (int addr)
29: {
30: printf ("$%x", addr);
31: }
32:
33: unsigned char rd_byte(void)
34: {
35: int val = STMemory_ReadByte (buf_pos);
36: buf_pos++;
37: return val;
38: }
39:
40: short rd_short(void)
41: {
42: short val = STMemory_ReadWord (buf_pos);
43: buf_pos+=2;
44: return val;
45: }
46:
47: int rd_int(void)
48: {
49: int val = STMemory_ReadLong (buf_pos);
50: buf_pos+=4;
51: return val;
52: }
53:
54: const char *size_str[4] = { ".b", ".w", ".l", ".?" };
55: /* to convert weird move sizes to standard sizes */
56: const int move_size[4] = { 3, 0, 2, 1 };
57: const char *Bcc_str[16] = {
58: NULL,NULL,"hi","ls","cc","cs","ne","eq",
59: "vc","vs","pl","mi","ge","lt","gt","le"
60: };
61:
62: const char *DBcc_str[16] = {
63: "t","ra","hi","ls","cc","cs","ne","eq",
64: "vc","vs","pl","mi","ge","lt","gt","le"
65: };
66:
67: typedef union Opcode {
68: unsigned short code;
69: struct move {
70: uint src_reg : 3;
71: uint src_mode : 3;
72: uint dest_mode : 3;
73: uint dest_reg : 3;
74: uint size : 2;
75: uint op : 2;
76: } move;
77: struct adr_index {
78: int displacement : 8;
79: uint zeros : 3;
80: uint ind_size : 1;
81: uint reg : 3;
82: uint reg_type : 1;
83: } adr_index;
84: struct addq {
85: uint dest_reg : 3;
86: uint dest_mode : 3;
87: uint size : 2;
88: uint issub : 1;
89: uint data : 3;
90: uint op : 4;
91: } addq;
92: struct jmp {
93: uint dest_reg : 3;
94: uint dest_mode : 3;
95: uint op : 10;
96: } jmp;
97: struct addi {
98: uint dest_reg : 3;
99: uint dest_mode : 3;
100: uint size : 2;
101: uint OP6 : 8;
102: } addi;
103: /* size and effective address */
104: struct type1 {
105: uint ea_reg : 3;
106: uint ea_mode : 3;
107: uint size : 2;
108: uint op : 8;
109: } type1;
110: /* reg, opmode, ea */
111: struct type2 {
112: uint ea_reg : 3;
113: uint ea_mode : 3;
114: uint op_mode : 3;
115: uint reg : 3;
116: uint op : 4;
117: } type2;
118: struct MemShift {
119: uint ea_reg : 3;
120: uint ea_mode : 3;
121: uint OP3 : 2;
122: uint dr : 1;
123: uint type : 2;
124: uint OP0x1c : 5;
125: } MemShift;
126: struct ASx {
127: uint reg : 3;
128: uint OP0 : 2;
129: uint ir : 1;
130: uint size : 2;
131: uint dr : 1;
132: uint count_reg : 3;
133: uint OP0xe : 4;
134: } ASx;
135: struct abcd {
136: uint src_reg : 3;
137: uint rm : 1;
138: uint OP16 : 5;
139: uint dest_reg : 3;
140: uint OP12 : 4;
141: } abcd;
142: struct addx {
143: uint src_reg : 3;
144: uint rm : 1;
145: uint OP0 : 2;
146: uint size : 2;
147: uint OP1 : 1;
148: uint dest_reg : 3;
149: uint op : 4;
150: } addx;
151: struct cmpm {
152: uint src_reg : 3;
153: uint OP1_1 : 3;
154: uint size : 2;
155: uint OP2_1 : 1;
156: uint dest_reg : 3;
157: uint OP0xb : 4;
158: } cmpm;
159: /* branches */
160: struct DBcc {
161: uint reg : 3;
162: uint OP25 : 5;
163: uint cond : 4;
164: uint OP5 : 4;
165: } DBcc;
166: struct Bcc {
167: int displacement : 8;
168: uint cond : 4;
169: uint op : 4;
170: } Bcc;
171: struct bra {
172: int displacement : 8;
173: uint op : 8;
174: } bra;
175: struct movem {
176: uint dest_reg : 3;
177: uint dest_mode : 3;
178: uint sz : 1;
179: uint ONE : 3;
180: uint dr : 1;
181: uint NINE : 5;
182: } movem;
183: struct lea {
184: uint dest_reg : 3;
185: uint dest_mode : 3;
186: uint SEVEN : 3;
187: uint reg : 3;
188: uint FOUR : 4;
189: } lea;
190: struct moveq {
191: int data : 8;
192: uint ZERO : 1;
193: uint reg : 3;
194: uint SEVEN : 4;
195: } moveq;
196: struct exg {
197: uint dest_reg : 3;
198: uint op_mode : 5;
199: uint OP1 : 1;
200: uint src_reg : 3;
201: uint OP0xc : 4;
202: } exg;
203: } Opcode;
204:
205: /*
206: * Skip size is used when there is immediate data, for addressing
207: * modes $addr(Ax,Dy.s), and the PC flavoured version of that.
208: * The immediate data comes first and must be skipped
209: */
210: int is_adrmod (int mode, int reg, int op_size, int skip_size)
211: {
212: Opcode ext;
213: switch (skip_size) {
214: case -1: skip_size = 0; break;
215: case 0: case 1: skip_size = 2; break;
216: default: skip_size = 4; break;
217: }
218: switch (mode) {
219: case 0: case 1: case 2: case 3: case 4:
220: return 1;
221: case 5: return 1;
222: case 6: buf_pos += skip_size;
223: ext.code = rd_short ();
224: buf_pos -= 2 + skip_size;
225: if (ext.adr_index.zeros != 0) return 0;
226: else return 1;
227: case 7:
228: switch (reg) {
229: case 0: return 1;
230: case 1: return 1;
231: case 4:
232: return 1;
233: case 2:
234: return 1;
235: case 3: buf_pos += skip_size;
236: ext.code = rd_short ();
237: buf_pos -= 2 + skip_size;
238: if (ext.adr_index.zeros != 0) return 0;
239: else return 1;
240: default:
241: return 0;
242: }
243: break;
244: default:
245: return 0;
246: }
247:
248: }
249:
250: /* returns abs address if possible or 0xdeadbeef if not */
251: uint put_adrmod (int mode, int reg, int op_size)
252: {
253: uint temp;
254: Opcode ext;
255: switch (mode) {
256: case 0: output ("d%d", reg); break;
257: case 1: output ("a%d", reg); break;
258: case 2: output ("(a%d)", reg); break;
259: case 3: output ("(a%d)+", reg); break;
260: case 4: output ("-(a%d)", reg); break;
261: case 5: output ("%hd(a%d)", rd_short(), reg); break;
262: case 6: ext.code = rd_short ();
263: if (ext.adr_index.zeros != 0) output ("???");
264: output ("%hd(a%d,", ext.adr_index.displacement, reg);
265: if (ext.adr_index.reg_type) {
266: output ("a%d", ext.adr_index.reg);
267: } else {
268: output ("d%d", ext.adr_index.reg);
269: }
270: if (ext.adr_index.ind_size) {
271: output (".l)");
272: } else {
273: output (".w)");
274: }
275: break;
276: case 7:
277: switch (reg) {
278: case 0: output ("$%hx.w", rd_short()); break;
279: case 1: temp = rd_int ();
280: output ("$%x.l", temp);
281: return temp;
282: case 4:
283: if (op_size == 0) {
284: if (rd_byte () != 0) output ("???");
285: output ("#$%x", rd_byte ());
286: } else if (op_size == 2) {
287: output ("#");
288: output ("$%x", rd_int ());
289: } else if (op_size == 1) {
290: output ("#$%hx", rd_short ());
291: } else {
292: output ("#???");
293: }
294: break;
295: case 2:
296: temp = buf_pos;
297: temp += rd_short ();
298: output ("$%x(pc)", temp);
299: return temp;
300: case 3: temp = buf_pos;
301: ext.code = rd_short ();
302: if (ext.adr_index.zeros != 0) output ("???");
303: output ("$%x", temp + ext.adr_index.displacement);
304: if (ext.adr_index.reg_type) {
305: output ("(pc,a%d", ext.adr_index.reg);
306: } else {
307: output ("(pc,d%d", ext.adr_index.reg);
308: }
309: if (ext.adr_index.ind_size) {
310: output (".l)");
311: } else {
312: output (".w)");
313: }
314: break;
315: default:
316: output ("???"); break;
317: }
318: break;
319: default:
320: output ("???"); break;
321: }
322: return 0xdeadbeef;
323: }
324:
325: void aux_put_movem_regs (int mode, int low, int high)
326: {
327: if (!mode) {
328: /* (Ax)+ and control modes */
329: if (low < 8) {
330: if (low == high) {
331: output ("d%d", low);
332: return;
333: }
334: if (high >7) {
335: if (low == 7) output ("d7/");
336: else output ("d%d-7/", low);
337: } else {
338: output ("d%d-%d", low, high);
339: return;
340: }
341: }
342: if (high > 7) {
343: if (low == high) {
344: output ("a%d", low-8);
345: return;
346: }
347: if (low > 7) {
348: output ("a%d-%d", low-8, high-8);
349: } else {
350: if (high == 8) output ("a0");
351: else output ("a0-%d", high-8);
352: }
353: }
354: } else {
355: /* -(Ax) mode */
356: if (high > 7) {
357: if (low == high) {
358: output ("d%d", 15-low);
359: return;
360: }
361: if (low > 7) {
362: output ("d%d-%d", 15-high, 15-low);
363: return;
364: } else {
365: if (high == 8) output ("d7/");
366: else output ("d%d-7/", 15-high);
367: }
368: }
369: if (low < 8) {
370: if (low == high) {
371: output ("a%d", 7-low);
372: return;
373: }
374: if (high >7) {
375: if (low == 7) output ("a0");
376: else output ("a0-%d", 7-low);
377: } else {
378: output ("a%d-%d", 7-high, 7-low);
379: }
380: }
381: }
382: }
383:
384: void put_movem_regs (int mask, int mode)
385: {
386: int start;
387: int pos;
388: int pixie = 0;
389:
390: start = -1;
391: for (pos=0; pos < 16; pos++) {
392: if ((mask & (1<<pos)) && (start == -1)) start = pos;
393: else if ((!(mask & (1<<pos))) && (start != -1)) {
394: if (pixie) output ("/");
395: else pixie = 1;
396: aux_put_movem_regs (mode, start, pos-1);
397: start = -1;
398: }
399: }
400: if (mask & (1<<15)) {
401: if (pixie) output ("/");
402: else pixie = 1;
403: aux_put_movem_regs (mode, start, pos-1);
404: start = -1;
405: }
406: }
407:
408: void put_imm (int size)
409: {
410: if (size == 0) {
411: rd_byte ();
412: output ("#$%x", (int)rd_byte ());
413: } else if (size == 1) {
414: output ("#$%hx", (int)rd_short ());
415: } else {
416: output ("#$%x", (int)rd_int ());
417: }
418: }
419:
420: /*
421: * Disassemble _count bytes from _start.
422: */
423: void dump_code (int _start, int _count)
424: {
425: Opcode op;
426: int size;
427: int temp;
428: const char *str;
429: int last_ip;
430: buf_pos = _start;
431:
432: while (buf_pos < _start+_count) {
433: output ("\r\n$%x\t", buf_pos);
434: last_ip = buf_pos;
435: op.code = rd_short ();
436: output ("($%hx)\t", op.code);
437: /* ABCD/SBCD */
438: while (op.abcd.OP16 == 16) {
439: if (op.abcd.OP12 == 12) output ("abcd\t");
440: else if (op.abcd.OP12 == 8) output ("sbcd\t");
441: else break;
442: if (op.abcd.rm) {
443: output ("-(a%d),-(a%d)", op.abcd.src_reg, op.abcd.dest_reg);
444: } else {
445: output ("d%d,d%d", op.abcd.src_reg, op.abcd.dest_reg);
446: }
447: goto done;
448: }
449: /* ADD/SUB */
450: while ((op.type2.op == 0xd) || (op.type2.op == 0x9)) {
451: if (op.type2.op == 0xd) str = "add";
452: else str = "sub";
453: if (op.type2.op_mode == 3) {
454: /* ADDA.W */
455: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break;
456: output ("%sa.w\t", str);
457: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1);
458: output (",a%d", op.type2.reg);
459: }
460: else if (op.type2.op_mode == 7) {
461: /* ADDA.L */
462: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2, -1)) break;
463: output ("%sa.l\t", str);
464: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2);
465: output (",a%d", op.type2.reg);
466: }
467: else if (op.type2.op_mode < 3) {
468: /* dest is reg */
469: /* no .b size Ax sources */
470: if ((op.type2.op_mode == 0) && (op.type2.ea_mode == 0x1)) break;
471: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode, -1)) break;
472: output ("%s%s\t", str, size_str[op.type2.op_mode]);
473: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode);
474: output (",d%d", op.type2.reg);
475: } else {
476: /* dest is ea */
477: if (op.type2.ea_mode == 0x0) break;
478: if (op.type2.ea_mode == 0x1) break;
479: if (op.type2.ea_mode == 0x7) {
480: if ((op.type2.ea_reg == 2) ||
481: (op.type2.ea_reg == 3) ||
482: (op.type2.ea_reg == 4)) break;
483: }
484: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4, -1)) break;
485: output ("%s%s\t", str, size_str[op.type2.op_mode-4]);
486: output ("d%d,", op.type2.reg);
487: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4);
488: }
489: goto done;
490: }
491: /* ADDI/SUBI */
492: while ((op.addi.OP6 == 6) || (op.addi.OP6 == 4)) {
493: if (op.addi.size == 3) break;
494: if (op.addi.dest_mode == 0x1) break;
495: if (op.addi.dest_mode == 0x7) {
496: if ((op.addi.dest_reg == 2) ||
497: (op.addi.dest_reg == 3) ||
498: (op.addi.dest_reg == 4)) break;
499: }
500: if (!is_adrmod (op.addi.dest_mode, op.addi.dest_reg, op.addi.size, op.addi.size)) break;
501: if (op.addi.OP6 == 6) output ("addi%s\t", size_str[op.addi.size]);
502: else output ("subi%s\t", size_str[op.addi.size]);
503: put_imm (op.addi.size);
504: output (",");
505: put_adrmod (op.addi.dest_mode, op.addi.dest_reg, op.addi.size);
506: goto done;
507: }
508: /* ADDQ/SUBQ */
509: while (op.addq.op == 0x5) {
510: if (op.addq.size == 3) break;
511: /* no immediate or pc relative dest */
512: if (op.addq.dest_mode == 0x7) {
513: if (op.addq.dest_reg > 0x1) break;
514: }
515: /* no addq.b to address registers */
516: if ((op.addq.size == 0) && (op.addq.dest_mode == 1)) break;
517: if (!is_adrmod (op.addq.dest_mode, op.addq.dest_reg, op.addq.size, -1)) break;
518: if (op.addq.issub) output ("subq%s\t", size_str[op.addq.size]);
519: else output ("addq%s\t", size_str[op.addq.size]);
520: output ("#%d,", (op.addq.data == 0 ? 8 : op.addq.data));
521: put_adrmod (op.addq.dest_mode, op.addq.dest_reg, op.addq.size);
522: goto done;
523: }
524: /* ADDX/SUBX */
525: while (((op.addx.op == 0xd) || (op.addx.op == 0x9)) && (op.addx.OP1 == 1) && (op.addx.OP0 == 0)) {
526: if (op.addx.size == 3) break;
527: if (op.addx.op == 0xd) output ("addx%s\t", size_str[op.addx.size]);
528: else output ("subx%s\t", size_str[op.addx.size]);
529: if (op.addx.rm) {
530: /* memory to memory */
531: output ("-(a%d),-(a%d)", op.addx.src_reg, op.addx.dest_reg);
532: } else {
533: output ("d%d,d%d", op.addx.src_reg, op.addx.dest_reg);
534: }
535:
536: goto done;
537: }
538: /* AND/OR */
539: while ((op.type2.op == 0xc) || (op.type2.op == 0x8)) {
540: if (op.type2.op_mode == 3) break;
541: if (op.type2.op_mode == 7) break;
542: if (op.type2.op == 0xc) str = "and";
543: else str = "or";
544: if (op.type2.op_mode < 3) {
545: /* dest is reg */
546: if (op.type2.ea_mode == 0x1) break;
547: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode, -1)) break;
548: output ("%s%s\t", str, size_str[op.type2.op_mode]);
549: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode);
550: output (",d%d", op.type2.reg);
551: } else {
552: /* dest is ea */
553: if (op.type2.ea_mode == 0x0) break;
554: if (op.type2.ea_mode == 0x1) break;
555: if (op.type2.ea_mode == 0x7) {
556: if (op.type2.ea_reg > 1) break;
557: }
558: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4, -1)) break;
559: output ("%s%s\t", str, size_str[op.type2.op_mode-4]);
560: output ("d%d,", op.type2.reg);
561: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode-4);
562: }
563: goto done;
564: }
565: /* ANDI/EORI/ORI */
566: while ((op.type1.op == 0x02) || (op.type1.op == 0xa) || (op.type1.op == 0x0)) {
567: if (op.type1.size == 3) break;
568: /* no address reg direct */
569: if (op.type1.ea_mode == 0x1) break;
570: /* no immediate or pc relative dest */
571: if (op.type1.ea_mode == 0x7) {
572: if (op.type1.ea_reg > 0x1) break;
573: }
574: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, op.type1.size)) break;
575: if (op.type1.op == 0x2) output ("andi%s\t", size_str[op.type1.size]);
576: else if (op.type1.op == 0xa) output ("eori%s\t", size_str[op.type1.size]);
577: else output ("ori%s\t", size_str[op.type1.size]);
578: put_imm (op.addi.size);
579: output (",");
580: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size);
581: goto done;
582: }
583: /* ANDI to CCR */
584: while (op.code == 0x023c) {
585: rd_byte ();
586: output ("andi\t#$%x,ccr", rd_byte ());
587: goto done;
588: }
589: /* ANDI to SR */
590: while (op.code == 0x027c) {
591: output ("andi\t#$%hx,sr", rd_short ());
592: goto done;
593: }
594: /* ASx/LSx reg/imm */
595: while (op.ASx.OP0xe == 0xe) {
596: if (op.ASx.size == 3) break;
597: switch (op.ASx.OP0) {
598: case 0: str = "as"; break;
599: case 1: str = "ls"; break;
600: case 2: str = "rox"; break;
601: default: case 3: str = "ro"; break;
602: }
603: if (op.ASx.ir) {
604: /* data register shift */
605: output ("%s%c%s\td%d,d%d", str,
606: (op.ASx.dr ? 'l' : 'r'),
607: size_str[op.ASx.size],
608: op.ASx.count_reg, op.ASx.reg);
609: } else {
610: /* count shift thingy */
611: output ("%s%c%s\t#%d,d%d", str,
612: (op.ASx.dr ? 'l' : 'r'),
613: size_str[op.ASx.size],
614: (op.ASx.count_reg == 0 ? 8 : op.ASx.count_reg),
615: op.ASx.reg);
616: }
617: goto done;
618: }
619: /* ASx/LSx memory shift */
620: while ((op.MemShift.OP3 == 3) && (op.MemShift.OP0x1c == 0x1c)) {
621: if (op.type1.ea_mode < 0x2) break;
622: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break;
623: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break;
624: switch (op.MemShift.type) {
625: case 0: str = "as"; break;
626: case 1: str = "ls"; break;
627: case 2: str = "rox"; break;
628: default: case 3: str = "ro"; break;
629: }
630: output ("%s%c.w\t", str, (op.ASx.dr ? 'l' : 'r'));
631: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1);
632: goto done;
633: }
634: /* Bcc */
635: while (op.Bcc.op == 0x6) {
636: if (Bcc_str [op.Bcc.cond] == NULL) break;
637: if (op.bra.displacement) {
638: temp = buf_pos + op.Bcc.displacement;
639: output ("b%s.s\t", Bcc_str[op.Bcc.cond]);
640: output_lab (temp);
641: } else {
642: temp = buf_pos;
643: temp += rd_short ();
644: output ("b%s.w\t", Bcc_str[op.Bcc.cond]);
645: output_lab (temp);
646: }
647: goto done;
648: }
649: /* BRA */
650: while (op.bra.op == 0x60) {
651: if (op.bra.displacement) {
652: temp = buf_pos + op.bra.displacement;
653: output ("bra.s\t");
654: output_lab (temp);
655: } else {
656: temp = buf_pos;
657: temp += rd_short ();
658: output ("bra.w\t");
659: output_lab (temp);
660: }
661: goto done;
662: }
663: /* BSR */
664: while ((op.code & 0xff00) == 0x6100) {
665: if (op.bra.displacement) {
666: temp = buf_pos + op.bra.displacement;
667: output ("bsr.s\t");
668: output_lab (temp);
669: } else {
670: temp = buf_pos;
671: temp += rd_short ();
672: output ("bsr.w\t");
673: output_lab (temp);
674: }
675: goto done;
676: }
677: /* BCHG/BCLR/BSET/BTST (Dn,ea) */
678: 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))) {
679: if (op.type2.ea_mode == 0x1) break;
680: if ((op.type2.op_mode != 0x4) && (op.type2.ea_mode == 0x7)) {
681: if (op.type2.ea_reg > 1) break;
682: }
683: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2, -1)) break;
684:
685: if (op.type2.op_mode == 0x4) output ("btst\t");
686: else if (op.type2.op_mode == 0x5) output ("bchg\t");
687: else if (op.type2.op_mode == 0x6) output ("bclr\t");
688: else output ("bset\t");
689: output ("d%d,", op.type2.reg);
690: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2);
691: goto done;
692: }
693: /* BCHG/BCLR/BSET (#<data>,ea) */
694: while ((op.type2.op == 0) && (op.type2.reg == 4) &&
695: ((op.type2.op_mode == 0) || (op.type2.op_mode == 1) || (op.type2.op_mode == 2) || (op.type2.op_mode == 3))) {
696: if (op.type2.ea_mode == 0x1) break;
697: if ((op.type2.ea_mode == 0x7) && (op.type2.ea_reg > 1)) break;
698: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2, 1)) break;
699: temp = rd_byte ();
700: if (temp != 0) {
701: buf_pos--;
702: break;
703: }
704: if (op.type2.op_mode == 0) {
705: output ("btst\t");
706: } else if (op.type2.op_mode == 1) {
707: output ("bchg\t");
708: } else if (op.type2.op_mode == 2) {
709: output ("bclr\t");
710: } else {
711: output ("bset\t");
712: }
713: output ("#$%x,", (int)rd_byte ());
714: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 2);
715: goto done;
716: }
717: /* BKPT */
718: /*while ((op.code & 0xfff8) == 0x4848) {
719: output ("bkpt\t#%d", op.code & 0x7);
720: goto done;
721: }*/
722: /* CHK */
723: while ((op.type2.op == 0x4) && (op.type2.op_mode == 0x6)) {
724: /* no address reg direct */
725: if (op.type2.ea_mode == 0x1) break;
726: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break;
727:
728: output ("chk\t");
729: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1);
730: output (",d%d", op.type2.reg);
731:
732: goto done;
733: }
734: /* CLR */
735: while (op.type1.op == 0x42) {
736: if (op.type1.size == 3) break;
737: /* no address reg direct */
738: if (op.type1.ea_mode == 0x1) break;
739: /* no immediate or pc relative dest */
740: if (op.type1.ea_mode == 0x7) {
741: if (op.type1.ea_reg > 0x1) break;
742: }
743: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break;
744: output ("clr%s\t", size_str[op.type1.size]);
745: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size);
746: goto done;
747: }
748: /* CMP */
749: while (op.type2.op == 11) {
750: if (op.type2.op_mode > 2) break;
751: /* no .b size for adr reg direct */
752: if ((op.type2.op_mode == 0) && (op.type2.ea_mode == 0x1)) break;
753: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode, -1)) break;
754: output ("cmp%s\t", size_str[op.type2.op_mode]);
755: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, op.type2.op_mode);
756: output (",d%d", op.type2.reg);
757: goto done;
758: }
759: /* CMPA */
760: while (op.type2.op == 11) {
761: if ((op.type2.op_mode != 0x3) && (op.type2.op_mode != 0x7)) break;
762: if (op.type2.op_mode == 0x3) size = 1;
763: else size = 2;
764: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, size, -1)) break;
765: output ("cmpa%s\t", size_str [size]);
766: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, size);
767: output (",a%d", op.type2.reg);
768: goto done;
769: }
770: /* CMPI */
771: while ((op.type1.op == 0x0c) && (op.type1.size != 0x3)) {
772: if (op.type1.ea_mode == 0x1) break;
773: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break;
774: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, op.type1.size)) break;
775: output ("cmpi%s\t", size_str [op.type1.size]);
776: put_imm (op.type1.size);
777: output (",");
778: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size);
779: goto done;
780: }
781: /* CMPM */
782: while ((op.cmpm.OP0xb == 0xb) && (op.cmpm.OP2_1 == 0x1) && (op.cmpm.OP1_1 == 0x1)) {
783: if (op.cmpm.size == 3) break;
784: output ("cmpm%s\t(a%d)+,(a%d)+", size_str [op.cmpm.size], op.cmpm.src_reg, op.cmpm.dest_reg);
785: goto done;
786: }
787: /* DBcc */
788: while ((op.DBcc.OP5 == 5) && (op.DBcc.OP25 == 25)) {
789: if (DBcc_str [op.DBcc.cond] == NULL) break;
790: temp = buf_pos;
791: temp += rd_short ();
792: output ("db%s\td%d,", DBcc_str[op.DBcc.cond],
793: op.DBcc.reg);
794: output_lab (temp);
795: goto done;
796: }
797: /* DIVS/DIVU */
798: while ((op.type2.op == 0x8) && ((op.type2.op_mode == 0x7) || (op.type2.op_mode == 0x3))) {
799: if (op.type2.ea_mode == 0x1) break;
800: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break;
801: if (op.type2.op_mode == 0x7) output ("divs\t");
802: else output ("divu\t");
803: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1);
804: output (",d%d", op.type2.reg);
805: goto done;
806: }
807: /* EOR */
808: while (op.type2.op == 0xb) {
809: if ((op.type2.op_mode < 4) || (op.type2.op_mode > 6)) break;
810: if (op.type2.ea_mode == 0x1) break;
811: if ((op.type2.ea_mode == 0x7) && (op.type2.ea_reg > 0x1)) break;
812: size = op.type2.op_mode - 4;
813: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, size, -1)) break;
814: output ("eor%s\t", size_str [size]);
815: output ("d%d,", op.type2.reg);
816: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, size);
817: goto done;
818: }
819: /* EORI to CCR */
820: while (op.code == 0x0a3c) {
821: rd_byte ();
822: output ("eori\t#$%x,ccr", rd_byte ());
823: goto done;
824: }
825: /* EORI to SR */
826: while (op.code == 0x0a7c) {
827: output ("eori\t#$%hx,sr", rd_short ());
828: goto done;
829: }
830: /* EXG */
831: while ((op.exg.OP0xc == 0xc) && (op.exg.OP1 == 1)) {
832: if (op.exg.op_mode == 0x8) {
833: /* data reg swap */
834: output ("exg\td%d,d%d", op.exg.src_reg, op.exg.dest_reg);
835: } else if (op.exg.op_mode == 0x9) {
836: /* address reg swap */
837: output ("exg\ta%d,a%d", op.exg.src_reg, op.exg.dest_reg);
838: } else if (op.exg.op_mode == 0x11) {
839: /* data & adr reg swap */
840: output ("exg\td%d,a%d", op.exg.src_reg, op.exg.dest_reg);
841: } else {
842: break;
843: }
844: goto done;
845: }
846: /* EXT */
847: while ((op.code & 0xfe38) == 0x4800) {
848: if (op.type2.op_mode == 0x2) {
849: output ("ext.w\td%d", op.type2.ea_reg);
850: } else if (op.type2.op_mode == 0x3) {
851: output ("ext.l\td%d", op.type2.ea_reg);
852: } else {
853: break;
854: }
855: goto done;
856: }
857: /* ILLEGAL */
858: while (op.code == 0x4afc) {
859: output ("illegal");
860: goto done;
861: }
862: /* JMP */
863: while ((op.code & 0xffc0) == 0x4ec0) {
864: if (op.jmp.dest_mode == 0) break;
865: if (op.jmp.dest_mode == 1) break;
866: if (op.jmp.dest_mode == 3) break;
867: if (op.jmp.dest_mode == 4) break;
868: if ((op.jmp.dest_mode == 7) &&
869: (op.jmp.dest_reg == 4)) break;
870: if (!is_adrmod (op.jmp.dest_mode, op.jmp.dest_reg, 2, -1)) break;
871: output ("jmp\t");
872: temp = put_adrmod (op.jmp.dest_mode, op.jmp.dest_reg, 2);
873: goto done;
874: }
875: /* JSR */
876: while ((op.code & 0xffc0) == 0x4e80) {
877: if (op.type1.ea_mode == 0) break;
878: if (op.type1.ea_mode == 1) break;
879: if (op.type1.ea_mode == 3) break;
880: if (op.type1.ea_mode == 4) break;
881: /* no immediate dest */
882: if ((op.type1.ea_mode == 7) && (op.type1.ea_reg == 4)) break;
883: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 2, -1)) break;
884: output ("jsr\t");
885: temp = put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 2);
886: goto done;
887: }
888: /* LEA */
889: while ((op.lea.SEVEN == 7) && (op.lea.FOUR == 4)) {
890: if (op.lea.dest_mode == 0) break;
891: if (op.lea.dest_mode == 1) break;
892: if (op.lea.dest_mode == 3) break;
893: if (op.lea.dest_mode == 4) break;
894: /* no immediate dest */
895: if ((op.lea.dest_mode == 7) && (op.lea.dest_reg == 4)) break;
896: if (!is_adrmod (op.lea.dest_mode, op.lea.dest_reg, 2, -1)) break;
897: output ("lea\t");
898: put_adrmod (op.lea.dest_mode, op.lea.dest_reg, 2);
899: output (",a%d", op.lea.reg);
900: goto done;
901: }
902: /* LINK */
903: while ((op.code & 0xfff8) == 0x4e50) {
904: output ("link\ta%d,", op.type1.ea_reg);
905: put_imm (1);
906: goto done;
907: }
908: /* MOVE/MOVEA */
909: while (op.move.op == 0) {
910: if (op.move.size == 0) break;
911: /* byte size and address reg direct is not allowed */
912: if ((op.move.size == 1) && (op.move.src_mode == 0x1)) break;
913: if ((op.move.size == 1) && (op.move.dest_mode == 0x1)) break;
914: if (op.move.dest_mode == 0x7) {
915: if (op.move.dest_reg > 1) break;
916: }
917: size = move_size [op.move.size];
918: if (!is_adrmod (op.move.src_mode, op.move.src_reg, size, -1)) break;
919: if ((op.move.src_mode == 0x7) && (op.move.src_reg == 0x4)) {
920: /* immediate crap in the source so we must skip it */
921: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, size)) break;
922: } else if ((op.move.src_mode == 0x7) && (op.move.src_reg > 0x1)) {
923: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 1)) break;
924: } else if ((op.move.src_mode == 0x7) && (op.move.src_reg == 0x1)) {
925: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 2)) break;
926: } else if ((op.move.src_mode == 0x7) && (op.move.src_reg == 0x0)) {
927: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 1)) break;
928: } else if ((op.move.src_mode == 0x6) || (op.move.src_mode == 0x5)) {
929: /* PC with disp + Dx, (Ax) with disp + Dx */
930: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, 1)) break;
931: } else {
932: if (!is_adrmod (op.move.dest_mode, op.move.dest_reg, size, -1)) break;
933: }
934: if (op.move.dest_mode == 0x1) {
935: output ("movea%s\t", size_str[size]);
936: } else {
937: output ("move%s\t", size_str[size]);
938: }
939:
940: put_adrmod (op.move.src_mode, op.move.src_reg, size);
941: output (",");
942: put_adrmod (op.move.dest_mode, op.move.dest_reg, size);
943: goto done;
944: }
945: /* MOVE to CCR */
946: while ((op.code & 0xffc0) == 0x44c0) {
947: if (op.type1.ea_mode == 0x1) break;
948: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break;
949: output ("move.w\t");
950: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1);
951: output (",ccr");
952: goto done;
953: }
954: /* MOVE from SR */
955: while ((op.code & 0xffc0) == 0x40c0) {
956: if (op.type1.ea_mode == 0x1) break;
957: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break;
958: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break;
959: output ("move.w\tsr,");
960: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1);
961: goto done;
962: }
963: /* MOVE to SR */
964: while ((op.code & 0xffc0) == 0x46c0) {
965: if (op.type1.ea_mode == 0x1) break;
966: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1, -1)) break;
967: output ("move.w\t");
968: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 1);
969: output (",sr");
970: goto done;
971: }
972: /* MOVE USP */
973: while ((op.code & 0xfff0) == 0x4e60) {
974: if (op.addx.rm) {
975: /* USP to Ax */
976: output ("move.l\tusp,a%d", op.addx.src_reg);
977: } else {
978: output ("move.l\ta%d,usp", op.addx.src_reg);
979: }
980: goto done;
981: }
982: /* TODO MOVEC */
983: /* TODO MOVEP */
984: /* MOVEM */
985: while ((op.movem.NINE == 9) && (op.movem.ONE == 1)) {
986: if (op.movem.dr) {
987: /* memory to register */
988: if (op.movem.dest_mode < 2) break;
989: if (op.movem.dest_mode == 4) break;
990: if ((op.movem.dest_mode == 7) && (op.movem.dest_reg == 4)) break;
991: if (!is_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1, 1)) break;
992: temp = rd_short ();
993: output ("movem%s\t", size_str [op.movem.sz+1]);
994: put_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1);
995: output (",");
996: put_movem_regs (temp, 0);
997: } else {
998: /* register to memory */
999: if (op.movem.dest_mode < 2) break;
1000: if (op.movem.dest_mode == 3) break;
1001: if ((op.movem.dest_mode == 7) && (op.movem.dest_reg > 1)) break;
1002: if (!is_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1, 1)) break;
1003: output ("movem%s\t", size_str [op.movem.sz+1]);
1004: put_movem_regs (rd_short (), (op.movem.dest_mode == 4));
1005: output (",");
1006: put_adrmod (op.movem.dest_mode, op.movem.dest_reg, op.movem.sz+1);
1007: }
1008: goto done;
1009: }
1010: /* MOVEQ */
1011: while ((op.moveq.SEVEN == 7) && (op.moveq.ZERO == 0)) {
1012: output ("moveq\t#%d,d%d", op.moveq.data, op.moveq.reg);
1013: goto done;
1014: }
1015: /* MULS/MULU */
1016: while ((op.type2.op == 0xc) && ((op.type2.op_mode == 0x7) || (op.type2.op_mode == 0x3))) {
1017: if (op.type2.ea_mode == 0x1) break;
1018: if (!is_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1, -1)) break;
1019: if (op.type2.op_mode == 0x7) output ("muls\t");
1020: else output ("mulu\t");
1021: put_adrmod (op.type2.ea_mode, op.type2.ea_reg, 1);
1022: output (",d%d", op.type2.reg);
1023: goto done;
1024: }
1025: /* NBCD */
1026: while ((op.code & 0xffc0) == 0x4800) {
1027: if (op.type1.ea_mode == 0x1) break;
1028: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 1)) break;
1029: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0, -1)) break;
1030: output ("nbcd\t");
1031: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0);
1032: goto done;
1033: }
1034: /* NEG/NEGX/NOT */
1035: while ((op.type1.op == 0x44) || (op.type1.op == 0x40) || (op.type1.op == 0x46)) {
1036: if (op.type1.size == 3) break;
1037: if (op.type1.ea_mode == 0x1) break;
1038: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 1)) break;
1039: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break;
1040: if (op.type1.op == 0x44) output ("neg%s\t", size_str [op.type1.size]);
1041: else if (op.type1.op == 0x40) output ("negx%s\t", size_str [op.type1.size]);
1042: else output ("not%s\t", size_str [op.type1.size]);
1043: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size);
1044: goto done;
1045: }
1046: /* NOP */
1047: while (op.code == 0x4e71) {
1048: output ("nop");
1049: goto done;
1050: }
1051: /* ORI to CCR */
1052: while (op.code == 0x003c) {
1053: rd_byte ();
1054: output ("ori\t#$%x,ccr", rd_byte ());
1055: goto done;
1056: }
1057: /* ORI to SR */
1058: while (op.code == 0x007c) {
1059: output ("ori\t#$%hx,sr", rd_short ());
1060: goto done;
1061: }
1062: /* PEA */
1063: while ((op.code & 0xffc0) == 0x4840) {
1064: if (op.type1.ea_mode < 2) break;
1065: if (op.type1.ea_mode == 3) break;
1066: if (op.type1.ea_mode == 4) break;
1067: if ((op.type1.ea_mode == 7) && (op.type1.ea_reg == 4)) break;
1068: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break;
1069: output ("pea\t");
1070: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 2);
1071: goto done;
1072: }
1073: /* RESET */
1074: while (op.code == 0x4e70) {
1075: output ("reset");
1076: goto done;
1077: }
1078: /* RTE */
1079: while (op.code == 0x4e73) {
1080: output ("rte");
1081: goto done;
1082: }
1083: /* RTR */
1084: while (op.code == 0x4e77) {
1085: output ("rtr");
1086: goto done;
1087: }
1088: /* RTS */
1089: while (op.code == 0x4e75) {
1090: output ("rts");
1091: goto done;
1092: }
1093: /* Scc */
1094: while ((op.code & 0xf0c0) == 0x50c0) {
1095: if (op.type1.ea_mode == 1) break;
1096: if ((op.type1.ea_mode == 7) && (op.type1.ea_reg > 1)) break;
1097: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0, -1)) break;
1098: output ("s%s\t", DBcc_str[op.DBcc.cond]);
1099: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0);
1100: goto done;
1101: }
1102: /* STOP */
1103: while (op.code == 0x4e72) {
1104: output ("stop\t");
1105: put_imm (1);
1106: goto done;
1107: }
1108: /* SWAP */
1109: while ((op.code & 0xfff8) == 0x4840) {
1110: output ("swap\td%d", op.code & 0x7);
1111: goto done;
1112: }
1113: /* TAS */
1114: while ((op.code & 0xffc0) == 0x4ac0) {
1115: if (op.type1.ea_mode == 0x1) break;
1116: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break;
1117: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0, -1)) break;
1118: output ("tas\t");
1119: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, 0);
1120: goto done;
1121: }
1122: /* TRAP */
1123: while ((op.code & 0xfff0) == 0x4e40) {
1124: output ("trap\t#%d", op.code & 0xf);
1125: goto done;
1126: }
1127: /* TRAPV */
1128: while (op.code == 0x4e76) {
1129: output ("trapv");
1130: goto done;
1131: }
1132: /* TST */
1133: while (op.type1.op == 0x4a) {
1134: if (op.type1.size == 3) break;
1135: /* no address reg direct */
1136: if (op.type1.ea_mode == 0x1) break;
1137: /* no immediate or pc relative dest */
1138: if ((op.type1.ea_mode == 0x7) && (op.type1.ea_reg > 0x1)) break;
1139: if (!is_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size, -1)) break;
1140: output ("tst%s\t", size_str[op.type1.size]);
1141: put_adrmod (op.type1.ea_mode, op.type1.ea_reg, op.type1.size);
1142: goto done;
1143: }
1144: /* UNLK */
1145: while ((op.code & 0xfff8) == 0x4e58) {
1146: output ("unlk\ta%d", op.code & 0x7);
1147: goto done;
1148: }
1149: /* fuck knows */
1150: output ("dc.w\t$%hx", op.code);
1151: done:
1152: continue;
1153: }
1154: output ("\r\n");
1155: }
1156:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.