xref: /plan9/sys/src/libmach/vcodas.c (revision eaba85aa6b158bdf68fdb77f770e3ba0899a8b5e)
1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include <mach.h>
5219b2ee8SDavid du Colombier 
6219b2ee8SDavid du Colombier 	/* mips native disassembler */
7219b2ee8SDavid du Colombier 
8219b2ee8SDavid du Colombier typedef struct {
94de34a7eSDavid du Colombier 	uvlong addr;			/* pc of instr */
10219b2ee8SDavid du Colombier 	uchar op;			/* bits 31-26 */
11219b2ee8SDavid du Colombier 	uchar rs;			/* bits 25-21 */
12219b2ee8SDavid du Colombier 	uchar rt;			/* bits 20-16 */
13219b2ee8SDavid du Colombier 	uchar rd;			/* bits 15-11 */
14219b2ee8SDavid du Colombier 	uchar sa;			/* bits 10-6 */
15219b2ee8SDavid du Colombier 	uchar function;			/* bits 5-0 */
16219b2ee8SDavid du Colombier 	long immediate;			/* bits 15-0 */
17219b2ee8SDavid du Colombier 	ulong cofun;			/* bits 24-0 */
18219b2ee8SDavid du Colombier 	ulong target;			/* bits 25-0 */
19219b2ee8SDavid du Colombier 	long w0;
20219b2ee8SDavid du Colombier 	char *curr;			/* current fill point */
21219b2ee8SDavid du Colombier 	char *end;			/* end of buffer */
22219b2ee8SDavid du Colombier 	char *err;
23219b2ee8SDavid du Colombier } Instr;
24219b2ee8SDavid du Colombier 
25219b2ee8SDavid du Colombier typedef struct {
26219b2ee8SDavid du Colombier 	char *mnemonic;
27219b2ee8SDavid du Colombier 	char *mipsco;
28219b2ee8SDavid du Colombier } Opcode;
29219b2ee8SDavid du Colombier 
30219b2ee8SDavid du Colombier static char mipscoload[] = "r%t,%l";
31219b2ee8SDavid du Colombier static char mipscoalui[] = "r%t,r%s,%i";
32219b2ee8SDavid du Colombier static char mipscoalu3op[] = "r%d,r%s,r%t";
33219b2ee8SDavid du Colombier static char mipscoboc[] = "r%s,r%t,%b";
34219b2ee8SDavid du Colombier static char mipscoboc0[] = "r%s,%b";
35219b2ee8SDavid du Colombier static char mipscorsrt[] = "r%s,r%t";
36219b2ee8SDavid du Colombier static char mipscorsi[] = "r%s,%i";
37219b2ee8SDavid du Colombier static char mipscoxxx[] = "%w";
38219b2ee8SDavid du Colombier static char mipscofp3[] = "f%a,f%d,f%t";	/* fd,fs,ft */
39219b2ee8SDavid du Colombier static char mipscofp2[] = "f%a,f%d";		/* fd,fs */
40219b2ee8SDavid du Colombier static char mipscofpc[] = "f%d,f%t";		/* fs,ft */
41219b2ee8SDavid du Colombier 
42219b2ee8SDavid du Colombier static Opcode opcodes[64] = {
43219b2ee8SDavid du Colombier 	0,		0,
44219b2ee8SDavid du Colombier 	0,		0,
45219b2ee8SDavid du Colombier 	"j",		"%j",
46219b2ee8SDavid du Colombier 	"jal",		"%j",
47219b2ee8SDavid du Colombier 	"beq",		mipscoboc,
48219b2ee8SDavid du Colombier 	"bne",		mipscoboc,
49219b2ee8SDavid du Colombier 	"blez",		mipscoboc0,
50219b2ee8SDavid du Colombier 	"bgtz",		mipscoboc0,
51219b2ee8SDavid du Colombier 	"addi",		mipscoalui,
52219b2ee8SDavid du Colombier 	"addiu",	mipscoalui,
53219b2ee8SDavid du Colombier 	"slti",		mipscoalui,
54219b2ee8SDavid du Colombier 	"sltiu",	mipscoalui,
55219b2ee8SDavid du Colombier 	"andi",		mipscoalui,
56219b2ee8SDavid du Colombier 	"ori",		mipscoalui,
57219b2ee8SDavid du Colombier 	"xori",		mipscoalui,
58219b2ee8SDavid du Colombier 	"lui",		"r%t,%u",
59219b2ee8SDavid du Colombier 	"cop0",		0,
60219b2ee8SDavid du Colombier 	"cop1",		0,
61219b2ee8SDavid du Colombier 	"cop2",		0,
62219b2ee8SDavid du Colombier 	"cop3",		0,
63219b2ee8SDavid du Colombier 	"beql",		mipscoboc,
64219b2ee8SDavid du Colombier 	"bnel",		mipscoboc,
65219b2ee8SDavid du Colombier 	"blezl",	mipscoboc0,
66219b2ee8SDavid du Colombier 	"bgtzl",	mipscoboc0,
67219b2ee8SDavid du Colombier 	"instr18",	mipscoxxx,
68219b2ee8SDavid du Colombier 	"instr19",	mipscoxxx,
69219b2ee8SDavid du Colombier 	"instr1A",	mipscoxxx,
70219b2ee8SDavid du Colombier 	"instr1B",	mipscoxxx,
71219b2ee8SDavid du Colombier 	"instr1C",	mipscoxxx,
72219b2ee8SDavid du Colombier 	"instr1D",	mipscoxxx,
73219b2ee8SDavid du Colombier 	"instr1E",	mipscoxxx,
74219b2ee8SDavid du Colombier 	"instr1F",	mipscoxxx,
75219b2ee8SDavid du Colombier 	"lb",		mipscoload,
76219b2ee8SDavid du Colombier 	"lh",		mipscoload,
77219b2ee8SDavid du Colombier 	"lwl",		mipscoload,
78219b2ee8SDavid du Colombier 	"lw",		mipscoload,
79219b2ee8SDavid du Colombier 	"lbu",		mipscoload,
80219b2ee8SDavid du Colombier 	"lhu",		mipscoload,
81219b2ee8SDavid du Colombier 	"lwr",		mipscoload,
82219b2ee8SDavid du Colombier 	"instr27",	mipscoxxx,
83219b2ee8SDavid du Colombier 	"sb",		mipscoload,
84219b2ee8SDavid du Colombier 	"sh",		mipscoload,
85219b2ee8SDavid du Colombier 	"swl",		mipscoload,
86219b2ee8SDavid du Colombier 	"sw",		mipscoload,
87219b2ee8SDavid du Colombier 	"instr2C",	mipscoxxx,
88219b2ee8SDavid du Colombier 	"instr2D",	mipscoxxx,
89219b2ee8SDavid du Colombier 	"swr",		mipscoload,
90219b2ee8SDavid du Colombier 	"cache",	"",
91219b2ee8SDavid du Colombier 	"ll",		mipscoload,
92219b2ee8SDavid du Colombier 	"lwc1",		mipscoload,
93219b2ee8SDavid du Colombier 	"lwc2",		mipscoload,
94219b2ee8SDavid du Colombier 	"lwc3",		mipscoload,
95219b2ee8SDavid du Colombier 	"instr34",	mipscoxxx,
96219b2ee8SDavid du Colombier 	"ld",		mipscoload,
97219b2ee8SDavid du Colombier 	"ld",		mipscoload,
98219b2ee8SDavid du Colombier 	"ld",		mipscoload,
99219b2ee8SDavid du Colombier 	"sc",		mipscoload,
100219b2ee8SDavid du Colombier 	"swc1",		mipscoload,
101219b2ee8SDavid du Colombier 	"swc2",		mipscoload,
102219b2ee8SDavid du Colombier 	"swc3",		mipscoload,
103219b2ee8SDavid du Colombier 	"instr3C",	mipscoxxx,
104219b2ee8SDavid du Colombier 	"sd",		mipscoload,
105219b2ee8SDavid du Colombier 	"sd",		mipscoload,
106219b2ee8SDavid du Colombier 	"sd",		mipscoload,
107219b2ee8SDavid du Colombier };
108219b2ee8SDavid du Colombier 
109219b2ee8SDavid du Colombier static Opcode sopcodes[64] = {
110219b2ee8SDavid du Colombier 	"sll",		"r%d,r%t,$%a",
111219b2ee8SDavid du Colombier 	"special01",	mipscoxxx,
112219b2ee8SDavid du Colombier 	"srl",		"r%d,r%t,$%a",
113219b2ee8SDavid du Colombier 	"sra",		"r%d,r%t,$%a",
114219b2ee8SDavid du Colombier 	"sllv",		"r%d,r%t,R%s",
115219b2ee8SDavid du Colombier 	"special05",	mipscoxxx,
116219b2ee8SDavid du Colombier 	"srlv",		"r%d,r%t,r%s",
117219b2ee8SDavid du Colombier 	"srav",		"r%d,r%t,r%s",
118219b2ee8SDavid du Colombier 	"jr",		"r%s",
119219b2ee8SDavid du Colombier 	"jalr",		"r%d,r%s",
120219b2ee8SDavid du Colombier 	"special0A",	mipscoxxx,
121219b2ee8SDavid du Colombier 	"special0B",	mipscoxxx,
122219b2ee8SDavid du Colombier 	"syscall",	"",
123219b2ee8SDavid du Colombier 	"break",	"",
124219b2ee8SDavid du Colombier 	"special0E",	mipscoxxx,
125219b2ee8SDavid du Colombier 	"sync",		"",
126219b2ee8SDavid du Colombier 	"mfhi",		"r%d",
127219b2ee8SDavid du Colombier 	"mthi",		"r%s",
128219b2ee8SDavid du Colombier 	"mflo",		"r%d",
129219b2ee8SDavid du Colombier 	"mtlo",		"r%s",
130219b2ee8SDavid du Colombier 	"special14",	mipscoxxx,
131219b2ee8SDavid du Colombier 	"special15",	mipscoxxx,
132219b2ee8SDavid du Colombier 	"special16",	mipscoxxx,
133219b2ee8SDavid du Colombier 	"special17",	mipscoxxx,
134219b2ee8SDavid du Colombier 	"mult",		mipscorsrt,
135219b2ee8SDavid du Colombier 	"multu",	mipscorsrt,
136219b2ee8SDavid du Colombier 	"div",		mipscorsrt,
137219b2ee8SDavid du Colombier 	"divu",		mipscorsrt,
138219b2ee8SDavid du Colombier 	"special1C",	mipscoxxx,
139219b2ee8SDavid du Colombier 	"special1D",	mipscoxxx,
140219b2ee8SDavid du Colombier 	"special1E",	mipscoxxx,
141219b2ee8SDavid du Colombier 	"special1F",	mipscoxxx,
142219b2ee8SDavid du Colombier 	"add",		mipscoalu3op,
143219b2ee8SDavid du Colombier 	"addu",		mipscoalu3op,
144219b2ee8SDavid du Colombier 	"sub",		mipscoalu3op,
145219b2ee8SDavid du Colombier 	"subu",		mipscoalu3op,
146219b2ee8SDavid du Colombier 	"and",		mipscoalu3op,
147219b2ee8SDavid du Colombier 	"or",		mipscoalu3op,
148219b2ee8SDavid du Colombier 	"xor",		mipscoalu3op,
149219b2ee8SDavid du Colombier 	"nor",		mipscoalu3op,
150219b2ee8SDavid du Colombier 	"special28",	mipscoxxx,
151219b2ee8SDavid du Colombier 	"special29",	mipscoxxx,
152219b2ee8SDavid du Colombier 	"slt",		mipscoalu3op,
153219b2ee8SDavid du Colombier 	"sltu",		mipscoalu3op,
154219b2ee8SDavid du Colombier 	"special2C",	mipscoxxx,
155219b2ee8SDavid du Colombier 	"special2D",	mipscoxxx,
156219b2ee8SDavid du Colombier 	"special2E",	mipscoxxx,
157219b2ee8SDavid du Colombier 	"special2F",	mipscoxxx,
158219b2ee8SDavid du Colombier 	"tge",		mipscorsrt,
159219b2ee8SDavid du Colombier 	"tgeu",		mipscorsrt,
160219b2ee8SDavid du Colombier 	"tlt",		mipscorsrt,
161219b2ee8SDavid du Colombier 	"tltu",		mipscorsrt,
162219b2ee8SDavid du Colombier 	"teq",		mipscorsrt,
163219b2ee8SDavid du Colombier 	"special35",	mipscoxxx,
164219b2ee8SDavid du Colombier 	"tne",		mipscorsrt,
165219b2ee8SDavid du Colombier 	"special37",	mipscoxxx,
166219b2ee8SDavid du Colombier 	"special38",	mipscoxxx,
167219b2ee8SDavid du Colombier 	"special39",	mipscoxxx,
168219b2ee8SDavid du Colombier 	"special3A",	mipscoxxx,
169219b2ee8SDavid du Colombier 	"special3B",	mipscoxxx,
170219b2ee8SDavid du Colombier 	"special3C",	mipscoxxx,
171219b2ee8SDavid du Colombier 	"special3D",	mipscoxxx,
172219b2ee8SDavid du Colombier 	"special3E",	mipscoxxx,
173219b2ee8SDavid du Colombier 	"special3F",	mipscoxxx,
174219b2ee8SDavid du Colombier };
175219b2ee8SDavid du Colombier 
176219b2ee8SDavid du Colombier static Opcode ropcodes[32] = {
177219b2ee8SDavid du Colombier 	"bltz",		mipscoboc0,
178219b2ee8SDavid du Colombier 	"bgez",		mipscoboc0,
179219b2ee8SDavid du Colombier 	"bltzl",	mipscoboc0,
180219b2ee8SDavid du Colombier 	"bgezl",	mipscoboc0,
181219b2ee8SDavid du Colombier 	"regimm04",	mipscoxxx,
182219b2ee8SDavid du Colombier 	"regimm05",	mipscoxxx,
183219b2ee8SDavid du Colombier 	"regimm06",	mipscoxxx,
184219b2ee8SDavid du Colombier 	"regimm07",	mipscoxxx,
185219b2ee8SDavid du Colombier 	"tgei",		mipscorsi,
186219b2ee8SDavid du Colombier 	"tgeiu",	mipscorsi,
187219b2ee8SDavid du Colombier 	"tlti",		mipscorsi,
188219b2ee8SDavid du Colombier 	"tltiu",	mipscorsi,
189219b2ee8SDavid du Colombier 	"teqi",		mipscorsi,
190219b2ee8SDavid du Colombier 	"regimm0D",	mipscoxxx,
191219b2ee8SDavid du Colombier 	"tnei",		mipscorsi,
192219b2ee8SDavid du Colombier 	"regimm0F",	mipscoxxx,
193219b2ee8SDavid du Colombier 	"bltzal",	mipscoboc0,
194219b2ee8SDavid du Colombier 	"bgezal",	mipscoboc0,
195219b2ee8SDavid du Colombier 	"bltzall",	mipscoboc0,
196219b2ee8SDavid du Colombier 	"bgezall",	mipscoboc0,
197219b2ee8SDavid du Colombier 	"regimm14",	mipscoxxx,
198219b2ee8SDavid du Colombier 	"regimm15",	mipscoxxx,
199219b2ee8SDavid du Colombier 	"regimm16",	mipscoxxx,
200219b2ee8SDavid du Colombier 	"regimm17",	mipscoxxx,
201219b2ee8SDavid du Colombier 	"regimm18",	mipscoxxx,
202219b2ee8SDavid du Colombier 	"regimm19",	mipscoxxx,
203219b2ee8SDavid du Colombier 	"regimm1A",	mipscoxxx,
204219b2ee8SDavid du Colombier 	"regimm1B",	mipscoxxx,
205219b2ee8SDavid du Colombier 	"regimm1C",	mipscoxxx,
206219b2ee8SDavid du Colombier 	"regimm1D",	mipscoxxx,
207219b2ee8SDavid du Colombier 	"regimm1E",	mipscoxxx,
208219b2ee8SDavid du Colombier 	"regimm1F",	mipscoxxx,
209219b2ee8SDavid du Colombier };
210219b2ee8SDavid du Colombier 
211219b2ee8SDavid du Colombier static Opcode fopcodes[64] = {
212219b2ee8SDavid du Colombier 	"add.%f",	mipscofp3,
213219b2ee8SDavid du Colombier 	"sub.%f",	mipscofp3,
214219b2ee8SDavid du Colombier 	"mul.%f",	mipscofp3,
215219b2ee8SDavid du Colombier 	"div.%f",	mipscofp3,
216219b2ee8SDavid du Colombier 	"sqrt.%f",	mipscofp2,
217219b2ee8SDavid du Colombier 	"abs.%f",	mipscofp2,
218219b2ee8SDavid du Colombier 	"mov.%f",	mipscofp2,
219219b2ee8SDavid du Colombier 	"neg.%f",	mipscofp2,
220219b2ee8SDavid du Colombier 	"finstr08",	mipscoxxx,
221219b2ee8SDavid du Colombier 	"finstr09",	mipscoxxx,
222219b2ee8SDavid du Colombier 	"finstr0A",	mipscoxxx,
223219b2ee8SDavid du Colombier 	"finstr0B",	mipscoxxx,
224219b2ee8SDavid du Colombier 	"round.w.%f",	mipscofp2,
225219b2ee8SDavid du Colombier 	"trunc.w%f",	mipscofp2,
226219b2ee8SDavid du Colombier 	"ceil.w%f",	mipscofp2,
227219b2ee8SDavid du Colombier 	"floor.w%f",	mipscofp2,
228219b2ee8SDavid du Colombier 	"finstr10",	mipscoxxx,
229219b2ee8SDavid du Colombier 	"finstr11",	mipscoxxx,
230219b2ee8SDavid du Colombier 	"finstr12",	mipscoxxx,
231219b2ee8SDavid du Colombier 	"finstr13",	mipscoxxx,
232219b2ee8SDavid du Colombier 	"finstr14",	mipscoxxx,
233219b2ee8SDavid du Colombier 	"finstr15",	mipscoxxx,
234219b2ee8SDavid du Colombier 	"finstr16",	mipscoxxx,
235219b2ee8SDavid du Colombier 	"finstr17",	mipscoxxx,
236219b2ee8SDavid du Colombier 	"finstr18",	mipscoxxx,
237219b2ee8SDavid du Colombier 	"finstr19",	mipscoxxx,
238219b2ee8SDavid du Colombier 	"finstr1A",	mipscoxxx,
239219b2ee8SDavid du Colombier 	"finstr1B",	mipscoxxx,
240219b2ee8SDavid du Colombier 	"finstr1C",	mipscoxxx,
241219b2ee8SDavid du Colombier 	"finstr1D",	mipscoxxx,
242219b2ee8SDavid du Colombier 	"finstr1E",	mipscoxxx,
243219b2ee8SDavid du Colombier 	"finstr1F",	mipscoxxx,
244219b2ee8SDavid du Colombier 	"cvt.s.%f",	mipscofp2,
245219b2ee8SDavid du Colombier 	"cvt.d.%f",	mipscofp2,
246219b2ee8SDavid du Colombier 	"cvt.e.%f",	mipscofp2,
247219b2ee8SDavid du Colombier 	"cvt.q.%f",	mipscofp2,
248219b2ee8SDavid du Colombier 	"cvt.w.%f",	mipscofp2,
249219b2ee8SDavid du Colombier 	"finstr25",	mipscoxxx,
250219b2ee8SDavid du Colombier 	"finstr26",	mipscoxxx,
251219b2ee8SDavid du Colombier 	"finstr27",	mipscoxxx,
252219b2ee8SDavid du Colombier 	"finstr28",	mipscoxxx,
253219b2ee8SDavid du Colombier 	"finstr29",	mipscoxxx,
254219b2ee8SDavid du Colombier 	"finstr2A",	mipscoxxx,
255219b2ee8SDavid du Colombier 	"finstr2B",	mipscoxxx,
256219b2ee8SDavid du Colombier 	"finstr2C",	mipscoxxx,
257219b2ee8SDavid du Colombier 	"finstr2D",	mipscoxxx,
258219b2ee8SDavid du Colombier 	"finstr2E",	mipscoxxx,
259219b2ee8SDavid du Colombier 	"finstr2F",	mipscoxxx,
260219b2ee8SDavid du Colombier 	"c.f.%f",	mipscofpc,
261219b2ee8SDavid du Colombier 	"c.un.%f",	mipscofpc,
262219b2ee8SDavid du Colombier 	"c.eq.%f",	mipscofpc,
263219b2ee8SDavid du Colombier 	"c.ueq.%f",	mipscofpc,
264219b2ee8SDavid du Colombier 	"c.olt.%f",	mipscofpc,
265219b2ee8SDavid du Colombier 	"c.ult.%f",	mipscofpc,
266219b2ee8SDavid du Colombier 	"c.ole.%f",	mipscofpc,
267219b2ee8SDavid du Colombier 	"c.ule.%f",	mipscofpc,
268219b2ee8SDavid du Colombier 	"c.sf.%f",	mipscofpc,
269219b2ee8SDavid du Colombier 	"c.ngle.%f",	mipscofpc,
270219b2ee8SDavid du Colombier 	"c.seq.%f",	mipscofpc,
271219b2ee8SDavid du Colombier 	"c.ngl.%f",	mipscofpc,
272219b2ee8SDavid du Colombier 	"c.lt.%f",	mipscofpc,
273219b2ee8SDavid du Colombier 	"c.nge.%f",	mipscofpc,
274219b2ee8SDavid du Colombier 	"c.le.%f",	mipscofpc,
275219b2ee8SDavid du Colombier 	"c.ngt.%f",	mipscofpc,
276219b2ee8SDavid du Colombier };
277219b2ee8SDavid du Colombier 
278219b2ee8SDavid du Colombier static char fsub[16] = {
279219b2ee8SDavid du Colombier 	's', 'd', 'e', 'q', 'w', '?', '?', '?',
280219b2ee8SDavid du Colombier 	'?', '?', '?', '?', '?', '?', '?', '?'
281219b2ee8SDavid du Colombier };
282219b2ee8SDavid du Colombier 
283219b2ee8SDavid du Colombier 
284219b2ee8SDavid du Colombier static int
mkinstr(Instr * i,Map * map,uvlong pc)2854de34a7eSDavid du Colombier mkinstr(Instr *i, Map *map, uvlong pc)
286219b2ee8SDavid du Colombier {
2874de34a7eSDavid du Colombier 	ulong w;
288219b2ee8SDavid du Colombier 
289219b2ee8SDavid du Colombier 	if (get4(map, pc, &w) < 0) {
290219b2ee8SDavid du Colombier 		werrstr("can't read instruction: %r");
291219b2ee8SDavid du Colombier 		return -1;
292219b2ee8SDavid du Colombier 	}
293219b2ee8SDavid du Colombier 	i->addr = pc;
294219b2ee8SDavid du Colombier 	i->op = (w >> 26) & 0x3F;
295219b2ee8SDavid du Colombier 	i->rs = (w >> 21) & 0x1F;
296219b2ee8SDavid du Colombier 	i->rt = (w >> 16) & 0x1F;
297219b2ee8SDavid du Colombier 	i->rd = (w >> 11) & 0x1F;
298219b2ee8SDavid du Colombier 	i->sa = (w >> 6) & 0x1F;
299219b2ee8SDavid du Colombier 	i->function = w & 0x3F;
300219b2ee8SDavid du Colombier 	i->immediate = w & 0x0000FFFF;
301219b2ee8SDavid du Colombier 	if (i->immediate & 0x8000)
302219b2ee8SDavid du Colombier 		i->immediate |= ~0x0000FFFF;
303219b2ee8SDavid du Colombier 	i->cofun = w & 0x01FFFFFF;
304219b2ee8SDavid du Colombier 	i->target = w & 0x03FFFFFF;
305219b2ee8SDavid du Colombier 	i->w0 = w;
306219b2ee8SDavid du Colombier 	return 1;
307219b2ee8SDavid du Colombier }
308219b2ee8SDavid du Colombier 
3091bd28109SDavid du Colombier #pragma	varargck	argpos	bprint		2
3101bd28109SDavid du Colombier 
311219b2ee8SDavid du Colombier static void
bprint(Instr * i,char * fmt,...)312219b2ee8SDavid du Colombier bprint(Instr *i, char *fmt, ...)
313219b2ee8SDavid du Colombier {
3147dd7cddfSDavid du Colombier 	va_list arg;
3157dd7cddfSDavid du Colombier 
3167dd7cddfSDavid du Colombier 	va_start(arg, fmt);
3179a747e4fSDavid du Colombier 	i->curr = vseprint(i->curr, i->end, fmt, arg);
3187dd7cddfSDavid du Colombier 	va_end(arg);
319219b2ee8SDavid du Colombier }
320219b2ee8SDavid du Colombier 
321219b2ee8SDavid du Colombier static void
format(char * mnemonic,Instr * i,char * f)322219b2ee8SDavid du Colombier format(char *mnemonic, Instr *i, char *f)
323219b2ee8SDavid du Colombier {
324219b2ee8SDavid du Colombier 	if (mnemonic)
325219b2ee8SDavid du Colombier 		format(0, i, mnemonic);
326219b2ee8SDavid du Colombier 	if (f == 0)
327219b2ee8SDavid du Colombier 		return;
328219b2ee8SDavid du Colombier 	if (i->curr < i->end)
329219b2ee8SDavid du Colombier 		*i->curr++ = '\t';
330219b2ee8SDavid du Colombier 	for ( ; *f && i->curr < i->end; f++) {
331219b2ee8SDavid du Colombier 		if (*f != '%') {
332219b2ee8SDavid du Colombier 			*i->curr++ = *f;
333219b2ee8SDavid du Colombier 			continue;
334219b2ee8SDavid du Colombier 		}
335219b2ee8SDavid du Colombier 		switch (*++f) {
336219b2ee8SDavid du Colombier 
337219b2ee8SDavid du Colombier 		case 's':
338219b2ee8SDavid du Colombier 			bprint(i, "%d", i->rs);
339219b2ee8SDavid du Colombier 			break;
340219b2ee8SDavid du Colombier 
341219b2ee8SDavid du Colombier 		case 't':
342219b2ee8SDavid du Colombier 			bprint(i, "%d", i->rt);
343219b2ee8SDavid du Colombier 			break;
344219b2ee8SDavid du Colombier 
345219b2ee8SDavid du Colombier 		case 'd':
346219b2ee8SDavid du Colombier 			bprint(i, "%d", i->rd);
347219b2ee8SDavid du Colombier 			break;
348219b2ee8SDavid du Colombier 
349219b2ee8SDavid du Colombier 		case 'a':
350219b2ee8SDavid du Colombier 			bprint(i, "%d", i->sa);
351219b2ee8SDavid du Colombier 			break;
352219b2ee8SDavid du Colombier 
353219b2ee8SDavid du Colombier 		case 'l':
354219b2ee8SDavid du Colombier 			if (i->rs == 30) {
355219b2ee8SDavid du Colombier 				i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
356219b2ee8SDavid du Colombier 				bprint(i, "(SB)");
357219b2ee8SDavid du Colombier 			} else
358219b2ee8SDavid du Colombier 				bprint(i, "%lx(r%d)", i->immediate, i->rs);
359219b2ee8SDavid du Colombier 			break;
360219b2ee8SDavid du Colombier 
361219b2ee8SDavid du Colombier 		case 'i':
362219b2ee8SDavid du Colombier 			bprint(i, "$%lx", i->immediate);
363219b2ee8SDavid du Colombier 			break;
364219b2ee8SDavid du Colombier 
365219b2ee8SDavid du Colombier 		case 'u':
366219b2ee8SDavid du Colombier 			*i->curr++ = '$';
367219b2ee8SDavid du Colombier 			i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
368219b2ee8SDavid du Colombier 			bprint(i, "(SB)");
369219b2ee8SDavid du Colombier 			break;
370219b2ee8SDavid du Colombier 
371219b2ee8SDavid du Colombier 		case 'j':
372219b2ee8SDavid du Colombier 			i->curr += symoff(i->curr, i->end-i->curr,
373219b2ee8SDavid du Colombier 				(i->target<<2)|(i->addr & 0xF0000000), CANY);
374219b2ee8SDavid du Colombier 			bprint(i, "(SB)");
375219b2ee8SDavid du Colombier 			break;
376219b2ee8SDavid du Colombier 
377219b2ee8SDavid du Colombier 		case 'b':
378219b2ee8SDavid du Colombier 			i->curr += symoff(i->curr, i->end-i->curr,
379219b2ee8SDavid du Colombier 				(i->immediate<<2)+i->addr+4, CANY);
380219b2ee8SDavid du Colombier 			break;
381219b2ee8SDavid du Colombier 
382219b2ee8SDavid du Colombier 		case 'c':
383219b2ee8SDavid du Colombier 			bprint(i, "%lux", i->cofun);
384219b2ee8SDavid du Colombier 			break;
385219b2ee8SDavid du Colombier 
386219b2ee8SDavid du Colombier 		case 'w':
387219b2ee8SDavid du Colombier 			bprint(i, "[%lux]", i->w0);
388219b2ee8SDavid du Colombier 			break;
389219b2ee8SDavid du Colombier 
390219b2ee8SDavid du Colombier 		case 'f':
391219b2ee8SDavid du Colombier 			*i->curr++ = fsub[i->rs & 0x0F];
392219b2ee8SDavid du Colombier 			break;
393219b2ee8SDavid du Colombier 
394219b2ee8SDavid du Colombier 		case '\0':
395219b2ee8SDavid du Colombier 			*i->curr++ = '%';
396219b2ee8SDavid du Colombier 			return;
397219b2ee8SDavid du Colombier 
398219b2ee8SDavid du Colombier 		default:
399219b2ee8SDavid du Colombier 			bprint(i, "%%%c", *f);
400219b2ee8SDavid du Colombier 			break;
401219b2ee8SDavid du Colombier 		}
402219b2ee8SDavid du Colombier 	}
403219b2ee8SDavid du Colombier }
404219b2ee8SDavid du Colombier 
405219b2ee8SDavid du Colombier static void
copz(int cop,Instr * i)406219b2ee8SDavid du Colombier copz(int cop, Instr *i)
407219b2ee8SDavid du Colombier {
408219b2ee8SDavid du Colombier 	char *f, *m, buf[16];
409219b2ee8SDavid du Colombier 
410219b2ee8SDavid du Colombier 	m = buf;
411219b2ee8SDavid du Colombier 	f = "%t,%d";
412219b2ee8SDavid du Colombier 	switch (i->rs) {
413219b2ee8SDavid du Colombier 
414219b2ee8SDavid du Colombier 	case 0:
415219b2ee8SDavid du Colombier 		sprint(buf, "mfc%d", cop);
416219b2ee8SDavid du Colombier 		break;
417219b2ee8SDavid du Colombier 
418219b2ee8SDavid du Colombier 	case 2:
419219b2ee8SDavid du Colombier 		sprint(buf, "cfc%d", cop);
420219b2ee8SDavid du Colombier 		break;
421219b2ee8SDavid du Colombier 
422219b2ee8SDavid du Colombier 	case 4:
423219b2ee8SDavid du Colombier 		sprint(buf, "mtc%d", cop);
424219b2ee8SDavid du Colombier 		break;
425219b2ee8SDavid du Colombier 
426219b2ee8SDavid du Colombier 	case 6:
427219b2ee8SDavid du Colombier 		sprint(buf, "ctc%d", cop);
428219b2ee8SDavid du Colombier 		break;
429219b2ee8SDavid du Colombier 
430219b2ee8SDavid du Colombier 	case 8:
431219b2ee8SDavid du Colombier 		f = "%b";
432219b2ee8SDavid du Colombier 		switch (i->rt) {
433219b2ee8SDavid du Colombier 
434219b2ee8SDavid du Colombier 		case 0:
435219b2ee8SDavid du Colombier 			sprint(buf, "bc%df", cop);
436219b2ee8SDavid du Colombier 			break;
437219b2ee8SDavid du Colombier 
438219b2ee8SDavid du Colombier 		case 1:
439219b2ee8SDavid du Colombier 			sprint(buf, "bc%dt", cop);
440219b2ee8SDavid du Colombier 			break;
441219b2ee8SDavid du Colombier 
442219b2ee8SDavid du Colombier 		case 2:
443219b2ee8SDavid du Colombier 			sprint(buf, "bc%dfl", cop);
444219b2ee8SDavid du Colombier 			break;
445219b2ee8SDavid du Colombier 
446219b2ee8SDavid du Colombier 		case 3:
447219b2ee8SDavid du Colombier 			sprint(buf, "bc%dtl", cop);
448219b2ee8SDavid du Colombier 			break;
449219b2ee8SDavid du Colombier 
450219b2ee8SDavid du Colombier 		default:
451219b2ee8SDavid du Colombier 			sprint(buf, "cop%d", cop);
452219b2ee8SDavid du Colombier 			f = mipscoxxx;
453219b2ee8SDavid du Colombier 			break;
454219b2ee8SDavid du Colombier 		}
455219b2ee8SDavid du Colombier 		break;
456219b2ee8SDavid du Colombier 
457219b2ee8SDavid du Colombier 	default:
458219b2ee8SDavid du Colombier 		sprint(buf, "cop%d", cop);
459219b2ee8SDavid du Colombier 		if (i->rs & 0x10)
460219b2ee8SDavid du Colombier 			f = "function %c";
461219b2ee8SDavid du Colombier 		else
462219b2ee8SDavid du Colombier 			f = mipscoxxx;
463219b2ee8SDavid du Colombier 		break;
464219b2ee8SDavid du Colombier 	}
465219b2ee8SDavid du Colombier 	format(m, i, f);
466219b2ee8SDavid du Colombier }
467219b2ee8SDavid du Colombier 
468219b2ee8SDavid du Colombier static void
cop0(Instr * i)469219b2ee8SDavid du Colombier cop0(Instr *i)
470219b2ee8SDavid du Colombier {
471219b2ee8SDavid du Colombier 	char *m = 0;
472219b2ee8SDavid du Colombier 
473219b2ee8SDavid du Colombier 	if (i->rs >= 0x10) {
474219b2ee8SDavid du Colombier 		switch (i->cofun) {
475219b2ee8SDavid du Colombier 
476219b2ee8SDavid du Colombier 		case 1:
477219b2ee8SDavid du Colombier 			m = "tlbr";
478219b2ee8SDavid du Colombier 			break;
479219b2ee8SDavid du Colombier 
480219b2ee8SDavid du Colombier 		case 2:
481219b2ee8SDavid du Colombier 			m = "tlbwi";
482219b2ee8SDavid du Colombier 			break;
483219b2ee8SDavid du Colombier 
484219b2ee8SDavid du Colombier 		case 6:
485219b2ee8SDavid du Colombier 			m = "tlbwr";
486219b2ee8SDavid du Colombier 			break;
487219b2ee8SDavid du Colombier 
488219b2ee8SDavid du Colombier 		case 8:
489219b2ee8SDavid du Colombier 			m = "tlbp";
490219b2ee8SDavid du Colombier 			break;
491219b2ee8SDavid du Colombier 
492219b2ee8SDavid du Colombier 		case 16:
493219b2ee8SDavid du Colombier 			m = "rfe";
494219b2ee8SDavid du Colombier 			break;
495219b2ee8SDavid du Colombier 
496*eaba85aaSDavid du Colombier 		case 24:
497219b2ee8SDavid du Colombier 			m = "eret";
498219b2ee8SDavid du Colombier 			break;
499*eaba85aaSDavid du Colombier 
500*eaba85aaSDavid du Colombier 		case 32:
501*eaba85aaSDavid du Colombier 			m = "wait";
502*eaba85aaSDavid du Colombier 			break;
503219b2ee8SDavid du Colombier 		}
504219b2ee8SDavid du Colombier 		if (m) {
505219b2ee8SDavid du Colombier 			format(m, i, 0);
506219b2ee8SDavid du Colombier 			if (i->curr < i->end)
507219b2ee8SDavid du Colombier 				*i->curr++ = 0;
508219b2ee8SDavid du Colombier 			return;
509219b2ee8SDavid du Colombier 		}
510219b2ee8SDavid du Colombier 	}
511219b2ee8SDavid du Colombier 	copz(0, i);
512219b2ee8SDavid du Colombier }
513219b2ee8SDavid du Colombier 
514219b2ee8SDavid du Colombier int
_mipscoinst(Map * map,uvlong pc,char * buf,int n)5154de34a7eSDavid du Colombier _mipscoinst(Map *map, uvlong pc, char *buf, int n)
516219b2ee8SDavid du Colombier {
517219b2ee8SDavid du Colombier 	Instr i;
518219b2ee8SDavid du Colombier 	Opcode *o;
519219b2ee8SDavid du Colombier 	uchar op;
520219b2ee8SDavid du Colombier 
521219b2ee8SDavid du Colombier 	i.curr = buf;
522219b2ee8SDavid du Colombier 	i.end = buf+n-1;
523219b2ee8SDavid du Colombier 	if (mkinstr(&i, map, pc) < 0)
524219b2ee8SDavid du Colombier 		return -1;
525219b2ee8SDavid du Colombier 	switch (i.op) {
526219b2ee8SDavid du Colombier 
527219b2ee8SDavid du Colombier 	case 0x00:					/* SPECIAL */
528219b2ee8SDavid du Colombier 		o = sopcodes;
529219b2ee8SDavid du Colombier 		op = i.function;
530219b2ee8SDavid du Colombier 		break;
531219b2ee8SDavid du Colombier 
532219b2ee8SDavid du Colombier 	case 0x01:					/* REGIMM */
533219b2ee8SDavid du Colombier 		o = ropcodes;
534219b2ee8SDavid du Colombier 		op = i.rt;
535219b2ee8SDavid du Colombier 		break;
536219b2ee8SDavid du Colombier 
537219b2ee8SDavid du Colombier 	case 0x10:					/* COP0 */
538219b2ee8SDavid du Colombier 		cop0(&i);
539219b2ee8SDavid du Colombier 		return 4;
540219b2ee8SDavid du Colombier 
541219b2ee8SDavid du Colombier 	case 0x11:					/* COP1 */
542219b2ee8SDavid du Colombier 		if (i.rs & 0x10) {
543219b2ee8SDavid du Colombier 			o = fopcodes;
544219b2ee8SDavid du Colombier 			op = i.function;
545219b2ee8SDavid du Colombier 			break;
546219b2ee8SDavid du Colombier 		}
547219b2ee8SDavid du Colombier 		/*FALLTHROUGH*/
548219b2ee8SDavid du Colombier 	case 0x12:					/* COP2 */
549219b2ee8SDavid du Colombier 	case 0x13:					/* COP3 */
550219b2ee8SDavid du Colombier 		copz(i.op-0x10, &i);
551219b2ee8SDavid du Colombier 		return 4;
552219b2ee8SDavid du Colombier 
553219b2ee8SDavid du Colombier 	default:
554219b2ee8SDavid du Colombier 		o = opcodes;
555219b2ee8SDavid du Colombier 		op = i.op;
556219b2ee8SDavid du Colombier 		break;
557219b2ee8SDavid du Colombier 	}
558219b2ee8SDavid du Colombier 	format(o[op].mnemonic, &i, o[op].mipsco);
559219b2ee8SDavid du Colombier 	return 4;
560219b2ee8SDavid du Colombier }
561