123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <mach.h>
- /* mips native disassembler */
- typedef struct {
- uvlong addr; /* pc of instr */
- uchar op; /* bits 31-26 */
- uchar rs; /* bits 25-21 */
- uchar rt; /* bits 20-16 */
- uchar rd; /* bits 15-11 */
- uchar sa; /* bits 10-6 */
- uchar function; /* bits 5-0 */
- long immediate; /* bits 15-0 */
- ulong cofun; /* bits 24-0 */
- ulong target; /* bits 25-0 */
- long w0;
- char *curr; /* current fill point */
- char *end; /* end of buffer */
- char *err;
- } Instr;
- typedef struct {
- char *mnemonic;
- char *mipsco;
- } Opcode;
- static char mipscoload[] = "r%t,%l";
- static char mipscoalui[] = "r%t,r%s,%i";
- static char mipscoalu3op[] = "r%d,r%s,r%t";
- static char mipscoboc[] = "r%s,r%t,%b";
- static char mipscoboc0[] = "r%s,%b";
- static char mipscorsrt[] = "r%s,r%t";
- static char mipscorsi[] = "r%s,%i";
- static char mipscoxxx[] = "%w";
- static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */
- static char mipscofp2[] = "f%a,f%d"; /* fd,fs */
- static char mipscofpc[] = "f%d,f%t"; /* fs,ft */
- static Opcode opcodes[64] = {
- 0, 0,
- 0, 0,
- "j", "%j",
- "jal", "%j",
- "beq", mipscoboc,
- "bne", mipscoboc,
- "blez", mipscoboc0,
- "bgtz", mipscoboc0,
- "addi", mipscoalui,
- "addiu", mipscoalui,
- "slti", mipscoalui,
- "sltiu", mipscoalui,
- "andi", mipscoalui,
- "ori", mipscoalui,
- "xori", mipscoalui,
- "lui", "r%t,%u",
- "cop0", 0,
- "cop1", 0,
- "cop2", 0,
- "cop3", 0,
- "beql", mipscoboc,
- "bnel", mipscoboc,
- "blezl", mipscoboc0,
- "bgtzl", mipscoboc0,
- "instr18", mipscoxxx,
- "instr19", mipscoxxx,
- "instr1A", mipscoxxx,
- "instr1B", mipscoxxx,
- "instr1C", mipscoxxx,
- "instr1D", mipscoxxx,
- "instr1E", mipscoxxx,
- "instr1F", mipscoxxx,
- "lb", mipscoload,
- "lh", mipscoload,
- "lwl", mipscoload,
- "lw", mipscoload,
- "lbu", mipscoload,
- "lhu", mipscoload,
- "lwr", mipscoload,
- "instr27", mipscoxxx,
- "sb", mipscoload,
- "sh", mipscoload,
- "swl", mipscoload,
- "sw", mipscoload,
- "instr2C", mipscoxxx,
- "instr2D", mipscoxxx,
- "swr", mipscoload,
- "cache", "",
- "ll", mipscoload,
- "lwc1", mipscoload,
- "lwc2", mipscoload,
- "lwc3", mipscoload,
- "instr34", mipscoxxx,
- "ld", mipscoload,
- "ld", mipscoload,
- "ld", mipscoload,
- "sc", mipscoload,
- "swc1", mipscoload,
- "swc2", mipscoload,
- "swc3", mipscoload,
- "instr3C", mipscoxxx,
- "sd", mipscoload,
- "sd", mipscoload,
- "sd", mipscoload,
- };
- static Opcode sopcodes[64] = {
- "sll", "r%d,r%t,$%a",
- "special01", mipscoxxx,
- "srl", "r%d,r%t,$%a",
- "sra", "r%d,r%t,$%a",
- "sllv", "r%d,r%t,R%s",
- "special05", mipscoxxx,
- "srlv", "r%d,r%t,r%s",
- "srav", "r%d,r%t,r%s",
- "jr", "r%s",
- "jalr", "r%d,r%s",
- "special0A", mipscoxxx,
- "special0B", mipscoxxx,
- "syscall", "",
- "break", "",
- "special0E", mipscoxxx,
- "sync", "",
- "mfhi", "r%d",
- "mthi", "r%s",
- "mflo", "r%d",
- "mtlo", "r%s",
- "special14", mipscoxxx,
- "special15", mipscoxxx,
- "special16", mipscoxxx,
- "special17", mipscoxxx,
- "mult", mipscorsrt,
- "multu", mipscorsrt,
- "div", mipscorsrt,
- "divu", mipscorsrt,
- "special1C", mipscoxxx,
- "special1D", mipscoxxx,
- "special1E", mipscoxxx,
- "special1F", mipscoxxx,
- "add", mipscoalu3op,
- "addu", mipscoalu3op,
- "sub", mipscoalu3op,
- "subu", mipscoalu3op,
- "and", mipscoalu3op,
- "or", mipscoalu3op,
- "xor", mipscoalu3op,
- "nor", mipscoalu3op,
- "special28", mipscoxxx,
- "special29", mipscoxxx,
- "slt", mipscoalu3op,
- "sltu", mipscoalu3op,
- "special2C", mipscoxxx,
- "special2D", mipscoxxx,
- "special2E", mipscoxxx,
- "special2F", mipscoxxx,
- "tge", mipscorsrt,
- "tgeu", mipscorsrt,
- "tlt", mipscorsrt,
- "tltu", mipscorsrt,
- "teq", mipscorsrt,
- "special35", mipscoxxx,
- "tne", mipscorsrt,
- "special37", mipscoxxx,
- "special38", mipscoxxx,
- "special39", mipscoxxx,
- "special3A", mipscoxxx,
- "special3B", mipscoxxx,
- "special3C", mipscoxxx,
- "special3D", mipscoxxx,
- "special3E", mipscoxxx,
- "special3F", mipscoxxx,
- };
- static Opcode ropcodes[32] = {
- "bltz", mipscoboc0,
- "bgez", mipscoboc0,
- "bltzl", mipscoboc0,
- "bgezl", mipscoboc0,
- "regimm04", mipscoxxx,
- "regimm05", mipscoxxx,
- "regimm06", mipscoxxx,
- "regimm07", mipscoxxx,
- "tgei", mipscorsi,
- "tgeiu", mipscorsi,
- "tlti", mipscorsi,
- "tltiu", mipscorsi,
- "teqi", mipscorsi,
- "regimm0D", mipscoxxx,
- "tnei", mipscorsi,
- "regimm0F", mipscoxxx,
- "bltzal", mipscoboc0,
- "bgezal", mipscoboc0,
- "bltzall", mipscoboc0,
- "bgezall", mipscoboc0,
- "regimm14", mipscoxxx,
- "regimm15", mipscoxxx,
- "regimm16", mipscoxxx,
- "regimm17", mipscoxxx,
- "regimm18", mipscoxxx,
- "regimm19", mipscoxxx,
- "regimm1A", mipscoxxx,
- "regimm1B", mipscoxxx,
- "regimm1C", mipscoxxx,
- "regimm1D", mipscoxxx,
- "regimm1E", mipscoxxx,
- "regimm1F", mipscoxxx,
- };
- static Opcode fopcodes[64] = {
- "add.%f", mipscofp3,
- "sub.%f", mipscofp3,
- "mul.%f", mipscofp3,
- "div.%f", mipscofp3,
- "sqrt.%f", mipscofp2,
- "abs.%f", mipscofp2,
- "mov.%f", mipscofp2,
- "neg.%f", mipscofp2,
- "finstr08", mipscoxxx,
- "finstr09", mipscoxxx,
- "finstr0A", mipscoxxx,
- "finstr0B", mipscoxxx,
- "round.w.%f", mipscofp2,
- "trunc.w%f", mipscofp2,
- "ceil.w%f", mipscofp2,
- "floor.w%f", mipscofp2,
- "finstr10", mipscoxxx,
- "finstr11", mipscoxxx,
- "finstr12", mipscoxxx,
- "finstr13", mipscoxxx,
- "finstr14", mipscoxxx,
- "finstr15", mipscoxxx,
- "finstr16", mipscoxxx,
- "finstr17", mipscoxxx,
- "finstr18", mipscoxxx,
- "finstr19", mipscoxxx,
- "finstr1A", mipscoxxx,
- "finstr1B", mipscoxxx,
- "finstr1C", mipscoxxx,
- "finstr1D", mipscoxxx,
- "finstr1E", mipscoxxx,
- "finstr1F", mipscoxxx,
- "cvt.s.%f", mipscofp2,
- "cvt.d.%f", mipscofp2,
- "cvt.e.%f", mipscofp2,
- "cvt.q.%f", mipscofp2,
- "cvt.w.%f", mipscofp2,
- "finstr25", mipscoxxx,
- "finstr26", mipscoxxx,
- "finstr27", mipscoxxx,
- "finstr28", mipscoxxx,
- "finstr29", mipscoxxx,
- "finstr2A", mipscoxxx,
- "finstr2B", mipscoxxx,
- "finstr2C", mipscoxxx,
- "finstr2D", mipscoxxx,
- "finstr2E", mipscoxxx,
- "finstr2F", mipscoxxx,
- "c.f.%f", mipscofpc,
- "c.un.%f", mipscofpc,
- "c.eq.%f", mipscofpc,
- "c.ueq.%f", mipscofpc,
- "c.olt.%f", mipscofpc,
- "c.ult.%f", mipscofpc,
- "c.ole.%f", mipscofpc,
- "c.ule.%f", mipscofpc,
- "c.sf.%f", mipscofpc,
- "c.ngle.%f", mipscofpc,
- "c.seq.%f", mipscofpc,
- "c.ngl.%f", mipscofpc,
- "c.lt.%f", mipscofpc,
- "c.nge.%f", mipscofpc,
- "c.le.%f", mipscofpc,
- "c.ngt.%f", mipscofpc,
- };
- static char fsub[16] = {
- 's', 'd', 'e', 'q', 'w', '?', '?', '?',
- '?', '?', '?', '?', '?', '?', '?', '?'
- };
- static int
- mkinstr(Instr *i, Map *map, uvlong pc)
- {
- ulong w;
- if (get4(map, pc, &w) < 0) {
- werrstr("can't read instruction: %r");
- return -1;
- }
- i->addr = pc;
- i->op = (w >> 26) & 0x3F;
- i->rs = (w >> 21) & 0x1F;
- i->rt = (w >> 16) & 0x1F;
- i->rd = (w >> 11) & 0x1F;
- i->sa = (w >> 6) & 0x1F;
- i->function = w & 0x3F;
- i->immediate = w & 0x0000FFFF;
- if (i->immediate & 0x8000)
- i->immediate |= ~0x0000FFFF;
- i->cofun = w & 0x01FFFFFF;
- i->target = w & 0x03FFFFFF;
- i->w0 = w;
- return 1;
- }
- #pragma varargck argpos bprint 2
- static void
- bprint(Instr *i, char *fmt, ...)
- {
- va_list arg;
- va_start(arg, fmt);
- i->curr = vseprint(i->curr, i->end, fmt, arg);
- va_end(arg);
- }
- static void
- format(char *mnemonic, Instr *i, char *f)
- {
- if (mnemonic)
- format(0, i, mnemonic);
- if (f == 0)
- return;
- if (i->curr < i->end)
- *i->curr++ = '\t';
- for ( ; *f && i->curr < i->end; f++) {
- if (*f != '%') {
- *i->curr++ = *f;
- continue;
- }
- switch (*++f) {
- case 's':
- bprint(i, "%d", i->rs);
- break;
- case 't':
- bprint(i, "%d", i->rt);
- break;
- case 'd':
- bprint(i, "%d", i->rd);
- break;
- case 'a':
- bprint(i, "%d", i->sa);
- break;
- case 'l':
- if (i->rs == 30) {
- i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
- bprint(i, "(SB)");
- } else
- bprint(i, "%lx(r%d)", i->immediate, i->rs);
- break;
- case 'i':
- bprint(i, "$%lx", i->immediate);
- break;
- case 'u':
- *i->curr++ = '$';
- i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
- bprint(i, "(SB)");
- break;
- case 'j':
- i->curr += symoff(i->curr, i->end-i->curr,
- (i->target<<2)|(i->addr & 0xF0000000), CANY);
- bprint(i, "(SB)");
- break;
- case 'b':
- i->curr += symoff(i->curr, i->end-i->curr,
- (i->immediate<<2)+i->addr+4, CANY);
- break;
- case 'c':
- bprint(i, "%lux", i->cofun);
- break;
- case 'w':
- bprint(i, "[%lux]", i->w0);
- break;
- case 'f':
- *i->curr++ = fsub[i->rs & 0x0F];
- break;
- case '\0':
- *i->curr++ = '%';
- return;
- default:
- bprint(i, "%%%c", *f);
- break;
- }
- }
- }
- static void
- copz(int cop, Instr *i)
- {
- char *f, *m, buf[16];
- m = buf;
- f = "%t,%d";
- switch (i->rs) {
- case 0:
- sprint(buf, "mfc%d", cop);
- break;
- case 2:
- sprint(buf, "cfc%d", cop);
- break;
- case 4:
- sprint(buf, "mtc%d", cop);
- break;
- case 6:
- sprint(buf, "ctc%d", cop);
- break;
- case 8:
- f = "%b";
- switch (i->rt) {
- case 0:
- sprint(buf, "bc%df", cop);
- break;
- case 1:
- sprint(buf, "bc%dt", cop);
- break;
- case 2:
- sprint(buf, "bc%dfl", cop);
- break;
- case 3:
- sprint(buf, "bc%dtl", cop);
- break;
- default:
- sprint(buf, "cop%d", cop);
- f = mipscoxxx;
- break;
- }
- break;
- default:
- sprint(buf, "cop%d", cop);
- if (i->rs & 0x10)
- f = "function %c";
- else
- f = mipscoxxx;
- break;
- }
- format(m, i, f);
- }
- static void
- cop0(Instr *i)
- {
- char *m = 0;
- if (i->rs >= 0x10) {
- switch (i->cofun) {
-
- case 1:
- m = "tlbr";
- break;
-
- case 2:
- m = "tlbwi";
- break;
-
- case 6:
- m = "tlbwr";
- break;
-
- case 8:
- m = "tlbp";
- break;
-
- case 16:
- m = "rfe";
- break;
-
- case 32:
- m = "eret";
- break;
- }
- if (m) {
- format(m, i, 0);
- if (i->curr < i->end)
- *i->curr++ = 0;
- return;
- }
- }
- copz(0, i);
- }
- int
- _mipscoinst(Map *map, uvlong pc, char *buf, int n)
- {
- Instr i;
- Opcode *o;
- uchar op;
- i.curr = buf;
- i.end = buf+n-1;
- if (mkinstr(&i, map, pc) < 0)
- return -1;
- switch (i.op) {
- case 0x00: /* SPECIAL */
- o = sopcodes;
- op = i.function;
- break;
- case 0x01: /* REGIMM */
- o = ropcodes;
- op = i.rt;
- break;
- case 0x10: /* COP0 */
- cop0(&i);
- return 4;
- case 0x11: /* COP1 */
- if (i.rs & 0x10) {
- o = fopcodes;
- op = i.function;
- break;
- }
- /*FALLTHROUGH*/
- case 0x12: /* COP2 */
- case 0x13: /* COP3 */
- copz(i.op-0x10, &i);
- return 4;
- default:
- o = opcodes;
- op = i.op;
- break;
- }
- format(o[op].mnemonic, &i, o[op].mipsco);
- return 4;
- }
|