12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <mach.h>
- /*
- * Mips-specific debugger interface
- */
- static char *mipsexcep(Map*, Rgetter);
- static int mipsfoll(Map*, uvlong, Rgetter, uvlong*);
- static int mipsinst(Map*, uvlong, char, char*, int);
- static int mipsdas(Map*, uvlong, char*, int);
- static int mipsinstlen(Map*, uvlong);
- /*
- * Debugger interface
- */
- Machdata mipsmach =
- {
- {0, 0, 0, 0xD}, /* break point */
- 4, /* break point size */
- beswab, /* short to local byte order */
- beswal, /* long to local byte order */
- beswav, /* vlong to local byte order */
- risctrace, /* C traceback */
- riscframe, /* Frame finder */
- mipsexcep, /* print exception */
- 0, /* breakpoint fixup */
- beieeesftos, /* single precision float printer */
- beieeedftos, /* double precisioin float printer */
- mipsfoll, /* following addresses */
- mipsinst, /* print instruction */
- mipsdas, /* dissembler */
- mipsinstlen, /* instruction size */
- };
- Machdata mipsmachle =
- {
- {0, 0, 0, 0xD}, /* break point */
- 4, /* break point size */
- leswab, /* short to local byte order */
- leswal, /* long to local byte order */
- leswav, /* vlong to local byte order */
- risctrace, /* C traceback */
- riscframe, /* Frame finder */
- mipsexcep, /* print exception */
- 0, /* breakpoint fixup */
- leieeesftos, /* single precision float printer */
- leieeedftos, /* double precisioin float printer */
- mipsfoll, /* following addresses */
- mipsinst, /* print instruction */
- mipsdas, /* dissembler */
- mipsinstlen, /* instruction size */
- };
- /*
- * mips r4k little-endian
- */
- Machdata mipsmach2le =
- {
- {0, 0, 0, 0xD}, /* break point */
- 4, /* break point size */
- leswab, /* short to local byte order */
- leswal, /* long to local byte order */
- leswav, /* vlong to local byte order */
- risctrace, /* C traceback */
- riscframe, /* Frame finder */
- mipsexcep, /* print exception */
- 0, /* breakpoint fixup */
- leieeesftos, /* single precision float printer */
- leieeedftos, /* double precisioin float printer */
- mipsfoll, /* following addresses */
- mipsinst, /* print instruction */
- mipsdas, /* dissembler */
- mipsinstlen, /* instruction size */
- };
- /*
- * mips r4k big-endian
- */
- Machdata mipsmach2be =
- {
- {0, 0, 0, 0xD}, /* break point */
- 4, /* break point size */
- beswab, /* short to local byte order */
- beswal, /* long to local byte order */
- beswav, /* vlong to local byte order */
- risctrace, /* C traceback */
- riscframe, /* Frame finder */
- mipsexcep, /* print exception */
- 0, /* breakpoint fixup */
- beieeesftos, /* single precision float printer */
- beieeedftos, /* double precisioin float printer */
- mipsfoll, /* following addresses */
- mipsinst, /* print instruction */
- mipsdas, /* dissembler */
- mipsinstlen, /* instruction size */
- };
- static char *excname[] =
- {
- "external interrupt",
- "TLB modification",
- "TLB miss (load or fetch)",
- "TLB miss (store)",
- "address error (load or fetch)",
- "address error (store)",
- "bus error (fetch)",
- "bus error (data load or store)",
- "system call",
- "breakpoint",
- "reserved instruction",
- "coprocessor unusable",
- "arithmetic overflow",
- "undefined 13",
- "undefined 14",
- "system call",
- /* the following is made up */
- "floating point exception" /* FPEXC */
- };
- static char*
- mipsexcep(Map *map, Rgetter rget)
- {
- int e;
- long c;
- c = (*rget)(map, "CAUSE");
- if(c & 0x00002000) /* INTR3 */
- e = 16; /* Floating point exception */
- else
- e = (c>>2)&0x0F;
- return excname[e];
- }
- /* mips disassembler and related functions */
- static char FRAMENAME[] = ".frame";
- typedef struct {
- uvlong addr;
- 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;
- long w1;
- int size; /* instruction size */
- char *curr; /* fill point in buffer */
- char *end; /* end of buffer */
- char *err; /* error message */
- } Instr;
- static Map *mymap;
- static int
- decode(uvlong pc, Instr *i)
- {
- ulong w;
- if (get4(mymap, pc, &w) < 0) {
- werrstr("can't read instruction: %r");
- return -1;
- }
- i->addr = pc;
- i->size = 1;
- 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;
- }
- static int
- mkinstr(uvlong pc, Instr *i)
- {
- Instr x;
- if (decode(pc, i) < 0)
- return -1;
- /*
- * if it's a LUI followed by an ORI,
- * it's an immediate load of a large constant.
- * fix the LUI immediate in any case.
- */
- if (i->op == 0x0F) {
- if (decode(pc+4, &x) < 0)
- return 0;
- i->immediate <<= 16;
- if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) {
- i->immediate |= (x.immediate & 0xFFFF);
- i->w1 = x.w0;
- i->size++;
- return 1;
- }
- }
- /*
- * if it's a LWC1 followed by another LWC1
- * into an adjacent register, it's a load of
- * a floating point double.
- */
- else if (i->op == 0x31 && (i->rt & 0x01)) {
- if (decode(pc+4, &x) < 0)
- return 0;
- if (x.op == 0x31 && x.rt == (i->rt - 1) && x.rs == i->rs) {
- i->rt -= 1;
- i->w1 = x.w0;
- i->size++;
- return 1;
- }
- }
- /*
- * similarly for double stores
- */
- else if (i->op == 0x39 && (i->rt & 0x01)) {
- if (decode(pc+4, &x) < 0)
- return 0;
- if (x.op == 0x39 && x.rt == (i->rt - 1) && x.rs == i->rs) {
- i->rt -= 1;
- i->w1 = x.w0;
- i->size++;
- }
- }
- 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);
- }
- typedef struct Opcode Opcode;
- struct Opcode {
- char *mnemonic;
- void (*f)(Opcode *, Instr *);
- char *ken;
- };
- static void format(char *, Instr *, char *);
- static void
- branch(Opcode *o, Instr *i)
- {
- if (i->rs == 0 && i->rt == 0)
- format("JMP", i, "%b");
- else if (i->rs == 0)
- format(o->mnemonic, i, "R%t,%b");
- else if (i->rt < 2)
- format(o->mnemonic, i, "R%s,%b");
- else
- format(o->mnemonic, i, "R%s,R%t,%b");
- }
- static void
- addi(Opcode *o, Instr *i)
- {
- if (i->rs == i->rt)
- format(o->mnemonic, i, "%i,R%t");
- else if (i->rs == 0)
- format("MOVW", i, "%i,R%t");
- else if (i->rs == 30) {
- bprint(i, "MOVW\t$");
- i->curr += symoff(i->curr, i->end-i->curr,
- i->immediate+mach->sb, CANY);
- bprint(i, "(SB),R%d", i->rt);
- }
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- andi(Opcode *o, Instr *i)
- {
- if (i->rs == i->rt)
- format(o->mnemonic, i, "%i,R%t");
- else
- format(o->mnemonic, i, o->ken);
- }
- static int
- plocal(Instr *i, char *m, char r, int store)
- {
- int offset;
- char *reg;
- Symbol s;
- if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
- return 0;
- if (s.value > i->immediate) {
- if(!getauto(&s, s.value-i->immediate, CAUTO, &s))
- return 0;
- reg = "(SP)";
- offset = i->immediate;
- } else {
- offset = i->immediate-s.value;
- if (!getauto(&s, offset-4, CPARAM, &s))
- return 0;
- reg = "(FP)";
- }
- if (store)
- bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->rt, s.name, offset, reg);
- else
- bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->rt);
- return 1;
- }
- static void
- lw(Opcode *o, Instr *i, char r)
- {
- char *m;
- if (r == 'F') {
- if (i->size == 2)
- m = "MOVD";
- else
- m = "MOVF";
- }
- else
- m = o->mnemonic;
- if (i->rs == 29 && plocal(i, m, r, 0))
- return;
- if (i->rs == 30 && mach->sb) {
- bprint(i, "%s\t", m);
- i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
- bprint(i, "(SB),%c%d", r, i->rt);
- return;
- }
- if (r == 'F')
- format(m, i, "%l,F%t");
- else
- format(m, i, o->ken);
- }
- static void
- load(Opcode *o, Instr *i)
- {
- lw(o, i, 'R');
- }
- static void
- lwc1(Opcode *o, Instr *i)
- {
- lw(o, i, 'F');
- }
- static void
- sw(Opcode *o, Instr *i, char r)
- {
- char *m;
- if (r == 'F') {
- if (i->size == 2)
- m = "MOVD";
- else
- m = "MOVF";
- }
- else
- m = o->mnemonic;
- if (i->rs == 29 && plocal(i, m, r, 1))
- return;
- if (i->rs == 30 && mach->sb) {
- bprint(i, "%s\t%c%d,", m, r, i->rt);
- i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
- bprint(i, "(SB)");
- return;
- }
- if (r == 'F')
- format(m, i, "F%t,%l");
- else
- format(m, i, o->ken);
- }
- static void
- store(Opcode *o, Instr *i)
- {
- sw(o, i, 'R');
- }
- static void
- swc1(Opcode *o, Instr *i)
- {
- sw(o, i, 'F');
- }
- static void
- sll(Opcode *o, Instr *i)
- {
- if (i->w0 == 0)
- bprint(i, "NOOP");
- else if (i->rd == i->rt)
- format(o->mnemonic, i, "$%a,R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- sl32(Opcode *o, Instr *i)
- {
- i->sa += 32;
- if (i->rd == i->rt)
- format(o->mnemonic, i, "$%a,R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- sllv(Opcode *o, Instr *i)
- {
- if (i->rd == i->rt)
- format(o->mnemonic, i, "R%s,R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- jal(Opcode *o, Instr *i)
- {
- if (i->rd == 31)
- format("JAL", i, "(R%s)");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- add(Opcode *o, Instr *i)
- {
- if (i->rd == i->rs)
- format(o->mnemonic, i, "R%t,R%d");
- else if (i->rd == i->rt)
- format(o->mnemonic, i, "R%s,R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- sub(Opcode *o, Instr *i)
- {
- if (i->rd == i->rs)
- format(o->mnemonic, i, "R%t,R%d");
- else
- format(o->mnemonic, i, o->ken);
- }
- static void
- or(Opcode *o, Instr *i)
- {
- if (i->rs == 0 && i->rt == 0)
- format("MOVW", i, "$0,R%d");
- else if (i->rs == 0)
- format("MOVW", i, "R%t,R%d");
- else if (i->rt == 0)
- format("MOVW", i, "R%s,R%d");
- else
- add(o, i);
- }
- static void
- nor(Opcode *o, Instr *i)
- {
- if (i->rs == 0 && i->rt == 0 && i->rd == 0)
- format("NOP", i, 0);
- else
- add(o, i);
- }
- static char mipscoload[] = "r%t,%l";
- static char mipsload[] = "%l,R%t";
- static char mipsstore[] = "R%t,%l";
- static char mipsalui[] = "%i,R%s,R%t";
- static char mipsalu3op[] = "R%t,R%s,R%d";
- static char mipsrtrs[] = "R%t,R%s";
- 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 mipsfp3[] = "F%t,F%d,F%a";
- static char mipscofp2[] = "f%a,f%d"; /* fd,fs */
- static char mipsfp2[] = "F%d,F%a";
- static char mipscofpc[] = "f%d,f%t"; /* fs,ft */
- static char mipsfpc[] = "F%t,F%d";
- static Opcode opcodes[64] = {
- 0, 0, 0,
- 0, 0, 0,
- "JMP", 0, "%j",
- "JAL", 0, "%j",
- "BEQ", branch, 0,
- "BNE", branch, 0,
- "BLEZ", branch, 0,
- "BGTZ", branch, 0,
- "ADD", addi, mipsalui,
- "ADDU", addi, mipsalui,
- "SGT", 0, mipsalui,
- "SGTU", 0, mipsalui,
- "AND", andi, mipsalui,
- "OR", andi, mipsalui,
- "XOR", andi, mipsalui,
- "MOVW", 0, "$%u,R%t",
- "cop0", 0, 0,
- "cop1", 0, 0,
- "cop2", 0, 0,
- "cop3", 0, 0,
- "BEQL", branch, 0,
- "BNEL", branch, 0,
- "BLEZL", branch, 0,
- "BGTZL", branch, 0,
- "instr18", 0, mipscoxxx,
- "instr19", 0, mipscoxxx,
- "MOVVL", load, mipsload,
- "MOVVR", load, mipsload,
- "instr1C", 0, mipscoxxx,
- "instr1D", 0, mipscoxxx,
- "instr1E", 0, mipscoxxx,
- "instr1F", 0, mipscoxxx,
- "MOVB", load, mipsload,
- "MOVH", load, mipsload,
- "lwl", 0, mipscoload,
- "MOVW", load, mipsload,
- "MOVBU", load, mipsload,
- "MOVHU", load, mipsload,
- "lwr", 0, mipscoload,
- "instr27", 0, mipscoxxx,
- "MOVB", store, mipsstore,
- "MOVH", store, mipsstore,
- "swl", 0, mipscoload,
- "MOVW", store, mipsstore,
- "MOVVL", store, mipsstore,
- "MOVVR", store, mipsstore,
- "swr", 0, mipscoload,
- "CACHE", 0, "%C,%l",
- "ll", 0, mipscoload,
- "MOVW", lwc1, mipscoload,
- "lwc2", 0, mipscoload,
- "lwc3", 0, mipscoload,
- "instr34", 0, mipscoxxx,
- "ldc1", 0, mipscoload,
- "ldc2", 0, mipscoload,
- "MOVV", load, mipsload,
- "sc", 0, mipscoload,
- "swc1", swc1, mipscoload,
- "swc2", 0, mipscoload,
- "swc3", 0, mipscoload,
- "instr3C", 0, mipscoxxx,
- "sdc1", 0, mipscoload,
- "sdc2", 0, mipscoload,
- "MOVV", store, mipsstore,
- };
- static Opcode sopcodes[64] = {
- "SLL", sll, "$%a,R%t,R%d",
- "special01", 0, mipscoxxx,
- "SRL", sll, "$%a,R%t,R%d",
- "SRA", sll, "$%a,R%t,R%d",
- "SLL", sllv, "R%s,R%t,R%d",
- "special05", 0, mipscoxxx,
- "SRL", sllv, "R%s,R%t,R%d",
- "SRA", sllv, "R%s,R%t,R%d",
- "JMP", 0, "(R%s)",
- "jal", jal, "r%d,r%s",
- "special0A", 0, mipscoxxx,
- "special0B", 0, mipscoxxx,
- "SYSCALL", 0, 0,
- "BREAK", 0, 0,
- "special0E", 0, mipscoxxx,
- "SYNC", 0, 0,
- "MOVW", 0, "HI,R%d",
- "MOVW", 0, "R%s,HI",
- "MOVW", 0, "LO,R%d",
- "MOVW", 0, "R%s,LO",
- "SLLV", sllv, "R%s,R%t,R%d",
- "special15", 0, mipscoxxx,
- "SRLV", sllv, "R%s,R%t,R%d",
- "SRAV", sllv, "R%s,R%t,R%d",
- "MUL", 0, mipsrtrs,
- "MULU", 0, mipsrtrs,
- "DIV", 0, mipsrtrs,
- "DIVU", 0, mipsrtrs,
- "special1C", 0, mipscoxxx,
- "special1D", 0, mipscoxxx,
- "DDIV", 0, "R%s,R%t",
- "special1F", 0, mipscoxxx,
- "ADD", add, mipsalu3op,
- "ADDU", add, mipsalu3op,
- "SUB", sub, mipsalu3op,
- "SUBU", sub, mipsalu3op,
- "AND", add, mipsalu3op,
- "OR", or, mipsalu3op,
- "XOR", add, mipsalu3op,
- "NOR", nor, mipsalu3op,
- "special28", 0, mipscoxxx,
- "special29", 0, mipscoxxx,
- "SGT", 0, mipsalu3op,
- "SGTU", 0, mipsalu3op,
- "special2C", 0, mipscoxxx,
- "special2D", 0, mipscoxxx,
- "special2E", 0, mipscoxxx,
- "DSUBU", 0, "R%s,R%t,R%d",
- "tge", 0, mipscorsrt,
- "tgeu", 0, mipscorsrt,
- "tlt", 0, mipscorsrt,
- "tltu", 0, mipscorsrt,
- "teq", 0, mipscorsrt,
- "special35", 0, mipscoxxx,
- "tne", 0, mipscorsrt,
- "special37", 0, mipscoxxx,
- "SLLV", sll, "$%a,R%t,R%d",
- "special39", 0, mipscoxxx,
- "SRLV", sll, "$%a,R%t,R%d",
- "SRAV", sll, "$%a,R%t,R%d",
- "SLLV", sl32, "$%a,R%t,R%d",
- "special3D", 0, mipscoxxx,
- "SRLV", sl32, "$%a,R%t,R%d",
- "SRAV", sl32, "$%a,R%t,R%d",
- };
- static Opcode ropcodes[32] = {
- "BLTZ", branch, 0,
- "BGEZ", branch, 0,
- "BLTZL", branch, 0,
- "BGEZL", branch, 0,
- "regimm04", 0, mipscoxxx,
- "regimm05", 0, mipscoxxx,
- "regimm06", 0, mipscoxxx,
- "regimm07", 0, mipscoxxx,
- "tgei", 0, mipscorsi,
- "tgeiu", 0, mipscorsi,
- "tlti", 0, mipscorsi,
- "tltiu", 0, mipscorsi,
- "teqi", 0, mipscorsi,
- "regimm0D", 0, mipscoxxx,
- "tnei", 0, mipscorsi,
- "regimm0F", 0, mipscoxxx,
- "BLTZAL", branch, 0,
- "BGEZAL", branch, 0,
- "BLTZALL", branch, 0,
- "BGEZALL", branch, 0,
- "regimm14", 0, mipscoxxx,
- "regimm15", 0, mipscoxxx,
- "regimm16", 0, mipscoxxx,
- "regimm17", 0, mipscoxxx,
- "regimm18", 0, mipscoxxx,
- "regimm19", 0, mipscoxxx,
- "regimm1A", 0, mipscoxxx,
- "regimm1B", 0, mipscoxxx,
- "regimm1C", 0, mipscoxxx,
- "regimm1D", 0, mipscoxxx,
- "regimm1E", 0, mipscoxxx,
- "regimm1F", 0, mipscoxxx,
- };
- static Opcode fopcodes[64] = {
- "ADD%f", 0, mipsfp3,
- "SUB%f", 0, mipsfp3,
- "MUL%f", 0, mipsfp3,
- "DIV%f", 0, mipsfp3,
- "sqrt.%f", 0, mipscofp2,
- "ABS%f", 0, mipsfp2,
- "MOV%f", 0, mipsfp2,
- "NEG%f", 0, mipsfp2,
- "finstr08", 0, mipscoxxx,
- "finstr09", 0, mipscoxxx,
- "finstr0A", 0, mipscoxxx,
- "finstr0B", 0, mipscoxxx,
- "round.w.%f", 0, mipscofp2,
- "trunc.w%f", 0, mipscofp2,
- "ceil.w%f", 0, mipscofp2,
- "floor.w%f", 0, mipscofp2,
- "finstr10", 0, mipscoxxx,
- "finstr11", 0, mipscoxxx,
- "finstr12", 0, mipscoxxx,
- "finstr13", 0, mipscoxxx,
- "finstr14", 0, mipscoxxx,
- "finstr15", 0, mipscoxxx,
- "finstr16", 0, mipscoxxx,
- "finstr17", 0, mipscoxxx,
- "finstr18", 0, mipscoxxx,
- "finstr19", 0, mipscoxxx,
- "finstr1A", 0, mipscoxxx,
- "finstr1B", 0, mipscoxxx,
- "finstr1C", 0, mipscoxxx,
- "finstr1D", 0, mipscoxxx,
- "finstr1E", 0, mipscoxxx,
- "finstr1F", 0, mipscoxxx,
- "cvt.s.%f", 0, mipscofp2,
- "cvt.d.%f", 0, mipscofp2,
- "cvt.e.%f", 0, mipscofp2,
- "cvt.q.%f", 0, mipscofp2,
- "cvt.w.%f", 0, mipscofp2,
- "finstr25", 0, mipscoxxx,
- "finstr26", 0, mipscoxxx,
- "finstr27", 0, mipscoxxx,
- "finstr28", 0, mipscoxxx,
- "finstr29", 0, mipscoxxx,
- "finstr2A", 0, mipscoxxx,
- "finstr2B", 0, mipscoxxx,
- "finstr2C", 0, mipscoxxx,
- "finstr2D", 0, mipscoxxx,
- "finstr2E", 0, mipscoxxx,
- "finstr2F", 0, mipscoxxx,
- "c.f.%f", 0, mipscofpc,
- "c.un.%f", 0, mipscofpc,
- "CMPEQ%f", 0, mipsfpc,
- "c.ueq.%f", 0, mipscofpc,
- "c.olt.%f", 0, mipscofpc,
- "c.ult.%f", 0, mipscofpc,
- "c.ole.%f", 0, mipscofpc,
- "c.ule.%f", 0, mipscofpc,
- "c.sf.%f", 0, mipscofpc,
- "c.ngle.%f", 0, mipscofpc,
- "c.seq.%f", 0, mipscofpc,
- "c.ngl.%f", 0, mipscofpc,
- "CMPGT%f", 0, mipsfpc,
- "c.nge.%f", 0, mipscofpc,
- "CMPGE%f", 0, mipsfpc,
- "c.ngt.%f", 0, mipscofpc,
- };
- static char *cop0regs[32] = {
- "INDEX", "RANDOM", "TLBPHYS", "EntryLo0",
- "CONTEXT", "PageMask", "Wired", "Error",
- "BADVADDR", "Count", "TLBVIRT", "Compare",
- "STATUS", "CAUSE", "EPC", "PRID",
- "Config", "LLadr", "WatchLo", "WatchHi",
- "20", "21", "22", "23",
- "24", "25", "26", "CacheErr",
- "TagLo", "TagHi", "ErrorEPC", "31"
- };
- static char fsub[16] = {
- 'F', 'D', 'e', 'q', 'W', '?', '?', '?',
- '?', '?', '?', '?', '?', '?', '?', '?'
- };
- static char *cacheps[] = {
- "I", "D", "SI", "SD"
- };
- static char *cacheop[] = {
- "IWBI", "ILT", "IST", "CDE", "HI", "HWBI", "HWB", "HSV"
- };
- static void
- format(char *mnemonic, Instr *i, char *f)
- {
- if (mnemonic)
- format(0, i, mnemonic);
- if (f == 0)
- return;
- if (mnemonic)
- 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':
- bprint(i, "%lx(R%d)",i->immediate, i->rs);
- break;
- case 'i':
- bprint(i, "$%lx", i->immediate);
- break;
- case 'u':
- 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, "$%lx", i->cofun);
- break;
- case 'w':
- bprint(i, "[%lux]", i->w0);
- break;
- case 'm':
- bprint(i, "M(%s)", cop0regs[i->rd]);
- break;
- case 'f':
- *i->curr++ = fsub[i->rs & 0x0F];
- break;
- case 'C':
- bprint(i, "%s%s", cacheps[i->rt & 3], cacheop[(i->rt>>2) & 7]);
- break;
- case '\0':
- *i->curr++ = '%';
- return;
- default:
- bprint(i, "%%%c", *f);
- break;
- }
- }
- *i->curr = 0;
- }
- 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 < 8) {
- switch (i->rs) {
- case 0:
- case 1:
- format("MOVW", i, "%m,R%t");
- return;
- case 4:
- case 5:
- format("MOVW", i, "R%t,%m");
- return;
- }
- }
- else 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);
- return;
- }
- }
- copz(0, i);
- }
- static void
- cop1(Instr *i)
- {
- char *m = "MOVW";
- switch (i->rs) {
- case 0:
- format(m, i, "F%d,R%t");
- return;
- case 2:
- format(m, i, "FCR%d,R%t");
- return;
- case 4:
- format(m, i, "R%t,F%d");
- return;
- case 6:
- format(m, i, "R%t,FCR%d");
- return;
- case 8:
- switch (i->rt) {
- case 0:
- format("BFPF", i, "%b");
- return;
- case 1:
- format("BFPT", i, "%b");
- return;
- }
- break;
- }
- copz(1, i);
- }
- static int
- printins(Map *map, uvlong pc, char *buf, int n)
- {
- Instr i;
- Opcode *o;
- uchar op;
- i.curr = buf;
- i.end = buf+n-1;
- mymap = map;
- if (mkinstr(pc, &i) < 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 i.size*4;
- case 0x11: /* COP1 */
- if (i.rs & 0x10) {
- o = fopcodes;
- op = i.function;
- break;
- }
- cop1(&i);
- return i.size*4;
- case 0x12: /* COP2 */
- case 0x13: /* COP3 */
- copz(i.op-0x10, &i);
- return i.size*4;
- default:
- o = opcodes;
- op = i.op;
- break;
- }
- if (o[op].f)
- (*o[op].f)(&o[op], &i);
- else
- format(o[op].mnemonic, &i, o[op].ken);
- return i.size*4;
- }
- extern int _mipscoinst(Map *, uvlong, char*, int);
- /* modifier 'I' toggles the default disassembler type */
- static int
- mipsinst(Map *map, uvlong pc, char modifier, char *buf, int n)
- {
- if ((asstype == AMIPSCO && modifier == 'i')
- || (asstype == AMIPS && modifier == 'I'))
- return _mipscoinst(map, pc, buf, n);
- else
- return printins(map, pc, buf, n);
- }
- static int
- mipsdas(Map *map, uvlong pc, char *buf, int n)
- {
- Instr i;
- i.curr = buf;
- i.end = buf+n;
- mymap = map;
- if (mkinstr(pc, &i) < 0)
- return -1;
- if (i.end-i.curr > 8)
- i.curr = _hexify(buf, i.w0, 7);
- if (i.size == 2 && i.end-i.curr > 9) {
- *i.curr++ = ' ';
- i.curr = _hexify(i.curr, i.w1, 7);
- }
- *i.curr = 0;
- return i.size*4;
- }
- static int
- mipsinstlen(Map *map, uvlong pc)
- {
- Instr i;
- mymap = map;
- if (mkinstr(pc, &i) < 0)
- return -1;
- return i.size*4;
- }
- static int
- mipsfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
- {
- ulong w, l;
- char buf[8];
- Instr i;
- mymap = map;
- if (mkinstr(pc, &i) < 0)
- return -1;
- w = i.w0;
- if((w&0xF3600000) == 0x41000000){ /* branch on coprocessor */
- Conditional:
- foll[0] = pc+8;
- l = ((w&0xFFFF)<<2);
- if(w & 0x8000)
- l |= 0xFFFC0000;
- foll[1] = pc+4 + l;
- return 2;
- }
- l = (w&0xFC000000)>>26;
- switch(l){
- case 0: /* SPECIAL */
- if((w&0x3E) == 0x08){ /* JR, JALR */
- sprint(buf, "R%ld", (w>>21)&0x1F);
- foll[0] = (*rget)(map, buf);
- return 1;
- }
- foll[0] = pc+i.size*4;
- return 1;
- case 0x30: /* Load-Linked followed by NOP, STC */
- foll[0] = pc+12;
- return 1;
- case 1: /* BCOND */
- case 4: /* BEQ */
- case 20: /* BEQL */
- case 5: /* BNE */
- case 21: /* BNEL */
- case 6: /* BLEZ */
- case 22: /* BLEZL */
- case 7: /* BGTZ */
- case 23: /* BGTZL */
- goto Conditional;
- case 2: /* J */
- case 3: /* JAL */
- foll[0] = (pc&0xF0000000) | ((w&0x03FFFFFF)<<2);
- return 1;
- }
- foll[0] = pc+i.size*4;
- return 1;
- }
|