xref: /inferno-os/libinterp/das-mips.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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