6 /* mips native disassembler */
9 uvlong addr; /* pc of instr */
10 uchar op; /* bits 31-26 */
11 uchar rs; /* bits 25-21 */
12 uchar rt; /* bits 20-16 */
13 uchar rd; /* bits 15-11 */
14 uchar sa; /* bits 10-6 */
15 uchar function; /* bits 5-0 */
16 long immediate; /* bits 15-0 */
17 ulong cofun; /* bits 24-0 */
18 ulong target; /* bits 25-0 */
20 char *curr; /* current fill point */
21 char *end; /* end of buffer */
30 static char mipscoload[] = "r%t,%l";
31 static char mipscoalui[] = "r%t,r%s,%i";
32 static char mipscoalu3op[] = "r%d,r%s,r%t";
33 static char mipscoboc[] = "r%s,r%t,%b";
34 static char mipscoboc0[] = "r%s,%b";
35 static char mipscorsrt[] = "r%s,r%t";
36 static char mipscorsi[] = "r%s,%i";
37 static char mipscoxxx[] = "%w";
38 static char mipscofp3[] = "f%a,f%d,f%t"; /* fd,fs,ft */
39 static char mipscofp2[] = "f%a,f%d"; /* fd,fs */
40 static char mipscofpc[] = "f%d,f%t"; /* fs,ft */
42 static Opcode opcodes[64] = {
103 "instr3C", mipscoxxx,
109 static Opcode sopcodes[64] = {
110 "sll", "r%d,r%t,$%a",
111 "special01", mipscoxxx,
112 "srl", "r%d,r%t,$%a",
113 "sra", "r%d,r%t,$%a",
114 "sllv", "r%d,r%t,R%s",
115 "special05", mipscoxxx,
116 "srlv", "r%d,r%t,r%s",
117 "srav", "r%d,r%t,r%s",
120 "special0A", mipscoxxx,
121 "special0B", mipscoxxx,
124 "special0E", mipscoxxx,
130 "special14", mipscoxxx,
131 "special15", mipscoxxx,
132 "special16", mipscoxxx,
133 "special17", mipscoxxx,
138 "special1C", mipscoxxx,
139 "special1D", mipscoxxx,
140 "special1E", mipscoxxx,
141 "special1F", mipscoxxx,
143 "addu", mipscoalu3op,
145 "subu", mipscoalu3op,
150 "special28", mipscoxxx,
151 "special29", mipscoxxx,
153 "sltu", mipscoalu3op,
154 "special2C", mipscoxxx,
155 "special2D", mipscoxxx,
156 "special2E", mipscoxxx,
157 "special2F", mipscoxxx,
163 "special35", mipscoxxx,
165 "special37", mipscoxxx,
166 "special38", mipscoxxx,
167 "special39", mipscoxxx,
168 "special3A", mipscoxxx,
169 "special3B", mipscoxxx,
170 "special3C", mipscoxxx,
171 "special3D", mipscoxxx,
172 "special3E", mipscoxxx,
173 "special3F", mipscoxxx,
176 static Opcode ropcodes[32] = {
181 "regimm04", mipscoxxx,
182 "regimm05", mipscoxxx,
183 "regimm06", mipscoxxx,
184 "regimm07", mipscoxxx,
190 "regimm0D", mipscoxxx,
192 "regimm0F", mipscoxxx,
193 "bltzal", mipscoboc0,
194 "bgezal", mipscoboc0,
195 "bltzall", mipscoboc0,
196 "bgezall", mipscoboc0,
197 "regimm14", mipscoxxx,
198 "regimm15", mipscoxxx,
199 "regimm16", mipscoxxx,
200 "regimm17", mipscoxxx,
201 "regimm18", mipscoxxx,
202 "regimm19", mipscoxxx,
203 "regimm1A", mipscoxxx,
204 "regimm1B", mipscoxxx,
205 "regimm1C", mipscoxxx,
206 "regimm1D", mipscoxxx,
207 "regimm1E", mipscoxxx,
208 "regimm1F", mipscoxxx,
211 static Opcode fopcodes[64] = {
216 "sqrt.%f", mipscofp2,
220 "finstr08", mipscoxxx,
221 "finstr09", mipscoxxx,
222 "finstr0A", mipscoxxx,
223 "finstr0B", mipscoxxx,
224 "round.w.%f", mipscofp2,
225 "trunc.w%f", mipscofp2,
226 "ceil.w%f", mipscofp2,
227 "floor.w%f", mipscofp2,
228 "finstr10", mipscoxxx,
229 "finstr11", mipscoxxx,
230 "finstr12", mipscoxxx,
231 "finstr13", mipscoxxx,
232 "finstr14", mipscoxxx,
233 "finstr15", mipscoxxx,
234 "finstr16", mipscoxxx,
235 "finstr17", mipscoxxx,
236 "finstr18", mipscoxxx,
237 "finstr19", mipscoxxx,
238 "finstr1A", mipscoxxx,
239 "finstr1B", mipscoxxx,
240 "finstr1C", mipscoxxx,
241 "finstr1D", mipscoxxx,
242 "finstr1E", mipscoxxx,
243 "finstr1F", mipscoxxx,
244 "cvt.s.%f", mipscofp2,
245 "cvt.d.%f", mipscofp2,
246 "cvt.e.%f", mipscofp2,
247 "cvt.q.%f", mipscofp2,
248 "cvt.w.%f", mipscofp2,
249 "finstr25", mipscoxxx,
250 "finstr26", mipscoxxx,
251 "finstr27", mipscoxxx,
252 "finstr28", mipscoxxx,
253 "finstr29", mipscoxxx,
254 "finstr2A", mipscoxxx,
255 "finstr2B", mipscoxxx,
256 "finstr2C", mipscoxxx,
257 "finstr2D", mipscoxxx,
258 "finstr2E", mipscoxxx,
259 "finstr2F", mipscoxxx,
261 "c.un.%f", mipscofpc,
262 "c.eq.%f", mipscofpc,
263 "c.ueq.%f", mipscofpc,
264 "c.olt.%f", mipscofpc,
265 "c.ult.%f", mipscofpc,
266 "c.ole.%f", mipscofpc,
267 "c.ule.%f", mipscofpc,
268 "c.sf.%f", mipscofpc,
269 "c.ngle.%f", mipscofpc,
270 "c.seq.%f", mipscofpc,
271 "c.ngl.%f", mipscofpc,
272 "c.lt.%f", mipscofpc,
273 "c.nge.%f", mipscofpc,
274 "c.le.%f", mipscofpc,
275 "c.ngt.%f", mipscofpc,
278 static char fsub[16] = {
279 's', 'd', 'e', 'q', 'w', '?', '?', '?',
280 '?', '?', '?', '?', '?', '?', '?', '?'
285 mkinstr(Instr *i, Map *map, uvlong pc)
289 if (get4(map, pc, &w) < 0) {
290 werrstr("can't read instruction: %r");
294 i->op = (w >> 26) & 0x3F;
295 i->rs = (w >> 21) & 0x1F;
296 i->rt = (w >> 16) & 0x1F;
297 i->rd = (w >> 11) & 0x1F;
298 i->sa = (w >> 6) & 0x1F;
299 i->function = w & 0x3F;
300 i->immediate = w & 0x0000FFFF;
301 if (i->immediate & 0x8000)
302 i->immediate |= ~0x0000FFFF;
303 i->cofun = w & 0x01FFFFFF;
304 i->target = w & 0x03FFFFFF;
309 #pragma varargck argpos bprint 2
312 bprint(Instr *i, char *fmt, ...)
317 i->curr = vseprint(i->curr, i->end, fmt, arg);
322 format(char *mnemonic, Instr *i, char *f)
325 format(0, i, mnemonic);
328 if (i->curr < i->end)
330 for ( ; *f && i->curr < i->end; f++) {
338 bprint(i, "%d", i->rs);
342 bprint(i, "%d", i->rt);
346 bprint(i, "%d", i->rd);
350 bprint(i, "%d", i->sa);
355 i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
358 bprint(i, "%lx(r%d)", i->immediate, i->rs);
362 bprint(i, "$%lx", i->immediate);
367 i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
372 i->curr += symoff(i->curr, i->end-i->curr,
373 (i->target<<2)|(i->addr & 0xF0000000), CANY);
378 i->curr += symoff(i->curr, i->end-i->curr,
379 (i->immediate<<2)+i->addr+4, CANY);
383 bprint(i, "%lux", i->cofun);
387 bprint(i, "[%lux]", i->w0);
391 *i->curr++ = fsub[i->rs & 0x0F];
399 bprint(i, "%%%c", *f);
406 copz(int cop, Instr *i)
408 char *f, *m, buf[16];
415 sprint(buf, "mfc%d", cop);
419 sprint(buf, "cfc%d", cop);
423 sprint(buf, "mtc%d", cop);
427 sprint(buf, "ctc%d", cop);
435 sprint(buf, "bc%df", cop);
439 sprint(buf, "bc%dt", cop);
443 sprint(buf, "bc%dfl", cop);
447 sprint(buf, "bc%dtl", cop);
451 sprint(buf, "cop%d", cop);
458 sprint(buf, "cop%d", cop);
506 if (i->curr < i->end)
515 _mipscoinst(Map *map, uvlong pc, char *buf, int n)
523 if (mkinstr(&i, map, pc) < 0)
527 case 0x00: /* SPECIAL */
532 case 0x01: /* REGIMM */
537 case 0x10: /* COP0 */
541 case 0x11: /* COP1 */
548 case 0x12: /* COP2 */
549 case 0x13: /* COP3 */
558 format(o[op].mnemonic, &i, o[op].mipsco);