|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <mach.h> ! 5: ! 6: /* mips native disassembler */ ! 7: ! 8: typedef struct { ! 9: long addr; /* pc of instr */ ! 10: uchar op; /* bits 31-26 */ ! 11: uchar rs; /* bits 25-21 */ ! 12: uchar rt; /* bits 20-16 */ ! 13: uchar rd; /* bits 15-11 */ ! 14: uchar sa; /* bits 10-6 */ ! 15: uchar function; /* bits 5-0 */ ! 16: long immediate; /* bits 15-0 */ ! 17: ulong cofun; /* bits 24-0 */ ! 18: ulong target; /* bits 25-0 */ ! 19: long w0; ! 20: char *curr; /* current fill point */ ! 21: char *end; /* end of buffer */ ! 22: char *err; ! 23: } Instr; ! 24: ! 25: typedef struct { ! 26: char *mnemonic; ! 27: char *mipsco; ! 28: } Opcode; ! 29: ! 30: static char mipscoload[] = "r%t,%l"; ! 31: static char mipscoalui[] = "r%t,r%s,%i"; ! 32: static char mipscoalu3op[] = "r%d,r%s,r%t"; ! 33: static char mipscoboc[] = "r%s,r%t,%b"; ! 34: static char mipscoboc0[] = "r%s,%b"; ! 35: static char mipscorsrt[] = "r%s,r%t"; ! 36: static char mipscorsi[] = "r%s,%i"; ! 37: static char mipscoxxx[] = "%w"; ! 38: static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */ ! 39: static char mipscofp2[] = "f%a,f%d"; /* fd,fs */ ! 40: static char mipscofpc[] = "f%d,f%t"; /* fs,ft */ ! 41: ! 42: static Opcode opcodes[64] = { ! 43: 0, 0, ! 44: 0, 0, ! 45: "j", "%j", ! 46: "jal", "%j", ! 47: "beq", mipscoboc, ! 48: "bne", mipscoboc, ! 49: "blez", mipscoboc0, ! 50: "bgtz", mipscoboc0, ! 51: "addi", mipscoalui, ! 52: "addiu", mipscoalui, ! 53: "slti", mipscoalui, ! 54: "sltiu", mipscoalui, ! 55: "andi", mipscoalui, ! 56: "ori", mipscoalui, ! 57: "xori", mipscoalui, ! 58: "lui", "r%t,%u", ! 59: "cop0", 0, ! 60: "cop1", 0, ! 61: "cop2", 0, ! 62: "cop3", 0, ! 63: "beql", mipscoboc, ! 64: "bnel", mipscoboc, ! 65: "blezl", mipscoboc0, ! 66: "bgtzl", mipscoboc0, ! 67: "instr18", mipscoxxx, ! 68: "instr19", mipscoxxx, ! 69: "instr1A", mipscoxxx, ! 70: "instr1B", mipscoxxx, ! 71: "instr1C", mipscoxxx, ! 72: "instr1D", mipscoxxx, ! 73: "instr1E", mipscoxxx, ! 74: "instr1F", mipscoxxx, ! 75: "lb", mipscoload, ! 76: "lh", mipscoload, ! 77: "lwl", mipscoload, ! 78: "lw", mipscoload, ! 79: "lbu", mipscoload, ! 80: "lhu", mipscoload, ! 81: "lwr", mipscoload, ! 82: "instr27", mipscoxxx, ! 83: "sb", mipscoload, ! 84: "sh", mipscoload, ! 85: "swl", mipscoload, ! 86: "sw", mipscoload, ! 87: "instr2C", mipscoxxx, ! 88: "instr2D", mipscoxxx, ! 89: "swr", mipscoload, ! 90: "cache", "", ! 91: "ll", mipscoload, ! 92: "lwc1", mipscoload, ! 93: "lwc2", mipscoload, ! 94: "lwc3", mipscoload, ! 95: "instr34", mipscoxxx, ! 96: "ld", mipscoload, ! 97: "ld", mipscoload, ! 98: "ld", mipscoload, ! 99: "sc", mipscoload, ! 100: "swc1", mipscoload, ! 101: "swc2", mipscoload, ! 102: "swc3", mipscoload, ! 103: "instr3C", mipscoxxx, ! 104: "sd", mipscoload, ! 105: "sd", mipscoload, ! 106: "sd", mipscoload, ! 107: }; ! 108: ! 109: static Opcode sopcodes[64] = { ! 110: "sll", "r%d,r%t,$%a", ! 111: "special01", mipscoxxx, ! 112: "srl", "r%d,r%t,$%a", ! 113: "sra", "r%d,r%t,$%a", ! 114: "sllv", "r%d,r%t,R%s", ! 115: "special05", mipscoxxx, ! 116: "srlv", "r%d,r%t,r%s", ! 117: "srav", "r%d,r%t,r%s", ! 118: "jr", "r%s", ! 119: "jalr", "r%d,r%s", ! 120: "special0A", mipscoxxx, ! 121: "special0B", mipscoxxx, ! 122: "syscall", "", ! 123: "break", "", ! 124: "special0E", mipscoxxx, ! 125: "sync", "", ! 126: "mfhi", "r%d", ! 127: "mthi", "r%s", ! 128: "mflo", "r%d", ! 129: "mtlo", "r%s", ! 130: "special14", mipscoxxx, ! 131: "special15", mipscoxxx, ! 132: "special16", mipscoxxx, ! 133: "special17", mipscoxxx, ! 134: "mult", mipscorsrt, ! 135: "multu", mipscorsrt, ! 136: "div", mipscorsrt, ! 137: "divu", mipscorsrt, ! 138: "special1C", mipscoxxx, ! 139: "special1D", mipscoxxx, ! 140: "special1E", mipscoxxx, ! 141: "special1F", mipscoxxx, ! 142: "add", mipscoalu3op, ! 143: "addu", mipscoalu3op, ! 144: "sub", mipscoalu3op, ! 145: "subu", mipscoalu3op, ! 146: "and", mipscoalu3op, ! 147: "or", mipscoalu3op, ! 148: "xor", mipscoalu3op, ! 149: "nor", mipscoalu3op, ! 150: "special28", mipscoxxx, ! 151: "special29", mipscoxxx, ! 152: "slt", mipscoalu3op, ! 153: "sltu", mipscoalu3op, ! 154: "special2C", mipscoxxx, ! 155: "special2D", mipscoxxx, ! 156: "special2E", mipscoxxx, ! 157: "special2F", mipscoxxx, ! 158: "tge", mipscorsrt, ! 159: "tgeu", mipscorsrt, ! 160: "tlt", mipscorsrt, ! 161: "tltu", mipscorsrt, ! 162: "teq", mipscorsrt, ! 163: "special35", mipscoxxx, ! 164: "tne", mipscorsrt, ! 165: "special37", mipscoxxx, ! 166: "special38", mipscoxxx, ! 167: "special39", mipscoxxx, ! 168: "special3A", mipscoxxx, ! 169: "special3B", mipscoxxx, ! 170: "special3C", mipscoxxx, ! 171: "special3D", mipscoxxx, ! 172: "special3E", mipscoxxx, ! 173: "special3F", mipscoxxx, ! 174: }; ! 175: ! 176: static Opcode ropcodes[32] = { ! 177: "bltz", mipscoboc0, ! 178: "bgez", mipscoboc0, ! 179: "bltzl", mipscoboc0, ! 180: "bgezl", mipscoboc0, ! 181: "regimm04", mipscoxxx, ! 182: "regimm05", mipscoxxx, ! 183: "regimm06", mipscoxxx, ! 184: "regimm07", mipscoxxx, ! 185: "tgei", mipscorsi, ! 186: "tgeiu", mipscorsi, ! 187: "tlti", mipscorsi, ! 188: "tltiu", mipscorsi, ! 189: "teqi", mipscorsi, ! 190: "regimm0D", mipscoxxx, ! 191: "tnei", mipscorsi, ! 192: "regimm0F", mipscoxxx, ! 193: "bltzal", mipscoboc0, ! 194: "bgezal", mipscoboc0, ! 195: "bltzall", mipscoboc0, ! 196: "bgezall", mipscoboc0, ! 197: "regimm14", mipscoxxx, ! 198: "regimm15", mipscoxxx, ! 199: "regimm16", mipscoxxx, ! 200: "regimm17", mipscoxxx, ! 201: "regimm18", mipscoxxx, ! 202: "regimm19", mipscoxxx, ! 203: "regimm1A", mipscoxxx, ! 204: "regimm1B", mipscoxxx, ! 205: "regimm1C", mipscoxxx, ! 206: "regimm1D", mipscoxxx, ! 207: "regimm1E", mipscoxxx, ! 208: "regimm1F", mipscoxxx, ! 209: }; ! 210: ! 211: static Opcode fopcodes[64] = { ! 212: "add.%f", mipscofp3, ! 213: "sub.%f", mipscofp3, ! 214: "mul.%f", mipscofp3, ! 215: "div.%f", mipscofp3, ! 216: "sqrt.%f", mipscofp2, ! 217: "abs.%f", mipscofp2, ! 218: "mov.%f", mipscofp2, ! 219: "neg.%f", mipscofp2, ! 220: "finstr08", mipscoxxx, ! 221: "finstr09", mipscoxxx, ! 222: "finstr0A", mipscoxxx, ! 223: "finstr0B", mipscoxxx, ! 224: "round.w.%f", mipscofp2, ! 225: "trunc.w%f", mipscofp2, ! 226: "ceil.w%f", mipscofp2, ! 227: "floor.w%f", mipscofp2, ! 228: "finstr10", mipscoxxx, ! 229: "finstr11", mipscoxxx, ! 230: "finstr12", mipscoxxx, ! 231: "finstr13", mipscoxxx, ! 232: "finstr14", mipscoxxx, ! 233: "finstr15", mipscoxxx, ! 234: "finstr16", mipscoxxx, ! 235: "finstr17", mipscoxxx, ! 236: "finstr18", mipscoxxx, ! 237: "finstr19", mipscoxxx, ! 238: "finstr1A", mipscoxxx, ! 239: "finstr1B", mipscoxxx, ! 240: "finstr1C", mipscoxxx, ! 241: "finstr1D", mipscoxxx, ! 242: "finstr1E", mipscoxxx, ! 243: "finstr1F", mipscoxxx, ! 244: "cvt.s.%f", mipscofp2, ! 245: "cvt.d.%f", mipscofp2, ! 246: "cvt.e.%f", mipscofp2, ! 247: "cvt.q.%f", mipscofp2, ! 248: "cvt.w.%f", mipscofp2, ! 249: "finstr25", mipscoxxx, ! 250: "finstr26", mipscoxxx, ! 251: "finstr27", mipscoxxx, ! 252: "finstr28", mipscoxxx, ! 253: "finstr29", mipscoxxx, ! 254: "finstr2A", mipscoxxx, ! 255: "finstr2B", mipscoxxx, ! 256: "finstr2C", mipscoxxx, ! 257: "finstr2D", mipscoxxx, ! 258: "finstr2E", mipscoxxx, ! 259: "finstr2F", mipscoxxx, ! 260: "c.f.%f", mipscofpc, ! 261: "c.un.%f", mipscofpc, ! 262: "c.eq.%f", mipscofpc, ! 263: "c.ueq.%f", mipscofpc, ! 264: "c.olt.%f", mipscofpc, ! 265: "c.ult.%f", mipscofpc, ! 266: "c.ole.%f", mipscofpc, ! 267: "c.ule.%f", mipscofpc, ! 268: "c.sf.%f", mipscofpc, ! 269: "c.ngle.%f", mipscofpc, ! 270: "c.seq.%f", mipscofpc, ! 271: "c.ngl.%f", mipscofpc, ! 272: "c.lt.%f", mipscofpc, ! 273: "c.nge.%f", mipscofpc, ! 274: "c.le.%f", mipscofpc, ! 275: "c.ngt.%f", mipscofpc, ! 276: }; ! 277: ! 278: static char fsub[16] = { ! 279: 's', 'd', 'e', 'q', 'w', '?', '?', '?', ! 280: '?', '?', '?', '?', '?', '?', '?', '?' ! 281: }; ! 282: ! 283: ! 284: static int ! 285: mkinstr(Instr *i, Map *map, ulong pc) ! 286: { ! 287: long w; ! 288: ! 289: if (get4(map, pc, &w) < 0) { ! 290: werrstr("can't read instruction: %r"); ! 291: return -1; ! 292: } ! 293: i->addr = pc; ! 294: i->op = (w >> 26) & 0x3F; ! 295: i->rs = (w >> 21) & 0x1F; ! 296: i->rt = (w >> 16) & 0x1F; ! 297: i->rd = (w >> 11) & 0x1F; ! 298: i->sa = (w >> 6) & 0x1F; ! 299: i->function = w & 0x3F; ! 300: i->immediate = w & 0x0000FFFF; ! 301: if (i->immediate & 0x8000) ! 302: i->immediate |= ~0x0000FFFF; ! 303: i->cofun = w & 0x01FFFFFF; ! 304: i->target = w & 0x03FFFFFF; ! 305: i->w0 = w; ! 306: return 1; ! 307: } ! 308: ! 309: static void ! 310: bprint(Instr *i, char *fmt, ...) ! 311: { ! 312: i->curr = doprint(i->curr, i->end, fmt, (&fmt+1)); ! 313: } ! 314: ! 315: static void ! 316: format(char *mnemonic, Instr *i, char *f) ! 317: { ! 318: if (mnemonic) ! 319: format(0, i, mnemonic); ! 320: if (f == 0) ! 321: return; ! 322: if (i->curr < i->end) ! 323: *i->curr++ = '\t'; ! 324: for ( ; *f && i->curr < i->end; f++) { ! 325: if (*f != '%') { ! 326: *i->curr++ = *f; ! 327: continue; ! 328: } ! 329: switch (*++f) { ! 330: ! 331: case 's': ! 332: bprint(i, "%d", i->rs); ! 333: break; ! 334: ! 335: case 't': ! 336: bprint(i, "%d", i->rt); ! 337: break; ! 338: ! 339: case 'd': ! 340: bprint(i, "%d", i->rd); ! 341: break; ! 342: ! 343: case 'a': ! 344: bprint(i, "%d", i->sa); ! 345: break; ! 346: ! 347: case 'l': ! 348: if (i->rs == 30) { ! 349: i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY); ! 350: bprint(i, "(SB)"); ! 351: } else ! 352: bprint(i, "%lx(r%d)", i->immediate, i->rs); ! 353: break; ! 354: ! 355: case 'i': ! 356: bprint(i, "$%lx", i->immediate); ! 357: break; ! 358: ! 359: case 'u': ! 360: *i->curr++ = '$'; ! 361: i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY); ! 362: bprint(i, "(SB)"); ! 363: break; ! 364: ! 365: case 'j': ! 366: i->curr += symoff(i->curr, i->end-i->curr, ! 367: (i->target<<2)|(i->addr & 0xF0000000), CANY); ! 368: bprint(i, "(SB)"); ! 369: break; ! 370: ! 371: case 'b': ! 372: i->curr += symoff(i->curr, i->end-i->curr, ! 373: (i->immediate<<2)+i->addr+4, CANY); ! 374: break; ! 375: ! 376: case 'c': ! 377: bprint(i, "%lux", i->cofun); ! 378: break; ! 379: ! 380: case 'w': ! 381: bprint(i, "[%lux]", i->w0); ! 382: break; ! 383: ! 384: case 'f': ! 385: *i->curr++ = fsub[i->rs & 0x0F]; ! 386: break; ! 387: ! 388: case '\0': ! 389: *i->curr++ = '%'; ! 390: return; ! 391: ! 392: default: ! 393: bprint(i, "%%%c", *f); ! 394: break; ! 395: } ! 396: } ! 397: } ! 398: ! 399: static void ! 400: copz(int cop, Instr *i) ! 401: { ! 402: char *f, *m, buf[16]; ! 403: ! 404: m = buf; ! 405: f = "%t,%d"; ! 406: switch (i->rs) { ! 407: ! 408: case 0: ! 409: sprint(buf, "mfc%d", cop); ! 410: break; ! 411: ! 412: case 2: ! 413: sprint(buf, "cfc%d", cop); ! 414: break; ! 415: ! 416: case 4: ! 417: sprint(buf, "mtc%d", cop); ! 418: break; ! 419: ! 420: case 6: ! 421: sprint(buf, "ctc%d", cop); ! 422: break; ! 423: ! 424: case 8: ! 425: f = "%b"; ! 426: switch (i->rt) { ! 427: ! 428: case 0: ! 429: sprint(buf, "bc%df", cop); ! 430: break; ! 431: ! 432: case 1: ! 433: sprint(buf, "bc%dt", cop); ! 434: break; ! 435: ! 436: case 2: ! 437: sprint(buf, "bc%dfl", cop); ! 438: break; ! 439: ! 440: case 3: ! 441: sprint(buf, "bc%dtl", cop); ! 442: break; ! 443: ! 444: default: ! 445: sprint(buf, "cop%d", cop); ! 446: f = mipscoxxx; ! 447: break; ! 448: } ! 449: break; ! 450: ! 451: default: ! 452: sprint(buf, "cop%d", cop); ! 453: if (i->rs & 0x10) ! 454: f = "function %c"; ! 455: else ! 456: f = mipscoxxx; ! 457: break; ! 458: } ! 459: format(m, i, f); ! 460: } ! 461: ! 462: static void ! 463: cop0(Instr *i) ! 464: { ! 465: char *m = 0; ! 466: ! 467: if (i->rs >= 0x10) { ! 468: switch (i->cofun) { ! 469: ! 470: case 1: ! 471: m = "tlbr"; ! 472: break; ! 473: ! 474: case 2: ! 475: m = "tlbwi"; ! 476: break; ! 477: ! 478: case 6: ! 479: m = "tlbwr"; ! 480: break; ! 481: ! 482: case 8: ! 483: m = "tlbp"; ! 484: break; ! 485: ! 486: case 16: ! 487: m = "rfe"; ! 488: break; ! 489: ! 490: case 32: ! 491: m = "eret"; ! 492: break; ! 493: } ! 494: if (m) { ! 495: format(m, i, 0); ! 496: if (i->curr < i->end) ! 497: *i->curr++ = 0; ! 498: return; ! 499: } ! 500: } ! 501: copz(0, i); ! 502: } ! 503: ! 504: int ! 505: _mipscoinst(Map *map, ulong pc, char *buf, int n) ! 506: { ! 507: Instr i; ! 508: Opcode *o; ! 509: uchar op; ! 510: ! 511: i.curr = buf; ! 512: i.end = buf+n-1; ! 513: if (mkinstr(&i, map, pc) < 0) ! 514: return -1; ! 515: switch (i.op) { ! 516: ! 517: case 0x00: /* SPECIAL */ ! 518: o = sopcodes; ! 519: op = i.function; ! 520: break; ! 521: ! 522: case 0x01: /* REGIMM */ ! 523: o = ropcodes; ! 524: op = i.rt; ! 525: break; ! 526: ! 527: case 0x10: /* COP0 */ ! 528: cop0(&i); ! 529: return 4; ! 530: ! 531: case 0x11: /* COP1 */ ! 532: if (i.rs & 0x10) { ! 533: o = fopcodes; ! 534: op = i.function; ! 535: break; ! 536: } ! 537: /*FALLTHROUGH*/ ! 538: case 0x12: /* COP2 */ ! 539: case 0x13: /* COP3 */ ! 540: copz(i.op-0x10, &i); ! 541: return 4; ! 542: ! 543: default: ! 544: o = opcodes; ! 545: op = i.op; ! 546: break; ! 547: } ! 548: format(o[op].mnemonic, &i, o[op].mipsco); ! 549: return 4; ! 550: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.