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