/* Copyright (c) 1990 by Sozobon, Limited. Authors: Johann Ruegg, Don Dugger * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * dis3.c */ /* * Modifications: * - in case of ailure to disassemble print operand as a constant * in 'dc.w' instruction * - make printout to align in a nicer way * * Michal Jaegermann, November 1990 */ #include "adb.h" extern long dot; extern int dotoff; extern int opcode_pos; /* this value depends on resolution */ #define DOT (dot+dotoff) int cursz; nextw () { return getwd (); } long nextl () { unsigned int i[2]; i[0] = getwd (); i[1] = getwd (); return ((long) i[0]) << 16 | i[1]; } int op0 (), op1 (), op2 (), op3 (), op4 (), op5 (), op6 (), op7 (); int op8 (), op9 (), opa (), opb (), opc (), opd (), ope (), opf (); int (*funhi[]) () = { op0, op1, op2, op3, op4, op5, op6, op7, op8, op9, opa, opb, opc, opd, ope, opf }; puti () { unsigned int op; int ar_pos; align (opcode_pos); op = nextw (); if (!(*funhi[op >> 12]) (op, ar_pos = opcode_pos + ALIGN_OP)) { prt ("dc.w"); align (ar_pos); prtn ((unsigned long) op, 0); } } #define M_IMM 1 #define M_PX 2 #define M_POFF 4 #define M_ABSL 010 #define M_ABSW 020 #define M_AX 040 #define M_AOFF 0100 #define M_ADEC 0200 #define M_AINC 0400 #define M_ATA 01000 #define M_AREG 02000 #define M_DREG 04000 valid (mode, reg, mask) { if (mode == 7) switch (reg) { case 0: return mask & M_ABSW; case 1: return mask & M_ABSL; case 2: return mask & M_POFF; case 3: return mask & M_PX; case 4: return mask & M_IMM; default: return 0; } else switch (mode) { case 0: return mask & M_DREG; case 1: return mask & M_AREG; case 2: return mask & M_ATA; case 3: return mask & M_AINC; case 4: return mask & M_ADEC; case 5: return mask & M_AOFF; case 6: return mask & M_AX; } } ix_str (n) { int op, r; char c; char *fmt; op = nextw (); r = (op >> 12) & 7; c = (op & 0x800) ? 'l' : 'w'; if (n >= 8) { if (op < 0) fmt = "%i(pc,%a.%c)"; else fmt = "%i(pc,%d.%c)"; prtf (fmt, (char) op, r, c); } else { if (op < 0) fmt = "%i(%a,%a.%c)"; else fmt = "%i(%a,%d.%c)"; prtf (fmt, (char) op, n, r, c); } } modepr (mode, reg) { char *p; switch (mode) { case 0: prtf ("%d", reg); break; case 1: prtf ("%a", reg); break; case 2: prtf ("(%a)", reg); break; case 3: prtf ("(%a)+", reg); break; case 4: prtf ("-(%a)", reg); break; case 5: prtf ("%i(%a)", nextw (), reg); break; case 6: ix_str (reg); break; case 7: switch (reg) { case 0: prtf ("%i", nextw ()); break; case 1: longval (); break; case 2: prtf ("%i(pc)", nextw ()); break; case 3: ix_str (8); break; case 4: switch (cursz) { case 0: case 1: prtf ("#%i", nextw ()); break; case 2: putchr ('#'); longval (); break; } break; } } } longval () { long l; struct sym *sp; prtf ("%A", nextl ()); } char szchr[] = {'b', 'w', 'l'}; struct optbl { char sel[6]; char *name; int allow; char arg[4]; char sz; }; struct optbl t0[] = { {"0s", "or", 05770, "ie"}, {"00", "or", 1, "ic"}, {"01", "or", 1, "is", 1}, {"*4", "btst", 05777, "De"}, {"*5", "bchg", 05770, "De"}, {"*6", "bclr", 05770, "De"}, {"*7", "bset", 05770, "De"}, {"*4", "movep.w", 02000, "oD"}, {"*5", "movep.l", 02000, "oD"}, {"*6", "movep.w", 02000, "Do"}, {"*7", "movep.l", 02000, "Do"}, {"1s", "and", 05770, "ie"}, {"10", "and", 1, "ic"}, {"11", "and", 1, "is", 1}, {"2s", "sub", 05770, "ie"}, {"3s", "add", 05770, "ie"}, {"40", "btst", 05776, "ie"}, {"41", "bchg", 05770, "ie"}, {"42", "bclr", 05770, "ie"}, {"43", "bset", 05770, "ie"}, {"5s", "eor", 05770, "ie"}, {"50", "eor", 1, "ic"}, {"51", "eor", 1, "is", 1}, {"6s", "cmp", 05770, "ie"}, {0, 0, 0, 0} }; op0 (op, pos) unsigned int op; int pos; { return tblop (op, t0, pos); } match (c, val) { switch (c) { case '*': return 1; case 's': return val <= 2; case 'S': return val >= 4 && val <= 6; case 'z': return val >= 1 && val <= 2; case 'Z': return val == 3 || val == 7; default: return val == (c - '0'); } } op1 (op, pos) unsigned int op; int pos; { int sm, sr, dm, dr; sm = (op >> 3) & 7; sr = op & 7; dm = (op >> 6) & 7; dr = (op >> 9) & 7; cursz = 0; if (valid (sm, sr, 07777) && valid (dm, dr, 05770)) { prt ("move.b"); align (pos); modepr (sm, sr); putchr (','); modepr (dm, dr); return 1; } return 0; } op2 (op, pos) unsigned int op; int pos; { int sm, sr, dm, dr; sm = (op >> 3) & 7; sr = op & 7; dm = (op >> 6) & 7; dr = (op >> 9) & 7; cursz = 2; if (valid (sm, sr, 07777) && valid (dm, dr, 07770)) { prt ("move.l"); align (pos); modepr (sm, sr); putchr (','); modepr (dm, dr); return 1; } return 0; } op3 (op, pos) unsigned int op; int pos; { int sm, sr, dm, dr; sm = (op >> 3) & 7; sr = op & 7; dm = (op >> 6) & 7; dr = (op >> 9) & 7; cursz = 1; if (valid (sm, sr, 07777) && valid (dm, dr, 07770)) { prt ("move.w"); align (pos); modepr (sm, sr); putchr (','); modepr (dm, dr); return 1; } return 0; } struct optbl t4[] = { {"0s", "negx", 05770, "e"}, {"03", "move.w", 05770, "se"}, {"*6", "chk", 05777, "eD"}, {"*7", "lea", 01176, "eA"}, {"1s", "clr", 05770, "e"}, {"2s", "neg", 05770, "e"}, {"23", "move.b", 05777, "ec"}, {"3s", "not", 05770, "e"}, {"33", "move.w", 05777, "es", 1}, {"40", "nbcd", 05770, "e"}, {"41", "swap", 04000, "d"}, {"41", "pea", 01176, "e"}, {"42", "ext.w", 04000, "d"}, {"42", "movem.w", 01170, "le"}, {"42", "movem.w", 00200, "Le"}, {"43", "movem.l", 01170, "le"}, {"43", "movem.l", 00200, "Le"}, {"43", "ext.l", 04000, "d"}, {"5s", "tst", 05770, "e"}, {"53", "tas", 05770, "e"}, {"53", "illegal", 0001, ""}, {"71", "trap", 06000, "t"}, {"71", "link", 01000, "ai", 1}, {"71", "unlk", 00400, "a"}, {"71", "move", 00200, "au"}, {"71", "move", 00100, "ua"}, {"7160", "reset", 0, ""}, {"7161", "nop", 0, ""}, {"7162", "stop", 0, ""}, {"7163", "rte", 0, ""}, {"7165", "rts", 0, ""}, {"7166", "trapv", 0, ""}, {"7167", "rtr", 0, ""}, {"72", "jsr", 01176, "e"}, {"73", "jmp", 01176, "e"}, {0, 0, 0, 0} }; op4 (op, pos) unsigned int op; int pos; { int mode, reg, list; if ((op & 07600) == 06200) { reg = op & 7; mode = (op >> 3) & 7; if (valid (mode, reg, 01576)) { prtf ("movem.%c", op & 0100 ? 'l' : 'w'); align (pos); list = nextw (); modepr (mode, reg); putchr (','); rlist (list); return 1; } else return 0; } return tblop (op, t4, pos); } tblop (op, tp, pos) unsigned op; register struct optbl *tp; int pos; { int mode, reg; int hi, lo; reg = op & 7; mode = (op >> 3) & 7; lo = (op >> 6) & 7; hi = (op >> 9) & 7; for (; tp->name; tp++) if (match (tp->sel[0], hi) && match (tp->sel[1], lo) && (tp->allow == 0 || valid (mode, reg, tp->allow)) && (tp->sel[2] == 0 || match (tp->sel[2], mode)) && (tp->sel[3] == 0 || match (tp->sel[3], reg))) { prt (tp->name); switch (tp->sel[1]) { case 's': cursz = lo; break; case 'S': cursz = lo - 4; break; case 'z': cursz = (lo == 1) ? 1 : 2; break; case 'Z': cursz = (lo == 3) ? 1 : 2; break; default: cursz = tp->sz; goto noszpr; } prtf (".%c", szchr[cursz]); noszpr: align (pos); if (tp->arg[0]) { puta (tp->arg[0], op); if (tp->arg[1]) { putchr (','); puta (tp->arg[1], op); } } return 1; } return 0; } puta (c, op) { int reg, mode, hi; reg = op & 7; mode = (op >> 3) & 7; hi = (op >> 9) & 7; switch (c) { case 'i': modepr (7, 4); break; case 'e': modepr (mode, reg); break; case 'c': prt ("ccr"); break; case 's': prt ("sr"); break; case 'D': modepr (0, hi); break; case 'd': modepr (0, reg); break; case 'A': modepr (1, hi); break; case 'a': modepr (1, reg); break; case 'o': modepr (5, reg); break; case 'm': modepr (4, reg); break; case 'M': modepr (4, hi); break; case 'p': modepr (3, reg); break; case 'P': modepr (3, hi); break; case 'l': rlist (nextw ()); break; case 'L': blist (nextw ()); break; case 'u': prt ("usp"); break; case 't': prtf ("#%i", op & 0xf); break; case 'k': prtf ("#%i", hi ? hi : 8); break; } } rlist (x) { int as, ds; ds = x & 0xff; as = (x >> 8) & 0xff; putchr ('['); if (ds) { listc ('d', ds); if (as) { putchr (','); listc ('a', as); } } else if (as) listc ('a', as); putchr (']'); } listc (c, x) char c; { int i; for (i = 0; i < 8;) if (x & (1 << i)) i += chunk (c, x, i); else i++; } chunk (c, x, i) char c; { int j; putchr (c); j = cnt1s (x >> i); if (j == 1) { putchr ('0' + i); return j; } else { putchr ('0' + i); putchr ('-'); putchr ('0' + i + (j - 1)); return j; } } cnt1s (x) { int i; for (i = 0; i < 9; i++) if ((x & (1 << i)) == 0) return i; } blist (x) { int y; int i; unsigned uw = 0x8000; y = 0; for (i = 0; i < 16; i++) if (x & (1 << i)) y |= (uw >> i); rlist (y); } char *bnm[] = {"t", "f", "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le"}; op5 (op, pos) unsigned int op; int pos; { int cond, mode, reg; int sz, k; long svdot = DOT; sz = (op >> 6) & 3; reg = op & 7; mode = (op >> 3) & 7; if (sz == 3) { cond = (op >> 8) & 0xf; if (mode == 1) { prtf ("db%s", bnm[cond]); align (pos); prtf ("%d,%A", reg, svdot + nextw ()); return 1; } else if (valid (mode, reg, 05770)) { prtf ("s%s", bnm[cond]); align (pos); modepr (mode, reg); return 1; } } else { k = (op >> 9) & 7; if (k == 0) k = 8; if (valid (mode, reg, sz ? 07770 : 05770)) { prtf ((op & 0x100) ? "subq.%c" : "addq.%c", szchr[sz]); align (pos); prtf ("#%i,", k); modepr (mode, reg); return 1; } } return 0; } op6 (op, pos) unsigned int op; int pos; { int cond, k; long svdot = DOT; cond = (op >> 8) & 0xf; k = (char) op; if (k == 0) svdot += nextw (); else svdot += k; if (cond < 2) prt (cond ? "bsr" : "bra"); else prtf ("b%s", bnm[cond]); align (pos); prtf ("%A", svdot); return 1; } op7 (op, pos) unsigned int op; int pos; { register int val, reg, k; if (val = (0 == (op & 0x100))) { k = (char) op; reg = (op >> 9) & 7; prt ("moveq"); align (pos); prtf ("#%i,%d", k, reg); } return val; } struct optbl t8[] = { {"*s", "or", 05777, "eD"}, {"*S", "or", 01770, "De"}, {"*3", "divu", 05777, "eD"}, {"*7", "divs", 05777, "eD"}, {"*4", "sbcd", 04000, "dD"}, {"*4", "sbcd", 02000, "mM"}, {0, 0, 0, 0} }; op8 (op, pos) unsigned int op; int pos; { return tblop (op, t8, pos); } struct optbl t9[] = { {"*0", "sub.b", 05777, "eD"}, {"*z", "sub", 07777, "eD"}, {"*S", "sub", 01770, "De"}, {"*Z", "sub", 07777, "eA"}, {"*S", "subx", 04000, "dD"}, {"*S", "subx", 02000, "mM"}, {0, 0, 0, 0} }; op9 (op, pos) unsigned int op; int pos; { return tblop (op, t9, pos); } opa (op, pos) unsigned int op; int pos; { return 0; } struct optbl tb[] = { {"*0", "cmp.b", 05777, "eD"}, {"*z", "cmp", 07777, "eD"}, {"*Z", "cmp", 07777, "eA"}, {"*S", "eor", 05770, "De"}, {"*S", "cmpm", 02000, "pP"}, {0, 0, 0, 0} }; opb (op, pos) unsigned int op; int pos; { return tblop (op, tb, pos); } struct optbl tc[] = { {"*s", "and", 05777, "eD"}, {"*S", "and", 01770, "De"}, {"*3", "mulu", 05777, "eD"}, {"*7", "muls", 05777, "eD"}, {"*4", "abcd", 04000, "dD"}, {"*4", "abcd", 02000, "mM"}, {"*5", "exg", 04000, "dD"}, {"*5", "exg", 02000, "aA"}, {"*6", "exg", 02000, "aD"}, {0, 0, 0, 0} }; opc (op, pos) unsigned op; int pos; { return tblop (op, tc, pos); } struct optbl td[] = { {"*0", "add.b", 05777, "eD"}, {"*z", "add", 07777, "eD"}, {"*S", "add", 01770, "De"}, {"*Z", "add", 07777, "eA"}, {"*S", "addx", 04000, "dD"}, {"*S", "addx", 02000, "mM"}, {0, 0, 0, 0} }; opd (op, pos) unsigned int op; int pos; { return tblop (op, td, pos); } char *shiftnm[] = {"as", "ls", "rox", "ro"}; ope (op, pos) unsigned int op; int pos; { int sz, c_r; int mode, reg; sz = (op >> 6) & 3; if (sz == 3) { mode = (op >> 3) & 7; reg = op & 7; if (valid (mode, reg, 01770)) { prtf ("%s%c.w,", shiftnm[(op >> 9) & 3], (op & 0x100) ? 'l' : 'r'); align (pos); prtf ("#1,"); modepr (mode, reg); return 1; } } else { prtf ("%s%c.%c", shiftnm[(op >> 3) & 3], (op & 0x100) ? 'l' : 'r', szchr[sz]); align (pos); c_r = (op >> 9) & 7; if (op & 040) prtf ("%d", c_r); else prtf ("#%i", c_r ? c_r : 8); prtf (",%d", op & 7); return 1; } return 0; } opf (op, pos) unsigned int op; int pos; { return 0; }