|
|
1.1 ! root 1: /*************************************************************************** ! 2: ! 3: i860dis.c ! 4: ! 5: Disassembler for the Intel i860 emulator. ! 6: ! 7: Copyright (C) 1995-present Jason Eckhardt ([email protected]) ! 8: Released for general non-commercial use under the MAME license ! 9: with the additional requirement that you are free to use and ! 10: redistribute this code in modified or unmodified form, provided ! 11: you list me in the credits. ! 12: Visit http://mamedev.org for licensing and usage restrictions. ! 13: ! 14: Changes for previous/NeXTdimension by Simon Schubiger (SC) ! 15: ! 16: ***************************************************************************/ ! 17: ! 18: #include <string.h> ! 19: #include <stdio.h> ! 20: #include "i860.hpp" ! 21: ! 22: /* Macros for accessing register fields in instruction word. */ ! 23: #define get_isrc1(bits) (((bits) >> 11) & 0x1f) ! 24: #define get_isrc2(bits) (((bits) >> 21) & 0x1f) ! 25: #define get_idest(bits) (((bits) >> 16) & 0x1f) ! 26: #define get_fsrc1(bits) (((bits) >> 11) & 0x1f) ! 27: #define get_fsrc2(bits) (((bits) >> 21) & 0x1f) ! 28: #define get_fdest(bits) (((bits) >> 16) & 0x1f) ! 29: #define get_creg(bits) (((bits) >> 21) & 0x7) ! 30: ! 31: /* Macros for accessing immediate fields. */ ! 32: /* 16-bit immediate. */ ! 33: #define get_imm16(insn) ((insn) & 0xffff) ! 34: ! 35: ! 36: /* Control register names. */ ! 37: static const char *const cr2str[] = ! 38: {"fir", "psr", "dirbase", "db", "fsr", "epsr", "!", "!"}; ! 39: ! 40: ! 41: /* Sign extend N-bit number. */ ! 42: static INT32 sign_ext(UINT32 x, int n) ! 43: { ! 44: INT32 t; ! 45: t = x >> (n - 1); ! 46: t = ((-t) << n) | x; ! 47: return t; ! 48: } ! 49: ! 50: ! 51: /* Basic integer 3-address register format: ! 52: * mnemonic %rs1,%rs2,%rd */ ! 53: static void int_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 54: { ! 55: /* Possibly prefix shrd with 'd.' */ ! 56: if (((insn & 0xfc000000) == 0xb0000000) && (insn & 0x200)) ! 57: sprintf(buf, "d.%s\t%%r%d,%%r%d,%%r%d", mnemonic, ! 58: get_isrc1 (insn), get_isrc2 (insn), get_idest (insn)); ! 59: else ! 60: sprintf(buf, " %s\t%%r%d,%%r%d,%%r%d", mnemonic, ! 61: get_isrc1 (insn), get_isrc2 (insn), get_idest (insn)); ! 62: } ! 63: ! 64: ! 65: /* Basic integer 3-address imm16 format: ! 66: * mnemonic #imm16,%rs2,%rd */ ! 67: static void int_i2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 68: { ! 69: /* Sign extend the 16-bit immediate. ! 70: Print as hex for the bitwise operations. */ ! 71: int upper_6bits = (insn >> 26) & 0x3f; ! 72: if (upper_6bits >= 0x30 && upper_6bits <= 0x3f) ! 73: sprintf(buf, " %s\t0x%04x,%%r%d,%%r%d", mnemonic, ! 74: (UINT32)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn)); ! 75: else ! 76: sprintf(buf, " %s\t%d,%%r%d,%%r%d", mnemonic, ! 77: sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn)); ! 78: } ! 79: ! 80: ! 81: /* Integer (mixed) 2-address isrc1ni,fdest. */ ! 82: static void int_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 83: { ! 84: sprintf(buf, " %s\t%%r%d,%%f%d", mnemonic, get_isrc1 (insn), get_fdest (insn)); ! 85: } ! 86: ! 87: ! 88: /* Integer (mixed) 2-address csrc2,idest. */ ! 89: static void int_cd(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 90: { ! 91: sprintf(buf, " %s\t%%%s,%%r%d", mnemonic, cr2str[get_creg (insn)], get_idest (insn)); ! 92: } ! 93: ! 94: ! 95: /* Integer (mixed) 2-address isrc1,csrc2. */ ! 96: static void int_1c(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 97: { ! 98: sprintf(buf, " %s\t%%r%d,%%%s", mnemonic, get_isrc1(insn), cr2str[get_creg (insn)]); ! 99: } ! 100: ! 101: ! 102: /* Integer 1-address register format: ! 103: * mnemonic %rs1 */ ! 104: static void int_1(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 105: { ! 106: sprintf(buf, " %s\t%%r%d", mnemonic, get_isrc1 (insn)); ! 107: } ! 108: ! 109: ! 110: /* Integer no-address register format: ! 111: * mnemonic */ ! 112: static void int_0(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 113: { ! 114: sprintf(buf, " %s", mnemonic); ! 115: } ! 116: ! 117: ! 118: /* Basic floating-point 3-address register format: ! 119: * mnemonic %fs1,%fs2,%fd */ ! 120: static void flop_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 121: { ! 122: const char *const suffix[4] = { "ss", "sd", "ds", "dd" }; ! 123: const char *prefix_d, *prefix_p; ! 124: prefix_p = (insn & 0x400) ? "p" : ""; ! 125: prefix_d = (insn & 0x200) ? "d." : " "; ! 126: ! 127: /* Special case: pf[m]am and pf[m]sm families are always pipelined, so they ! 128: do not have a prefix. Also, for the pfmam and pfmsm families, replace ! 129: any 'a' in the mnemonic with 'm' and prepend an 'm'. */ ! 130: if ((insn & 0x7f) < 0x20) ! 131: { ! 132: int is_pfam = insn & 0x400; ! 133: if (!is_pfam) ! 134: { ! 135: char newname[256]; ! 136: char *op = mnemonic; ! 137: char *np = newname + 1; ! 138: newname[0] = 'm'; ! 139: while (*op) ! 140: { ! 141: if (*op == 'a') ! 142: *np = 'm'; ! 143: else ! 144: *np = *op; ! 145: np++; ! 146: op++; ! 147: } ! 148: *np = 0; ! 149: mnemonic = newname; ! 150: } ! 151: prefix_p = ""; ! 152: } ! 153: ! 154: /* Special case: pfgt/pfle-- R-bit distinguishes the two. */ ! 155: if ((insn & 0x7f) == 0x34) ! 156: { ! 157: const char *const mn[2] = { "fgt.", "fle." }; ! 158: int r = (insn & 0x080) >> 7; ! 159: int s = (insn & 0x100) ? 3 : 0; ! 160: sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mn[r], ! 161: suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn)); ! 162: } ! 163: else ! 164: { ! 165: int s = (insn & 0x180) >> 7; ! 166: sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mnemonic, ! 167: suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn)); ! 168: } ! 169: } ! 170: ! 171: ! 172: /* Floating-point 2-address register format: ! 173: * mnemonic %fs1,%fd */ ! 174: static void flop_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 175: { ! 176: const char *const suffix[4] = { "ss", "sd", "ds", "dd" }; ! 177: const char *prefix_d, *prefix_p; ! 178: int s = (insn & 0x180) >> 7; ! 179: prefix_p = (insn & 0x400) ? "p" : ""; ! 180: prefix_d = (insn & 0x200) ? "d." : " "; ! 181: sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d", prefix_d, prefix_p, mnemonic, ! 182: suffix[s], get_fsrc1 (insn), get_fdest (insn)); ! 183: } ! 184: ! 185: ! 186: /* Floating-point 2-address register format: ! 187: * mnemonic %fs2,%fd */ ! 188: static void flop_2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 189: { ! 190: const char *const suffix[4] = { "ss", "sd", "ds", "dd" }; ! 191: const char *prefix_d; ! 192: int s = (insn & 0x180) >> 7; ! 193: prefix_d = (insn & 0x200) ? "d." : " "; ! 194: sprintf(buf, "%s%s%s\t%%f%d,%%f%d", prefix_d, mnemonic, suffix[s], ! 195: get_fsrc2 (insn), get_fdest (insn)); ! 196: } ! 197: ! 198: ! 199: /* Floating-point (mixed) 2-address register format: ! 200: * fxfr fsrc1,idest. */ ! 201: static void flop_fxfr(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 202: { ! 203: const char *prefix_d = (insn & 0x200) ? "d." : " "; ! 204: sprintf(buf, "%s%s\t%%f%d,%%r%d", prefix_d, mnemonic, get_fsrc1 (insn), ! 205: get_idest (insn)); ! 206: } ! 207: ! 208: ! 209: /* Branch with reg,reg,sbroff format: ! 210: * mnemonic %rs1,%rs2,sbroff */ ! 211: static void int_12S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 212: { ! 213: INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); ! 214: INT32 rel = (INT32)pc + (sbroff << 2) + 4; ! 215: ! 216: sprintf(buf, " %s\t%%r%d,%%r%d,0x%08x", mnemonic, get_isrc1 (insn), ! 217: get_isrc2 (insn), (UINT32)rel); ! 218: } ! 219: ! 220: ! 221: /* Branch with #const5,reg,sbroff format: ! 222: * mnemonic #const5,%rs2,sbroff */ ! 223: static void int_i2S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 224: { ! 225: INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); ! 226: INT32 rel = (INT32)pc + (sbroff << 2) + 4; ! 227: ! 228: sprintf(buf, " %s\t%d,%%r%d,0x%08x", mnemonic, ((insn >> 11) & 0x1f), ! 229: get_isrc2 (insn), (UINT32)rel); ! 230: } ! 231: ! 232: ! 233: /* Branch with lbroff format: ! 234: * mnemonic lbroff */ ! 235: static void int_L(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 236: { ! 237: INT32 lbroff = sign_ext ((insn & 0x03ffffff), 26); ! 238: INT32 rel = (INT32)pc + (lbroff << 2) + 4; ! 239: ! 240: sprintf(buf, " %s\t0x%08x", mnemonic, (UINT32)rel); ! 241: } ! 242: ! 243: ! 244: /* Integer load. ! 245: * ld.{b,s,l} isrc1(isrc2),idest ! 246: * ld.{b,s,l} #const(isrc2),idest */ ! 247: static void int_ldx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 248: { ! 249: /* Operand size, in bytes. */ ! 250: int sizes[4] = { 1, 1, 2, 4 }; ! 251: const char *const suffix[4] = { "b", "b", "s", "l" }; ! 252: UINT32 idx = 0; ! 253: ! 254: /* Bits 28 and 0 determine the operand size. */ ! 255: idx = ((insn >> 27) & 2) | (insn & 1); ! 256: ! 257: /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ ! 258: if (insn & 0x04000000) ! 259: { ! 260: /* Chop off lower bits of displacement. */ ! 261: INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); ! 262: int size = sizes[idx]; ! 263: immsrc1 &= ~(size - 1); ! 264: sprintf(buf, " %s%s\t%d(%%r%d),%%r%d", mnemonic, suffix[idx], ! 265: immsrc1, get_isrc2 (insn), get_idest (insn)); ! 266: } ! 267: else ! 268: sprintf(buf, " %s%s\t%%r%d(%%r%d),%%r%d", mnemonic, suffix[idx], ! 269: get_isrc1 (insn), get_isrc2 (insn), get_idest (insn)); ! 270: } ! 271: ! 272: ! 273: /* Integer store: st.b isrc1ni,#const(isrc2) */ ! 274: static void int_stx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 275: { ! 276: /* Operand size, in bytes. */ ! 277: int sizes[4] = { 1, 1, 2, 4 }; ! 278: const char *const suffix[4] = { "b", "b", "s", "l" }; ! 279: int idx = 0; ! 280: int size; ! 281: INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16); ! 282: ! 283: /* Bits 28 and 0 determine the operand size. */ ! 284: idx = ((insn >> 27) & 2) | (insn & 1); ! 285: ! 286: /* Chop off lower bits of displacement. */ ! 287: size = sizes[idx]; ! 288: immsrc &= ~(size - 1); ! 289: sprintf(buf, " %s%s\t%%r%d,%d(%%r%d)", mnemonic, suffix[idx], ! 290: get_isrc1 (insn), immsrc, get_isrc2 (insn)); ! 291: } ! 292: ! 293: ! 294: /* Disassemble: ! 295: * "[p]fld.y isrc1(isrc2),fdest", "[p]fld.y isrc1(isrc2)++,idest", ! 296: * "[p]fld.y #const(isrc2),fdest" or "[p]fld.y #const(isrc2)++,idest". ! 297: * "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++", ! 298: * "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++" ! 299: * Where y = {l,d,q}. Note, there is no pfld.q, though. */ ! 300: static void int_fldst(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 301: { ! 302: INT32 immsrc1 = sign_ext (get_imm16 (insn), 16); ! 303: /* Operand size, in bytes. */ ! 304: int sizes[4] = { 8, 4, 16, 4 }; ! 305: const char *const suffix[4] = { "d", "l", "q", "l" }; ! 306: int idx = 0; ! 307: int size = 0; ! 308: int auto_inc = (insn & 1); ! 309: const char *const auto_suff[2] = { "", "++" }; ! 310: int piped = (insn & 0x40000000) >> 30; ! 311: const char *const piped_suff[2] = { "", "p" }; ! 312: int upper_6bits = (insn >> 26) & 0x3f; ! 313: int is_load = (upper_6bits == 8 || upper_6bits == 9 || upper_6bits == 24 ! 314: || upper_6bits == 25); ! 315: ! 316: /* Bits 2 and 1 determine the operand size. */ ! 317: idx = ((insn >> 1) & 3); ! 318: size = sizes[idx]; ! 319: ! 320: /* There is no pipelined load quad on XR. */ ! 321: if (piped && size == 16) ! 322: { ! 323: sprintf (buf, ".long\t%#08x; *", insn); ! 324: return; ! 325: } ! 326: ! 327: /* There is only a 64-bit pixel store. */ ! 328: if ((upper_6bits == 15) && size != 8) ! 329: { ! 330: sprintf (buf, ".long\t%#08x", insn); ! 331: return; ! 332: } ! 333: ! 334: /* Bit 26 determines the addressing mode (reg+reg or disp+reg). */ ! 335: if (insn & 0x04000000) ! 336: { ! 337: /* Chop off lower bits of displacement. */ ! 338: immsrc1 &= ~(size - 1); ! 339: if (is_load) ! 340: sprintf(buf, " %s%s%s\t%d(%%r%d)%s,%%f%d", piped_suff[piped], mnemonic, ! 341: suffix[idx], immsrc1, get_isrc2 (insn), auto_suff[auto_inc], ! 342: get_fdest (insn)); ! 343: else ! 344: sprintf(buf, " %s%s\t%%f%d,%d(%%r%d)%s", mnemonic, suffix[idx], ! 345: get_fdest (insn), immsrc1, get_isrc2 (insn), auto_suff[auto_inc]); ! 346: } ! 347: else ! 348: { ! 349: if (is_load) ! 350: sprintf(buf, " %s%s%s\t%%r%d(%%r%d)%s,%%f%d", piped_suff[piped], ! 351: mnemonic, suffix[idx], get_isrc1 (insn), get_isrc2 (insn), ! 352: auto_suff[auto_inc], get_fdest (insn)); ! 353: else ! 354: sprintf(buf, " %s%s\t%%f%d,%%r%d(%%r%d)%s", mnemonic, suffix[idx], ! 355: get_fdest (insn), get_isrc1 (insn), get_isrc2 (insn), ! 356: auto_suff[auto_inc]); ! 357: } ! 358: } ! 359: ! 360: ! 361: /* flush #const(isrc2)[++]. */ ! 362: static void int_flush(char *buf, char *mnemonic, UINT32 pc, UINT32 insn) ! 363: { ! 364: const char *const auto_suff[2] = { "", "++" }; ! 365: INT32 immsrc = sign_ext (get_imm16 (insn), 16); ! 366: immsrc &= ~(16-1); ! 367: sprintf(buf, " %s\t%d(%%r%d)%s", mnemonic, immsrc, get_isrc2 (insn), ! 368: auto_suff[(insn & 1)]); ! 369: } ! 370: ! 371: ! 372: /* Flags for the decode table. */ ! 373: enum ! 374: { ! 375: DEC_MORE = 1, /* More decoding necessary. */ ! 376: DEC_DECODED = 2 /* Fully decoded, go. */ ! 377: }; ! 378: ! 379: ! 380: struct decode_tbl_t ! 381: { ! 382: /* Disassembly function for this opcode. ! 383: Call with buffer, mnemonic, pc, insn. */ ! 384: void (*insn_dis)(char *, char *, UINT32, UINT32); ! 385: ! 386: /* Flags for this opcode. */ ! 387: char flags; ! 388: ! 389: /* Mnemonic of this opcode (sometimes partial when more decode is ! 390: done in disassembly routines-- e.g., loads and stores). */ ! 391: const char *mnemonic; ! 392: }; ! 393: ! 394: ! 395: /* First-level decode table (i.e., for the 6 primary opcode bits). */ ! 396: static const decode_tbl_t decode_tbl[64] = ! 397: { ! 398: /* A slight bit of decoding for loads and stores is done in the ! 399: execution routines (operand size and addressing mode), which ! 400: is why their respective entries are identical. */ ! 401: { int_ldx, DEC_DECODED, "ld." }, /* ld.b isrc1(isrc2),idest. */ ! 402: { int_ldx, DEC_DECODED, "ld." }, /* ld.b #const(isrc2),idest. */ ! 403: { int_1d, DEC_DECODED, "ixfr" }, /* ixfr isrc1ni,fdest. */ ! 404: { int_stx, DEC_DECODED, "st." }, /* st.b isrc1ni,#const(isrc2). */ ! 405: { int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} isrc1(isrc2),idest. */ ! 406: { int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} #const(isrc2),idest. */ ! 407: { 0, 0 , 0 }, ! 408: { int_stx, DEC_DECODED, "st." }, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/ ! 409: { int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */ ! 410: { int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} #const(isrc2)[++],fdest. */ ! 411: { int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */ ! 412: { int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,#const(isrc2)[++] */ ! 413: { int_cd, DEC_DECODED, "ld.c" }, /* ld.c csrc2,idest. */ ! 414: { int_flush, DEC_DECODED, "flush" }, /* flush #const(isrc2) (or autoinc). */ ! 415: { int_1c, DEC_DECODED, "st.c" }, /* st.c isrc1,csrc2. */ ! 416: { int_fldst, DEC_DECODED, "pstd." }, /* pst.d fdest,#const(isrc2)[++]. */ ! 417: { int_1, DEC_DECODED, "bri" }, /* bri isrc1ni. */ ! 418: { int_12d, DEC_DECODED, "trap" }, /* trap isrc1ni,isrc2,idest. */ ! 419: { 0, DEC_MORE, 0 }, /* FP ESCAPE FORMAT, more decode. */ ! 420: { 0, DEC_MORE, 0 }, /* CORE ESCAPE FORMAT, more decode. */ ! 421: { int_12S, DEC_DECODED, "btne" }, /* btne isrc1,isrc2,sbroff. */ ! 422: { int_i2S, DEC_DECODED, "btne" }, /* btne #const,isrc2,sbroff. */ ! 423: { int_12S, DEC_DECODED, "bte" }, /* bte isrc1,isrc2,sbroff. */ ! 424: { int_i2S, DEC_DECODED, "bte" }, /* bte #const5,isrc2,idest. */ ! 425: { int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest. */ ! 426: { int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/ ! 427: { int_L, DEC_DECODED, "br" }, /* br lbroff. */ ! 428: { int_L, DEC_DECODED, "call" }, /* call lbroff . */ ! 429: { int_L, DEC_DECODED, "bc" }, /* bc lbroff. */ ! 430: { int_L, DEC_DECODED, "bc.t" }, /* bc.t lbroff. */ ! 431: { int_L, DEC_DECODED, "bnc" }, /* bnc lbroff. */ ! 432: { int_L, DEC_DECODED, "bnc.t" }, /* bnc.t lbroff. */ ! 433: { int_12d, DEC_DECODED, "addu" }, /* addu isrc1,isrc2,idest. */ ! 434: { int_i2d, DEC_DECODED, "addu" }, /* addu #const,isrc2,idest. */ ! 435: { int_12d, DEC_DECODED, "subu" }, /* subu isrc1,isrc2,idest. */ ! 436: { int_i2d, DEC_DECODED, "subu" }, /* subu #const,isrc2,idest. */ ! 437: { int_12d, DEC_DECODED, "adds" }, /* adds isrc1,isrc2,idest. */ ! 438: { int_i2d, DEC_DECODED, "adds" }, /* adds #const,isrc2,idest. */ ! 439: { int_12d, DEC_DECODED, "subs" }, /* subs isrc1,isrc2,idest. */ ! 440: { int_i2d, DEC_DECODED, "subs" }, /* subs #const,isrc2,idest. */ ! 441: { int_12d, DEC_DECODED, "shl" }, /* shl isrc1,isrc2,idest. */ ! 442: { int_i2d, DEC_DECODED, "shl" }, /* shl #const,isrc2,idest. */ ! 443: { int_12d, DEC_DECODED, "shr" }, /* shr isrc1,isrc2,idest. */ ! 444: { int_i2d, DEC_DECODED, "shr" }, /* shr #const,isrc2,idest. */ ! 445: { int_12d, DEC_DECODED, "shrd" }, /* shrd isrc1ni,isrc2,idest. */ ! 446: { int_12S, DEC_DECODED, "bla" }, /* bla isrc1ni,isrc2,sbroff. */ ! 447: { int_12d, DEC_DECODED, "shra" }, /* shra isrc1,isrc2,idest. */ ! 448: { int_i2d, DEC_DECODED, "shra" }, /* shra #const,isrc2,idest. */ ! 449: { int_12d, DEC_DECODED, "and" }, /* and isrc1,isrc2,idest. */ ! 450: { int_i2d, DEC_DECODED, "and" }, /* and #const,isrc2,idest. */ ! 451: { 0, 0 , 0 }, ! 452: { int_i2d, DEC_DECODED, "andh" }, /* andh #const,isrc2,idest. */ ! 453: { int_12d, DEC_DECODED, "andnot" }, /* andnot isrc1,isrc2,idest. */ ! 454: { int_i2d, DEC_DECODED, "andnot" }, /* andnot #const,isrc2,idest. */ ! 455: { 0, 0 , 0 }, ! 456: { int_i2d, DEC_DECODED, "andnoth" }, /* andnoth #const,isrc2,idest.*/ ! 457: { int_12d, DEC_DECODED, "or" }, /* or isrc1,isrc2,idest. */ ! 458: { int_i2d, DEC_DECODED, "or" }, /* or #const,isrc2,idest. */ ! 459: { 0, 0 , 0 }, ! 460: { int_i2d, DEC_DECODED, "orh" }, /* orh #const,isrc2,idest. */ ! 461: { int_12d, DEC_DECODED, "xor" }, /* xor isrc1,isrc2,idest. */ ! 462: { int_i2d, DEC_DECODED, "xor" }, /* xor #const,isrc2,idest. */ ! 463: { 0, 0 , 0 }, ! 464: { int_i2d, DEC_DECODED, "xorh" }, /* xorh #const,isrc2,idest. */ ! 465: }; ! 466: ! 467: ! 468: /* Second-level decode table (i.e., for the 3 core escape opcode bits). */ ! 469: static const decode_tbl_t core_esc_decode_tbl[8] = ! 470: { ! 471: { 0, 0 , 0 }, ! 472: { int_0, DEC_DECODED, "lock" }, /* lock. */ ! 473: { int_1, DEC_DECODED, "calli" }, /* calli isrc1ni. */ ! 474: { 0, 0 , 0 }, ! 475: { int_0, DEC_DECODED, "intovr" }, /* intovr. */ ! 476: { 0, 0 , 0 }, ! 477: { 0, 0 , 0 }, ! 478: { int_0, DEC_DECODED, "unlock" }, /* unlock. */ ! 479: }; ! 480: ! 481: ! 482: /* Second-level decode table (i.e., for the 7 FP extended opcode bits). */ ! 483: static const decode_tbl_t fp_decode_tbl[128] = ! 484: { ! 485: /* Floating point instructions. The least significant 7 bits are ! 486: the (extended) opcode and bits 10:7 are P,D,S,R respectively ! 487: ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.). ! 488: For some operations, I defer decoding the P,S,R bits to the ! 489: emulation routine for them. */ ! 490: { flop_12d, DEC_DECODED, "r2p1." }, /* 0x00 pf[m]am */ ! 491: { flop_12d, DEC_DECODED, "r2pt." }, /* 0x01 pf[m]am */ ! 492: { flop_12d, DEC_DECODED, "r2ap1." }, /* 0x02 pf[m]am */ ! 493: { flop_12d, DEC_DECODED, "r2apt." }, /* 0x03 pf[m]am */ ! 494: { flop_12d, DEC_DECODED, "i2p1." }, /* 0x04 pf[m]am */ ! 495: { flop_12d, DEC_DECODED, "i2pt." }, /* 0x05 pf[m]am */ ! 496: { flop_12d, DEC_DECODED, "i2ap1." }, /* 0x06 pf[m]am */ ! 497: { flop_12d, DEC_DECODED, "i2apt." }, /* 0x07 pf[m]am */ ! 498: { flop_12d, DEC_DECODED, "rat1p2." }, /* 0x08 pf[m]am */ ! 499: { flop_12d, DEC_DECODED, "m12apm." }, /* 0x09 pf[m]am */ ! 500: { flop_12d, DEC_DECODED, "ra1p2." }, /* 0x0A pf[m]am */ ! 501: { flop_12d, DEC_DECODED, "m12ttpa." }, /* 0x0B pf[m]am */ ! 502: { flop_12d, DEC_DECODED, "iat1p2." }, /* 0x0C pf[m]am */ ! 503: { flop_12d, DEC_DECODED, "m12tpm." }, /* 0x0D pf[m]am */ ! 504: { flop_12d, DEC_DECODED, "ia1p2." }, /* 0x0E pf[m]am */ ! 505: { flop_12d, DEC_DECODED, "m12tpa." }, /* 0x0F pf[m]am */ ! 506: { flop_12d, DEC_DECODED, "r2s1." }, /* 0x10 pf[m]sm */ ! 507: { flop_12d, DEC_DECODED, "r2st." }, /* 0x11 pf[m]sm */ ! 508: { flop_12d, DEC_DECODED, "r2as1." }, /* 0x12 pf[m]sm */ ! 509: { flop_12d, DEC_DECODED, "r2ast." }, /* 0x13 pf[m]sm */ ! 510: { flop_12d, DEC_DECODED, "i2s1." }, /* 0x14 pf[m]sm */ ! 511: { flop_12d, DEC_DECODED, "i2st." }, /* 0x15 pf[m]sm */ ! 512: { flop_12d, DEC_DECODED, "i2as1." }, /* 0x16 pf[m]sm */ ! 513: { flop_12d, DEC_DECODED, "i2ast." }, /* 0x17 pf[m]sm */ ! 514: { flop_12d, DEC_DECODED, "rat1s2." }, /* 0x18 pf[m]sm */ ! 515: { flop_12d, DEC_DECODED, "m12asm." }, /* 0x19 pf[m]sm */ ! 516: { flop_12d, DEC_DECODED, "ra1s2." }, /* 0x1A pf[m]sm */ ! 517: { flop_12d, DEC_DECODED, "m12ttsa." }, /* 0x1B pf[m]sm */ ! 518: { flop_12d, DEC_DECODED, "iat1s2." }, /* 0x1C pf[m]sm */ ! 519: { flop_12d, DEC_DECODED, "m12tsm." }, /* 0x1D pf[m]sm */ ! 520: { flop_12d, DEC_DECODED, "ia1s2." }, /* 0x1E pf[m]sm */ ! 521: { flop_12d, DEC_DECODED, "m12tsa." }, /* 0x1F pf[m]sm */ ! 522: { flop_12d, DEC_DECODED, "fmul." }, /* 0x20 [p]fmul */ ! 523: { flop_12d, DEC_DECODED, "fmlow." }, /* 0x21 fmlow.dd */ ! 524: { flop_2d, DEC_DECODED, "frcp." }, /* 0x22 frcp.{ss,sd,dd} */ ! 525: { flop_2d, DEC_DECODED, "frsqr." }, /* 0x23 frsqr.{ss,sd,dd} */ ! 526: { flop_12d, DEC_DECODED, "pfmul3.dd" }, /* 0x24 pfmul3.dd */ ! 527: { 0, 0 , 0 }, /* 0x25 */ ! 528: { 0, 0 , 0 }, /* 0x26 */ ! 529: { 0, 0 , 0 }, /* 0x27 */ ! 530: { 0, 0 , 0 }, /* 0x28 */ ! 531: { 0, 0 , 0 }, /* 0x29 */ ! 532: { 0, 0 , 0 }, /* 0x2A */ ! 533: { 0, 0 , 0 }, /* 0x2B */ ! 534: { 0, 0 , 0 }, /* 0x2C */ ! 535: { 0, 0 , 0 }, /* 0x2D */ ! 536: { 0, 0 , 0 }, /* 0x2E */ ! 537: { 0, 0 , 0 }, /* 0x2F */ ! 538: { flop_12d, DEC_DECODED, "fadd." }, /* 0x30, [p]fadd.{ss,sd,dd} */ ! 539: { flop_12d, DEC_DECODED, "fsub." }, /* 0x31, [p]fsub.{ss,sd,dd} */ ! 540: { flop_1d, DEC_DECODED, "fix." }, /* 0x32, [p]fix.{ss,sd,dd} */ ! 541: { flop_1d, DEC_DECODED, "famov." }, /* 0x33, [p]famov.{ss,sd,ds,dd} */ ! 542: { flop_12d, DEC_DECODED, "f{gt,le}" }, /* 0x34, pf{gt,le}.{ss,dd} */ ! 543: { flop_12d, DEC_DECODED, "feq." }, /* 0x35, pfeq.{ss,dd} */ ! 544: { 0, 0 , 0 }, /* 0x36 */ ! 545: { 0, 0 , 0 }, /* 0x37 */ ! 546: { 0, 0 , 0 }, /* 0x38 */ ! 547: { 0, 0 , 0 }, /* 0x39 */ ! 548: { flop_1d, DEC_DECODED, "ftrunc." }, /* 0x3A, [p]ftrunc.{ss,sd,dd} */ ! 549: { 0, 0 , 0 }, /* 0x3B */ ! 550: { 0, 0 , 0 }, /* 0x3C */ ! 551: { 0, 0 , 0 }, /* 0x3D */ ! 552: { 0, 0 , 0 }, /* 0x3E */ ! 553: { 0, 0 , 0 }, /* 0x3F */ ! 554: { flop_fxfr, DEC_DECODED, "fxfr" }, /* 0x40, fxfr fsrc1,idest. */ ! 555: { 0, 0 , 0 }, /* 0x41 */ ! 556: { 0, 0 , 0 }, /* 0x42 */ ! 557: { 0, 0 , 0 }, /* 0x43 */ ! 558: { 0, 0 , 0 }, /* 0x44 */ ! 559: { 0, 0 , 0 }, /* 0x45 */ ! 560: { 0, 0 , 0 }, /* 0x46 */ ! 561: { 0, 0 , 0 }, /* 0x47 */ ! 562: { 0, 0 , 0 }, /* 0x48 */ ! 563: { flop_12d, DEC_DECODED, "fiadd." }, /* 0x49, [p]fiadd.{ss,dd} */ ! 564: { 0, 0 , 0 }, /* 0x4A */ ! 565: { 0, 0 , 0 }, /* 0x4B */ ! 566: { 0, 0 , 0 }, /* 0x4C */ ! 567: { flop_12d, DEC_DECODED, "fisub." }, /* 0x4D, [p]fisub.{ss,dd} */ ! 568: { 0, 0 , 0 }, /* 0x4E */ ! 569: { 0, 0 , 0 }, /* 0x4F */ ! 570: { flop_12d, DEC_DECODED, "faddp" }, /* 0x50, [p]faddp */ ! 571: { flop_12d, DEC_DECODED, "faddz" }, /* 0x51, [p]faddz */ ! 572: { 0, 0 , 0 }, /* 0x52 */ ! 573: { 0, 0 , 0 }, /* 0x53 */ ! 574: { 0, 0 , 0 }, /* 0x54 */ ! 575: { 0, 0 , 0 }, /* 0x55 */ ! 576: { 0, 0 , 0 }, /* 0x56 */ ! 577: { flop_12d, DEC_DECODED, "fzchkl" }, /* 0x57, [p]fzchkl */ ! 578: { 0, 0 , 0 }, /* 0x58 */ ! 579: { 0, 0 , 0 }, /* 0x59 */ ! 580: { flop_1d, DEC_DECODED, "form" }, /* 0x5A, [p]form.dd */ ! 581: { 0, 0 , 0 }, /* 0x5B */ ! 582: { 0, 0 , 0 }, /* 0x5C */ ! 583: { 0, 0 , 0 }, /* 0x5D */ ! 584: { 0, 0 , 0 }, /* 0x5E */ ! 585: { flop_12d, DEC_DECODED, "fzchks" }, /* 0x5F, [p]fzchks */ ! 586: { 0, 0 , 0 }, /* 0x60 */ ! 587: { 0, 0 , 0 }, /* 0x61 */ ! 588: { 0, 0 , 0 }, /* 0x62 */ ! 589: { 0, 0 , 0 }, /* 0x63 */ ! 590: { 0, 0 , 0 }, /* 0x64 */ ! 591: { 0, 0 , 0 }, /* 0x65 */ ! 592: { 0, 0 , 0 }, /* 0x66 */ ! 593: { 0, 0 , 0 }, /* 0x67 */ ! 594: { 0, 0 , 0 }, /* 0x68 */ ! 595: { 0, 0 , 0 }, /* 0x69 */ ! 596: { 0, 0 , 0 }, /* 0x6A */ ! 597: { 0, 0 , 0 }, /* 0x6B */ ! 598: { 0, 0 , 0 }, /* 0x6C */ ! 599: { 0, 0 , 0 }, /* 0x6D */ ! 600: { 0, 0 , 0 }, /* 0x6E */ ! 601: { 0, 0 , 0 }, /* 0x6F */ ! 602: { 0, 0 , 0 }, /* 0x70 */ ! 603: { 0, 0 , 0 }, /* 0x71 */ ! 604: { 0, 0 , 0 }, /* 0x72 */ ! 605: { 0, 0 , 0 }, /* 0x73 */ ! 606: { 0, 0 , 0 }, /* 0x74 */ ! 607: { 0, 0 , 0 }, /* 0x75 */ ! 608: { 0, 0 , 0 }, /* 0x76 */ ! 609: { 0, 0 , 0 }, /* 0x77 */ ! 610: { 0, 0 , 0 }, /* 0x78 */ ! 611: { 0, 0 , 0 }, /* 0x79 */ ! 612: { 0, 0 , 0 }, /* 0x7A */ ! 613: { 0, 0 , 0 }, /* 0x7B */ ! 614: { 0, 0 , 0 }, /* 0x7C */ ! 615: { 0, 0 , 0 }, /* 0x7D */ ! 616: { 0, 0 , 0 }, /* 0x7E */ ! 617: { 0, 0 , 0 }, /* 0x7F */ ! 618: }; ! 619: ! 620: ! 621: /* Replaces tabs with spaces. */ ! 622: static void i860_dasm_tab_replacer(char* buf, int tab_size) ! 623: { ! 624: int i = 0; ! 625: int tab_count = 0; ! 626: char tab_buf[1024]; ! 627: memset(tab_buf, 0, 1024); ! 628: ! 629: while (i != strlen(buf)) ! 630: { ! 631: if (buf[i] != '\t') ! 632: { ! 633: tab_buf[tab_count] = buf[i]; ! 634: tab_count++; ! 635: } ! 636: else ! 637: { ! 638: while (tab_count % tab_size != 0) ! 639: { ! 640: strcat(tab_buf, " "); ! 641: tab_count++; ! 642: } ! 643: } ! 644: i++; ! 645: } ! 646: ! 647: tab_buf[tab_count] = 0x00; ! 648: strcpy(buf, tab_buf); ! 649: } ! 650: ! 651: ! 652: int i860_disassembler(UINT32 pc, UINT32 insn, char* buffer) { ! 653: int unrecognized_op = 1; ! 654: ! 655: int upper_6bits = (insn >> 26) & 0x3f; ! 656: char flags = decode_tbl[upper_6bits].flags; ! 657: if(insn == INSN_NOP) { ! 658: strcpy(buffer, " nop"); ! 659: unrecognized_op = 0; ! 660: } else if(insn == INSN_FNOP) { ! 661: strcpy(buffer, " fnop"); ! 662: unrecognized_op = 0; ! 663: } else if(insn == INSN_FNOP_DIM) { ! 664: strcpy(buffer, "d.fnop"); ! 665: unrecognized_op = 0; ! 666: } else if (flags & DEC_DECODED) { ! 667: const char *s = decode_tbl[upper_6bits].mnemonic; ! 668: decode_tbl[upper_6bits].insn_dis (buffer, (char *)s, pc, insn); ! 669: unrecognized_op = 0; ! 670: } else if (flags & DEC_MORE) { ! 671: if (upper_6bits == 0x12) { ! 672: /* FP instruction format handled here. */ ! 673: char fp_flags = fp_decode_tbl[insn & 0x7f].flags; ! 674: const char *s = fp_decode_tbl[insn & 0x7f].mnemonic; ! 675: if (fp_flags & DEC_DECODED) { ! 676: fp_decode_tbl[insn & 0x7f].insn_dis (buffer, (char *)s, pc, insn); ! 677: unrecognized_op = 0; ! 678: } ! 679: } ! 680: else if (upper_6bits == 0x13) { ! 681: /* Core escape instruction format handled here. */ ! 682: char esc_flags = core_esc_decode_tbl[insn & 0x3].flags; ! 683: const char *s = core_esc_decode_tbl[insn & 0x3].mnemonic; ! 684: if (esc_flags & DEC_DECODED) ! 685: { ! 686: core_esc_decode_tbl[insn & 0x3].insn_dis (buffer, (char *)s, pc, insn); ! 687: unrecognized_op = 0; ! 688: } ! 689: } ! 690: } ! 691: ! 692: if (unrecognized_op) ! 693: sprintf (buffer, " .long\t%#08x", insn); ! 694: ! 695: /* Replace tabs with spaces */ ! 696: i860_dasm_tab_replacer(buffer, 10); ! 697: ! 698: /* Return number of bytes disassembled. */ ! 699: /* MAME dasm flags haven't been added yet */ ! 700: return (4); ! 701: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.