174a4d8c2SCharles.Forsyth #include <lib9.h>
274a4d8c2SCharles.Forsyth #include <bio.h>
374a4d8c2SCharles.Forsyth #include "mach.h"
474a4d8c2SCharles.Forsyth /*
574a4d8c2SCharles.Forsyth * Mips-specific debugger interface
674a4d8c2SCharles.Forsyth */
774a4d8c2SCharles.Forsyth
8*d67b7dadSforsyth static char *mipsexcep(Map*, Rgetter);
9*d67b7dadSforsyth static int mipsfoll(Map*, uvlong, Rgetter, uvlong*);
10*d67b7dadSforsyth static int mipsinst(Map*, uvlong, char, char*, int);
11*d67b7dadSforsyth static int mipsdas(Map*, uvlong, char*, int);
12*d67b7dadSforsyth static int mipsinstlen(Map*, uvlong);
13*d67b7dadSforsyth
1474a4d8c2SCharles.Forsyth /*
1574a4d8c2SCharles.Forsyth * Debugger interface
1674a4d8c2SCharles.Forsyth */
1774a4d8c2SCharles.Forsyth Machdata mipsmach =
1874a4d8c2SCharles.Forsyth {
1974a4d8c2SCharles.Forsyth {0, 0, 0, 0xD}, /* break point */
2074a4d8c2SCharles.Forsyth 4, /* break point size */
2174a4d8c2SCharles.Forsyth
2274a4d8c2SCharles.Forsyth beswab, /* short to local byte order */
2374a4d8c2SCharles.Forsyth beswal, /* long to local byte order */
2474a4d8c2SCharles.Forsyth beswav, /* vlong to local byte order */
2574a4d8c2SCharles.Forsyth risctrace, /* C traceback */
2674a4d8c2SCharles.Forsyth riscframe, /* Frame finder */
2774a4d8c2SCharles.Forsyth mipsexcep, /* print exception */
2874a4d8c2SCharles.Forsyth 0, /* breakpoint fixup */
2974a4d8c2SCharles.Forsyth beieeesftos, /* single precision float printer */
3074a4d8c2SCharles.Forsyth beieeedftos, /* double precisioin float printer */
3174a4d8c2SCharles.Forsyth mipsfoll, /* following addresses */
3274a4d8c2SCharles.Forsyth mipsinst, /* print instruction */
3374a4d8c2SCharles.Forsyth mipsdas, /* dissembler */
3474a4d8c2SCharles.Forsyth mipsinstlen, /* instruction size */
3574a4d8c2SCharles.Forsyth };
3674a4d8c2SCharles.Forsyth
37*d67b7dadSforsyth Machdata mipsmachle =
38*d67b7dadSforsyth {
39*d67b7dadSforsyth {0, 0, 0, 0xD}, /* break point */
40*d67b7dadSforsyth 4, /* break point size */
41*d67b7dadSforsyth
42*d67b7dadSforsyth leswab, /* short to local byte order */
43*d67b7dadSforsyth leswal, /* long to local byte order */
44*d67b7dadSforsyth leswav, /* vlong to local byte order */
45*d67b7dadSforsyth risctrace, /* C traceback */
46*d67b7dadSforsyth riscframe, /* Frame finder */
47*d67b7dadSforsyth mipsexcep, /* print exception */
48*d67b7dadSforsyth 0, /* breakpoint fixup */
49*d67b7dadSforsyth leieeesftos, /* single precision float printer */
50*d67b7dadSforsyth leieeedftos, /* double precisioin float printer */
51*d67b7dadSforsyth mipsfoll, /* following addresses */
52*d67b7dadSforsyth mipsinst, /* print instruction */
53*d67b7dadSforsyth mipsdas, /* dissembler */
54*d67b7dadSforsyth mipsinstlen, /* instruction size */
55*d67b7dadSforsyth };
56*d67b7dadSforsyth
57*d67b7dadSforsyth /*
58*d67b7dadSforsyth * mips r4k little-endian
59*d67b7dadSforsyth */
60*d67b7dadSforsyth Machdata mipsmach2le =
61*d67b7dadSforsyth {
62*d67b7dadSforsyth {0, 0, 0, 0xD}, /* break point */
63*d67b7dadSforsyth 4, /* break point size */
64*d67b7dadSforsyth
65*d67b7dadSforsyth leswab, /* short to local byte order */
66*d67b7dadSforsyth leswal, /* long to local byte order */
67*d67b7dadSforsyth leswav, /* vlong to local byte order */
68*d67b7dadSforsyth risctrace, /* C traceback */
69*d67b7dadSforsyth riscframe, /* Frame finder */
70*d67b7dadSforsyth mipsexcep, /* print exception */
71*d67b7dadSforsyth 0, /* breakpoint fixup */
72*d67b7dadSforsyth leieeesftos, /* single precision float printer */
73*d67b7dadSforsyth leieeedftos, /* double precisioin float printer */
74*d67b7dadSforsyth mipsfoll, /* following addresses */
75*d67b7dadSforsyth mipsinst, /* print instruction */
76*d67b7dadSforsyth mipsdas, /* dissembler */
77*d67b7dadSforsyth mipsinstlen, /* instruction size */
78*d67b7dadSforsyth };
79*d67b7dadSforsyth
80*d67b7dadSforsyth /*
81*d67b7dadSforsyth * mips r4k big-endian
82*d67b7dadSforsyth */
83*d67b7dadSforsyth Machdata mipsmach2be =
84*d67b7dadSforsyth {
85*d67b7dadSforsyth {0, 0, 0, 0xD}, /* break point */
86*d67b7dadSforsyth 4, /* break point size */
87*d67b7dadSforsyth
88*d67b7dadSforsyth beswab, /* short to local byte order */
89*d67b7dadSforsyth beswal, /* long to local byte order */
90*d67b7dadSforsyth beswav, /* vlong to local byte order */
91*d67b7dadSforsyth risctrace, /* C traceback */
92*d67b7dadSforsyth riscframe, /* Frame finder */
93*d67b7dadSforsyth mipsexcep, /* print exception */
94*d67b7dadSforsyth 0, /* breakpoint fixup */
95*d67b7dadSforsyth beieeesftos, /* single precision float printer */
96*d67b7dadSforsyth beieeedftos, /* double precisioin float printer */
97*d67b7dadSforsyth mipsfoll, /* following addresses */
98*d67b7dadSforsyth mipsinst, /* print instruction */
99*d67b7dadSforsyth mipsdas, /* dissembler */
100*d67b7dadSforsyth mipsinstlen, /* instruction size */
101*d67b7dadSforsyth };
102*d67b7dadSforsyth
103*d67b7dadSforsyth
10474a4d8c2SCharles.Forsyth static char *excname[] =
10574a4d8c2SCharles.Forsyth {
10674a4d8c2SCharles.Forsyth "external interrupt",
10774a4d8c2SCharles.Forsyth "TLB modification",
10874a4d8c2SCharles.Forsyth "TLB miss (load or fetch)",
10974a4d8c2SCharles.Forsyth "TLB miss (store)",
11074a4d8c2SCharles.Forsyth "address error (load or fetch)",
11174a4d8c2SCharles.Forsyth "address error (store)",
11274a4d8c2SCharles.Forsyth "bus error (fetch)",
11374a4d8c2SCharles.Forsyth "bus error (data load or store)",
11474a4d8c2SCharles.Forsyth "system call",
11574a4d8c2SCharles.Forsyth "breakpoint",
11674a4d8c2SCharles.Forsyth "reserved instruction",
11774a4d8c2SCharles.Forsyth "coprocessor unusable",
11874a4d8c2SCharles.Forsyth "arithmetic overflow",
11974a4d8c2SCharles.Forsyth "undefined 13",
12074a4d8c2SCharles.Forsyth "undefined 14",
12174a4d8c2SCharles.Forsyth "system call",
12274a4d8c2SCharles.Forsyth /* the following is made up */
12374a4d8c2SCharles.Forsyth "floating point exception" /* FPEXC */
12474a4d8c2SCharles.Forsyth };
12574a4d8c2SCharles.Forsyth
126*d67b7dadSforsyth static char*
mipsexcep(Map * map,Rgetter rget)12774a4d8c2SCharles.Forsyth mipsexcep(Map *map, Rgetter rget)
12874a4d8c2SCharles.Forsyth {
12974a4d8c2SCharles.Forsyth int e;
13074a4d8c2SCharles.Forsyth long c;
13174a4d8c2SCharles.Forsyth
13274a4d8c2SCharles.Forsyth c = (*rget)(map, "CAUSE");
13374a4d8c2SCharles.Forsyth if(c & 0x00002000) /* INTR3 */
13474a4d8c2SCharles.Forsyth e = 16; /* Floating point exception */
13574a4d8c2SCharles.Forsyth else
13674a4d8c2SCharles.Forsyth e = (c>>2)&0x0F;
13774a4d8c2SCharles.Forsyth return excname[e];
13874a4d8c2SCharles.Forsyth }
13974a4d8c2SCharles.Forsyth
14074a4d8c2SCharles.Forsyth /* mips disassembler and related functions */
14174a4d8c2SCharles.Forsyth
14274a4d8c2SCharles.Forsyth static char FRAMENAME[] = ".frame";
14374a4d8c2SCharles.Forsyth
14474a4d8c2SCharles.Forsyth typedef struct {
145*d67b7dadSforsyth uvlong addr;
14674a4d8c2SCharles.Forsyth uchar op; /* bits 31-26 */
14774a4d8c2SCharles.Forsyth uchar rs; /* bits 25-21 */
14874a4d8c2SCharles.Forsyth uchar rt; /* bits 20-16 */
14974a4d8c2SCharles.Forsyth uchar rd; /* bits 15-11 */
15074a4d8c2SCharles.Forsyth uchar sa; /* bits 10-6 */
15174a4d8c2SCharles.Forsyth uchar function; /* bits 5-0 */
15274a4d8c2SCharles.Forsyth long immediate; /* bits 15-0 */
15374a4d8c2SCharles.Forsyth ulong cofun; /* bits 24-0 */
15474a4d8c2SCharles.Forsyth ulong target; /* bits 25-0 */
15574a4d8c2SCharles.Forsyth long w0;
15674a4d8c2SCharles.Forsyth long w1;
15774a4d8c2SCharles.Forsyth int size; /* instruction size */
15874a4d8c2SCharles.Forsyth char *curr; /* fill point in buffer */
15974a4d8c2SCharles.Forsyth char *end; /* end of buffer */
16074a4d8c2SCharles.Forsyth char *err; /* error message */
16174a4d8c2SCharles.Forsyth } Instr;
16274a4d8c2SCharles.Forsyth
16374a4d8c2SCharles.Forsyth static Map *mymap;
16474a4d8c2SCharles.Forsyth
16574a4d8c2SCharles.Forsyth static int
decode(uvlong pc,Instr * i)166*d67b7dadSforsyth decode(uvlong pc, Instr *i)
16774a4d8c2SCharles.Forsyth {
168*d67b7dadSforsyth ulong w;
16974a4d8c2SCharles.Forsyth
17074a4d8c2SCharles.Forsyth if (get4(mymap, pc, &w) < 0) {
17174a4d8c2SCharles.Forsyth werrstr("can't read instruction: %r");
17274a4d8c2SCharles.Forsyth return -1;
17374a4d8c2SCharles.Forsyth }
174*d67b7dadSforsyth
17574a4d8c2SCharles.Forsyth i->addr = pc;
17674a4d8c2SCharles.Forsyth i->size = 1;
17774a4d8c2SCharles.Forsyth i->op = (w >> 26) & 0x3F;
17874a4d8c2SCharles.Forsyth i->rs = (w >> 21) & 0x1F;
17974a4d8c2SCharles.Forsyth i->rt = (w >> 16) & 0x1F;
18074a4d8c2SCharles.Forsyth i->rd = (w >> 11) & 0x1F;
18174a4d8c2SCharles.Forsyth i->sa = (w >> 6) & 0x1F;
18274a4d8c2SCharles.Forsyth i->function = w & 0x3F;
18374a4d8c2SCharles.Forsyth i->immediate = w & 0x0000FFFF;
18474a4d8c2SCharles.Forsyth if (i->immediate & 0x8000)
18574a4d8c2SCharles.Forsyth i->immediate |= ~0x0000FFFF;
18674a4d8c2SCharles.Forsyth i->cofun = w & 0x01FFFFFF;
18774a4d8c2SCharles.Forsyth i->target = w & 0x03FFFFFF;
18874a4d8c2SCharles.Forsyth i->w0 = w;
18974a4d8c2SCharles.Forsyth return 1;
19074a4d8c2SCharles.Forsyth }
19174a4d8c2SCharles.Forsyth
19274a4d8c2SCharles.Forsyth static int
mkinstr(uvlong pc,Instr * i)193*d67b7dadSforsyth mkinstr(uvlong pc, Instr *i)
19474a4d8c2SCharles.Forsyth {
19574a4d8c2SCharles.Forsyth Instr x;
19674a4d8c2SCharles.Forsyth
19774a4d8c2SCharles.Forsyth if (decode(pc, i) < 0)
19874a4d8c2SCharles.Forsyth return -1;
19974a4d8c2SCharles.Forsyth /*
20074a4d8c2SCharles.Forsyth * if it's a LUI followed by an ORI,
20174a4d8c2SCharles.Forsyth * it's an immediate load of a large constant.
20274a4d8c2SCharles.Forsyth * fix the LUI immediate in any case.
20374a4d8c2SCharles.Forsyth */
20474a4d8c2SCharles.Forsyth if (i->op == 0x0F) {
20574a4d8c2SCharles.Forsyth if (decode(pc+4, &x) < 0)
20674a4d8c2SCharles.Forsyth return 0;
20774a4d8c2SCharles.Forsyth i->immediate <<= 16;
20874a4d8c2SCharles.Forsyth if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) {
20974a4d8c2SCharles.Forsyth i->immediate |= (x.immediate & 0xFFFF);
21074a4d8c2SCharles.Forsyth i->w1 = x.w0;
21174a4d8c2SCharles.Forsyth i->size++;
21274a4d8c2SCharles.Forsyth return 1;
21374a4d8c2SCharles.Forsyth }
21474a4d8c2SCharles.Forsyth }
21574a4d8c2SCharles.Forsyth /*
21674a4d8c2SCharles.Forsyth * if it's a LWC1 followed by another LWC1
21774a4d8c2SCharles.Forsyth * into an adjacent register, it's a load of
21874a4d8c2SCharles.Forsyth * a floating point double.
21974a4d8c2SCharles.Forsyth */
22074a4d8c2SCharles.Forsyth else if (i->op == 0x31 && (i->rt & 0x01)) {
22174a4d8c2SCharles.Forsyth if (decode(pc+4, &x) < 0)
22274a4d8c2SCharles.Forsyth return 0;
22374a4d8c2SCharles.Forsyth if (x.op == 0x31 && x.rt == (i->rt - 1) && x.rs == i->rs) {
22474a4d8c2SCharles.Forsyth i->rt -= 1;
22574a4d8c2SCharles.Forsyth i->w1 = x.w0;
22674a4d8c2SCharles.Forsyth i->size++;
22774a4d8c2SCharles.Forsyth return 1;
22874a4d8c2SCharles.Forsyth }
22974a4d8c2SCharles.Forsyth }
23074a4d8c2SCharles.Forsyth /*
23174a4d8c2SCharles.Forsyth * similarly for double stores
23274a4d8c2SCharles.Forsyth */
23374a4d8c2SCharles.Forsyth else if (i->op == 0x39 && (i->rt & 0x01)) {
23474a4d8c2SCharles.Forsyth if (decode(pc+4, &x) < 0)
23574a4d8c2SCharles.Forsyth return 0;
23674a4d8c2SCharles.Forsyth if (x.op == 0x39 && x.rt == (i->rt - 1) && x.rs == i->rs) {
23774a4d8c2SCharles.Forsyth i->rt -= 1;
23874a4d8c2SCharles.Forsyth i->w1 = x.w0;
23974a4d8c2SCharles.Forsyth i->size++;
24074a4d8c2SCharles.Forsyth }
24174a4d8c2SCharles.Forsyth }
24274a4d8c2SCharles.Forsyth return 1;
24374a4d8c2SCharles.Forsyth }
24474a4d8c2SCharles.Forsyth
245*d67b7dadSforsyth #pragma varargck argpos bprint 2
246*d67b7dadSforsyth
24774a4d8c2SCharles.Forsyth static void
bprint(Instr * i,char * fmt,...)24874a4d8c2SCharles.Forsyth bprint(Instr *i, char *fmt, ...)
24974a4d8c2SCharles.Forsyth {
25074a4d8c2SCharles.Forsyth va_list arg;
25174a4d8c2SCharles.Forsyth
25274a4d8c2SCharles.Forsyth va_start(arg, fmt);
25374a4d8c2SCharles.Forsyth i->curr = vseprint(i->curr, i->end, fmt, arg);
25474a4d8c2SCharles.Forsyth va_end(arg);
25574a4d8c2SCharles.Forsyth }
25674a4d8c2SCharles.Forsyth
25774a4d8c2SCharles.Forsyth typedef struct Opcode Opcode;
25874a4d8c2SCharles.Forsyth
25974a4d8c2SCharles.Forsyth struct Opcode {
26074a4d8c2SCharles.Forsyth char *mnemonic;
26174a4d8c2SCharles.Forsyth void (*f)(Opcode *, Instr *);
26274a4d8c2SCharles.Forsyth char *ken;
26374a4d8c2SCharles.Forsyth };
26474a4d8c2SCharles.Forsyth
26574a4d8c2SCharles.Forsyth static void format(char *, Instr *, char *);
26674a4d8c2SCharles.Forsyth
26774a4d8c2SCharles.Forsyth static void
branch(Opcode * o,Instr * i)26874a4d8c2SCharles.Forsyth branch(Opcode *o, Instr *i)
26974a4d8c2SCharles.Forsyth {
27074a4d8c2SCharles.Forsyth if (i->rs == 0 && i->rt == 0)
27174a4d8c2SCharles.Forsyth format("JMP", i, "%b");
27274a4d8c2SCharles.Forsyth else if (i->rs == 0)
27374a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%t,%b");
27474a4d8c2SCharles.Forsyth else if (i->rt < 2)
27574a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%s,%b");
27674a4d8c2SCharles.Forsyth else
27774a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%s,R%t,%b");
27874a4d8c2SCharles.Forsyth }
27974a4d8c2SCharles.Forsyth
28074a4d8c2SCharles.Forsyth static void
addi(Opcode * o,Instr * i)28174a4d8c2SCharles.Forsyth addi(Opcode *o, Instr *i)
28274a4d8c2SCharles.Forsyth {
28374a4d8c2SCharles.Forsyth if (i->rs == i->rt)
28474a4d8c2SCharles.Forsyth format(o->mnemonic, i, "%i,R%t");
28574a4d8c2SCharles.Forsyth else if (i->rs == 0)
28674a4d8c2SCharles.Forsyth format("MOVW", i, "%i,R%t");
28774a4d8c2SCharles.Forsyth else if (i->rs == 30) {
28874a4d8c2SCharles.Forsyth bprint(i, "MOVW\t$");
28974a4d8c2SCharles.Forsyth i->curr += symoff(i->curr, i->end-i->curr,
29074a4d8c2SCharles.Forsyth i->immediate+mach->sb, CANY);
29174a4d8c2SCharles.Forsyth bprint(i, "(SB),R%d", i->rt);
29274a4d8c2SCharles.Forsyth }
29374a4d8c2SCharles.Forsyth else
29474a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
29574a4d8c2SCharles.Forsyth }
29674a4d8c2SCharles.Forsyth
29774a4d8c2SCharles.Forsyth static void
andi(Opcode * o,Instr * i)29874a4d8c2SCharles.Forsyth andi(Opcode *o, Instr *i)
29974a4d8c2SCharles.Forsyth {
30074a4d8c2SCharles.Forsyth if (i->rs == i->rt)
30174a4d8c2SCharles.Forsyth format(o->mnemonic, i, "%i,R%t");
30274a4d8c2SCharles.Forsyth else
30374a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
30474a4d8c2SCharles.Forsyth }
30574a4d8c2SCharles.Forsyth
30674a4d8c2SCharles.Forsyth static int
plocal(Instr * i,char * m,char r,int store)30774a4d8c2SCharles.Forsyth plocal(Instr *i, char *m, char r, int store)
30874a4d8c2SCharles.Forsyth {
30974a4d8c2SCharles.Forsyth int offset;
31074a4d8c2SCharles.Forsyth char *reg;
31174a4d8c2SCharles.Forsyth Symbol s;
31274a4d8c2SCharles.Forsyth
31374a4d8c2SCharles.Forsyth if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
31474a4d8c2SCharles.Forsyth return 0;
31574a4d8c2SCharles.Forsyth if (s.value > i->immediate) {
31674a4d8c2SCharles.Forsyth if(!getauto(&s, s.value-i->immediate, CAUTO, &s))
31774a4d8c2SCharles.Forsyth return 0;
31874a4d8c2SCharles.Forsyth reg = "(SP)";
31974a4d8c2SCharles.Forsyth offset = i->immediate;
32074a4d8c2SCharles.Forsyth } else {
32174a4d8c2SCharles.Forsyth offset = i->immediate-s.value;
32274a4d8c2SCharles.Forsyth if (!getauto(&s, offset-4, CPARAM, &s))
32374a4d8c2SCharles.Forsyth return 0;
32474a4d8c2SCharles.Forsyth reg = "(FP)";
32574a4d8c2SCharles.Forsyth }
32674a4d8c2SCharles.Forsyth if (store)
32774a4d8c2SCharles.Forsyth bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->rt, s.name, offset, reg);
32874a4d8c2SCharles.Forsyth else
32974a4d8c2SCharles.Forsyth bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->rt);
33074a4d8c2SCharles.Forsyth return 1;
33174a4d8c2SCharles.Forsyth }
33274a4d8c2SCharles.Forsyth
33374a4d8c2SCharles.Forsyth static void
lw(Opcode * o,Instr * i,char r)33474a4d8c2SCharles.Forsyth lw(Opcode *o, Instr *i, char r)
33574a4d8c2SCharles.Forsyth {
33674a4d8c2SCharles.Forsyth char *m;
33774a4d8c2SCharles.Forsyth
33874a4d8c2SCharles.Forsyth if (r == 'F') {
33974a4d8c2SCharles.Forsyth if (i->size == 2)
34074a4d8c2SCharles.Forsyth m = "MOVD";
34174a4d8c2SCharles.Forsyth else
34274a4d8c2SCharles.Forsyth m = "MOVF";
34374a4d8c2SCharles.Forsyth }
34474a4d8c2SCharles.Forsyth else
34574a4d8c2SCharles.Forsyth m = o->mnemonic;
34674a4d8c2SCharles.Forsyth if (i->rs == 29 && plocal(i, m, r, 0))
34774a4d8c2SCharles.Forsyth return;
34874a4d8c2SCharles.Forsyth
34974a4d8c2SCharles.Forsyth if (i->rs == 30 && mach->sb) {
35074a4d8c2SCharles.Forsyth bprint(i, "%s\t", m);
35174a4d8c2SCharles.Forsyth i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
35274a4d8c2SCharles.Forsyth bprint(i, "(SB),%c%d", r, i->rt);
35374a4d8c2SCharles.Forsyth return;
35474a4d8c2SCharles.Forsyth }
35574a4d8c2SCharles.Forsyth if (r == 'F')
35674a4d8c2SCharles.Forsyth format(m, i, "%l,F%t");
35774a4d8c2SCharles.Forsyth else
35874a4d8c2SCharles.Forsyth format(m, i, o->ken);
35974a4d8c2SCharles.Forsyth }
36074a4d8c2SCharles.Forsyth
36174a4d8c2SCharles.Forsyth static void
load(Opcode * o,Instr * i)36274a4d8c2SCharles.Forsyth load(Opcode *o, Instr *i)
36374a4d8c2SCharles.Forsyth {
36474a4d8c2SCharles.Forsyth lw(o, i, 'R');
36574a4d8c2SCharles.Forsyth }
36674a4d8c2SCharles.Forsyth
36774a4d8c2SCharles.Forsyth static void
lwc1(Opcode * o,Instr * i)36874a4d8c2SCharles.Forsyth lwc1(Opcode *o, Instr *i)
36974a4d8c2SCharles.Forsyth {
37074a4d8c2SCharles.Forsyth lw(o, i, 'F');
37174a4d8c2SCharles.Forsyth }
37274a4d8c2SCharles.Forsyth
37374a4d8c2SCharles.Forsyth static void
sw(Opcode * o,Instr * i,char r)37474a4d8c2SCharles.Forsyth sw(Opcode *o, Instr *i, char r)
37574a4d8c2SCharles.Forsyth {
37674a4d8c2SCharles.Forsyth char *m;
37774a4d8c2SCharles.Forsyth
37874a4d8c2SCharles.Forsyth if (r == 'F') {
37974a4d8c2SCharles.Forsyth if (i->size == 2)
38074a4d8c2SCharles.Forsyth m = "MOVD";
38174a4d8c2SCharles.Forsyth else
38274a4d8c2SCharles.Forsyth m = "MOVF";
38374a4d8c2SCharles.Forsyth }
38474a4d8c2SCharles.Forsyth else
38574a4d8c2SCharles.Forsyth m = o->mnemonic;
38674a4d8c2SCharles.Forsyth if (i->rs == 29 && plocal(i, m, r, 1))
38774a4d8c2SCharles.Forsyth return;
38874a4d8c2SCharles.Forsyth
38974a4d8c2SCharles.Forsyth if (i->rs == 30 && mach->sb) {
39074a4d8c2SCharles.Forsyth bprint(i, "%s\t%c%d,", m, r, i->rt);
39174a4d8c2SCharles.Forsyth i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
39274a4d8c2SCharles.Forsyth bprint(i, "(SB)");
39374a4d8c2SCharles.Forsyth return;
39474a4d8c2SCharles.Forsyth }
39574a4d8c2SCharles.Forsyth if (r == 'F')
39674a4d8c2SCharles.Forsyth format(m, i, "F%t,%l");
39774a4d8c2SCharles.Forsyth else
39874a4d8c2SCharles.Forsyth format(m, i, o->ken);
39974a4d8c2SCharles.Forsyth }
40074a4d8c2SCharles.Forsyth
40174a4d8c2SCharles.Forsyth static void
store(Opcode * o,Instr * i)40274a4d8c2SCharles.Forsyth store(Opcode *o, Instr *i)
40374a4d8c2SCharles.Forsyth {
40474a4d8c2SCharles.Forsyth sw(o, i, 'R');
40574a4d8c2SCharles.Forsyth }
40674a4d8c2SCharles.Forsyth
40774a4d8c2SCharles.Forsyth static void
swc1(Opcode * o,Instr * i)40874a4d8c2SCharles.Forsyth swc1(Opcode *o, Instr *i)
40974a4d8c2SCharles.Forsyth {
41074a4d8c2SCharles.Forsyth sw(o, i, 'F');
41174a4d8c2SCharles.Forsyth }
41274a4d8c2SCharles.Forsyth
41374a4d8c2SCharles.Forsyth static void
sll(Opcode * o,Instr * i)41474a4d8c2SCharles.Forsyth sll(Opcode *o, Instr *i)
41574a4d8c2SCharles.Forsyth {
41674a4d8c2SCharles.Forsyth if (i->w0 == 0)
41774a4d8c2SCharles.Forsyth bprint(i, "NOOP");
41874a4d8c2SCharles.Forsyth else if (i->rd == i->rt)
41974a4d8c2SCharles.Forsyth format(o->mnemonic, i, "$%a,R%d");
42074a4d8c2SCharles.Forsyth else
42174a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
42274a4d8c2SCharles.Forsyth }
42374a4d8c2SCharles.Forsyth
42474a4d8c2SCharles.Forsyth static void
sl32(Opcode * o,Instr * i)42574a4d8c2SCharles.Forsyth sl32(Opcode *o, Instr *i)
42674a4d8c2SCharles.Forsyth {
42774a4d8c2SCharles.Forsyth i->sa += 32;
42874a4d8c2SCharles.Forsyth if (i->rd == i->rt)
42974a4d8c2SCharles.Forsyth format(o->mnemonic, i, "$%a,R%d");
43074a4d8c2SCharles.Forsyth else
43174a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
43274a4d8c2SCharles.Forsyth }
43374a4d8c2SCharles.Forsyth
43474a4d8c2SCharles.Forsyth static void
sllv(Opcode * o,Instr * i)43574a4d8c2SCharles.Forsyth sllv(Opcode *o, Instr *i)
43674a4d8c2SCharles.Forsyth {
43774a4d8c2SCharles.Forsyth if (i->rd == i->rt)
43874a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%s,R%d");
43974a4d8c2SCharles.Forsyth else
44074a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
44174a4d8c2SCharles.Forsyth }
44274a4d8c2SCharles.Forsyth
44374a4d8c2SCharles.Forsyth static void
jal(Opcode * o,Instr * i)44474a4d8c2SCharles.Forsyth jal(Opcode *o, Instr *i)
44574a4d8c2SCharles.Forsyth {
44674a4d8c2SCharles.Forsyth if (i->rd == 31)
44774a4d8c2SCharles.Forsyth format("JAL", i, "(R%s)");
44874a4d8c2SCharles.Forsyth else
44974a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
45074a4d8c2SCharles.Forsyth }
45174a4d8c2SCharles.Forsyth
45274a4d8c2SCharles.Forsyth static void
add(Opcode * o,Instr * i)45374a4d8c2SCharles.Forsyth add(Opcode *o, Instr *i)
45474a4d8c2SCharles.Forsyth {
45574a4d8c2SCharles.Forsyth if (i->rd == i->rs)
45674a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%t,R%d");
45774a4d8c2SCharles.Forsyth else if (i->rd == i->rt)
45874a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%s,R%d");
45974a4d8c2SCharles.Forsyth else
46074a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
46174a4d8c2SCharles.Forsyth }
46274a4d8c2SCharles.Forsyth
46374a4d8c2SCharles.Forsyth static void
sub(Opcode * o,Instr * i)46474a4d8c2SCharles.Forsyth sub(Opcode *o, Instr *i)
46574a4d8c2SCharles.Forsyth {
46674a4d8c2SCharles.Forsyth if (i->rd == i->rs)
46774a4d8c2SCharles.Forsyth format(o->mnemonic, i, "R%t,R%d");
46874a4d8c2SCharles.Forsyth else
46974a4d8c2SCharles.Forsyth format(o->mnemonic, i, o->ken);
47074a4d8c2SCharles.Forsyth }
47174a4d8c2SCharles.Forsyth
47274a4d8c2SCharles.Forsyth static void
or(Opcode * o,Instr * i)47374a4d8c2SCharles.Forsyth or(Opcode *o, Instr *i)
47474a4d8c2SCharles.Forsyth {
47574a4d8c2SCharles.Forsyth if (i->rs == 0 && i->rt == 0)
47674a4d8c2SCharles.Forsyth format("MOVW", i, "$0,R%d");
47774a4d8c2SCharles.Forsyth else if (i->rs == 0)
47874a4d8c2SCharles.Forsyth format("MOVW", i, "R%t,R%d");
47974a4d8c2SCharles.Forsyth else if (i->rt == 0)
48074a4d8c2SCharles.Forsyth format("MOVW", i, "R%s,R%d");
48174a4d8c2SCharles.Forsyth else
48274a4d8c2SCharles.Forsyth add(o, i);
48374a4d8c2SCharles.Forsyth }
48474a4d8c2SCharles.Forsyth
48574a4d8c2SCharles.Forsyth static void
nor(Opcode * o,Instr * i)48674a4d8c2SCharles.Forsyth nor(Opcode *o, Instr *i)
48774a4d8c2SCharles.Forsyth {
48874a4d8c2SCharles.Forsyth if (i->rs == 0 && i->rt == 0 && i->rd == 0)
48974a4d8c2SCharles.Forsyth format("NOP", i, 0);
49074a4d8c2SCharles.Forsyth else
49174a4d8c2SCharles.Forsyth add(o, i);
49274a4d8c2SCharles.Forsyth }
49374a4d8c2SCharles.Forsyth
49474a4d8c2SCharles.Forsyth static char mipscoload[] = "r%t,%l";
49574a4d8c2SCharles.Forsyth static char mipsload[] = "%l,R%t";
49674a4d8c2SCharles.Forsyth static char mipsstore[] = "R%t,%l";
49774a4d8c2SCharles.Forsyth static char mipsalui[] = "%i,R%s,R%t";
49874a4d8c2SCharles.Forsyth static char mipsalu3op[] = "R%t,R%s,R%d";
49974a4d8c2SCharles.Forsyth static char mipsrtrs[] = "R%t,R%s";
50074a4d8c2SCharles.Forsyth static char mipscorsrt[] = "r%s,r%t";
50174a4d8c2SCharles.Forsyth static char mipscorsi[] = "r%s,%i";
50274a4d8c2SCharles.Forsyth static char mipscoxxx[] = "%w";
50374a4d8c2SCharles.Forsyth static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */
50474a4d8c2SCharles.Forsyth static char mipsfp3[] = "F%t,F%d,F%a";
50574a4d8c2SCharles.Forsyth static char mipscofp2[] = "f%a,f%d"; /* fd,fs */
50674a4d8c2SCharles.Forsyth static char mipsfp2[] = "F%d,F%a";
50774a4d8c2SCharles.Forsyth static char mipscofpc[] = "f%d,f%t"; /* fs,ft */
50874a4d8c2SCharles.Forsyth static char mipsfpc[] = "F%t,F%d";
50974a4d8c2SCharles.Forsyth
51074a4d8c2SCharles.Forsyth static Opcode opcodes[64] = {
51174a4d8c2SCharles.Forsyth 0, 0, 0,
51274a4d8c2SCharles.Forsyth 0, 0, 0,
51374a4d8c2SCharles.Forsyth "JMP", 0, "%j",
51474a4d8c2SCharles.Forsyth "JAL", 0, "%j",
51574a4d8c2SCharles.Forsyth "BEQ", branch, 0,
51674a4d8c2SCharles.Forsyth "BNE", branch, 0,
51774a4d8c2SCharles.Forsyth "BLEZ", branch, 0,
51874a4d8c2SCharles.Forsyth "BGTZ", branch, 0,
51974a4d8c2SCharles.Forsyth "ADD", addi, mipsalui,
52074a4d8c2SCharles.Forsyth "ADDU", addi, mipsalui,
52174a4d8c2SCharles.Forsyth "SGT", 0, mipsalui,
52274a4d8c2SCharles.Forsyth "SGTU", 0, mipsalui,
52374a4d8c2SCharles.Forsyth "AND", andi, mipsalui,
52474a4d8c2SCharles.Forsyth "OR", andi, mipsalui,
52574a4d8c2SCharles.Forsyth "XOR", andi, mipsalui,
52674a4d8c2SCharles.Forsyth "MOVW", 0, "$%u,R%t",
52774a4d8c2SCharles.Forsyth "cop0", 0, 0,
52874a4d8c2SCharles.Forsyth "cop1", 0, 0,
52974a4d8c2SCharles.Forsyth "cop2", 0, 0,
53074a4d8c2SCharles.Forsyth "cop3", 0, 0,
53174a4d8c2SCharles.Forsyth "BEQL", branch, 0,
53274a4d8c2SCharles.Forsyth "BNEL", branch, 0,
53374a4d8c2SCharles.Forsyth "BLEZL", branch, 0,
53474a4d8c2SCharles.Forsyth "BGTZL", branch, 0,
53574a4d8c2SCharles.Forsyth "instr18", 0, mipscoxxx,
53674a4d8c2SCharles.Forsyth "instr19", 0, mipscoxxx,
53774a4d8c2SCharles.Forsyth "MOVVL", load, mipsload,
53874a4d8c2SCharles.Forsyth "MOVVR", load, mipsload,
53974a4d8c2SCharles.Forsyth "instr1C", 0, mipscoxxx,
54074a4d8c2SCharles.Forsyth "instr1D", 0, mipscoxxx,
54174a4d8c2SCharles.Forsyth "instr1E", 0, mipscoxxx,
54274a4d8c2SCharles.Forsyth "instr1F", 0, mipscoxxx,
54374a4d8c2SCharles.Forsyth "MOVB", load, mipsload,
54474a4d8c2SCharles.Forsyth "MOVH", load, mipsload,
54574a4d8c2SCharles.Forsyth "lwl", 0, mipscoload,
54674a4d8c2SCharles.Forsyth "MOVW", load, mipsload,
54774a4d8c2SCharles.Forsyth "MOVBU", load, mipsload,
54874a4d8c2SCharles.Forsyth "MOVHU", load, mipsload,
54974a4d8c2SCharles.Forsyth "lwr", 0, mipscoload,
55074a4d8c2SCharles.Forsyth "instr27", 0, mipscoxxx,
55174a4d8c2SCharles.Forsyth "MOVB", store, mipsstore,
55274a4d8c2SCharles.Forsyth "MOVH", store, mipsstore,
55374a4d8c2SCharles.Forsyth "swl", 0, mipscoload,
55474a4d8c2SCharles.Forsyth "MOVW", store, mipsstore,
55574a4d8c2SCharles.Forsyth "MOVVL", store, mipsstore,
55674a4d8c2SCharles.Forsyth "MOVVR", store, mipsstore,
55774a4d8c2SCharles.Forsyth "swr", 0, mipscoload,
55874a4d8c2SCharles.Forsyth "CACHE", 0, "%C,%l",
55974a4d8c2SCharles.Forsyth "ll", 0, mipscoload,
56074a4d8c2SCharles.Forsyth "MOVW", lwc1, mipscoload,
56174a4d8c2SCharles.Forsyth "lwc2", 0, mipscoload,
56274a4d8c2SCharles.Forsyth "lwc3", 0, mipscoload,
56374a4d8c2SCharles.Forsyth "instr34", 0, mipscoxxx,
56474a4d8c2SCharles.Forsyth "ldc1", 0, mipscoload,
56574a4d8c2SCharles.Forsyth "ldc2", 0, mipscoload,
56674a4d8c2SCharles.Forsyth "MOVV", load, mipsload,
56774a4d8c2SCharles.Forsyth "sc", 0, mipscoload,
56874a4d8c2SCharles.Forsyth "swc1", swc1, mipscoload,
56974a4d8c2SCharles.Forsyth "swc2", 0, mipscoload,
57074a4d8c2SCharles.Forsyth "swc3", 0, mipscoload,
57174a4d8c2SCharles.Forsyth "instr3C", 0, mipscoxxx,
57274a4d8c2SCharles.Forsyth "sdc1", 0, mipscoload,
57374a4d8c2SCharles.Forsyth "sdc2", 0, mipscoload,
57474a4d8c2SCharles.Forsyth "MOVV", store, mipsstore,
57574a4d8c2SCharles.Forsyth };
57674a4d8c2SCharles.Forsyth
57774a4d8c2SCharles.Forsyth static Opcode sopcodes[64] = {
57874a4d8c2SCharles.Forsyth "SLL", sll, "$%a,R%t,R%d",
57974a4d8c2SCharles.Forsyth "special01", 0, mipscoxxx,
58074a4d8c2SCharles.Forsyth "SRL", sll, "$%a,R%t,R%d",
58174a4d8c2SCharles.Forsyth "SRA", sll, "$%a,R%t,R%d",
58274a4d8c2SCharles.Forsyth "SLL", sllv, "R%s,R%t,R%d",
58374a4d8c2SCharles.Forsyth "special05", 0, mipscoxxx,
58474a4d8c2SCharles.Forsyth "SRL", sllv, "R%s,R%t,R%d",
58574a4d8c2SCharles.Forsyth "SRA", sllv, "R%s,R%t,R%d",
58674a4d8c2SCharles.Forsyth "JMP", 0, "(R%s)",
58774a4d8c2SCharles.Forsyth "jal", jal, "r%d,r%s",
58874a4d8c2SCharles.Forsyth "special0A", 0, mipscoxxx,
58974a4d8c2SCharles.Forsyth "special0B", 0, mipscoxxx,
59074a4d8c2SCharles.Forsyth "SYSCALL", 0, 0,
59174a4d8c2SCharles.Forsyth "BREAK", 0, 0,
59274a4d8c2SCharles.Forsyth "special0E", 0, mipscoxxx,
59374a4d8c2SCharles.Forsyth "SYNC", 0, 0,
59474a4d8c2SCharles.Forsyth "MOVW", 0, "HI,R%d",
59574a4d8c2SCharles.Forsyth "MOVW", 0, "R%s,HI",
59674a4d8c2SCharles.Forsyth "MOVW", 0, "LO,R%d",
59774a4d8c2SCharles.Forsyth "MOVW", 0, "R%s,LO",
59874a4d8c2SCharles.Forsyth "SLLV", sllv, "R%s,R%t,R%d",
59974a4d8c2SCharles.Forsyth "special15", 0, mipscoxxx,
60074a4d8c2SCharles.Forsyth "SRLV", sllv, "R%s,R%t,R%d",
60174a4d8c2SCharles.Forsyth "SRAV", sllv, "R%s,R%t,R%d",
60274a4d8c2SCharles.Forsyth "MUL", 0, mipsrtrs,
60374a4d8c2SCharles.Forsyth "MULU", 0, mipsrtrs,
60474a4d8c2SCharles.Forsyth "DIV", 0, mipsrtrs,
60574a4d8c2SCharles.Forsyth "DIVU", 0, mipsrtrs,
60674a4d8c2SCharles.Forsyth "special1C", 0, mipscoxxx,
60774a4d8c2SCharles.Forsyth "special1D", 0, mipscoxxx,
60874a4d8c2SCharles.Forsyth "DDIV", 0, "R%s,R%t",
60974a4d8c2SCharles.Forsyth "special1F", 0, mipscoxxx,
61074a4d8c2SCharles.Forsyth "ADD", add, mipsalu3op,
61174a4d8c2SCharles.Forsyth "ADDU", add, mipsalu3op,
61274a4d8c2SCharles.Forsyth "SUB", sub, mipsalu3op,
61374a4d8c2SCharles.Forsyth "SUBU", sub, mipsalu3op,
61474a4d8c2SCharles.Forsyth "AND", add, mipsalu3op,
61574a4d8c2SCharles.Forsyth "OR", or, mipsalu3op,
61674a4d8c2SCharles.Forsyth "XOR", add, mipsalu3op,
61774a4d8c2SCharles.Forsyth "NOR", nor, mipsalu3op,
61874a4d8c2SCharles.Forsyth "special28", 0, mipscoxxx,
61974a4d8c2SCharles.Forsyth "special29", 0, mipscoxxx,
62074a4d8c2SCharles.Forsyth "SGT", 0, mipsalu3op,
62174a4d8c2SCharles.Forsyth "SGTU", 0, mipsalu3op,
62274a4d8c2SCharles.Forsyth "special2C", 0, mipscoxxx,
62374a4d8c2SCharles.Forsyth "special2D", 0, mipscoxxx,
62474a4d8c2SCharles.Forsyth "special2E", 0, mipscoxxx,
62574a4d8c2SCharles.Forsyth "DSUBU", 0, "R%s,R%t,R%d",
62674a4d8c2SCharles.Forsyth "tge", 0, mipscorsrt,
62774a4d8c2SCharles.Forsyth "tgeu", 0, mipscorsrt,
62874a4d8c2SCharles.Forsyth "tlt", 0, mipscorsrt,
62974a4d8c2SCharles.Forsyth "tltu", 0, mipscorsrt,
63074a4d8c2SCharles.Forsyth "teq", 0, mipscorsrt,
63174a4d8c2SCharles.Forsyth "special35", 0, mipscoxxx,
63274a4d8c2SCharles.Forsyth "tne", 0, mipscorsrt,
63374a4d8c2SCharles.Forsyth "special37", 0, mipscoxxx,
63474a4d8c2SCharles.Forsyth "SLLV", sll, "$%a,R%t,R%d",
63574a4d8c2SCharles.Forsyth "special39", 0, mipscoxxx,
63674a4d8c2SCharles.Forsyth "SRLV", sll, "$%a,R%t,R%d",
63774a4d8c2SCharles.Forsyth "SRAV", sll, "$%a,R%t,R%d",
63874a4d8c2SCharles.Forsyth "SLLV", sl32, "$%a,R%t,R%d",
63974a4d8c2SCharles.Forsyth "special3D", 0, mipscoxxx,
64074a4d8c2SCharles.Forsyth "SRLV", sl32, "$%a,R%t,R%d",
64174a4d8c2SCharles.Forsyth "SRAV", sl32, "$%a,R%t,R%d",
64274a4d8c2SCharles.Forsyth };
64374a4d8c2SCharles.Forsyth
64474a4d8c2SCharles.Forsyth static Opcode ropcodes[32] = {
64574a4d8c2SCharles.Forsyth "BLTZ", branch, 0,
64674a4d8c2SCharles.Forsyth "BGEZ", branch, 0,
64774a4d8c2SCharles.Forsyth "BLTZL", branch, 0,
64874a4d8c2SCharles.Forsyth "BGEZL", branch, 0,
64974a4d8c2SCharles.Forsyth "regimm04", 0, mipscoxxx,
65074a4d8c2SCharles.Forsyth "regimm05", 0, mipscoxxx,
65174a4d8c2SCharles.Forsyth "regimm06", 0, mipscoxxx,
65274a4d8c2SCharles.Forsyth "regimm07", 0, mipscoxxx,
65374a4d8c2SCharles.Forsyth "tgei", 0, mipscorsi,
65474a4d8c2SCharles.Forsyth "tgeiu", 0, mipscorsi,
65574a4d8c2SCharles.Forsyth "tlti", 0, mipscorsi,
65674a4d8c2SCharles.Forsyth "tltiu", 0, mipscorsi,
65774a4d8c2SCharles.Forsyth "teqi", 0, mipscorsi,
65874a4d8c2SCharles.Forsyth "regimm0D", 0, mipscoxxx,
65974a4d8c2SCharles.Forsyth "tnei", 0, mipscorsi,
66074a4d8c2SCharles.Forsyth "regimm0F", 0, mipscoxxx,
66174a4d8c2SCharles.Forsyth "BLTZAL", branch, 0,
66274a4d8c2SCharles.Forsyth "BGEZAL", branch, 0,
66374a4d8c2SCharles.Forsyth "BLTZALL", branch, 0,
66474a4d8c2SCharles.Forsyth "BGEZALL", branch, 0,
66574a4d8c2SCharles.Forsyth "regimm14", 0, mipscoxxx,
66674a4d8c2SCharles.Forsyth "regimm15", 0, mipscoxxx,
66774a4d8c2SCharles.Forsyth "regimm16", 0, mipscoxxx,
66874a4d8c2SCharles.Forsyth "regimm17", 0, mipscoxxx,
66974a4d8c2SCharles.Forsyth "regimm18", 0, mipscoxxx,
67074a4d8c2SCharles.Forsyth "regimm19", 0, mipscoxxx,
67174a4d8c2SCharles.Forsyth "regimm1A", 0, mipscoxxx,
67274a4d8c2SCharles.Forsyth "regimm1B", 0, mipscoxxx,
67374a4d8c2SCharles.Forsyth "regimm1C", 0, mipscoxxx,
67474a4d8c2SCharles.Forsyth "regimm1D", 0, mipscoxxx,
67574a4d8c2SCharles.Forsyth "regimm1E", 0, mipscoxxx,
67674a4d8c2SCharles.Forsyth "regimm1F", 0, mipscoxxx,
67774a4d8c2SCharles.Forsyth };
67874a4d8c2SCharles.Forsyth
67974a4d8c2SCharles.Forsyth static Opcode fopcodes[64] = {
68074a4d8c2SCharles.Forsyth "ADD%f", 0, mipsfp3,
68174a4d8c2SCharles.Forsyth "SUB%f", 0, mipsfp3,
68274a4d8c2SCharles.Forsyth "MUL%f", 0, mipsfp3,
68374a4d8c2SCharles.Forsyth "DIV%f", 0, mipsfp3,
68474a4d8c2SCharles.Forsyth "sqrt.%f", 0, mipscofp2,
68574a4d8c2SCharles.Forsyth "ABS%f", 0, mipsfp2,
68674a4d8c2SCharles.Forsyth "MOV%f", 0, mipsfp2,
68774a4d8c2SCharles.Forsyth "NEG%f", 0, mipsfp2,
68874a4d8c2SCharles.Forsyth "finstr08", 0, mipscoxxx,
68974a4d8c2SCharles.Forsyth "finstr09", 0, mipscoxxx,
69074a4d8c2SCharles.Forsyth "finstr0A", 0, mipscoxxx,
69174a4d8c2SCharles.Forsyth "finstr0B", 0, mipscoxxx,
69274a4d8c2SCharles.Forsyth "round.w.%f", 0, mipscofp2,
69374a4d8c2SCharles.Forsyth "trunc.w%f", 0, mipscofp2,
69474a4d8c2SCharles.Forsyth "ceil.w%f", 0, mipscofp2,
69574a4d8c2SCharles.Forsyth "floor.w%f", 0, mipscofp2,
69674a4d8c2SCharles.Forsyth "finstr10", 0, mipscoxxx,
69774a4d8c2SCharles.Forsyth "finstr11", 0, mipscoxxx,
69874a4d8c2SCharles.Forsyth "finstr12", 0, mipscoxxx,
69974a4d8c2SCharles.Forsyth "finstr13", 0, mipscoxxx,
70074a4d8c2SCharles.Forsyth "finstr14", 0, mipscoxxx,
70174a4d8c2SCharles.Forsyth "finstr15", 0, mipscoxxx,
70274a4d8c2SCharles.Forsyth "finstr16", 0, mipscoxxx,
70374a4d8c2SCharles.Forsyth "finstr17", 0, mipscoxxx,
70474a4d8c2SCharles.Forsyth "finstr18", 0, mipscoxxx,
70574a4d8c2SCharles.Forsyth "finstr19", 0, mipscoxxx,
70674a4d8c2SCharles.Forsyth "finstr1A", 0, mipscoxxx,
70774a4d8c2SCharles.Forsyth "finstr1B", 0, mipscoxxx,
70874a4d8c2SCharles.Forsyth "finstr1C", 0, mipscoxxx,
70974a4d8c2SCharles.Forsyth "finstr1D", 0, mipscoxxx,
71074a4d8c2SCharles.Forsyth "finstr1E", 0, mipscoxxx,
71174a4d8c2SCharles.Forsyth "finstr1F", 0, mipscoxxx,
71274a4d8c2SCharles.Forsyth "cvt.s.%f", 0, mipscofp2,
71374a4d8c2SCharles.Forsyth "cvt.d.%f", 0, mipscofp2,
71474a4d8c2SCharles.Forsyth "cvt.e.%f", 0, mipscofp2,
71574a4d8c2SCharles.Forsyth "cvt.q.%f", 0, mipscofp2,
71674a4d8c2SCharles.Forsyth "cvt.w.%f", 0, mipscofp2,
71774a4d8c2SCharles.Forsyth "finstr25", 0, mipscoxxx,
71874a4d8c2SCharles.Forsyth "finstr26", 0, mipscoxxx,
71974a4d8c2SCharles.Forsyth "finstr27", 0, mipscoxxx,
72074a4d8c2SCharles.Forsyth "finstr28", 0, mipscoxxx,
72174a4d8c2SCharles.Forsyth "finstr29", 0, mipscoxxx,
72274a4d8c2SCharles.Forsyth "finstr2A", 0, mipscoxxx,
72374a4d8c2SCharles.Forsyth "finstr2B", 0, mipscoxxx,
72474a4d8c2SCharles.Forsyth "finstr2C", 0, mipscoxxx,
72574a4d8c2SCharles.Forsyth "finstr2D", 0, mipscoxxx,
72674a4d8c2SCharles.Forsyth "finstr2E", 0, mipscoxxx,
72774a4d8c2SCharles.Forsyth "finstr2F", 0, mipscoxxx,
72874a4d8c2SCharles.Forsyth "c.f.%f", 0, mipscofpc,
72974a4d8c2SCharles.Forsyth "c.un.%f", 0, mipscofpc,
73074a4d8c2SCharles.Forsyth "CMPEQ%f", 0, mipsfpc,
73174a4d8c2SCharles.Forsyth "c.ueq.%f", 0, mipscofpc,
73274a4d8c2SCharles.Forsyth "c.olt.%f", 0, mipscofpc,
73374a4d8c2SCharles.Forsyth "c.ult.%f", 0, mipscofpc,
73474a4d8c2SCharles.Forsyth "c.ole.%f", 0, mipscofpc,
73574a4d8c2SCharles.Forsyth "c.ule.%f", 0, mipscofpc,
73674a4d8c2SCharles.Forsyth "c.sf.%f", 0, mipscofpc,
73774a4d8c2SCharles.Forsyth "c.ngle.%f", 0, mipscofpc,
73874a4d8c2SCharles.Forsyth "c.seq.%f", 0, mipscofpc,
73974a4d8c2SCharles.Forsyth "c.ngl.%f", 0, mipscofpc,
74074a4d8c2SCharles.Forsyth "CMPGT%f", 0, mipsfpc,
74174a4d8c2SCharles.Forsyth "c.nge.%f", 0, mipscofpc,
74274a4d8c2SCharles.Forsyth "CMPGE%f", 0, mipsfpc,
74374a4d8c2SCharles.Forsyth "c.ngt.%f", 0, mipscofpc,
74474a4d8c2SCharles.Forsyth };
74574a4d8c2SCharles.Forsyth
74674a4d8c2SCharles.Forsyth static char *cop0regs[32] = {
74774a4d8c2SCharles.Forsyth "INDEX", "RANDOM", "TLBPHYS", "EntryLo0",
74874a4d8c2SCharles.Forsyth "CONTEXT", "PageMask", "Wired", "Error",
74974a4d8c2SCharles.Forsyth "BADVADDR", "Count", "TLBVIRT", "Compare",
75074a4d8c2SCharles.Forsyth "STATUS", "CAUSE", "EPC", "PRID",
75174a4d8c2SCharles.Forsyth "Config", "LLadr", "WatchLo", "WatchHi",
75274a4d8c2SCharles.Forsyth "20", "21", "22", "23",
75374a4d8c2SCharles.Forsyth "24", "25", "26", "CacheErr",
75474a4d8c2SCharles.Forsyth "TagLo", "TagHi", "ErrorEPC", "31"
75574a4d8c2SCharles.Forsyth };
75674a4d8c2SCharles.Forsyth
75774a4d8c2SCharles.Forsyth static char fsub[16] = {
75874a4d8c2SCharles.Forsyth 'F', 'D', 'e', 'q', 'W', '?', '?', '?',
75974a4d8c2SCharles.Forsyth '?', '?', '?', '?', '?', '?', '?', '?'
76074a4d8c2SCharles.Forsyth };
76174a4d8c2SCharles.Forsyth
76274a4d8c2SCharles.Forsyth static char *cacheps[] = {
76374a4d8c2SCharles.Forsyth "I", "D", "SI", "SD"
76474a4d8c2SCharles.Forsyth };
76574a4d8c2SCharles.Forsyth
76674a4d8c2SCharles.Forsyth static char *cacheop[] = {
76774a4d8c2SCharles.Forsyth "IWBI", "ILT", "IST", "CDE", "HI", "HWBI", "HWB", "HSV"
76874a4d8c2SCharles.Forsyth };
76974a4d8c2SCharles.Forsyth
77074a4d8c2SCharles.Forsyth static void
format(char * mnemonic,Instr * i,char * f)77174a4d8c2SCharles.Forsyth format(char *mnemonic, Instr *i, char *f)
77274a4d8c2SCharles.Forsyth {
77374a4d8c2SCharles.Forsyth if (mnemonic)
77474a4d8c2SCharles.Forsyth format(0, i, mnemonic);
77574a4d8c2SCharles.Forsyth if (f == 0)
77674a4d8c2SCharles.Forsyth return;
77774a4d8c2SCharles.Forsyth if (mnemonic)
77874a4d8c2SCharles.Forsyth if (i->curr < i->end)
77974a4d8c2SCharles.Forsyth *i->curr++ = '\t';
78074a4d8c2SCharles.Forsyth for ( ; *f && i->curr < i->end; f++) {
78174a4d8c2SCharles.Forsyth if (*f != '%') {
78274a4d8c2SCharles.Forsyth *i->curr++ = *f;
78374a4d8c2SCharles.Forsyth continue;
78474a4d8c2SCharles.Forsyth }
78574a4d8c2SCharles.Forsyth switch (*++f) {
78674a4d8c2SCharles.Forsyth
78774a4d8c2SCharles.Forsyth case 's':
78874a4d8c2SCharles.Forsyth bprint(i, "%d", i->rs);
78974a4d8c2SCharles.Forsyth break;
79074a4d8c2SCharles.Forsyth
79174a4d8c2SCharles.Forsyth case 't':
79274a4d8c2SCharles.Forsyth bprint(i, "%d", i->rt);
79374a4d8c2SCharles.Forsyth break;
79474a4d8c2SCharles.Forsyth
79574a4d8c2SCharles.Forsyth case 'd':
79674a4d8c2SCharles.Forsyth bprint(i, "%d", i->rd);
79774a4d8c2SCharles.Forsyth break;
79874a4d8c2SCharles.Forsyth
79974a4d8c2SCharles.Forsyth case 'a':
80074a4d8c2SCharles.Forsyth bprint(i, "%d", i->sa);
80174a4d8c2SCharles.Forsyth break;
80274a4d8c2SCharles.Forsyth
80374a4d8c2SCharles.Forsyth case 'l':
80474a4d8c2SCharles.Forsyth bprint(i, "%lx(R%d)",i->immediate, i->rs);
80574a4d8c2SCharles.Forsyth break;
80674a4d8c2SCharles.Forsyth
80774a4d8c2SCharles.Forsyth case 'i':
80874a4d8c2SCharles.Forsyth bprint(i, "$%lx", i->immediate);
80974a4d8c2SCharles.Forsyth break;
81074a4d8c2SCharles.Forsyth
81174a4d8c2SCharles.Forsyth case 'u':
81274a4d8c2SCharles.Forsyth i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
81374a4d8c2SCharles.Forsyth bprint(i, "(SB)");
81474a4d8c2SCharles.Forsyth break;
81574a4d8c2SCharles.Forsyth
81674a4d8c2SCharles.Forsyth case 'j':
81774a4d8c2SCharles.Forsyth i->curr += symoff(i->curr, i->end-i->curr,
81874a4d8c2SCharles.Forsyth (i->target<<2)|(i->addr & 0xF0000000), CANY);
81974a4d8c2SCharles.Forsyth bprint(i, "(SB)");
82074a4d8c2SCharles.Forsyth break;
82174a4d8c2SCharles.Forsyth
82274a4d8c2SCharles.Forsyth case 'b':
82374a4d8c2SCharles.Forsyth i->curr += symoff(i->curr, i->end-i->curr,
82474a4d8c2SCharles.Forsyth (i->immediate<<2)+i->addr+4, CANY);
82574a4d8c2SCharles.Forsyth break;
82674a4d8c2SCharles.Forsyth
82774a4d8c2SCharles.Forsyth case 'c':
82874a4d8c2SCharles.Forsyth bprint(i, "$%lx", i->cofun);
82974a4d8c2SCharles.Forsyth break;
83074a4d8c2SCharles.Forsyth
83174a4d8c2SCharles.Forsyth case 'w':
83274a4d8c2SCharles.Forsyth bprint(i, "[%lux]", i->w0);
83374a4d8c2SCharles.Forsyth break;
83474a4d8c2SCharles.Forsyth
83574a4d8c2SCharles.Forsyth case 'm':
83674a4d8c2SCharles.Forsyth bprint(i, "M(%s)", cop0regs[i->rd]);
83774a4d8c2SCharles.Forsyth break;
83874a4d8c2SCharles.Forsyth
83974a4d8c2SCharles.Forsyth case 'f':
84074a4d8c2SCharles.Forsyth *i->curr++ = fsub[i->rs & 0x0F];
84174a4d8c2SCharles.Forsyth break;
84274a4d8c2SCharles.Forsyth
84374a4d8c2SCharles.Forsyth case 'C':
84474a4d8c2SCharles.Forsyth bprint(i, "%s%s", cacheps[i->rt & 3], cacheop[(i->rt>>2) & 7]);
84574a4d8c2SCharles.Forsyth break;
84674a4d8c2SCharles.Forsyth
84774a4d8c2SCharles.Forsyth case '\0':
84874a4d8c2SCharles.Forsyth *i->curr++ = '%';
84974a4d8c2SCharles.Forsyth return;
85074a4d8c2SCharles.Forsyth
85174a4d8c2SCharles.Forsyth default:
85274a4d8c2SCharles.Forsyth bprint(i, "%%%c", *f);
85374a4d8c2SCharles.Forsyth break;
85474a4d8c2SCharles.Forsyth }
85574a4d8c2SCharles.Forsyth }
85674a4d8c2SCharles.Forsyth *i->curr = 0;
85774a4d8c2SCharles.Forsyth }
85874a4d8c2SCharles.Forsyth
85974a4d8c2SCharles.Forsyth static void
copz(int cop,Instr * i)86074a4d8c2SCharles.Forsyth copz(int cop, Instr *i)
86174a4d8c2SCharles.Forsyth {
86274a4d8c2SCharles.Forsyth char *f, *m, buf[16];
86374a4d8c2SCharles.Forsyth
86474a4d8c2SCharles.Forsyth m = buf;
86574a4d8c2SCharles.Forsyth f = "%t,%d";
86674a4d8c2SCharles.Forsyth switch (i->rs) {
86774a4d8c2SCharles.Forsyth
86874a4d8c2SCharles.Forsyth case 0:
86974a4d8c2SCharles.Forsyth sprint(buf, "mfc%d", cop);
87074a4d8c2SCharles.Forsyth break;
87174a4d8c2SCharles.Forsyth
87274a4d8c2SCharles.Forsyth case 2:
87374a4d8c2SCharles.Forsyth sprint(buf, "cfc%d", cop);
87474a4d8c2SCharles.Forsyth break;
87574a4d8c2SCharles.Forsyth
87674a4d8c2SCharles.Forsyth case 4:
87774a4d8c2SCharles.Forsyth sprint(buf, "mtc%d", cop);
87874a4d8c2SCharles.Forsyth break;
87974a4d8c2SCharles.Forsyth
88074a4d8c2SCharles.Forsyth case 6:
88174a4d8c2SCharles.Forsyth sprint(buf, "ctc%d", cop);
88274a4d8c2SCharles.Forsyth break;
88374a4d8c2SCharles.Forsyth
88474a4d8c2SCharles.Forsyth case 8:
88574a4d8c2SCharles.Forsyth f = "%b";
88674a4d8c2SCharles.Forsyth switch (i->rt) {
88774a4d8c2SCharles.Forsyth
88874a4d8c2SCharles.Forsyth case 0:
88974a4d8c2SCharles.Forsyth sprint(buf, "bc%df", cop);
89074a4d8c2SCharles.Forsyth break;
89174a4d8c2SCharles.Forsyth
89274a4d8c2SCharles.Forsyth case 1:
89374a4d8c2SCharles.Forsyth sprint(buf, "bc%dt", cop);
89474a4d8c2SCharles.Forsyth break;
89574a4d8c2SCharles.Forsyth
89674a4d8c2SCharles.Forsyth case 2:
89774a4d8c2SCharles.Forsyth sprint(buf, "bc%dfl", cop);
89874a4d8c2SCharles.Forsyth break;
89974a4d8c2SCharles.Forsyth
90074a4d8c2SCharles.Forsyth case 3:
90174a4d8c2SCharles.Forsyth sprint(buf, "bc%dtl", cop);
90274a4d8c2SCharles.Forsyth break;
90374a4d8c2SCharles.Forsyth
90474a4d8c2SCharles.Forsyth default:
90574a4d8c2SCharles.Forsyth sprint(buf, "cop%d", cop);
90674a4d8c2SCharles.Forsyth f = mipscoxxx;
90774a4d8c2SCharles.Forsyth break;
90874a4d8c2SCharles.Forsyth }
90974a4d8c2SCharles.Forsyth break;
91074a4d8c2SCharles.Forsyth
91174a4d8c2SCharles.Forsyth default:
91274a4d8c2SCharles.Forsyth sprint(buf, "cop%d", cop);
91374a4d8c2SCharles.Forsyth if (i->rs & 0x10)
91474a4d8c2SCharles.Forsyth f = "function %c";
91574a4d8c2SCharles.Forsyth else
91674a4d8c2SCharles.Forsyth f = mipscoxxx;
91774a4d8c2SCharles.Forsyth break;
91874a4d8c2SCharles.Forsyth }
91974a4d8c2SCharles.Forsyth format(m, i, f);
92074a4d8c2SCharles.Forsyth }
92174a4d8c2SCharles.Forsyth
92274a4d8c2SCharles.Forsyth static void
cop0(Instr * i)92374a4d8c2SCharles.Forsyth cop0(Instr *i)
92474a4d8c2SCharles.Forsyth {
92574a4d8c2SCharles.Forsyth char *m = 0;
92674a4d8c2SCharles.Forsyth
92774a4d8c2SCharles.Forsyth if (i->rs < 8) {
92874a4d8c2SCharles.Forsyth switch (i->rs) {
92974a4d8c2SCharles.Forsyth
93074a4d8c2SCharles.Forsyth case 0:
93174a4d8c2SCharles.Forsyth case 1:
93274a4d8c2SCharles.Forsyth format("MOVW", i, "%m,R%t");
93374a4d8c2SCharles.Forsyth return;
93474a4d8c2SCharles.Forsyth
93574a4d8c2SCharles.Forsyth case 4:
93674a4d8c2SCharles.Forsyth case 5:
93774a4d8c2SCharles.Forsyth format("MOVW", i, "R%t,%m");
93874a4d8c2SCharles.Forsyth return;
93974a4d8c2SCharles.Forsyth }
94074a4d8c2SCharles.Forsyth }
94174a4d8c2SCharles.Forsyth else if (i->rs >= 0x10) {
94274a4d8c2SCharles.Forsyth switch (i->cofun) {
94374a4d8c2SCharles.Forsyth
94474a4d8c2SCharles.Forsyth case 1:
94574a4d8c2SCharles.Forsyth m = "TLBR";
94674a4d8c2SCharles.Forsyth break;
94774a4d8c2SCharles.Forsyth
94874a4d8c2SCharles.Forsyth case 2:
94974a4d8c2SCharles.Forsyth m = "TLBWI";
95074a4d8c2SCharles.Forsyth break;
95174a4d8c2SCharles.Forsyth
95274a4d8c2SCharles.Forsyth case 6:
95374a4d8c2SCharles.Forsyth m = "TLBWR";
95474a4d8c2SCharles.Forsyth break;
95574a4d8c2SCharles.Forsyth
95674a4d8c2SCharles.Forsyth case 8:
95774a4d8c2SCharles.Forsyth m = "TLBP";
95874a4d8c2SCharles.Forsyth break;
95974a4d8c2SCharles.Forsyth
96074a4d8c2SCharles.Forsyth case 16:
96174a4d8c2SCharles.Forsyth m = "RFE";
96274a4d8c2SCharles.Forsyth break;
96374a4d8c2SCharles.Forsyth
96474a4d8c2SCharles.Forsyth case 32:
96574a4d8c2SCharles.Forsyth m = "ERET";
96674a4d8c2SCharles.Forsyth break;
96774a4d8c2SCharles.Forsyth }
96874a4d8c2SCharles.Forsyth if (m) {
96974a4d8c2SCharles.Forsyth format(m, i, 0);
97074a4d8c2SCharles.Forsyth return;
97174a4d8c2SCharles.Forsyth }
97274a4d8c2SCharles.Forsyth }
97374a4d8c2SCharles.Forsyth copz(0, i);
97474a4d8c2SCharles.Forsyth }
97574a4d8c2SCharles.Forsyth
97674a4d8c2SCharles.Forsyth static void
cop1(Instr * i)97774a4d8c2SCharles.Forsyth cop1(Instr *i)
97874a4d8c2SCharles.Forsyth {
97974a4d8c2SCharles.Forsyth char *m = "MOVW";
98074a4d8c2SCharles.Forsyth
98174a4d8c2SCharles.Forsyth switch (i->rs) {
98274a4d8c2SCharles.Forsyth
98374a4d8c2SCharles.Forsyth case 0:
98474a4d8c2SCharles.Forsyth format(m, i, "F%d,R%t");
98574a4d8c2SCharles.Forsyth return;
98674a4d8c2SCharles.Forsyth
98774a4d8c2SCharles.Forsyth case 2:
98874a4d8c2SCharles.Forsyth format(m, i, "FCR%d,R%t");
98974a4d8c2SCharles.Forsyth return;
99074a4d8c2SCharles.Forsyth
99174a4d8c2SCharles.Forsyth case 4:
99274a4d8c2SCharles.Forsyth format(m, i, "R%t,F%d");
99374a4d8c2SCharles.Forsyth return;
99474a4d8c2SCharles.Forsyth
99574a4d8c2SCharles.Forsyth case 6:
99674a4d8c2SCharles.Forsyth format(m, i, "R%t,FCR%d");
99774a4d8c2SCharles.Forsyth return;
99874a4d8c2SCharles.Forsyth
99974a4d8c2SCharles.Forsyth case 8:
100074a4d8c2SCharles.Forsyth switch (i->rt) {
100174a4d8c2SCharles.Forsyth
100274a4d8c2SCharles.Forsyth case 0:
100374a4d8c2SCharles.Forsyth format("BFPF", i, "%b");
100474a4d8c2SCharles.Forsyth return;
100574a4d8c2SCharles.Forsyth
100674a4d8c2SCharles.Forsyth case 1:
100774a4d8c2SCharles.Forsyth format("BFPT", i, "%b");
100874a4d8c2SCharles.Forsyth return;
100974a4d8c2SCharles.Forsyth }
101074a4d8c2SCharles.Forsyth break;
101174a4d8c2SCharles.Forsyth }
101274a4d8c2SCharles.Forsyth copz(1, i);
101374a4d8c2SCharles.Forsyth }
101474a4d8c2SCharles.Forsyth
101574a4d8c2SCharles.Forsyth static int
printins(Map * map,uvlong pc,char * buf,int n)1016*d67b7dadSforsyth printins(Map *map, uvlong pc, char *buf, int n)
101774a4d8c2SCharles.Forsyth {
101874a4d8c2SCharles.Forsyth Instr i;
101974a4d8c2SCharles.Forsyth Opcode *o;
102074a4d8c2SCharles.Forsyth uchar op;
102174a4d8c2SCharles.Forsyth
102274a4d8c2SCharles.Forsyth i.curr = buf;
102374a4d8c2SCharles.Forsyth i.end = buf+n-1;
102474a4d8c2SCharles.Forsyth mymap = map;
102574a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
102674a4d8c2SCharles.Forsyth return -1;
102774a4d8c2SCharles.Forsyth switch (i.op) {
102874a4d8c2SCharles.Forsyth
102974a4d8c2SCharles.Forsyth case 0x00: /* SPECIAL */
103074a4d8c2SCharles.Forsyth o = sopcodes;
103174a4d8c2SCharles.Forsyth op = i.function;
103274a4d8c2SCharles.Forsyth break;
103374a4d8c2SCharles.Forsyth
103474a4d8c2SCharles.Forsyth case 0x01: /* REGIMM */
103574a4d8c2SCharles.Forsyth o = ropcodes;
103674a4d8c2SCharles.Forsyth op = i.rt;
103774a4d8c2SCharles.Forsyth break;
103874a4d8c2SCharles.Forsyth
103974a4d8c2SCharles.Forsyth case 0x10: /* COP0 */
104074a4d8c2SCharles.Forsyth cop0(&i);
104174a4d8c2SCharles.Forsyth return i.size*4;
104274a4d8c2SCharles.Forsyth
104374a4d8c2SCharles.Forsyth case 0x11: /* COP1 */
104474a4d8c2SCharles.Forsyth if (i.rs & 0x10) {
104574a4d8c2SCharles.Forsyth o = fopcodes;
104674a4d8c2SCharles.Forsyth op = i.function;
104774a4d8c2SCharles.Forsyth break;
104874a4d8c2SCharles.Forsyth }
104974a4d8c2SCharles.Forsyth cop1(&i);
105074a4d8c2SCharles.Forsyth return i.size*4;
105174a4d8c2SCharles.Forsyth
105274a4d8c2SCharles.Forsyth case 0x12: /* COP2 */
105374a4d8c2SCharles.Forsyth case 0x13: /* COP3 */
105474a4d8c2SCharles.Forsyth copz(i.op-0x10, &i);
105574a4d8c2SCharles.Forsyth return i.size*4;
105674a4d8c2SCharles.Forsyth
105774a4d8c2SCharles.Forsyth default:
105874a4d8c2SCharles.Forsyth o = opcodes;
105974a4d8c2SCharles.Forsyth op = i.op;
106074a4d8c2SCharles.Forsyth break;
106174a4d8c2SCharles.Forsyth }
106274a4d8c2SCharles.Forsyth if (o[op].f)
106374a4d8c2SCharles.Forsyth (*o[op].f)(&o[op], &i);
106474a4d8c2SCharles.Forsyth else
106574a4d8c2SCharles.Forsyth format(o[op].mnemonic, &i, o[op].ken);
106674a4d8c2SCharles.Forsyth return i.size*4;
106774a4d8c2SCharles.Forsyth }
106874a4d8c2SCharles.Forsyth
1069*d67b7dadSforsyth extern int _mipscoinst(Map *, uvlong, char*, int);
107074a4d8c2SCharles.Forsyth
107174a4d8c2SCharles.Forsyth /* modifier 'I' toggles the default disassembler type */
1072*d67b7dadSforsyth static int
mipsinst(Map * map,uvlong pc,char modifier,char * buf,int n)1073*d67b7dadSforsyth mipsinst(Map *map, uvlong pc, char modifier, char *buf, int n)
107474a4d8c2SCharles.Forsyth {
107574a4d8c2SCharles.Forsyth if ((asstype == AMIPSCO && modifier == 'i')
107674a4d8c2SCharles.Forsyth || (asstype == AMIPS && modifier == 'I'))
107774a4d8c2SCharles.Forsyth return _mipscoinst(map, pc, buf, n);
107874a4d8c2SCharles.Forsyth else
107974a4d8c2SCharles.Forsyth return printins(map, pc, buf, n);
108074a4d8c2SCharles.Forsyth }
108174a4d8c2SCharles.Forsyth
1082*d67b7dadSforsyth static int
mipsdas(Map * map,uvlong pc,char * buf,int n)1083*d67b7dadSforsyth mipsdas(Map *map, uvlong pc, char *buf, int n)
108474a4d8c2SCharles.Forsyth {
108574a4d8c2SCharles.Forsyth Instr i;
108674a4d8c2SCharles.Forsyth
108774a4d8c2SCharles.Forsyth i.curr = buf;
108874a4d8c2SCharles.Forsyth i.end = buf+n;
108974a4d8c2SCharles.Forsyth mymap = map;
109074a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
109174a4d8c2SCharles.Forsyth return -1;
109274a4d8c2SCharles.Forsyth if (i.end-i.curr > 8)
109374a4d8c2SCharles.Forsyth i.curr = _hexify(buf, i.w0, 7);
109474a4d8c2SCharles.Forsyth if (i.size == 2 && i.end-i.curr > 9) {
109574a4d8c2SCharles.Forsyth *i.curr++ = ' ';
109674a4d8c2SCharles.Forsyth i.curr = _hexify(i.curr, i.w1, 7);
109774a4d8c2SCharles.Forsyth }
109874a4d8c2SCharles.Forsyth *i.curr = 0;
109974a4d8c2SCharles.Forsyth return i.size*4;
110074a4d8c2SCharles.Forsyth }
110174a4d8c2SCharles.Forsyth
1102*d67b7dadSforsyth static int
mipsinstlen(Map * map,uvlong pc)1103*d67b7dadSforsyth mipsinstlen(Map *map, uvlong pc)
110474a4d8c2SCharles.Forsyth {
110574a4d8c2SCharles.Forsyth Instr i;
110674a4d8c2SCharles.Forsyth
110774a4d8c2SCharles.Forsyth mymap = map;
110874a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
110974a4d8c2SCharles.Forsyth return -1;
111074a4d8c2SCharles.Forsyth return i.size*4;
111174a4d8c2SCharles.Forsyth }
111274a4d8c2SCharles.Forsyth
1113*d67b7dadSforsyth static int
mipsfoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)1114*d67b7dadSforsyth mipsfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
111574a4d8c2SCharles.Forsyth {
111674a4d8c2SCharles.Forsyth ulong w, l;
111774a4d8c2SCharles.Forsyth char buf[8];
111874a4d8c2SCharles.Forsyth Instr i;
111974a4d8c2SCharles.Forsyth
112074a4d8c2SCharles.Forsyth mymap = map;
112174a4d8c2SCharles.Forsyth if (mkinstr(pc, &i) < 0)
112274a4d8c2SCharles.Forsyth return -1;
112374a4d8c2SCharles.Forsyth w = i.w0;
112474a4d8c2SCharles.Forsyth if((w&0xF3600000) == 0x41000000){ /* branch on coprocessor */
112574a4d8c2SCharles.Forsyth Conditional:
112674a4d8c2SCharles.Forsyth foll[0] = pc+8;
112774a4d8c2SCharles.Forsyth l = ((w&0xFFFF)<<2);
112874a4d8c2SCharles.Forsyth if(w & 0x8000)
112974a4d8c2SCharles.Forsyth l |= 0xFFFC0000;
113074a4d8c2SCharles.Forsyth foll[1] = pc+4 + l;
113174a4d8c2SCharles.Forsyth return 2;
113274a4d8c2SCharles.Forsyth }
113374a4d8c2SCharles.Forsyth
113474a4d8c2SCharles.Forsyth l = (w&0xFC000000)>>26;
113574a4d8c2SCharles.Forsyth switch(l){
113674a4d8c2SCharles.Forsyth case 0: /* SPECIAL */
113774a4d8c2SCharles.Forsyth if((w&0x3E) == 0x08){ /* JR, JALR */
113874a4d8c2SCharles.Forsyth sprint(buf, "R%ld", (w>>21)&0x1F);
113974a4d8c2SCharles.Forsyth foll[0] = (*rget)(map, buf);
114074a4d8c2SCharles.Forsyth return 1;
114174a4d8c2SCharles.Forsyth }
114274a4d8c2SCharles.Forsyth foll[0] = pc+i.size*4;
114374a4d8c2SCharles.Forsyth return 1;
114474a4d8c2SCharles.Forsyth case 0x30: /* Load-Linked followed by NOP, STC */
114574a4d8c2SCharles.Forsyth foll[0] = pc+12;
114674a4d8c2SCharles.Forsyth return 1;
114774a4d8c2SCharles.Forsyth case 1: /* BCOND */
114874a4d8c2SCharles.Forsyth case 4: /* BEQ */
114974a4d8c2SCharles.Forsyth case 20: /* BEQL */
115074a4d8c2SCharles.Forsyth case 5: /* BNE */
115174a4d8c2SCharles.Forsyth case 21: /* BNEL */
115274a4d8c2SCharles.Forsyth case 6: /* BLEZ */
115374a4d8c2SCharles.Forsyth case 22: /* BLEZL */
115474a4d8c2SCharles.Forsyth case 7: /* BGTZ */
115574a4d8c2SCharles.Forsyth case 23: /* BGTZL */
115674a4d8c2SCharles.Forsyth goto Conditional;
115774a4d8c2SCharles.Forsyth case 2: /* J */
115874a4d8c2SCharles.Forsyth case 3: /* JAL */
115974a4d8c2SCharles.Forsyth foll[0] = (pc&0xF0000000) | ((w&0x03FFFFFF)<<2);
116074a4d8c2SCharles.Forsyth return 1;
116174a4d8c2SCharles.Forsyth }
116274a4d8c2SCharles.Forsyth
116374a4d8c2SCharles.Forsyth foll[0] = pc+i.size*4;
116474a4d8c2SCharles.Forsyth return 1;
116574a4d8c2SCharles.Forsyth }
1166