|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <mach.h> ! 5: ! 6: /* ! 7: * 68020-specific debugger interface ! 8: */ ! 9: ! 10: static int m68020ufix(Map*, long*); ! 11: static char *m68020excep(Map*, Rgetter); ! 12: ! 13: static int m68020foll(Map*, ulong, Rgetter, ulong*); ! 14: static int m68020inst(Map*, ulong, char, char*, int); ! 15: static int m68020das(Map*, ulong, char*, int); ! 16: static int m68020instlen(Map*, ulong); ! 17: ! 18: Machdata m68020mach = ! 19: { ! 20: {0x48,0x48,0,0}, /* break point #0 instr. */ ! 21: 2, /* size of break point instr. */ ! 22: ! 23: beswab, /* convert short to local byte order */ ! 24: beswal, /* convert long to local byte order */ ! 25: cisctrace, /* C traceback */ ! 26: ciscframe, /* frame finder */ ! 27: m68020ufix, /* base of ublock with fixup applied */ ! 28: m68020excep, /* print exception */ ! 29: 0, /* breakpoint fixup */ ! 30: beieeesftos, ! 31: beieeedftos, ! 32: m68020foll, /* follow-set calculation */ ! 33: m68020inst, /* print instruction */ ! 34: m68020das, /* dissembler */ ! 35: m68020instlen, /* instruction size */ ! 36: }; ! 37: ! 38: /* ! 39: * 68020 exception frames ! 40: */ ! 41: ! 42: #define BPTTRAP 4 /* breakpoint gives illegal inst */ ! 43: ! 44: static char * excep[] = { ! 45: [2] "bus error", ! 46: [3] "address error", ! 47: [4] "illegal instruction", ! 48: [5] "zero divide", ! 49: [6] "CHK", ! 50: [7] "TRAP", ! 51: [8] "privilege violation", ! 52: [9] "Trace", ! 53: [10] "line 1010", ! 54: [11] "line 1011", ! 55: [13] "coprocessor protocol violation", ! 56: [24] "spurious", ! 57: [25] "incon", ! 58: [26] "tac", ! 59: [27] "auto 3", ! 60: [28] "clock", ! 61: [29] "auto 5", ! 62: [30] "parity", ! 63: [31] "mouse", ! 64: [32] "system call", ! 65: [33] "system call 1", ! 66: [48] "FPCP branch", ! 67: [49] "FPCP inexact", ! 68: [50] "FPCP zero div", ! 69: [51] "FPCP underflow", ! 70: [52] "FPCP operand err", ! 71: [53] "FPCP overflow", ! 72: [54] "FPCP signal NAN", ! 73: }; ! 74: ! 75: static int m68020vec; ! 76: static ! 77: struct ftype{ ! 78: short fmt; ! 79: short len; ! 80: char *name; ! 81: } ftype[] = { /* section 6.5.7 page 6-24 */ ! 82: { 0, 4*2, "Short Format" }, ! 83: { 1, 4*2, "Throwaway" }, ! 84: { 2, 6*2, "Instruction Exception" }, ! 85: { 3, 6*2, "MC68040 Floating Point Exception" }, ! 86: { 8, 29*2, "MC68010 Bus Fault" }, ! 87: { 7, 30*2, "MC68040 Bus Fault" }, ! 88: { 9, 10*2, "Coprocessor mid-Instruction" }, ! 89: { 10, 16*2, "MC68020 Short Bus Fault" }, ! 90: { 11, 46*2, "MC68020 Long Bus Fault" }, ! 91: { 0, 0, 0 } ! 92: }; ! 93: ! 94: static int ! 95: m68020ufix(Map *map, long *val) ! 96: { ! 97: struct ftype *ft; ! 98: int i, size, vec; ! 99: ulong efl[2], stktop; ! 100: uchar *ef=(uchar*)efl; ! 101: long l; ! 102: short fvo; ! 103: ! 104: /* The kernel proc pointer on a 68020 is always ! 105: * at #8xxxxxxx; on the 68040 NeXT, the address ! 106: * is always #04xxxxxx. the sun3 port at sydney ! 107: * uses 0xf8xxxxxx to 0xffxxxxxx. ! 108: */ ! 109: m68020vec = 0; ! 110: *val = 0; ! 111: ! 112: if (get4(map, mach->kbase, (&l)) < 0) ! 113: return -1; ! 114: if ((l&0xfc000000) == 0x04000000) /* if NeXT */ ! 115: size = 30*2; ! 116: else ! 117: size = 46*2; /* 68020 */ ! 118: ! 119: stktop = mach->kbase+mach->pgsize; ! 120: for(i=3; i<100; i++){ ! 121: if (get1(map, stktop-i*4, (uchar*)&l, 4)< 0) ! 122: return -1; ! 123: ! 124: if(machdata->swal(l) == 0xBADC0C0A){ ! 125: if (get1(map, stktop-(i-1)*4, (uchar *)&efl[0], 4) < 0) ! 126: return -1; ! 127: if (get1(map, stktop-(i-2)*4, (uchar *)&efl[1], 4) < 0) ! 128: return -1; ! 129: fvo = (ef[6]<<8)|ef[7]; ! 130: vec = fvo & 0xfff; ! 131: vec >>= 2; ! 132: if(vec >= 256) ! 133: continue; ! 134: ! 135: for(ft=ftype; ft->name; ft++) { ! 136: if(ft->fmt == ((fvo>>12) & 0xF)){ ! 137: m68020vec = vec; ! 138: *val = size+ft->len-8; ! 139: return 1; ! 140: } ! 141: } ! 142: break; ! 143: } ! 144: } ! 145: *val = size; ! 146: werrstr("can't crack exception frame"); ! 147: return -1; ! 148: } ! 149: ! 150: static char * ! 151: m68020excep(Map *map, Rgetter rget) ! 152: { ! 153: ulong pc; ! 154: uchar buf[4]; ! 155: ! 156: USED(map, rget); ! 157: if(excep[m68020vec] == 0) ! 158: return "bad exeception type"; ! 159: ! 160: ! 161: if(m68020vec == BPTTRAP) { ! 162: pc = (*rget)(map, "PC"); ! 163: if (get1(map, pc, buf, machdata->bpsize) > 0) ! 164: if(memcmp(buf, machdata->bpinst, machdata->bpsize) == 0) ! 165: return "breakpoint"; ! 166: } ! 167: return excep[m68020vec]; ! 168: } ! 169: /* 68020 Disassembler and related functions */ ! 170: /* ! 171: not supported: cpBcc, cpDBcc, cpGEN, cpScc, cpTRAPcc, cpRESTORE, cpSAVE ! 172: ! 173: opcode: 1 1 1 1 1 1 ! 174: 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ! 175: %y - register number x x x ! 176: %f - trap vector x x x ! 177: %e - destination eff addr x x x x x x ! 178: %p - conditional predicate x x x x x x ! 179: %s - size code x x ! 180: %C - cache code x x ! 181: %E - source eff addr. x x x x x x ! 182: %d - direction bit x ! 183: %c - condition code x x x x ! 184: %x - register number x x x ! 185: %b - shift count x x x ! 186: %q - daffy 3-bit quick operand or shift count x x x ! 187: %i - immediate operand <varies> ! 188: %t - offset(PC) <varies> ! 189: ! 190: word 1: 1 1 1 1 1 1 ! 191: 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ! 192: %a - register number x x x ! 193: %w - bit field width x x x x x ! 194: %L - MMU function code (SFC/DFC/D%a/#[0-3]) x x x x x ! 195: %P - conditional predicate x x x x x x ! 196: %k - k factor x x x x x x x ! 197: %m - register mask x x x x x x x x ! 198: %N - control register id x x x x x x x x x x x x ! 199: %j - (Dq != Dr) ? Dq:Dr : Dr x x x x x x ! 200: %K - dynamic k register x x x ! 201: %h - register number x x x ! 202: %I - MMU function code mask x x x x ! 203: %o - bit field offset x x x x x ! 204: %u - register number x x x ! 205: %D - float dest reg x x x ! 206: %F - (fdr==fsr) ? "F%D" :"F%B,F%D" x x x x x x ! 207: %S - float source type x x x ! 208: %B - float source register x x x ! 209: %Z - ATC level number x x x ! 210: %H - MMU register x x x x ! 211: %r - register type/number x x x x ! 212: ! 213: word 2: 1 1 1 1 1 1 ! 214: 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 ! 215: %A - register number x x x ! 216: %U - register number x x x ! 217: %R - register type,number x x x x ! 218: ! 219: ----------------------------------------------------------------------------- ! 220: ! 221: %a - register [word 1: 0-2] ! 222: %c - condition code [opcode: 8-11] ! 223: %d - direction [opcode: 8] ! 224: %e - destination effective address [opcode: 0-5] ! 225: %f - trap vector [opcode: 0-3] ! 226: %h - register [word 1: 5-7] ! 227: %i - immediate operand (1, 2, or 4 bytes) ! 228: %j - Dq:Dr if Dq != Dr; else Dr => Dr [word 1: 0-2] Dq [word 1: 12-14] ! 229: %k - k factor [word 1: 0-6] ! 230: %m - register mask [word 1: 0-7] ! 231: %o - bit field offset [word 1: 6-10] ! 232: %p - conditional predicate [opcode: 0-5] ! 233: %q - daffy 3-bit quick operand [opcode: 9-11] ! 234: %r - register type, [word 1: 15], register [word 1: 12-14] ! 235: %s - size [opcode: 6-7] ! 236: %t - offset beyond pc (text address) (2 or 4 bytes) ! 237: %u - register [word 1: 6-8] ! 238: %w - bit field width [word 1: 0-4] ! 239: %x - register [opcode: 9-11] ! 240: %y - register [opcode: 0-2] ! 241: %A - register [word 2: 0-2] ! 242: %B - float source register [word 1: 10-12] ! 243: %C - cache identifier [opcode: 6-7] (IC, DC, or BC) ! 244: %D - float dest reg [word 1: 7-9] ! 245: %E - dest effective address [opcode: 6-11] ! 246: %F - float dest reg == float src reg => "F%D"; else "F%B,F%D" ! 247: %H - MMU reg [word 1: 10-13] (see above & p 4-53/54) ! 248: %I - MMU function code mask [word 1: 5-8] ! 249: %K - dynamic k factor register [word 1: 4-6] ! 250: %L - MMU function code [word 1: 0-4] (SFC, DFC, D%a, or #[0-3]) ! 251: %N - control register [word 1: 0-11] ! 252: %P - conditional predicate [word 1: 0-5] ! 253: %R - register type, [word 2: 15], register [word 2: 12-14] ! 254: %S - float source type code [word 1: 10-12] ! 255: %U - register [word 2: 6-8] ! 256: %Z - ATC level number [word 1: 10-12] ! 257: %1 - Special case: EA as second operand ! 258: */ ! 259: /* Operand classes */ ! 260: enum { ! 261: EAPI = 1, /* extended address: pre decrement only */ ! 262: EACA, /* extended address: control alterable */ ! 263: EACAD, /* extended address: control alterable or Dreg */ ! 264: EACAPI, /* extended address: control alterable or post-incr */ ! 265: EACAPD, /* extended address: control alterable or pre-decr */ ! 266: EAMA, /* extended address: memory alterable */ ! 267: EADA, /* extended address: data alterable */ ! 268: EAA, /* extended address: alterable */ ! 269: EAC, /* extended address: control addressing */ ! 270: EACPI, /* extended address: control addressing or post-incr */ ! 271: EACD, /* extended address: control addressing or Dreg */ ! 272: EAD, /* extended address: data addressing */ ! 273: EAM, /* extended address: memory addressing */ ! 274: EAM_B, /* EAM with byte immediate data */ ! 275: EADI, /* extended address: data addressing or immediate */ ! 276: EADI_L, /* EADI with long immediate data */ ! 277: EADI_W, /* EADI with word immediate data */ ! 278: EAALL, /* extended address: all modes */ ! 279: EAALL_L, /* EAALL with long immediate data */ ! 280: EAALL_W, /* EAALL with word immediate data */ ! 281: EAALL_B, /* EAALL with byte immediate date */ ! 282: /* special codes not directly used for validation */ ! 283: EAFLT, /* extended address: EADI for B, W, L, or S; else EAM */ ! 284: EADDA, /* destination extended address: EADA */ ! 285: BREAC, /* EAC operand for JMP or CALL */ ! 286: OP8, /* low 8 bits of op word */ ! 287: I8, /* low 8-bits of first extension word */ ! 288: I16, /* 16 bits in first extension word */ ! 289: I32, /* 32 bits in first and second extension words */ ! 290: IV, /* 8, 16 or 32 bit data in first & 2nd extension words */ ! 291: C16, /* CAS2 16 bit immediate with bits 9-11 & 3-5 zero */ ! 292: BR8, /* 8 bits in op word or 16 or 32 bits in extension words ! 293: branch instruction format (p. 2-25) */ ! 294: BR16, /* 16-bit branch displacement */ ! 295: BR32, /* 32-bit branch displacement */ ! 296: STACK, /* return PC on stack - follow set only */ ! 297: }; ! 298: /* validation bit masks for various EA classes */ ! 299: enum { ! 300: Dn = 0x0001, /* Data register */ ! 301: An = 0x0002, /* Address register */ ! 302: Ind = 0x0004, /* Address register indirect */ ! 303: Pinc = 0x0008, /* Address register indirect post-increment */ ! 304: Pdec = 0x0010, /* Address register indirect pre-decrement */ ! 305: Bdisp = 0x0020, /* Base/Displacement in all its forms */ ! 306: PCrel = 0x0040, /* PC relative addressing in all its forms */ ! 307: Imm = 0x0080, /* Immediate data */ ! 308: Abs = 0x0100, /* Absolute */ ! 309: }; ! 310: /* EA validation table indexed by operand class number */ ! 311: ! 312: static short validea[] = ! 313: { ! 314: 0, /* none */ ! 315: Pdec, /* EAPI */ ! 316: Abs|Bdisp|Ind, /* EACA */ ! 317: Abs|Bdisp|Ind|Dn, /* EACAD */ ! 318: Abs|Bdisp|Pinc|Ind, /* EACAPI */ ! 319: Abs|Bdisp|Pdec|Ind, /* EACAPD */ ! 320: Abs|Bdisp|Pdec|Pinc|Ind, /* EAMA */ ! 321: Abs|Bdisp|Pdec|Pinc|Ind|Dn, /* EADA */ ! 322: Abs|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAA */ ! 323: Abs|PCrel|Bdisp|Ind, /* EAC */ ! 324: Abs|PCrel|Bdisp|Pinc|Ind, /* EACPI */ ! 325: Abs|PCrel|Bdisp|Ind|Dn, /* EACD */ ! 326: Abs|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EAD */ ! 327: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind, /* EAM */ ! 328: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind, /* EAM_B */ ! 329: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI */ ! 330: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI_L */ ! 331: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|Dn, /* EADI_W */ ! 332: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL */ ! 333: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_L */ ! 334: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_W */ ! 335: Abs|Imm|PCrel|Bdisp|Pdec|Pinc|Ind|An|Dn, /* EAALL_B */ ! 336: }; ! 337: /* EA types */ ! 338: enum ! 339: { ! 340: Dreg, /* Dn */ ! 341: Areg, /* An */ ! 342: AInd, /* (An) */ ! 343: APdec, /* -(An) */ ! 344: APinc, /* (An)+ */ ! 345: ADisp, /* Displacement beyond (An) */ ! 346: BXD, /* Base, Index, Displacement */ ! 347: PDisp, /* Displacement beyond PC */ ! 348: PXD, /* PC, Index, Displacement */ ! 349: ABS, /* absolute */ ! 350: IMM, /* immediate */ ! 351: IREAL, /* single precision real immediate */ ! 352: IEXT, /* extended precision real immediate */ ! 353: IPACK, /* packed real immediate */ ! 354: IDBL, /* double precision real immediate */ ! 355: }; ! 356: ! 357: typedef struct optable Optable; ! 358: typedef struct operand Operand; ! 359: typedef struct inst Inst; ! 360: ! 361: struct optable ! 362: { ! 363: ushort opcode; ! 364: ushort mask0; ! 365: ushort op2; ! 366: ushort mask1; ! 367: char opdata[2]; ! 368: char *format; ! 369: }; ! 370: ! 371: struct operand ! 372: { ! 373: int eatype; ! 374: short ext; ! 375: union { ! 376: long immediate; /* sign-extended integer byte/word/long */ ! 377: struct { /* index mode displacements */ ! 378: long disp; ! 379: long outer; ! 380: }; ! 381: char floater[24]; /* floating point immediates */ ! 382: }; ! 383: }; ! 384: ! 385: struct inst ! 386: { ! 387: int n; /* # bytes in instruction */ ! 388: ulong addr; /* addr of start of instruction */ ! 389: ushort raw[4+12]; /* longest instruction: 24 byte packed immediate */ ! 390: Operand and[2]; ! 391: char *end; /* end of print buffer */ ! 392: char *curr; /* current fill point in buffer */ ! 393: char *errmsg; ! 394: }; ! 395: /* class 0: bit field, MOVEP & immediate instructions */ ! 396: static Optable t0[] = { ! 397: { 0x003c, 0xffff, 0x0000, 0xff00, {I8}, "ORB %i,CCR" }, ! 398: { 0x007c, 0xffff, 0x0000, 0x0000, {I16}, "ORW %i,SR" }, ! 399: { 0x023c, 0xffff, 0x0000, 0xff00, {I8}, "ANDB %i,CCR" }, ! 400: { 0x027c, 0xffff, 0x0000, 0x0000, {I16}, "ANDW %i,SR" }, ! 401: { 0x0a3c, 0xffff, 0x0000, 0xff00, {I8}, "EORB %i,CCR" }, ! 402: { 0x0a7c, 0xffff, 0x0000, 0x0000, {I16}, "EORW %i,SR" }, ! 403: { 0x0cfc, 0xffff, 0x0000, 0x0000, {C16,C16}, "CAS2W R%a:R%A,R%u:R%U,(%r):(%R)"} , ! 404: { 0x0efc, 0xffff, 0x0000, 0x0000, {C16,C16}, "CAS2L R%a:R%A,R%u:R%U,(%r):(%R)"} , ! 405: ! 406: { 0x06c0, 0xfff8, 0x0000, 0x0000, {0}, "RTM R%y" }, ! 407: { 0x06c8, 0xfff8, 0x0000, 0x0000, {0}, "RTM A%y" }, ! 408: { 0x0800, 0xfff8, 0x0000, 0x0000, {I16}, "BTSTL %i,R%y" }, ! 409: { 0x0840, 0xfff8, 0x0000, 0x0000, {I16}, "BCHGL %i,R%y" }, ! 410: { 0x0880, 0xfff8, 0x0000, 0x0000, {I16}, "BCLRL %i,R%y" }, ! 411: ! 412: { 0x00c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2B %e,%r" }, ! 413: { 0x00c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2B %e,%r" }, ! 414: { 0x02c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2W %e,%r" }, ! 415: { 0x02c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2W %e,%r" }, ! 416: { 0x04c0, 0xffc0, 0x0000, 0x0fff, {EAC}, "CMP2L %e,%r" }, ! 417: { 0x04c0, 0xffc0, 0x0800, 0x0fff, {EAC}, "CHK2L %e,%r" }, ! 418: { 0x06c0, 0xffc0, 0x0000, 0x0000, {I16, BREAC}, "CALLM %i,%e" }, ! 419: { 0x0800, 0xffc0, 0x0000, 0x0000, {I16, EAD}, "BTSTB %i,%e" }, ! 420: { 0x0840, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BCHG %i,%e" }, ! 421: { 0x0880, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BCLR %i,%e" }, ! 422: { 0x08c0, 0xffc0, 0x0000, 0x0000, {I16, EADA}, "BSET %i,%e" }, ! 423: { 0x0ac0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASB R%a,R%u,%e" }, ! 424: { 0x0cc0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASW R%a,R%u,%e" }, ! 425: { 0x0ec0, 0xffc0, 0x0000, 0xfe38, {EAMA}, "CASL R%a,R%u,%e" }, ! 426: ! 427: { 0x0000, 0xff00, 0x0000, 0x0000, {IV, EADA}, "OR%s %i,%e" }, ! 428: { 0x0200, 0xff00, 0x0000, 0x0000, {IV, EADA}, "AND%s %i,%e" }, ! 429: { 0x0400, 0xff00, 0x0000, 0x0000, {IV, EADA}, "SUB%s %i,%e" }, ! 430: { 0x0600, 0xff00, 0x0000, 0x0000, {IV, EADA}, "ADD%s %i,%e" }, ! 431: { 0x0a00, 0xff00, 0x0000, 0x0000, {IV, EADA}, "EOR%s %i,%e" }, ! 432: { 0x0c00, 0xff00, 0x0000, 0x0000, {IV, EAD}, "CMP%s %i,%e" }, ! 433: { 0x0e00, 0xff00, 0x0000, 0x0800, {EAMA}, "MOVES%s %e,%r" }, ! 434: { 0x0e00, 0xff00, 0x0800, 0x0800, {EAMA}, "MOVES%s %r,%e" }, ! 435: ! 436: { 0x0108, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPW (%i,A%y),R%x" }, ! 437: { 0x0148, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPL (%i,A%y),R%x" }, ! 438: { 0x0188, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPW R%x,(%i,A%y)" }, ! 439: { 0x01c8, 0xf1f8, 0x0000, 0x0000, {I16}, "MOVEPL R%x,(%i,A%y)" }, ! 440: { 0x0100, 0xf1f8, 0x0000, 0x0000, {0}, "BTSTL R%x,R%y" }, ! 441: { 0x0140, 0xf1f8, 0x0000, 0x0000, {0}, "BCHGL R%x,R%y" }, ! 442: { 0x0180, 0xf1f8, 0x0000, 0x0000, {0}, "BCLRL R%x,R%y" }, ! 443: { 0x01c0, 0xf1f8, 0x0000, 0x0000, {0}, "BSET R%x,R%y" }, ! 444: ! 445: { 0x0100, 0xf1c0, 0x0000, 0x0000, {EAM_B}, "BTSTB R%x,%e" }, ! 446: { 0x0140, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BCHG R%x,%e" }, ! 447: { 0x0180, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BCLR R%x,%e" }, ! 448: { 0x01c0, 0xf1c0, 0x0000, 0x0000, {EAMA}, "BSET R%x,%e" }, ! 449: { 0,0,0,0,{0},0 }, ! 450: }; ! 451: /* class 1: move byte */ ! 452: static Optable t1[] = { ! 453: { 0x1000, 0xf000, 0x0000, 0x0000, {EAALL_B,EADDA},"MOVB %e,%E" }, ! 454: { 0,0,0,0,{0},0 }, ! 455: }; ! 456: /* class 2: move long */ ! 457: static Optable t2[] = { ! 458: { 0x2040, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "MOVL %e,A%x" }, ! 459: ! 460: { 0x2000, 0xf000, 0x0000, 0x0000, {EAALL_L,EADDA},"MOVL %e,%E" }, ! 461: { 0,0,0,0,{0},0 }, ! 462: }; ! 463: /* class 3: move word */ ! 464: static Optable t3[] = { ! 465: { 0x3040, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "MOVW %e,A%x" }, ! 466: ! 467: { 0x3000, 0xf000, 0x0000, 0x0000, {EAALL_W,EADDA},"MOVW %e,%E" }, ! 468: { 0,0,0,0,{0},0 }, ! 469: }; ! 470: /* class 4: miscellaneous */ ! 471: static Optable t4[] = { ! 472: { 0x4e75, 0xffff, 0x0000, 0x0000, {STACK}, "RTS" }, ! 473: { 0x4e77, 0xffff, 0x0000, 0x0000, {STACK}, "RTR" }, ! 474: { 0x4afc, 0xffff, 0x0000, 0x0000, {0}, "ILLEGAL" }, ! 475: { 0x4e71, 0xffff, 0x0000, 0x0000, {0}, "NOP" }, ! 476: { 0x4e74, 0xffff, 0x0000, 0x0000, {I16, STACK}, "RTD %i" }, ! 477: { 0x4e76, 0xffff, 0x0000, 0x0000, {0}, "TRAPV" }, ! 478: { 0x4e70, 0xffff, 0x0000, 0x0000, {0}, "RESET" }, ! 479: { 0x4e72, 0xffff, 0x0000, 0x0000, {I16}, "STOP %i" }, ! 480: { 0x4e73, 0xffff, 0x0000, 0x0000, {0}, "RTE" }, ! 481: { 0x4e7a, 0xffff, 0x0000, 0x0000, {I16}, "MOVEL %N,%r" }, ! 482: { 0x4e7b, 0xffff, 0x0000, 0x0000, {I16}, "MOVEL %r,%N" }, ! 483: ! 484: { 0x4808, 0xfff8, 0x0000, 0x0000, {I32}, "LINKL A%y,%i" }, ! 485: { 0x4840, 0xfff8, 0x0000, 0x0000, {0}, "SWAPW R%y" }, ! 486: { 0x4848, 0xfff8, 0x0000, 0x0000, {0}, "BKPT #%y" }, ! 487: { 0x4880, 0xfff8, 0x0000, 0x0000, {0}, "EXTW R%y" }, ! 488: { 0x48C0, 0xfff8, 0x0000, 0x0000, {0}, "EXTL R%y" }, ! 489: { 0x49C0, 0xfff8, 0x0000, 0x0000, {0}, "EXTBL R%y" }, ! 490: { 0x4e50, 0xfff8, 0x0000, 0x0000, {I16}, "LINKW A%y,%i" }, ! 491: { 0x4e58, 0xfff8, 0x0000, 0x0000, {0}, "UNLK A%y" }, ! 492: { 0x4e60, 0xfff8, 0x0000, 0x0000, {0}, "MOVEL (A%y),USP" }, ! 493: { 0x4e68, 0xfff8, 0x0000, 0x0000, {0}, "MOVEL USP,(A%y)" }, ! 494: ! 495: { 0x4e40, 0xfff0, 0x0000, 0x0000, {0}, "SYS %f" }, ! 496: ! 497: { 0x40c0, 0xffc0, 0x0000, 0x0000, {EADA}, "MOVW SR,%e" }, ! 498: { 0x42c0, 0xffc0, 0x0000, 0x0000, {EADA}, "MOVW CCR,%e" }, ! 499: { 0x44c0, 0xffc0, 0x0000, 0x0000, {EADI_W}, "MOVW %e,CCR" }, ! 500: { 0x46c0, 0xffc0, 0x0000, 0x0000, {EADI_W}, "MOVW %e,SR" }, ! 501: { 0x4800, 0xffc0, 0x0000, 0x0000, {EADA}, "NBCDB %e" }, ! 502: { 0x4840, 0xffc0, 0x0000, 0x0000, {EAC}, "PEA %e" }, ! 503: { 0x4880, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEMW %i,%e" }, ! 504: { 0x48c0, 0xffc0, 0x0000, 0x0000, {I16, EACAPD},"MOVEML %i,%e" }, ! 505: { 0x4ac0, 0xffc0, 0x0000, 0x0000, {EADA}, "TAS %e" }, ! 506: { 0x4a00, 0xffc0, 0x0000, 0x0000, {EAD}, "TSTB %e" }, ! 507: { 0x4c00, 0xffc0, 0x0000, 0x8ff8, {EADI_L}, "MULUL %e,%r" }, ! 508: { 0x4c00, 0xffc0, 0x0400, 0x8ff8, {EADI_L}, "MULUL %e,R%a:%r" }, ! 509: { 0x4c00, 0xffc0, 0x0800, 0x8ff8, {EADI_L}, "MULSL %e,%r" }, ! 510: { 0x4c00, 0xffc0, 0x0c00, 0x8ff8, {EADI_L}, "MULSL %e,R%a:%r" }, ! 511: { 0x4c40, 0xffc0, 0x0000, 0x8ff8, {EADI_L}, "DIVUL %e,%j" }, ! 512: { 0x4c40, 0xffc0, 0x0400, 0x8ff8, {EADI_L}, "DIVUD %e,%r:R%a" }, ! 513: { 0x4c40, 0xffc0, 0x0800, 0x8ff8, {EADI_L}, "DIVSL %e,%j" }, ! 514: { 0x4c40, 0xffc0, 0x0c00, 0x8ff8, {EADI_L}, "DIVSD %e,%r:R%a" }, ! 515: { 0x4c80, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEMW %1,%i" }, ! 516: { 0x4cc0, 0xffc0, 0x0000, 0x0000, {I16, EACPI}, "MOVEML %1,%i" }, ! 517: { 0x4e80, 0xffc0, 0x0000, 0x0000, {BREAC}, "JSR %e" }, ! 518: { 0x4ec0, 0xffc0, 0x0000, 0x0000, {BREAC}, "JMP %e" }, ! 519: ! 520: { 0x4000, 0xff00, 0x0000, 0x0000, {EADA}, "NEGX%s %e" }, ! 521: { 0x4200, 0xff00, 0x0000, 0x0000, {EADA}, "CLR%s %e" }, ! 522: { 0x4400, 0xff00, 0x0000, 0x0000, {EADA}, "NEG%s %e" }, ! 523: { 0x4600, 0xff00, 0x0000, 0x0000, {EADA}, "NOT%s %e" }, ! 524: { 0x4a00, 0xff00, 0x0000, 0x0000, {EAALL}, "TST%s %e" }, ! 525: ! 526: { 0x4180, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "CHKW %e,R%x" }, ! 527: { 0x41c0, 0xf1c0, 0x0000, 0x0000, {EAC}, "LEA %e,A%x" }, ! 528: { 0x4100, 0xf1c0, 0x0000, 0x0000, {EADI_L}, "CHKL %e,R%x" }, ! 529: { 0,0,0,0,{0},0 }, ! 530: }; ! 531: /* class 5: miscellaneous quick, branch & trap instructions */ ! 532: static Optable t5[] = { ! 533: { 0x5000, 0xf1c0, 0x0000, 0x0000, {EADA}, "ADDB $Q#%q,%e" }, ! 534: { 0x5100, 0xf1c0, 0x0000, 0x0000, {EADA}, "SUBB $Q#%q,%e" }, ! 535: ! 536: { 0x50c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" }, ! 537: { 0x51c8, 0xf1f8, 0x0000, 0x0000, {BR16}, "DB%c R%y,%t" }, ! 538: ! 539: { 0x5000, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDB $Q#%q,%e" }, ! 540: { 0x5040, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDW $Q#%q,%e" }, ! 541: { 0x5080, 0xf1c0, 0x0000, 0x0000, {EAA}, "ADDL $Q#%q,%e" }, ! 542: { 0x5100, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBB $Q#%q,%e" }, ! 543: { 0x5140, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBW $Q#%q,%e" }, ! 544: { 0x5180, 0xf1c0, 0x0000, 0x0000, {EAA}, "SUBL $Q#%q,%e" }, ! 545: ! 546: { 0x50fa, 0xf0ff, 0x0000, 0x0000, {I16}, "TRAP%cW %i" }, ! 547: { 0x50fb, 0xf0ff, 0x0000, 0x0000, {I32}, "TRAP%cL %i" }, ! 548: { 0x50fc, 0xf0ff, 0x0000, 0x0000, {0}, "TRAP%c" }, ! 549: ! 550: { 0x50c0, 0xf0c0, 0x0000, 0x0000, {EADA}, "S%c %e" }, ! 551: { 0,0,0,0,{0},0 }, ! 552: }; ! 553: /* class 6: branch instructions */ ! 554: static Optable t6[] = { ! 555: { 0x6000, 0xff00, 0x0000, 0x0000, {BR8}, "BRA %t" }, ! 556: { 0x6100, 0xff00, 0x0000, 0x0000, {BR8}, "BSR %t" }, ! 557: { 0x6000, 0xf000, 0x0000, 0x0000, {BR8}, "B%c %t" }, ! 558: { 0,0,0,0,{0},0 }, ! 559: }; ! 560: /* class 7: move quick */ ! 561: static Optable t7[] = { ! 562: { 0x7000, 0xf100, 0x0000, 0x0000, {OP8}, "MOVL $Q%i,R%x" }, ! 563: { 0,0,0,0,{0},0 }, ! 564: }; ! 565: /* class 8: BCD operations, DIV, and OR instructions */ ! 566: static Optable t8[] = { ! 567: { 0x8100, 0xf1f8, 0x0000, 0x0000, {0}, "SBCDB R%y,R%x" }, ! 568: { 0x8108, 0xf1f8, 0x0000, 0x0000, {0}, "SBCDB -(A%y),-(A%x)" }, ! 569: { 0x8140, 0xf1f8, 0x0000, 0x0000, {I16}, "PACK R%y,R%x,%i" }, ! 570: { 0x8148, 0xf1f8, 0x0000, 0x0000, {I16}, "PACK -(A%y),-(A%x),%i" }, ! 571: { 0x8180, 0xf1f8, 0x0000, 0x0000, {I16}, "UNPK R%y,R%x,%i" }, ! 572: { 0x8188, 0xf1f8, 0x0000, 0x0000, {I16}, "UNPK -(A%y),-(A%x),%i" }, ! 573: ! 574: { 0x80c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVUW %e,R%x" }, ! 575: { 0x81c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "DIVSW %e,R%x" }, ! 576: ! 577: { 0x8000, 0xf100, 0x0000, 0x0000, {EADI}, "OR%s %e,R%x" }, ! 578: { 0x8100, 0xf100, 0x0000, 0x0000, {EAMA}, "OR%s R%x,%e" }, ! 579: { 0,0,0,0,{0},0 }, ! 580: }; ! 581: /* class 9: subtract instruction */ ! 582: static Optable t9[] = { ! 583: { 0x90c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "SUBW %e,A%x" }, ! 584: { 0x91c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "SUBL %e,A%x" }, ! 585: ! 586: { 0x9100, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s R%y,R%x" }, ! 587: { 0x9108, 0xf138, 0x0000, 0x0000, {0}, "SUBX%s -(A%y),-(A%x)" }, ! 588: ! 589: { 0x9000, 0xf100, 0x0000, 0x0000, {EAALL}, "SUB%s %e,R%x" }, ! 590: { 0x9100, 0xf100, 0x0000, 0x0000, {EAMA}, "SUB%s R%x,%e" }, ! 591: { 0,0,0,0,{0},0 }, ! 592: }; ! 593: /* class b: CMP & EOR */ ! 594: static Optable tb[] = { ! 595: { 0xb000, 0xf1c0, 0x0000, 0x0000, {EADI}, "CMPB R%x,%e" }, ! 596: { 0xb040, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "CMPW R%x,%e" }, ! 597: { 0xb080, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "CMPL R%x,%e" }, ! 598: { 0xb0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "CMPW A%x,%e" }, ! 599: { 0xb1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "CMPL A%x,%e" }, ! 600: ! 601: { 0xb108, 0xf138, 0x0000, 0x0000, {0}, "CMP%s (A%y)+,(A%x)+" }, ! 602: ! 603: { 0xb100, 0xf100, 0x0000, 0x0000, {EADA}, "EOR%s %e,R%x" }, ! 604: { 0,0,0,0,{0},0 }, ! 605: }; ! 606: /* class c: AND, MUL, BCD & Exchange */ ! 607: static Optable tc[] = { ! 608: { 0xc100, 0xf1f8, 0x0000, 0x0000, {0}, "ABCDB R%y,R%x" }, ! 609: { 0xc108, 0xf1f8, 0x0000, 0x0000, {0}, "ABCDB -(A%y),-(A%x)" }, ! 610: { 0xc140, 0xf1f8, 0x0000, 0x0000, {0}, "EXG R%x,R%y" }, ! 611: { 0xc148, 0xf1f8, 0x0000, 0x0000, {0}, "EXG A%x,A%y" }, ! 612: { 0xc188, 0xf1f8, 0x0000, 0x0000, {0}, "EXG R%x,A%y" }, ! 613: ! 614: { 0xc0c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULUW %e,R%x" }, ! 615: { 0xc1c0, 0xf1c0, 0x0000, 0x0000, {EADI_W}, "MULSW %e,R%x" }, ! 616: ! 617: { 0xc000, 0xf100, 0x0000, 0x0000, {EADI}, "AND%s %e,R%x" }, ! 618: { 0xc100, 0xf100, 0x0000, 0x0000, {EAMA}, "AND%s R%x,%e" }, ! 619: { 0,0,0,0,{0},0 }, ! 620: }; ! 621: /* class d: addition */ ! 622: static Optable td[] = { ! 623: { 0xd000, 0xf1c0, 0x0000, 0x0000, {EADI}, "ADDB %e,R%x" }, ! 624: { 0xd0c0, 0xf1c0, 0x0000, 0x0000, {EAALL_W}, "ADDW %e,A%x" }, ! 625: { 0xd1c0, 0xf1c0, 0x0000, 0x0000, {EAALL_L}, "ADDL %e,A%x" }, ! 626: ! 627: { 0xd100, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s R%y,R%x" }, ! 628: { 0xd108, 0xf138, 0x0000, 0x0000, {0}, "ADDX%s -(A%y),-(A%x)" }, ! 629: ! 630: { 0xd000, 0xf100, 0x0000, 0x0000, {EAALL}, "ADD%s %e,R%x" }, ! 631: { 0xd100, 0xf100, 0x0000, 0x0000, {EAMA}, "ADD%s R%x,%e" }, ! 632: { 0,0,0,0,{0},0 }, ! 633: }; ! 634: /* class e: shift, rotate, bit field operations */ ! 635: static Optable te[] = { ! 636: { 0xe8c0, 0xffc0, 0x0820, 0xfe38, {EACD}, "BFTST %e{R%u:R%a}" }, ! 637: { 0xe8c0, 0xffc0, 0x0800, 0xfe20, {EACD}, "BFTST %e{R%u:%w}" }, ! 638: { 0xe8c0, 0xffc0, 0x0020, 0xf838, {EACD}, "BFTST %e{%o:R%a}" }, ! 639: { 0xe8c0, 0xffc0, 0x0000, 0xf820, {EACD}, "BFTST %e{%o:%w}" }, ! 640: ! 641: { 0xe9c0, 0xffc0, 0x0820, 0x8e38, {EACD}, "BFEXTU %e{R%u:R%a},%r" }, ! 642: { 0xe9c0, 0xffc0, 0x0800, 0x8e20, {EACD}, "BFEXTU %e{R%u:%w},%r" }, ! 643: { 0xe9c0, 0xffc0, 0x0020, 0x8838, {EACD}, "BFEXTU %e{%o:R%a},%r" }, ! 644: { 0xe9c0, 0xffc0, 0x0000, 0x8820, {EACD}, "BFEXTU %e{%o:%w},%r" }, ! 645: ! 646: { 0xeac0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFCHG %e{R%u:R%a}" }, ! 647: { 0xeac0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFCHG %e{R%u:%w}" }, ! 648: { 0xeac0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFCHG %e{%o:R%a}" }, ! 649: { 0xeac0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFCHG %e{%o:%w}" }, ! 650: ! 651: { 0xebc0, 0xffc0, 0x0820, 0x8e38, {EACD}, "BFEXTS %e{R%u:R%a},%r" }, ! 652: { 0xebc0, 0xffc0, 0x0800, 0x8e20, {EACD}, "BFEXTS %e{R%u:%w},%r" }, ! 653: { 0xebc0, 0xffc0, 0x0020, 0x8838, {EACD}, "BFEXTS %e{%o:R%a},%r" }, ! 654: { 0xebc0, 0xffc0, 0x0000, 0x8820, {EACD}, "BFEXTS %e{%o:%w},%r" }, ! 655: ! 656: { 0xecc0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFCLR %e{R%u:R%a}" }, ! 657: { 0xecc0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFCLR %e{R%u:%w}" }, ! 658: { 0xecc0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFCLR %e{%o:R%a}" }, ! 659: { 0xecc0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFCLR %e{%o:%w}" }, ! 660: ! 661: { 0xedc0, 0xffc0, 0x0820, 0x8e38, {EACAD}, "BFFFO %e{R%u:R%a},%r" }, ! 662: { 0xedc0, 0xffc0, 0x0800, 0x8e20, {EACAD}, "BFFFO %e{R%u:%w},%r" }, ! 663: { 0xedc0, 0xffc0, 0x0020, 0x8838, {EACAD}, "BFFFO %e{%o:R%a},%r" }, ! 664: { 0xedc0, 0xffc0, 0x0000, 0x8820, {EACAD}, "BFFFO %e{%o:%w},%r" }, ! 665: ! 666: { 0xeec0, 0xffc0, 0x0820, 0xfe38, {EACAD}, "BFSET %e{R%u:R%a}" }, ! 667: { 0xeec0, 0xffc0, 0x0800, 0xfe20, {EACAD}, "BFSET %e{R%u:%w}" }, ! 668: { 0xeec0, 0xffc0, 0x0020, 0xf838, {EACAD}, "BFSET %e{%o:R%a}" }, ! 669: { 0xeec0, 0xffc0, 0x0000, 0xf820, {EACAD}, "BFSET %e{%o:%w}" }, ! 670: ! 671: { 0xefc0, 0xffc0, 0x0820, 0x8e38, {EACAD}, "BFINS %r,%e{R%u:R%a}" }, ! 672: { 0xefc0, 0xffc0, 0x0800, 0x8e20, {EACAD}, "BFINS %r,%e{R%u:%w}" }, ! 673: { 0xefc0, 0xffc0, 0x0020, 0x8838, {EACAD}, "BFINS %r,%e{%o:R%a}" }, ! 674: { 0xefc0, 0xffc0, 0x0000, 0x8820, {EACAD}, "BFINS %r,%e{%o:%w}" }, ! 675: ! 676: { 0xe0c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "AS%dW %e" }, ! 677: { 0xe2c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "LS%dW %e" }, ! 678: { 0xe4c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "ROX%dW %e" }, ! 679: { 0xe6c0, 0xfec0, 0x0000, 0x0000, {EAMA}, "RO%dW %e" }, ! 680: ! 681: { 0xe000, 0xf038, 0x0000, 0x0000, {0}, "AS%d%s #%q,R%y" }, ! 682: { 0xe008, 0xf038, 0x0000, 0x0000, {0}, "LS%d%s #%q,R%y" }, ! 683: { 0xe010, 0xf038, 0x0000, 0x0000, {0}, "ROX%d%s #%q,R%y" }, ! 684: { 0xe018, 0xf038, 0x0000, 0x0000, {0}, "RO%d%s #%q,R%y" }, ! 685: { 0xe020, 0xf038, 0x0000, 0x0000, {0}, "AS%d%s R%x,R%y" }, ! 686: { 0xe028, 0xf038, 0x0000, 0x0000, {0}, "LS%d%s R%x,R%y" }, ! 687: { 0xe030, 0xf038, 0x0000, 0x0000, {0}, "ROX%d%s R%x,R%y" }, ! 688: { 0xe038, 0xf038, 0x0000, 0x0000, {0}, "RO%d%s R%x,R%y" }, ! 689: { 0,0,0,0,{0},0 }, ! 690: }; ! 691: /* class f: coprocessor and mmu instructions */ ! 692: static Optable tf[] = { ! 693: { 0xf280, 0xffff, 0x0000, 0xffff, {0}, "FNOP" }, ! 694: { 0xf200, 0xffff, 0x5c00, 0xfc00, {0}, "FMOVECRX %k,F%D" }, ! 695: { 0xf27a, 0xffff, 0x0000, 0xffc0, {I16}, "FTRAP%P %i" }, ! 696: { 0xf27b, 0xffff, 0x0000, 0xffc0, {I32}, "FTRAP%P %i" }, ! 697: { 0xf27c, 0xffff, 0x0000, 0xffc0, {0}, "FTRAP%P" }, ! 698: ! 699: { 0xf248, 0xfff8, 0x0000, 0xffc0, {BR16}, "FDB%P R%y,%t" }, ! 700: { 0xf620, 0xfff8, 0x8000, 0x8fff, {0}, "MOVE16 (A%y)+,(%r)+" }, ! 701: { 0xf500, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHN (A%y)" }, ! 702: { 0xf508, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSH (A%y)" }, ! 703: { 0xf510, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHAN" }, ! 704: { 0xf518, 0xfff8, 0x0000, 0x0000, {0}, "PFLUSHA" }, ! 705: { 0xf548, 0xfff8, 0x0000, 0x0000, {0}, "PTESTW (A%y)" }, ! 706: { 0xf568, 0xfff8, 0x0000, 0x0000, {0}, "PTESTR (A%y)" }, ! 707: { 0xf600, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 (A%y)+,$%i" }, ! 708: { 0xf608, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 $%i,(A%y)-" }, ! 709: { 0xf610, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 (A%y),$%i" }, ! 710: { 0xf618, 0xfff8, 0x0000, 0x0000, {I32}, "MOVE16 $%i,(A%y)" }, ! 711: ! 712: { 0xf000, 0xffc0, 0x0800, 0xffff, {EACA}, "PMOVE %e,TT0" }, ! 713: { 0xf000, 0xffc0, 0x0900, 0xffff, {EACA}, "PMOVEFD %e,TT0" }, ! 714: { 0xf000, 0xffc0, 0x0a00, 0xffff, {EACA}, "PMOVE TT0,%e" }, ! 715: { 0xf000, 0xffc0, 0x0b00, 0xffff, {EACA}, "PMOVEFD TT0,%e" }, ! 716: { 0xf000, 0xffc0, 0x0c00, 0xffff, {EACA}, "PMOVE %e,TT1" }, ! 717: { 0xf000, 0xffc0, 0x0d00, 0xffff, {EACA}, "PMOVEFD %e,TT1" }, ! 718: { 0xf000, 0xffc0, 0x0e00, 0xffff, {EACA}, "PMOVE TT1,%e" }, ! 719: { 0xf000, 0xffc0, 0x0f00, 0xffff, {EACA}, "PMOVEFD TT1,%e" }, ! 720: { 0xf000, 0xffc0, 0x2400, 0xffff, {0}, "PFLUSHA" }, ! 721: { 0xf000, 0xffc0, 0x2800, 0xffff, {EACA}, "PVALID VAL,%e" }, ! 722: { 0xf000, 0xffc0, 0x6000, 0xffff, {EACA}, "PMOVE %e,MMUSR" }, ! 723: { 0xf000, 0xffc0, 0x6200, 0xffff, {EACA}, "PMOVE MMUSR,%e" }, ! 724: { 0xf000, 0xffc0, 0x2800, 0xfff8, {EACA}, "PVALID A%a,%e" }, ! 725: { 0xf000, 0xffc0, 0x2000, 0xffe0, {EACA}, "PLOADW %L,%e" }, ! 726: { 0xf000, 0xffc0, 0x2200, 0xffe0, {EACA}, "PLOADR %L,%e" }, ! 727: { 0xf000, 0xffc0, 0x8000, 0xffe0, {EACA}, "PTESTW %L,%e,#0" }, ! 728: { 0xf000, 0xffc0, 0x8200, 0xffe0, {EACA}, "PTESTR %L,%e,#0" }, ! 729: { 0xf000, 0xffc0, 0x3000, 0xfe00, {0}, "PFLUSH %L,#%I" }, ! 730: { 0xf000, 0xffc0, 0x3800, 0xfe00, {EACA}, "PFLUSH %L,#%I,%e" }, ! 731: { 0xf000, 0xffc0, 0x8000, 0xe300, {EACA}, "PTESTW %L,%e,#%Z" }, ! 732: { 0xf000, 0xffc0, 0x8100, 0xe300, {EACA}, "PTESTW %L,%e,#%Z,A%h" }, ! 733: { 0xf000, 0xffc0, 0x8200, 0xe300, {EACA}, "PTESTR %L,%e,#%Z" }, ! 734: { 0xf000, 0xffc0, 0x8300, 0xe300, {EACA}, "PTESTR %L,%e,#%Z,A%h" }, ! 735: { 0xf000, 0xffc0, 0x4000, 0xc3ff, {EACA}, "PMOVE %e,%H" }, ! 736: { 0xf000, 0xffc0, 0x4100, 0xc3ff, {EACA}, "PMOVEFD %e,%H" }, ! 737: { 0xf000, 0xffc0, 0x4200, 0xc3ff, {EACA}, "PMOVE %H,%e" }, ! 738: ! 739: /* floating point (coprocessor 1)*/ ! 740: ! 741: { 0xf200, 0xffc0, 0x8400, 0xffff, {EAALL_L}, "FMOVEL %e,FPIAR" }, ! 742: { 0xf200, 0xffc0, 0x8800, 0xffff, {EADI_L}, "FMOVEL %e,FPSR" }, ! 743: { 0xf200, 0xffc0, 0x9000, 0xffff, {EADI_L}, "FMOVEL %e,FPCR" }, ! 744: { 0xf200, 0xffc0, 0xa400, 0xffff, {EAA}, "FMOVEL FPIAR,%e" }, ! 745: { 0xf200, 0xffc0, 0xa800, 0xffff, {EADA}, "FMOVEL FPSR,%e" }, ! 746: { 0xf200, 0xffc0, 0xb000, 0xffff, {EADA}, "FMOVEL FPCR,%e" }, ! 747: ! 748: { 0xf240, 0xffc0, 0x0000, 0xffc0, {EADA}, "FS%P %e" }, ! 749: ! 750: { 0xf200, 0xffc0, 0xd000, 0xff00, {EACPI}, "FMOVEMX %e,%m" }, ! 751: { 0xf200, 0xffc0, 0xd800, 0xff00, {EACPI}, "FMOVEMX %e,R%K" }, ! 752: { 0xf200, 0xffc0, 0xe000, 0xff00, {EAPI}, "FMOVEMX %m,-(A%y)" }, ! 753: { 0xf200, 0xffc0, 0xe800, 0xff00, {EAPI}, "FMOVEMX R%K,-(A%y)" }, ! 754: { 0xf200, 0xffc0, 0xf000, 0xff00, {EACAPD}, "FMOVEMX %m,%e" }, ! 755: { 0xf200, 0xffc0, 0xf800, 0xff00, {EACAPD}, "FMOVEMX R%K,%e" }, ! 756: ! 757: { 0xf200, 0xffc0, 0x6800, 0xfc00, {EAMA}, "FMOVEX F%D,%e" }, ! 758: { 0xf200, 0xffc0, 0x6c00, 0xfc00, {EAMA}, "FMOVEP F%D,%e,{%k}" }, ! 759: { 0xf200, 0xffc0, 0x7400, 0xfc00, {EAMA}, "FMOVED F%D,%e" }, ! 760: { 0xf200, 0xffc0, 0x7c00, 0xfc00, {EAMA}, "FMOVEP F%D,%e,{R%K}" }, ! 761: ! 762: { 0xf200, 0xffc0, 0x8000, 0xe3ff, {EAM}, "FMOVEML #%B,%e" }, ! 763: { 0xf200, 0xffc0, 0xa000, 0xe3ff, {EAMA}, "FMOVEML %e,#%B" }, ! 764: ! 765: { 0xf200, 0xffc0, 0x0000, 0xe07f, {0}, "FMOVE F%B,F%D" }, ! 766: { 0xf200, 0xffc0, 0x0001, 0xe07f, {0}, "FINTX %F" }, ! 767: { 0xf200, 0xffc0, 0x0002, 0xe07f, {0}, "FSINHX %F" }, ! 768: { 0xf200, 0xffc0, 0x0003, 0xe07f, {0}, "FINTRZ %F" }, ! 769: { 0xf200, 0xffc0, 0x0004, 0xe07f, {0}, "FSQRTX %F" }, ! 770: { 0xf200, 0xffc0, 0x0006, 0xe07f, {0}, "FLOGNP1X %F" }, ! 771: { 0xf200, 0xffc0, 0x0009, 0xe07f, {0}, "FTANHX %F" }, ! 772: { 0xf200, 0xffc0, 0x000a, 0xe07f, {0}, "FATANX %F" }, ! 773: { 0xf200, 0xffc0, 0x000c, 0xe07f, {0}, "FASINX %F" }, ! 774: { 0xf200, 0xffc0, 0x000d, 0xe07f, {0}, "FATANHX %F" }, ! 775: { 0xf200, 0xffc0, 0x000e, 0xe07f, {0}, "FSINX %F" }, ! 776: { 0xf200, 0xffc0, 0x000f, 0xe07f, {0}, "FTANX %F" }, ! 777: { 0xf200, 0xffc0, 0x0010, 0xe07f, {0}, "FETOXX %F" }, ! 778: { 0xf200, 0xffc0, 0x0011, 0xe07f, {0}, "FTWOTOXX %F" }, ! 779: { 0xf200, 0xffc0, 0x0012, 0xe07f, {0}, "FTENTOXX %F" }, ! 780: { 0xf200, 0xffc0, 0x0014, 0xe07f, {0}, "FLOGNX %F" }, ! 781: { 0xf200, 0xffc0, 0x0015, 0xe07f, {0}, "FLOG10X %F" }, ! 782: { 0xf200, 0xffc0, 0x0016, 0xe07f, {0}, "FLOG2X %F" }, ! 783: { 0xf200, 0xffc0, 0x0018, 0xe07f, {0}, "FABSX %F" }, ! 784: { 0xf200, 0xffc0, 0x0019, 0xe07f, {0}, "FCOSHX %F" }, ! 785: { 0xf200, 0xffc0, 0x001a, 0xe07f, {0}, "FNEGX %F" }, ! 786: { 0xf200, 0xffc0, 0x001c, 0xe07f, {0}, "FACOSX %F" }, ! 787: { 0xf200, 0xffc0, 0x001d, 0xe07f, {0}, "FCOSX %F" }, ! 788: { 0xf200, 0xffc0, 0x001e, 0xe07f, {0}, "FGETEXPX %F" }, ! 789: { 0xf200, 0xffc0, 0x001f, 0xe07f, {0}, "FGETMANX %F" }, ! 790: { 0xf200, 0xffc0, 0x0020, 0xe07f, {0}, "FDIVX F%B,F%D" }, ! 791: { 0xf200, 0xffc0, 0x0021, 0xe07f, {0}, "FMODX F%B,F%D" }, ! 792: { 0xf200, 0xffc0, 0x0022, 0xe07f, {0}, "FADDX F%B,F%D" }, ! 793: { 0xf200, 0xffc0, 0x0023, 0xe07f, {0}, "FMULX F%B,F%D" }, ! 794: { 0xf200, 0xffc0, 0x0024, 0xe07f, {0}, "FSGLDIVX F%B,F%D" }, ! 795: { 0xf200, 0xffc0, 0x0025, 0xe07f, {0}, "FREMX F%B,F%D" }, ! 796: { 0xf200, 0xffc0, 0x0026, 0xe07f, {0}, "FSCALEX F%B,F%D" }, ! 797: { 0xf200, 0xffc0, 0x0027, 0xe07f, {0}, "FSGLMULX F%B,F%D" }, ! 798: { 0xf200, 0xffc0, 0x0028, 0xe07f, {0}, "FSUBX F%B,F%D" }, ! 799: { 0xf200, 0xffc0, 0x0038, 0xe07f, {0}, "FCMPX F%B,F%D" }, ! 800: { 0xf200, 0xffc0, 0x003a, 0xe07f, {0}, "FTSTX F%B" }, ! 801: { 0xf200, 0xffc0, 0x0040, 0xe07f, {0}, "FSMOVE F%B,F%D" }, ! 802: { 0xf200, 0xffc0, 0x0041, 0xe07f, {0}, "FSSQRTX %F"}, ! 803: { 0xf200, 0xffc0, 0x0044, 0xe07f, {0}, "FDMOVE F%B,F%D" }, ! 804: { 0xf200, 0xffc0, 0x0045, 0xe07f, {0}, "FDSQRTX %F" }, ! 805: { 0xf200, 0xffc0, 0x0058, 0xe07f, {0}, "FSABSX %F" }, ! 806: { 0xf200, 0xffc0, 0x005a, 0xe07f, {0}, "FSNEGX %F" }, ! 807: { 0xf200, 0xffc0, 0x005c, 0xe07f, {0}, "FDABSX %F" }, ! 808: { 0xf200, 0xffc0, 0x005e, 0xe07f, {0}, "FDNEGX %F" }, ! 809: { 0xf200, 0xffc0, 0x0060, 0xe07f, {0}, "FSDIVX F%B,F%D" }, ! 810: { 0xf200, 0xffc0, 0x0062, 0xe07f, {0}, "FSADDX F%B,F%D" }, ! 811: { 0xf200, 0xffc0, 0x0063, 0xe07f, {0}, "FSMULX F%B,F%D" }, ! 812: { 0xf200, 0xffc0, 0x0064, 0xe07f, {0}, "FDDIVX F%B,F%D" }, ! 813: { 0xf200, 0xffc0, 0x0066, 0xe07f, {0}, "FDADDX F%B,F%D" }, ! 814: { 0xf200, 0xffc0, 0x0067, 0xe07f, {0}, "FDMULX F%B,F%D" }, ! 815: { 0xf200, 0xffc0, 0x0068, 0xe07f, {0}, "FSSUBX F%B,F%D" }, ! 816: { 0xf200, 0xffc0, 0x006c, 0xe07f, {0}, "FDSUBX F%B,F%D" }, ! 817: { 0xf200, 0xffc0, 0x4000, 0xe07f, {EAFLT}, "FMOVE%S %e,F%D" }, ! 818: { 0xf200, 0xffc0, 0x4001, 0xe07f, {EAFLT}, "FINT%S %e,F%D" }, ! 819: { 0xf200, 0xffc0, 0x4002, 0xe07f, {EAFLT}, "FSINH%S %e,F%D" }, ! 820: { 0xf200, 0xffc0, 0x4003, 0xe07f, {EAFLT}, "FINTRZ%S %e,F%D" }, ! 821: { 0xf200, 0xffc0, 0x4004, 0xe07f, {EAFLT}, "FSQRT%S %e,F%D" }, ! 822: { 0xf200, 0xffc0, 0x4006, 0xe07f, {EAFLT}, "FLOGNP1%S %e,F%D" }, ! 823: { 0xf200, 0xffc0, 0x4009, 0xe07f, {EAFLT}, "FTANH%S %e,F%D" }, ! 824: { 0xf200, 0xffc0, 0x400a, 0xe07f, {EAFLT}, "FATAN%S %e,F%D" }, ! 825: { 0xf200, 0xffc0, 0x400c, 0xe07f, {EAFLT}, "FASIN%S %e,F%D" }, ! 826: { 0xf200, 0xffc0, 0x400d, 0xe07f, {EAFLT}, "FATANH%S %e,F%D" }, ! 827: { 0xf200, 0xffc0, 0x400e, 0xe07f, {EAFLT}, "FSIN%S %e,F%D" }, ! 828: { 0xf200, 0xffc0, 0x400f, 0xe07f, {EAFLT}, "FTAN%S %e,F%D" }, ! 829: { 0xf200, 0xffc0, 0x4010, 0xe07f, {EAFLT}, "FETOX%S %e,F%D" }, ! 830: { 0xf200, 0xffc0, 0x4011, 0xe07f, {EAFLT}, "FTWOTOX%S %e,F%D" }, ! 831: { 0xf200, 0xffc0, 0x4012, 0xe07f, {EAFLT}, "FTENTOX%S %e,F%D" }, ! 832: { 0xf200, 0xffc0, 0x4014, 0xe07f, {EAFLT}, "FLOGN%S %e,F%D" }, ! 833: { 0xf200, 0xffc0, 0x4015, 0xe07f, {EAFLT}, "FLOG10%S %e,F%D" }, ! 834: { 0xf200, 0xffc0, 0x4016, 0xe07f, {EAFLT}, "FLOG2%S %e,F%D" }, ! 835: { 0xf200, 0xffc0, 0x4018, 0xe07f, {EAFLT}, "FABS%S %e,F%D" }, ! 836: { 0xf200, 0xffc0, 0x4019, 0xe07f, {EAFLT}, "FCOSH%S %e,F%D" }, ! 837: { 0xf200, 0xffc0, 0x401a, 0xe07f, {EAFLT}, "FNEG%S %e,F%D" }, ! 838: { 0xf200, 0xffc0, 0x401c, 0xe07f, {EAFLT}, "FACOS%S %e,F%D" }, ! 839: { 0xf200, 0xffc0, 0x401d, 0xe07f, {EAFLT}, "FCOS%S %e,F%D" }, ! 840: { 0xf200, 0xffc0, 0x401e, 0xe07f, {EAFLT}, "FGETEXP%S %e,F%D" }, ! 841: { 0xf200, 0xffc0, 0x401f, 0xe07f, {EAFLT}, "FGETMAN%S %e,F%D" }, ! 842: { 0xf200, 0xffc0, 0x4020, 0xe07f, {EAFLT}, "FDIV%S %e,F%D" }, ! 843: { 0xf200, 0xffc0, 0x4021, 0xe07f, {EAFLT}, "FMOD%S %e,F%D" }, ! 844: { 0xf200, 0xffc0, 0x4022, 0xe07f, {EAFLT}, "FADD%S %e,F%D" }, ! 845: { 0xf200, 0xffc0, 0x4023, 0xe07f, {EAFLT}, "FMUL%S %e,F%D" }, ! 846: { 0xf200, 0xffc0, 0x4024, 0xe07f, {EAFLT}, "FSGLDIV%S %e,F%D" }, ! 847: { 0xf200, 0xffc0, 0x4025, 0xe07f, {EAFLT}, "FREM%S %e,F%D" }, ! 848: { 0xf200, 0xffc0, 0x4026, 0xe07f, {EAFLT}, "FSCALE%S %e,F%D" }, ! 849: { 0xf200, 0xffc0, 0x4027, 0xe07f, {EAFLT}, "FSGLMUL%S %e,F%D" }, ! 850: { 0xf200, 0xffc0, 0x4028, 0xe07f, {EAFLT}, "FSUB%S %e,F%D" }, ! 851: { 0xf200, 0xffc0, 0x4038, 0xe07f, {EAFLT}, "FCMP%S %e,F%D" }, ! 852: { 0xf200, 0xffc0, 0x403a, 0xe07f, {EAFLT}, "FTST%S %e" }, ! 853: { 0xf200, 0xffc0, 0x4040, 0xe07f, {EAFLT}, "FSMOVE%S %e,F%D" }, ! 854: { 0xf200, 0xffc0, 0x4041, 0xe07f, {EAFLT}, "FSSQRT%S %e,F%D" }, ! 855: { 0xf200, 0xffc0, 0x4044, 0xe07f, {EAFLT}, "FDMOVE%S %e,F%D" }, ! 856: { 0xf200, 0xffc0, 0x4045, 0xe07f, {EAFLT}, "FDSQRT%S %e,F%D" }, ! 857: { 0xf200, 0xffc0, 0x4058, 0xe07f, {EAFLT}, "FSABS%S %e,F%D" }, ! 858: { 0xf200, 0xffc0, 0x405a, 0xe07f, {EAFLT}, "FSNEG%S %e,F%D" }, ! 859: { 0xf200, 0xffc0, 0x405c, 0xe07f, {EAFLT}, "FDABS%S %e,F%D" }, ! 860: { 0xf200, 0xffc0, 0x405e, 0xe07f, {EAFLT}, "FDNEG%S %e,F%D" }, ! 861: { 0xf200, 0xffc0, 0x4060, 0xe07f, {EAFLT}, "FSDIV%S %e,F%D" }, ! 862: { 0xf200, 0xffc0, 0x4062, 0xe07f, {EAFLT}, "FSADD%S %e,F%D" }, ! 863: { 0xf200, 0xffc0, 0x4063, 0xe07f, {EAFLT}, "FSMUL%S %e,F%D" }, ! 864: { 0xf200, 0xffc0, 0x4064, 0xe07f, {EAFLT}, "FDDIV%S %e,F%D" }, ! 865: { 0xf200, 0xffc0, 0x4066, 0xe07f, {EAFLT}, "FDADD%S %e,F%D" }, ! 866: { 0xf200, 0xffc0, 0x4067, 0xe07f, {EAFLT}, "FDMUL%S %e,F%D" }, ! 867: { 0xf200, 0xffc0, 0x4068, 0xe07f, {EAFLT}, "FSSUB%S %e,F%D" }, ! 868: { 0xf200, 0xffc0, 0x406c, 0xe07f, {EAFLT}, "FDSUB%S %e,F%D" }, ! 869: ! 870: { 0xf200, 0xffc0, 0x0030, 0xe078, {0}, "FSINCOSX F%B,F%a:F%D" }, ! 871: { 0xf200, 0xffc0, 0x4030, 0xe078, {EAFLT}, "FSINCOS%S %e,F%a:F%D" }, ! 872: ! 873: { 0xf200, 0xffc0, 0x6000, 0xe000, {EADA}, "FMOVE%S F%D,%e" }, ! 874: ! 875: { 0xf300, 0xffc0, 0x0000, 0x0000, {EACAPD}, "FSAVE %e" }, ! 876: { 0xf340, 0xffc0, 0x0000, 0x0000, {EACAPI}, "FRESTORE %e" }, ! 877: ! 878: { 0xf280, 0xffc0, 0x0000, 0x0000, {BR16}, "FB%p %t" }, ! 879: { 0xf2c0, 0xffc0, 0x0000, 0x0000, {BR32}, "FB%p %t" }, ! 880: ! 881: { 0xf408, 0xff38, 0x0000, 0x0000, {0}, "CINVL %C,(A%y)" }, ! 882: { 0xf410, 0xff38, 0x0000, 0x0000, {0}, "CINVP %C,(A%y)" }, ! 883: { 0xf418, 0xff38, 0x0000, 0x0000, {0}, "CINVA %C" }, ! 884: { 0xf428, 0xff38, 0x0000, 0x0000, {0}, "CPUSHL %C,(A%y)" }, ! 885: { 0xf430, 0xff38, 0x0000, 0x0000, {0}, "CPUSHP %C,(A%y)" }, ! 886: { 0xf438, 0xff38, 0x0000, 0x0000, {0}, "CPUSHA %C" }, ! 887: { 0,0,0,0,{0},0 }, ! 888: }; ! 889: ! 890: static Optable *optables[] = ! 891: { ! 892: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, 0, tb, tc, td, te, tf, ! 893: }; ! 894: ! 895: static Map *mymap; ! 896: ! 897: static int ! 898: dumpinst(Inst *ip, char *buf, int n) ! 899: { ! 900: int i; ! 901: ! 902: if (n <= 0) ! 903: return 0; ! 904: ! 905: *buf++ = '#'; ! 906: for (i = 0; i < ip->n && i*4+1 < n-4; i++, buf += 4) ! 907: _hexify(buf, ip->raw[i], 3); ! 908: *buf = 0; ! 909: return i*4+1; ! 910: } ! 911: ! 912: static int ! 913: getword(Inst *ip, long offset) ! 914: { ! 915: if (ip->n < nelem(ip->raw)) { ! 916: if (get2(mymap, offset, &ip->raw[ip->n++]) > 0) ! 917: return 1; ! 918: werrstr("can't read instruction: %r"); ! 919: } else ! 920: werrstr("instruction too big: %r"); ! 921: return -1; ! 922: } ! 923: ! 924: static int ! 925: getshorts(Inst *ip, void *where, int n) ! 926: { ! 927: if (ip->n+n < nelem(ip->raw)) { ! 928: if (get1(mymap, ip->addr+ip->n*2, (uchar*)&ip->raw[ip->n], n*2) < 0) { ! 929: werrstr("can't read instruction: %r"); ! 930: return 0; ! 931: } ! 932: memmove(where, &ip->raw[ip->n], n*2); ! 933: ip->n += n; ! 934: return 1; ! 935: } ! 936: werrstr("instruction too big: %r"); ! 937: return 0; ! 938: } ! 939: ! 940: static int ! 941: i8(Inst *ip, long *l) ! 942: { ! 943: if (getword(ip, ip->addr+ip->n*2) < 0) ! 944: return -1; ! 945: *l = ip->raw[ip->n-1]&0xff; ! 946: if (*l&0x80) ! 947: *l |= ~0xff; ! 948: return 1; ! 949: } ! 950: ! 951: static int ! 952: i16(Inst *ip, long *l) ! 953: { ! 954: if (getword(ip, ip->addr+ip->n*2) < 0) ! 955: return -1; ! 956: *l = ip->raw[ip->n-1]; ! 957: if (*l&0x8000) ! 958: *l |= ~0xffff; ! 959: return 1; ! 960: } ! 961: static int ! 962: i32(Inst *ip, long *l) ! 963: { ! 964: if (getword(ip, ip->addr+ip->n*2) < 0) ! 965: return -1; ! 966: if (getword(ip, ip->addr+ip->n*2) < 0) ! 967: return -1; ! 968: *l = (ip->raw[ip->n-2]<<16)|ip->raw[ip->n-1]; ! 969: return 1; ! 970: } ! 971: ! 972: static int ! 973: getimm(Inst *ip, Operand *ap, int mode) ! 974: { ! 975: ap->eatype = IMM; ! 976: switch(mode) ! 977: { ! 978: case EAM_B: /* byte */ ! 979: case EAALL_B: ! 980: return i8(ip, &ap->immediate); ! 981: case EADI_W: /* word */ ! 982: case EAALL_W: ! 983: return i16(ip, &ap->immediate); ! 984: case EADI_L: /* long */ ! 985: case EAALL_L: ! 986: return i32(ip, &ap->immediate); ! 987: case EAFLT: /* floating point - size in bits 10-12 or word 1 */ ! 988: switch((ip->raw[1]>>10)&0x07) ! 989: { ! 990: case 0: /* long integer */ ! 991: return i32(ip, &ap->immediate); ! 992: case 1: /* single precision real */ ! 993: ap->eatype = IREAL; ! 994: return getshorts(ip, ap->floater, 2); ! 995: case 2: /* extended precision real - not supported */ ! 996: ap->eatype = IEXT; ! 997: return getshorts(ip, ap->floater, 6); ! 998: case 3: /* packed decimal real - not supported */ ! 999: ap->eatype = IPACK; ! 1000: return getshorts(ip, ap->floater, 12); ! 1001: case 4: /* integer word */ ! 1002: return i16(ip, &ap->immediate); ! 1003: case 5: /* double precision real */ ! 1004: ap->eatype = IDBL; ! 1005: return getshorts(ip, ap->floater, 4); ! 1006: case 6: /* integer byte */ ! 1007: return i8(ip, &ap->immediate); ! 1008: default: ! 1009: ip->errmsg = "bad immediate float data"; ! 1010: return -1; ! 1011: } ! 1012: break; ! 1013: case IV: /* size encoded in bits 6&7 of opcode word */ ! 1014: default: ! 1015: switch((ip->raw[0]>>6)&0x03) ! 1016: { ! 1017: case 0x00: /* integer byte */ ! 1018: return i8(ip, &ap->immediate); ! 1019: case 0x01: /* integer word */ ! 1020: return i16(ip, &ap->immediate); ! 1021: case 0x02: /* integer long */ ! 1022: return i32(ip, &ap->immediate); ! 1023: default: ! 1024: ip->errmsg = "bad immediate size"; ! 1025: return -1; ! 1026: } ! 1027: break; ! 1028: } ! 1029: return 1; ! 1030: } ! 1031: ! 1032: static int ! 1033: getdisp(Inst *ip, Operand *ap) ! 1034: { ! 1035: short ext; ! 1036: ! 1037: if (getword(ip, ip->addr+ip->n*2) < 0) ! 1038: return -1; ! 1039: ext = ip->raw[ip->n-1]; ! 1040: ap->ext = ext; ! 1041: if ((ext&0x100) == 0) { /* indexed with 7-bit displacement */ ! 1042: ap->disp = ext&0x7f; ! 1043: if (ap->disp&0x40) ! 1044: ap->disp |= ~0x7f; ! 1045: return 1; ! 1046: } ! 1047: switch(ext&0x30) /* first (inner) displacement */ ! 1048: { ! 1049: case 0x10: ! 1050: break; ! 1051: case 0x20: ! 1052: if (i16(ip, &ap->disp) < 0) ! 1053: return -1; ! 1054: break; ! 1055: case 0x30: ! 1056: if (i32(ip, &ap->disp) < 0) ! 1057: return -1; ! 1058: break; ! 1059: default: ! 1060: ip->errmsg = "bad EA displacement"; ! 1061: return -1; ! 1062: } ! 1063: switch (ext&0x03) /* outer displacement */ ! 1064: { ! 1065: case 0x02: /* 16 bit displacement */ ! 1066: return i16(ip, &ap->outer); ! 1067: case 0x03: /* 32 bit displacement */ ! 1068: return i32(ip, &ap->outer); ! 1069: default: ! 1070: break; ! 1071: } ! 1072: return 1; ! 1073: } ! 1074: ! 1075: static int ! 1076: ea(Inst *ip, int ea, Operand *ap, int mode) ! 1077: { ! 1078: int type, size; ! 1079: ! 1080: type = 0; ! 1081: ap->ext = 0; ! 1082: switch((ea>>3)&0x07) ! 1083: { ! 1084: case 0x00: ! 1085: ap->eatype = Dreg; ! 1086: type = Dn; ! 1087: break; ! 1088: case 0x01: ! 1089: ap->eatype = Areg; ! 1090: type = An; ! 1091: break; ! 1092: case 0x02: ! 1093: ap->eatype = AInd; ! 1094: type = Ind; ! 1095: break; ! 1096: case 0x03: ! 1097: ap->eatype = APinc; ! 1098: type = Pinc; ! 1099: break; ! 1100: case 0x04: ! 1101: ap->eatype = APdec; ! 1102: type = Pdec; ! 1103: break; ! 1104: case 0x05: ! 1105: ap->eatype = ADisp; ! 1106: type = Bdisp; ! 1107: if (i16(ip, &ap->disp) < 0) ! 1108: return -1; ! 1109: break; ! 1110: case 0x06: ! 1111: ap->eatype = BXD; ! 1112: type = Bdisp; ! 1113: if (getdisp(ip, ap) < 0) ! 1114: return -1; ! 1115: break; ! 1116: case 0x07: ! 1117: switch(ea&0x07) ! 1118: { ! 1119: case 0x00: ! 1120: type = Abs; ! 1121: ap->eatype = ABS; ! 1122: if (i16(ip, &ap->immediate) < 0) ! 1123: return -1; ! 1124: break; ! 1125: case 0x01: ! 1126: type = Abs; ! 1127: ap->eatype = ABS; ! 1128: if (i32(ip, &ap->immediate) < 0) ! 1129: return -1; ! 1130: break; ! 1131: case 0x02: ! 1132: type = PCrel; ! 1133: ap->eatype = PDisp; ! 1134: if (i16(ip, &ap->disp) < 0) ! 1135: return -1; ! 1136: break; ! 1137: case 0x03: ! 1138: type = PCrel; ! 1139: ap->eatype = PXD; ! 1140: if (getdisp(ip, ap) < 0) ! 1141: return -1; ! 1142: break; ! 1143: case 0x04: ! 1144: type = Imm; ! 1145: if (getimm(ip, ap, mode) < 0) ! 1146: return -1; ! 1147: break; ! 1148: default: ! 1149: ip->errmsg = "bad EA mode"; ! 1150: return -1; ! 1151: } ! 1152: } ! 1153: /* Allowable floating point EAs are restricted for packed, ! 1154: * extended, and double precision operands ! 1155: */ ! 1156: if (mode == EAFLT) { ! 1157: size = (ip->raw[1]>>10)&0x07; ! 1158: if (size == 2 || size == 3 || size == 5) ! 1159: mode = EAM; ! 1160: else ! 1161: mode = EADI; ! 1162: } ! 1163: if (!(validea[mode]&type)) { ! 1164: ip->errmsg = "invalid EA"; ! 1165: return -1; ! 1166: } ! 1167: return 1; ! 1168: } ! 1169: ! 1170: static int ! 1171: decode(Inst *ip, Optable *op) ! 1172: { ! 1173: int i, t, mode; ! 1174: Operand *ap; ! 1175: short opcode; ! 1176: ! 1177: opcode = ip->raw[0]; ! 1178: for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) { ! 1179: ap = &ip->and[i]; ! 1180: mode = op->opdata[i]; ! 1181: switch(mode) ! 1182: { ! 1183: case EAPI: /* normal EA modes */ ! 1184: case EACA: ! 1185: case EACAD: ! 1186: case EACAPI: ! 1187: case EACAPD: ! 1188: case EAMA: ! 1189: case EADA: ! 1190: case EAA: ! 1191: case EAC: ! 1192: case EACPI: ! 1193: case EACD: ! 1194: case EAD: ! 1195: case EAM: ! 1196: case EAM_B: ! 1197: case EADI: ! 1198: case EADI_L: ! 1199: case EADI_W: ! 1200: case EAALL: ! 1201: case EAALL_L: ! 1202: case EAALL_W: ! 1203: case EAALL_B: ! 1204: case EAFLT: ! 1205: if (ea(ip, opcode&0x3f, ap, mode) < 0) ! 1206: return -1; ! 1207: break; ! 1208: case EADDA: /* stupid bit flop required */ ! 1209: t = ((opcode>>9)&0x07)|((opcode>>3)&0x38); ! 1210: if (ea(ip, t, ap, EADA)< 0) ! 1211: return -1; ! 1212: break; ! 1213: case BREAC: /* EAC JMP or CALL operand */ ! 1214: if (ea(ip, opcode&0x3f, ap, EAC) < 0) ! 1215: return -1; ! 1216: break; ! 1217: case OP8: /* weird movq instruction */ ! 1218: ap->eatype = IMM; ! 1219: ap->immediate = opcode&0xff; ! 1220: if (opcode&0x80) ! 1221: ap->immediate |= ~0xff; ! 1222: break; ! 1223: case I8: /* must be two-word opcode */ ! 1224: ap->eatype = IMM; ! 1225: ap->immediate = ip->raw[1]&0xff; ! 1226: if (ap->immediate&0x80) ! 1227: ap->immediate |= ~0xff; ! 1228: break; ! 1229: case I16: /* 16 bit immediate */ ! 1230: case BR16: ! 1231: ap->eatype = IMM; ! 1232: if (i16(ip, &ap->immediate) < 0) ! 1233: return -1; ! 1234: break; ! 1235: case C16: /* CAS2 16 bit immediate */ ! 1236: ap->eatype = IMM; ! 1237: if (i16(ip, &ap->immediate) < 0) ! 1238: return -1; ! 1239: if (ap->immediate & 0x0e38) { ! 1240: ip->errmsg = "bad CAS2W operand"; ! 1241: return 0; ! 1242: } ! 1243: break; ! 1244: case I32: /* 32 bit immediate */ ! 1245: case BR32: ! 1246: ap->eatype = IMM; ! 1247: if (i32(ip, &ap->immediate) < 0) ! 1248: return -1; ! 1249: break; ! 1250: case IV: /* immediate data depends on size field */ ! 1251: if (getimm(ip, ap, IV) < 0) ! 1252: return -1; ! 1253: break; ! 1254: case BR8: /* branch displacement format */ ! 1255: ap->eatype = IMM; ! 1256: ap->immediate = opcode&0xff; ! 1257: if (ap->immediate == 0) { ! 1258: if (i16(ip, &ap->immediate) < 0) ! 1259: return -1; ! 1260: } else if (ap->immediate == 0xff) { ! 1261: if (i32(ip, &ap->immediate) < 0) ! 1262: return -1; ! 1263: } else if (ap->immediate & 0x80) ! 1264: ap->immediate |= ~0xff; ! 1265: break; ! 1266: case STACK: /* Dummy operand type for Return instructions */ ! 1267: default: ! 1268: break; ! 1269: } ! 1270: } ! 1271: return 1; ! 1272: } ! 1273: ! 1274: static Optable * ! 1275: instruction(Inst *ip) ! 1276: { ! 1277: ushort opcode, op2; ! 1278: Optable *op; ! 1279: int class; ! 1280: ! 1281: ip->n = 0; ! 1282: if (getword(ip, ip->addr) < 0) ! 1283: return 0; ! 1284: opcode = ip->raw[0]; ! 1285: if (get2(mymap, ip->addr+2, &op2) < 0) ! 1286: op2 = 0; ! 1287: class = (opcode>>12)&0x0f; ! 1288: for (op = optables[class]; op && op->format; op++) { ! 1289: if (op->opcode != (opcode&op->mask0)) ! 1290: continue; ! 1291: if (op->op2 != (op2&op->mask1)) ! 1292: continue; ! 1293: if (op->mask1) ! 1294: ip->raw[ip->n++] = op2; ! 1295: return op; ! 1296: } ! 1297: ip->errmsg = "Invalid opcode"; ! 1298: return 0; ! 1299: } ! 1300: ! 1301: static void ! 1302: bprint(Inst *i, char *fmt, ...) ! 1303: { ! 1304: i->curr = doprint(i->curr, i->end, fmt, (&fmt+1)); ! 1305: } ! 1306: ! 1307: static char *regname[] = ! 1308: { ! 1309: "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0", ! 1310: "A1", "A2", "A3", "A4", "A5", "A6", "A7", "PC", "SB" ! 1311: }; ! 1312: ! 1313: static void ! 1314: plocal(Inst *ip, Operand *ap) ! 1315: { ! 1316: int ret, offset; ! 1317: long moved; ! 1318: Symbol s; ! 1319: ! 1320: offset = ap->disp; ! 1321: if (!findsym(ip->addr, CTEXT, &s)) ! 1322: goto none; ! 1323: ! 1324: moved = pc2sp(ip->addr); ! 1325: if (moved == -1) ! 1326: goto none; ! 1327: ! 1328: if (offset > moved) { /* above frame - must be argument */ ! 1329: offset -= moved; ! 1330: ret = getauto(&s, offset-mach->szaddr, CPARAM, &s); ! 1331: } else /* below frame - must be automatic */ ! 1332: ret = getauto(&s, moved-offset, CPARAM, &s); ! 1333: if (ret) ! 1334: bprint(ip, "%s+%lux", s.name, offset); ! 1335: else ! 1336: none: bprint(ip, "%lux", ap->disp); ! 1337: } ! 1338: ! 1339: /* ! 1340: * this guy does all the work of printing the base and index component ! 1341: * of an EA. ! 1342: */ ! 1343: static int ! 1344: pidx(Inst *ip, int ext, int reg, char *bfmt, char *ifmt, char *nobase) ! 1345: { ! 1346: char *s; ! 1347: int printed; ! 1348: char buf[512]; ! 1349: ! 1350: printed = 1; ! 1351: if (ext&0x80) { /* Base suppressed */ ! 1352: if (reg == 16) ! 1353: bprint(ip, bfmt, "(ZPC)"); ! 1354: else if (nobase) ! 1355: bprint(ip, nobase); ! 1356: else ! 1357: printed = 0; ! 1358: } else /* format base reg */ ! 1359: bprint(ip, bfmt, regname[reg]); ! 1360: if (ext & 0x40) /* index suppressed */ ! 1361: return printed; ! 1362: switch ((ext>>9)&0x03) ! 1363: { ! 1364: case 0x01: ! 1365: s = "*2"; ! 1366: break; ! 1367: case 0x02: ! 1368: s = "*4"; ! 1369: break; ! 1370: case 0x03: ! 1371: s = "*8"; ! 1372: break; ! 1373: default: ! 1374: if (ext&0x80) ! 1375: s = "*1"; ! 1376: else ! 1377: s = ""; ! 1378: break; ! 1379: } ! 1380: sprint(buf, "%s.%c%s", regname[(ext>>12)&0x0f], (ext&0x800) ? 'L' : 'W', s); ! 1381: if (!printed) ! 1382: bprint(ip, ifmt, buf); ! 1383: else ! 1384: bprint(ip, "(%s)", buf); ! 1385: return 1; ! 1386: } ! 1387: ! 1388: static void ! 1389: prindex(Inst *ip, int reg, Operand *ap) ! 1390: { ! 1391: short ext; ! 1392: int left; ! 1393: int disp; ! 1394: ! 1395: left = ip->end-ip->curr; ! 1396: if (left <= 0) ! 1397: return; ! 1398: ext = ap->ext; ! 1399: disp = ap->disp; ! 1400: /* look for static base register references */ ! 1401: if ((ext&0xa0) == 0x20 && reg == 14 && mach->sb && disp) { ! 1402: reg = 17; /* "A6" -> "SB" */ ! 1403: disp += mach->sb; ! 1404: } ! 1405: if ((ext&0x100) == 0) { /* brief form */ ! 1406: if (reg == 15) ! 1407: plocal(ip, ap); ! 1408: else if (disp) ! 1409: ip->curr += symoff(ip->curr, left, disp, CANY); ! 1410: pidx(ip, ext&0xff00, reg, "(%s)", "(%s)", 0); ! 1411: return; ! 1412: } ! 1413: switch(ext&0x3f) /* bd size, && i/is */ ! 1414: { ! 1415: case 0x10: ! 1416: if (!pidx(ip, ext, reg, "(%s)", "(%s)", 0)) ! 1417: bprint(ip, "#0"); ! 1418: break; ! 1419: case 0x11: ! 1420: if (pidx(ip, ext, reg, "((%s)", "((%s)", 0)) ! 1421: bprint(ip, ")"); ! 1422: else ! 1423: bprint(ip, "#0"); ! 1424: break; ! 1425: case 0x12: ! 1426: case 0x13: ! 1427: ip->curr += symoff(ip->curr, left, ap->outer, CANY); ! 1428: if (pidx(ip, ext, reg, "((%s)", "((%s)", 0)) ! 1429: bprint(ip, ")"); ! 1430: break; ! 1431: case 0x15: ! 1432: if (!pidx(ip, ext, reg, "((%s))", "(%s)", 0)) ! 1433: bprint(ip, "#0"); ! 1434: break; ! 1435: case 0x16: ! 1436: case 0x17: ! 1437: ip->curr += symoff(ip->curr, left, ap->outer, CANY); ! 1438: pidx(ip, ext, reg, "((%s))", "(%s)", 0); ! 1439: break; ! 1440: case 0x20: ! 1441: case 0x30: ! 1442: if (reg == 15) ! 1443: plocal(ip, ap); ! 1444: else ! 1445: ip->curr += symoff(ip->curr, left, disp, CANY); ! 1446: pidx(ip, ext, reg, "(%s)", "(%s)", 0); ! 1447: break; ! 1448: case 0x21: ! 1449: case 0x31: ! 1450: *ip->curr++ = '('; ! 1451: if (reg == 15) ! 1452: plocal(ip, ap); ! 1453: else ! 1454: ip->curr += symoff(ip->curr, left-1, disp, CANY); ! 1455: pidx(ip, ext, reg, "(%s)", "(%s)", 0); ! 1456: bprint(ip, ")"); ! 1457: break; ! 1458: case 0x22: ! 1459: case 0x23: ! 1460: case 0x32: ! 1461: case 0x33: ! 1462: ip->curr += symoff(ip->curr, left, ap->outer, CANY); ! 1463: bprint(ip, "("); ! 1464: if (reg == 15) ! 1465: plocal(ip, ap); ! 1466: else ! 1467: ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY); ! 1468: pidx(ip, ext, reg, "(%s)", "(%s)", 0); ! 1469: bprint(ip, ")"); ! 1470: break; ! 1471: case 0x25: ! 1472: case 0x35: ! 1473: *ip->curr++ = '('; ! 1474: if (reg == 15) ! 1475: plocal(ip, ap); ! 1476: else ! 1477: ip->curr += symoff(ip->curr, left-1, disp, CANY); ! 1478: if (!pidx(ip, ext, reg, "(%s))", "(%s)", "())")) ! 1479: bprint(ip, ")"); ! 1480: break; ! 1481: case 0x26: ! 1482: case 0x27: ! 1483: case 0x36: ! 1484: case 0x37: ! 1485: ip->curr += symoff(ip->curr, left, ap->outer, CANY); ! 1486: bprint(ip, "("); ! 1487: if (reg == 15) ! 1488: plocal(ip, ap); ! 1489: else ! 1490: ip->curr += symoff(ip->curr, ip->end-ip->curr, disp, CANY); ! 1491: pidx(ip, ext, reg, "(%s))", "(%s)", "())"); ! 1492: break; ! 1493: default: ! 1494: bprint(ip, "??%x??", ext); ! 1495: ip->errmsg = "bad EA"; ! 1496: break; ! 1497: } ! 1498: } ! 1499: ! 1500: static void ! 1501: pea(int reg, Inst *ip, Operand *ap) ! 1502: { ! 1503: int i, left; ! 1504: ! 1505: left = ip->end-ip->curr; ! 1506: if (left < 0) ! 1507: return; ! 1508: switch(ap->eatype) ! 1509: { ! 1510: case Dreg: ! 1511: bprint(ip, "R%d", reg); ! 1512: break; ! 1513: case Areg: ! 1514: bprint(ip, "A%d", reg); ! 1515: break; ! 1516: case AInd: ! 1517: bprint(ip, "(A%d)", reg); ! 1518: break; ! 1519: case APinc: ! 1520: bprint(ip, "(A%d)+", reg); ! 1521: break; ! 1522: case APdec: ! 1523: bprint(ip, "-(A%d)", reg); ! 1524: break; ! 1525: case PDisp: ! 1526: ip->curr += symoff(ip->curr, left, ip->addr+2+ap->disp, CANY); ! 1527: break; ! 1528: case PXD: ! 1529: prindex(ip, 16, ap); ! 1530: break; ! 1531: case ADisp: /* references off the static base */ ! 1532: if (reg == 6 && mach->sb && ap->disp) { ! 1533: ip->curr += symoff(ip->curr, left, ap->disp+mach->sb, CANY); ! 1534: bprint(ip, "(SB)", reg); ! 1535: break; ! 1536: } ! 1537: /* reference autos and parameters off the stack */ ! 1538: if (reg == 7) ! 1539: plocal(ip, ap); ! 1540: else ! 1541: ip->curr += symoff(ip->curr, left, ap->disp, CANY); ! 1542: bprint(ip, "(A%d)", reg); ! 1543: break; ! 1544: case BXD: ! 1545: prindex(ip, reg+8, ap); ! 1546: break; ! 1547: case ABS: ! 1548: ip->curr += symoff(ip->curr, left, ap->immediate, CANY); ! 1549: bprint(ip, "($0)"); ! 1550: break; ! 1551: case IMM: ! 1552: *ip->curr++ = '$'; ! 1553: ip->curr += symoff(ip->curr, left-1, ap->immediate, CANY); ! 1554: break; ! 1555: case IREAL: ! 1556: *ip->curr++ = '$'; ! 1557: ip->curr += beieeesftos(ip->curr, left-1, (void*) ap->floater); ! 1558: break; ! 1559: case IDBL: ! 1560: *ip->curr++ = '$'; ! 1561: ip->curr += beieeedftos(ip->curr, left-1, (void*) ap->floater); ! 1562: break; ! 1563: case IPACK: ! 1564: bprint(ip, "$#"); ! 1565: for (i = 0; i < 24 && ip->curr < ip->end-1; i++) { ! 1566: _hexify(ip->curr, ap->floater[i], 1); ! 1567: ip->curr += 2; ! 1568: } ! 1569: break; ! 1570: case IEXT: ! 1571: bprint(ip, "$#"); ! 1572: ip->curr += beieee80ftos(ip->curr, left-2, (void*)ap->floater); ! 1573: break; ! 1574: default: ! 1575: bprint(ip, "??%x??", ap->eatype); ! 1576: ip->errmsg = "bad EA type"; ! 1577: break; ! 1578: } ! 1579: } ! 1580: ! 1581: static char *cctab[] = { "F", "T", "HI", "LS", "CC", "CS", "NE", "EQ", ! 1582: "VC", "VS", "PL", "MI", "GE", "LT", "GT", "LE" }; ! 1583: static char *fcond[] = ! 1584: { ! 1585: "F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR", ! 1586: "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T", ! 1587: "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE", ! 1588: "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST" ! 1589: }; ! 1590: static char *cachetab[] = { "NC", "DC", "IC", "BC" }; ! 1591: static char *mmutab[] = { "TC", "??", "SRP", "CRP" }; ! 1592: static char *crtab0[] = ! 1593: { ! 1594: "SFC", "DFC", "CACR", "TC", "ITT0", "ITT1", "DTT0", "DTT1", ! 1595: }; ! 1596: static char *crtab1[] = ! 1597: { ! 1598: "USP", "VBR", "CAAR", "MSP", "ISP", "MMUSR", "URP", "SRP", ! 1599: }; ! 1600: static char typetab[] = { 'L', 'S', 'X', 'P', 'W', 'D', 'B', '?', }; ! 1601: static char sztab[] = {'?', 'B', 'W', 'L', '?' }; ! 1602: ! 1603: static void ! 1604: formatins(char *fmt, Inst *ip) ! 1605: { ! 1606: short op, w1; ! 1607: int r1, r2; ! 1608: int currand; ! 1609: ! 1610: op = ip->raw[0]; ! 1611: w1 = ip->raw[1]; ! 1612: currand = 0; ! 1613: for (; *fmt && ip->curr < ip->end; fmt++) { ! 1614: if (*fmt != '%') ! 1615: *ip->curr++ = *fmt; ! 1616: else switch(*++fmt) ! 1617: { ! 1618: case '%': ! 1619: *ip->curr++ = '%'; ! 1620: break; ! 1621: case 'a': /* register number; word 1:[0-2] */ ! 1622: *ip->curr++ = (w1&0x07)+'0'; ! 1623: break; ! 1624: case 'c': /* condition code; opcode: [8-11] */ ! 1625: bprint(ip, cctab[(op>>8)&0x0f]); ! 1626: break; ! 1627: case 'd': /* shift direction; opcode: [8] */ ! 1628: if (op&0x100) ! 1629: *ip->curr++ = 'L'; ! 1630: else ! 1631: *ip->curr++ = 'R'; ! 1632: break; ! 1633: case 'e': /* source effective address */ ! 1634: pea(op&0x07, ip, &ip->and[currand++]); ! 1635: break; ! 1636: case 'f': /* trap vector; op code: [0-3] */ ! 1637: bprint(ip, "%x", op&0x0f); ! 1638: break; ! 1639: case 'h': /* register number; word 1: [5-7] */ ! 1640: *ip->curr++ = (w1>>5)&0x07+'0'; ! 1641: break; ! 1642: case 'i': /* immediate operand */ ! 1643: ip->curr += symoff(ip->curr, ip->end-ip->curr, ! 1644: ip->and[currand++].immediate, CANY); ! 1645: break; ! 1646: case 'j': /* data registers; word 1: [0-2] & [12-14] */ ! 1647: r1 = w1&0x07; ! 1648: r2 = (w1>>12)&0x07; ! 1649: if (r1 == r2) ! 1650: bprint(ip, "R%d", r1); ! 1651: else ! 1652: bprint(ip, "R%d:R%d", r2, r1); ! 1653: break; ! 1654: case 'k': /* k factor; word 1 [0-6] */ ! 1655: bprint(ip, "%x", w1&0x7f); ! 1656: break; ! 1657: case 'm': /* register mask; word 1 [0-7] */ ! 1658: bprint(ip, "%x", w1&0xff); ! 1659: break; ! 1660: case 'o': /* bit field offset; word1: [6-10] */ ! 1661: bprint(ip, "%d", (w1>>6)&0x3f); ! 1662: break; ! 1663: case 'p': /* conditional predicate; opcode: [0-5] ! 1664: only bits 0-4 are defined */ ! 1665: bprint(ip, fcond[op&0x1f]); ! 1666: break; ! 1667: case 'q': /* 3-bit immediate value; opcode[9-11] */ ! 1668: r1 = (op>>9)&0x07; ! 1669: if (r1 == 0) ! 1670: *ip->curr++ = '8'; ! 1671: else ! 1672: *ip->curr++ = r1+'0'; ! 1673: break; ! 1674: case 'r': /* register type & number; word 1: [12-15] */ ! 1675: bprint(ip, regname[(w1>>12)&0x0f]); ! 1676: break; ! 1677: case 's': /* size; opcode [6-7] */ ! 1678: *ip->curr = sztab[((op>>6)&0x03)+1]; ! 1679: if (*ip->curr++ == '?') ! 1680: ip->errmsg = "bad size code"; ! 1681: break; ! 1682: case 't': /* text offset */ ! 1683: ip->curr += symoff(ip->curr, ip->end-ip->curr, ! 1684: ip->and[currand++].immediate+ip->addr+2, CTEXT); ! 1685: break; ! 1686: case 'u': /* register number; word 1: [6-8] */ ! 1687: *ip->curr++ = ((w1>>6)&0x07)+'0'; ! 1688: break; ! 1689: case 'w': /* bit field width; word 1: [0-4] */ ! 1690: bprint(ip, "%d", w1&0x0f); ! 1691: break; ! 1692: case 'x': /* register number; opcode: [9-11] */ ! 1693: *ip->curr++ = ((op>>9)&0x07)+'0'; ! 1694: break; ! 1695: case 'y': /* register number; opcode: [0-2] */ ! 1696: *ip->curr++ = (op&0x07)+'0'; ! 1697: break; ! 1698: case 'z': /* shift count; opcode: [9-11] */ ! 1699: *ip->curr++ = ((op>>9)&0x07)+'0'; ! 1700: break; ! 1701: case 'A': /* register number; word 2: [0-2] */ ! 1702: *ip->curr++ = (ip->raw[2]&0x07)+'0'; ! 1703: break; ! 1704: case 'B': /* float source reg; word 1: [10-12] */ ! 1705: *ip->curr++ = ((w1>>10)&0x07)+'0'; ! 1706: break; ! 1707: case 'C': /* cache identifier; opcode: [6-7] */ ! 1708: bprint(ip, cachetab[(op>>6)&0x03]); ! 1709: break; ! 1710: case 'D': /* float dest reg; word 1: [7-9] */ ! 1711: *ip->curr++ = ((w1>>7)&0x07)+'0'; ! 1712: break; ! 1713: case 'E': /* destination EA; opcode: [6-11] */ ! 1714: pea((op>>9)&0x07, ip, &ip->and[currand++]); ! 1715: break; ! 1716: case 'F': /* float dest register(s); word 1: [7-9] & [10-12] */ ! 1717: r1 = (w1>>7)&0x07; ! 1718: r2 = (w1>>10)&0x07; ! 1719: if (r1 == r2) ! 1720: bprint(ip, "F%d", r1); ! 1721: else ! 1722: bprint(ip, "F%d,F%d", r2, r1); ! 1723: break; ! 1724: case 'H': /* MMU register; word 1 [10-13] */ ! 1725: bprint(ip, mmutab[(w1>>10)&0x03]); ! 1726: if (ip->curr[-1] == '?') ! 1727: ip->errmsg = "bad mmu register"; ! 1728: break; ! 1729: case 'I': /* MMU function code mask; word 1: [5-8] */ ! 1730: bprint(ip, "%x", (w1>>4)&0x0f); ! 1731: break; ! 1732: case 'K': /* dynamic k-factor register; word 1: [5-8] */ ! 1733: bprint(ip, "%d", (w1>>4)&0x0f); ! 1734: break; ! 1735: case 'L': /* MMU function code; word 1: [0-6] */ ! 1736: if (w1&0x10) ! 1737: bprint(ip, "%x", w1&0x0f); ! 1738: else if (w1&0x08) ! 1739: bprint(ip, "R%d",w1&0x07); ! 1740: else if (w1&0x01) ! 1741: bprint(ip, "DFC"); ! 1742: else ! 1743: bprint(ip, "SFC"); ! 1744: break; ! 1745: case 'N': /* control register; word 1: [0-11] */ ! 1746: r1 = w1&0xfff; ! 1747: if (r1&0x800) ! 1748: bprint(ip, crtab1[r1&0x07]); ! 1749: else ! 1750: bprint(ip, crtab0[r1&0x07]); ! 1751: break; ! 1752: case 'P': /* conditional predicate; word 1: [0-5] */ ! 1753: bprint(ip, fcond[w1&0x1f]); ! 1754: break; ! 1755: case 'R': /* register type & number; word 2 [12-15] */ ! 1756: bprint(ip, regname[(ip->raw[2]>>12)&0x0f]); ! 1757: break; ! 1758: case 'S': /* float source type code; word 1: [10-12] */ ! 1759: *ip->curr = typetab[(w1>>10)&0x07]; ! 1760: if (*ip->curr++ == '?') ! 1761: ip->errmsg = "bad float type"; ! 1762: break; ! 1763: case 'U': /* register number; word 2: [6-8] */ ! 1764: *ip->curr++ = ((ip->raw[2]>>6)&0x07)+'0'; ! 1765: break; ! 1766: case 'Z': /* ATC level number; word 1: [10-12] */ ! 1767: bprint(ip, "%x", (w1>>10)&0x07); ! 1768: break; ! 1769: case '1': /* effective address in second operand*/ ! 1770: pea(op&0x07, ip, &ip->and[1]); ! 1771: break; ! 1772: default: ! 1773: bprint(ip, "%%%c", *fmt); ! 1774: break; ! 1775: } ! 1776: } ! 1777: *ip->curr = 0; /* there's always room for 1 byte */ ! 1778: } ! 1779: ! 1780: static int ! 1781: dispsize(Inst *ip) ! 1782: { ! 1783: ushort ext; ! 1784: static int dsize[] = {0, 0, 1, 2}; /* in words */ ! 1785: ! 1786: if (get2(mymap, ip->addr+ip->n*2, &ext) < 0) ! 1787: return -1; ! 1788: if ((ext&0x100) == 0) ! 1789: return 1; ! 1790: return dsize[(ext>>4)&0x03]+dsize[ext&0x03]+1; ! 1791: } ! 1792: ! 1793: static int ! 1794: immsize(Inst *ip, int mode) ! 1795: { ! 1796: static int fsize[] = { 2, 2, 6, 12, 1, 4, 1, -1 }; ! 1797: static int isize[] = { 1, 1, 2, -1 }; ! 1798: ! 1799: switch(mode) ! 1800: { ! 1801: case EAM_B: /* byte */ ! 1802: case EAALL_B: ! 1803: case EADI_W: /* word */ ! 1804: case EAALL_W: ! 1805: return 1; ! 1806: case EADI_L: /* long */ ! 1807: case EAALL_L: ! 1808: return 2; ! 1809: case EAFLT: /* floating point - size in bits 10-12 or word 1 */ ! 1810: return fsize[(ip->raw[1]>>10)&0x07]; ! 1811: case IV: /* size encoded in bits 6&7 of opcode word */ ! 1812: default: ! 1813: return isize[(ip->raw[0]>>6)&0x03]; ! 1814: } ! 1815: return -1; ! 1816: } ! 1817: ! 1818: static int ! 1819: easize(Inst *ip, int ea, int mode) ! 1820: { ! 1821: switch((ea>>3)&0x07) ! 1822: { ! 1823: case 0x00: ! 1824: case 0x01: ! 1825: case 0x02: ! 1826: case 0x03: ! 1827: case 0x04: ! 1828: return 0; ! 1829: case 0x05: ! 1830: return 1; ! 1831: case 0x06: ! 1832: return dispsize(ip); ! 1833: case 0x07: ! 1834: switch(ea&0x07) ! 1835: { ! 1836: case 0x00: ! 1837: case 0x02: ! 1838: return 1; ! 1839: case 0x01: ! 1840: return 2; ! 1841: case 0x03: ! 1842: return dispsize(ip); ! 1843: case 0x04: ! 1844: return immsize(ip, mode); ! 1845: default: ! 1846: return -1; ! 1847: } ! 1848: } ! 1849: return -1; ! 1850: } ! 1851: ! 1852: static int ! 1853: instrsize(Inst *ip, Optable *op) ! 1854: { ! 1855: int i, t, mode; ! 1856: short opcode; ! 1857: ! 1858: opcode = ip->raw[0]; ! 1859: for (i = 0; i < nelem(op->opdata) && op->opdata[i]; i++) { ! 1860: mode = op->opdata[i]; ! 1861: switch(mode) ! 1862: { ! 1863: case EAPI: /* normal EA modes */ ! 1864: case EACA: ! 1865: case EACAD: ! 1866: case EACAPI: ! 1867: case EACAPD: ! 1868: case EAMA: ! 1869: case EADA: ! 1870: case EAA: ! 1871: case EAC: ! 1872: case EACPI: ! 1873: case EACD: ! 1874: case EAD: ! 1875: case EAM: ! 1876: case EAM_B: ! 1877: case EADI: ! 1878: case EADI_L: ! 1879: case EADI_W: ! 1880: case EAALL: ! 1881: case EAALL_L: ! 1882: case EAALL_W: ! 1883: case EAALL_B: ! 1884: case EAFLT: ! 1885: t = easize(ip, opcode&0x3f, mode); ! 1886: if (t < 0) ! 1887: return -1; ! 1888: ip->n += t; ! 1889: break; ! 1890: case EADDA: /* stupid bit flop required */ ! 1891: t = ((opcode>>9)&0x07)|((opcode>>3)&0x38); ! 1892: t = easize(ip, t, mode); ! 1893: if (t < 0) ! 1894: return -1; ! 1895: ip->n += t; ! 1896: break; ! 1897: case BREAC: /* EAC JMP or CALL operand */ ! 1898: /* easy displacements for follow set */ ! 1899: if ((opcode&0x038) == 0x28 || (opcode&0x3f) == 0x3a) { ! 1900: if (i16(ip, &ip->and[i].immediate) < 0) ! 1901: return -1; ! 1902: } else { ! 1903: t = easize(ip, opcode&0x3f, mode); ! 1904: if (t < 0) ! 1905: return -1; ! 1906: ip->n += t; ! 1907: } ! 1908: break; ! 1909: case I16: /* 16 bit immediate */ ! 1910: case C16: /* CAS2 16 bit immediate */ ! 1911: ip->n++; ! 1912: break; ! 1913: case BR16: /* 16 bit branch displacement */ ! 1914: if (i16(ip, &ip->and[i].immediate) < 0) ! 1915: return -1; ! 1916: break; ! 1917: case BR32: /* 32 bit branch displacement */ ! 1918: if (i32(ip, &ip->and[i].immediate) < 0) ! 1919: return -1; ! 1920: break; ! 1921: case I32: /* 32 bit immediate */ ! 1922: ip->n += 2; ! 1923: break; ! 1924: case IV: /* immediate data depends on size field */ ! 1925: t = (ip->raw[0]>>6)&0x03; ! 1926: if (t < 2) ! 1927: ip->n++; ! 1928: else if (t == 2) ! 1929: ip->n += 2; ! 1930: else ! 1931: return -1; ! 1932: break; ! 1933: case BR8: /* loony branch displacement format */ ! 1934: t = opcode&0xff; ! 1935: if (t == 0) { ! 1936: if (i16(ip, &ip->and[i].immediate) < 0) ! 1937: return -1; ! 1938: } else if (t == 0xff) { ! 1939: if (i32(ip, &ip->and[i].immediate) < 0) ! 1940: return -1; ! 1941: } else { ! 1942: ip->and[i].immediate = t; ! 1943: if (t & 0x80) ! 1944: ip->and[i].immediate |= ~0xff; ! 1945: } ! 1946: break; ! 1947: case STACK: /* Dummy operand for Return instructions */ ! 1948: case OP8: /* weird movq instruction */ ! 1949: case I8: /* must be two-word opcode */ ! 1950: default: ! 1951: break; ! 1952: } ! 1953: } ! 1954: return 1; ! 1955: } ! 1956: ! 1957: static int ! 1958: eaval(Inst *ip, Operand *ap, Rgetter rget) ! 1959: { ! 1960: int reg; ! 1961: char buf[8]; ! 1962: ! 1963: reg = ip->raw[0]&0x07; ! 1964: switch(ap->eatype) ! 1965: { ! 1966: case AInd: ! 1967: sprint(buf, "A%d", reg); ! 1968: return (*rget)(mymap, buf); ! 1969: case PDisp: ! 1970: return ip->addr+2+ap->disp; ! 1971: case ADisp: ! 1972: sprint(buf, "A%d", reg); ! 1973: return ap->disp+(*rget)(mymap, buf); ! 1974: case ABS: ! 1975: return ap->immediate; ! 1976: default: ! 1977: return 0; ! 1978: } ! 1979: } ! 1980: ! 1981: static int ! 1982: m68020instlen(Map *map, ulong pc) ! 1983: { ! 1984: Inst i; ! 1985: Optable *op; ! 1986: ! 1987: mymap = map; ! 1988: i.addr = pc; ! 1989: i.errmsg = 0; ! 1990: op = instruction(&i); ! 1991: if (op && instrsize(&i, op) > 0) ! 1992: return i.n*2; ! 1993: return -1; ! 1994: } ! 1995: ! 1996: static int ! 1997: m68020foll(Map *map, ulong pc, Rgetter rget, ulong *foll) ! 1998: { ! 1999: int j; ! 2000: Inst i; ! 2001: Optable *op; ! 2002: ! 2003: mymap = map; ! 2004: i.addr = pc; ! 2005: i.errmsg = 0; ! 2006: op = instruction(&i); ! 2007: if (op == 0 || instrsize(&i, op) < 0) ! 2008: return -1; ! 2009: for (j = 0; j < nelem(op->opdata) && op->opdata[j]; j++) { ! 2010: switch(op->opdata[j]) ! 2011: { ! 2012: case BREAC: /* CALL, JMP, JSR */ ! 2013: foll[0] = pc+2+eaval(&i, &i.and[j], rget); ! 2014: return 1; ! 2015: case BR8: /* Bcc, BSR, & BRA */ ! 2016: case BR16: /* FBcc, FDBcc, DBcc */ ! 2017: case BR32: /* FBcc */ ! 2018: foll[0] = pc+i.n*2; ! 2019: foll[1] = pc+2+i.and[j].immediate; ! 2020: return 2; ! 2021: case STACK: /* RTR, RTS, RTD */ ! 2022: if (get4(map, (*rget)(map, mach->sp), (long*) foll) < 0) ! 2023: return -1; ! 2024: return 1; ! 2025: default: ! 2026: break; ! 2027: } ! 2028: } ! 2029: foll[0] = pc+i.n*2; ! 2030: return 1; ! 2031: } ! 2032: ! 2033: static int ! 2034: m68020inst(Map *map, ulong pc, char modifier, char *buf, int n) ! 2035: { ! 2036: Inst i; ! 2037: Optable *op; ! 2038: ! 2039: USED(modifier); ! 2040: mymap = map; ! 2041: i.addr = pc; ! 2042: i.curr = buf; ! 2043: i.end = buf+n-1; ! 2044: i.errmsg = 0; ! 2045: op = instruction(&i); ! 2046: if (!op) ! 2047: return -1; ! 2048: if (decode(&i, op) > 0) ! 2049: formatins(op->format, &i); ! 2050: if (i.errmsg) { ! 2051: if (i.curr != buf) ! 2052: bprint(&i, "\t\t;"); ! 2053: bprint(&i, "%s: ", i.errmsg); ! 2054: dumpinst(&i, i.curr, i.end-i.curr); ! 2055: } ! 2056: return i.n*2; ! 2057: } ! 2058: ! 2059: static int ! 2060: m68020das(Map *map, ulong pc, char *buf, int n) ! 2061: { ! 2062: Inst i; ! 2063: Optable *op; ! 2064: ! 2065: mymap = map; ! 2066: i.addr = pc; ! 2067: i.curr = buf; ! 2068: i.end = buf+n-1; ! 2069: i.errmsg = 0; ! 2070: ! 2071: op = instruction(&i); ! 2072: if (!op) ! 2073: return -1; ! 2074: decode(&i, op); ! 2075: if (i.errmsg) ! 2076: bprint(&i, "%s: ", i.errmsg); ! 2077: dumpinst(&i, i.curr, i.end-i.curr); ! 2078: return i.n*2; ! 2079: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.