|
|
1.1 root 1: #include <u.h>
2: #include <libc.h>
3: #include <bio.h>
4: #include <mach.h>
5:
6: /* mips native disassembler */
7:
8: typedef struct {
9: long 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 */
19: long w0;
20: char *curr; /* current fill point */
21: char *end; /* end of buffer */
22: char *err;
23: } Instr;
24:
25: typedef struct {
26: char *mnemonic;
27: char *mipsco;
28: } Opcode;
29:
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 */
41:
42: static Opcode opcodes[64] = {
43: 0, 0,
44: 0, 0,
45: "j", "%j",
46: "jal", "%j",
47: "beq", mipscoboc,
48: "bne", mipscoboc,
49: "blez", mipscoboc0,
50: "bgtz", mipscoboc0,
51: "addi", mipscoalui,
52: "addiu", mipscoalui,
53: "slti", mipscoalui,
54: "sltiu", mipscoalui,
55: "andi", mipscoalui,
56: "ori", mipscoalui,
57: "xori", mipscoalui,
58: "lui", "r%t,%u",
59: "cop0", 0,
60: "cop1", 0,
61: "cop2", 0,
62: "cop3", 0,
63: "beql", mipscoboc,
64: "bnel", mipscoboc,
65: "blezl", mipscoboc0,
66: "bgtzl", mipscoboc0,
67: "instr18", mipscoxxx,
68: "instr19", mipscoxxx,
69: "instr1A", mipscoxxx,
70: "instr1B", mipscoxxx,
71: "instr1C", mipscoxxx,
72: "instr1D", mipscoxxx,
73: "instr1E", mipscoxxx,
74: "instr1F", mipscoxxx,
75: "lb", mipscoload,
76: "lh", mipscoload,
77: "lwl", mipscoload,
78: "lw", mipscoload,
79: "lbu", mipscoload,
80: "lhu", mipscoload,
81: "lwr", mipscoload,
82: "instr27", mipscoxxx,
83: "sb", mipscoload,
84: "sh", mipscoload,
85: "swl", mipscoload,
86: "sw", mipscoload,
87: "instr2C", mipscoxxx,
88: "instr2D", mipscoxxx,
89: "swr", mipscoload,
90: "cache", "",
91: "ll", mipscoload,
92: "lwc1", mipscoload,
93: "lwc2", mipscoload,
94: "lwc3", mipscoload,
95: "instr34", mipscoxxx,
96: "ld", mipscoload,
97: "ld", mipscoload,
98: "ld", mipscoload,
99: "sc", mipscoload,
100: "swc1", mipscoload,
101: "swc2", mipscoload,
102: "swc3", mipscoload,
103: "instr3C", mipscoxxx,
104: "sd", mipscoload,
105: "sd", mipscoload,
106: "sd", mipscoload,
107: };
108:
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",
118: "jr", "r%s",
119: "jalr", "r%d,r%s",
120: "special0A", mipscoxxx,
121: "special0B", mipscoxxx,
122: "syscall", "",
123: "break", "",
124: "special0E", mipscoxxx,
125: "sync", "",
126: "mfhi", "r%d",
127: "mthi", "r%s",
128: "mflo", "r%d",
129: "mtlo", "r%s",
130: "special14", mipscoxxx,
131: "special15", mipscoxxx,
132: "special16", mipscoxxx,
133: "special17", mipscoxxx,
134: "mult", mipscorsrt,
135: "multu", mipscorsrt,
136: "div", mipscorsrt,
137: "divu", mipscorsrt,
138: "special1C", mipscoxxx,
139: "special1D", mipscoxxx,
140: "special1E", mipscoxxx,
141: "special1F", mipscoxxx,
142: "add", mipscoalu3op,
143: "addu", mipscoalu3op,
144: "sub", mipscoalu3op,
145: "subu", mipscoalu3op,
146: "and", mipscoalu3op,
147: "or", mipscoalu3op,
148: "xor", mipscoalu3op,
149: "nor", mipscoalu3op,
150: "special28", mipscoxxx,
151: "special29", mipscoxxx,
152: "slt", mipscoalu3op,
153: "sltu", mipscoalu3op,
154: "special2C", mipscoxxx,
155: "special2D", mipscoxxx,
156: "special2E", mipscoxxx,
157: "special2F", mipscoxxx,
158: "tge", mipscorsrt,
159: "tgeu", mipscorsrt,
160: "tlt", mipscorsrt,
161: "tltu", mipscorsrt,
162: "teq", mipscorsrt,
163: "special35", mipscoxxx,
164: "tne", mipscorsrt,
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,
174: };
175:
176: static Opcode ropcodes[32] = {
177: "bltz", mipscoboc0,
178: "bgez", mipscoboc0,
179: "bltzl", mipscoboc0,
180: "bgezl", mipscoboc0,
181: "regimm04", mipscoxxx,
182: "regimm05", mipscoxxx,
183: "regimm06", mipscoxxx,
184: "regimm07", mipscoxxx,
185: "tgei", mipscorsi,
186: "tgeiu", mipscorsi,
187: "tlti", mipscorsi,
188: "tltiu", mipscorsi,
189: "teqi", mipscorsi,
190: "regimm0D", mipscoxxx,
191: "tnei", mipscorsi,
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,
209: };
210:
211: static Opcode fopcodes[64] = {
212: "add.%f", mipscofp3,
213: "sub.%f", mipscofp3,
214: "mul.%f", mipscofp3,
215: "div.%f", mipscofp3,
216: "sqrt.%f", mipscofp2,
217: "abs.%f", mipscofp2,
218: "mov.%f", mipscofp2,
219: "neg.%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,
260: "c.f.%f", mipscofpc,
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,
276: };
277:
278: static char fsub[16] = {
279: 's', 'd', 'e', 'q', 'w', '?', '?', '?',
280: '?', '?', '?', '?', '?', '?', '?', '?'
281: };
282:
283:
284: static int
285: mkinstr(Instr *i, Map *map, ulong pc)
286: {
287: long w;
288:
289: if (get4(map, pc, &w) < 0) {
290: werrstr("can't read instruction: %r");
291: return -1;
292: }
293: i->addr = pc;
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;
305: i->w0 = w;
306: return 1;
307: }
308:
309: static void
310: bprint(Instr *i, char *fmt, ...)
311: {
312: i->curr = doprint(i->curr, i->end, fmt, (&fmt+1));
313: }
314:
315: static void
316: format(char *mnemonic, Instr *i, char *f)
317: {
318: if (mnemonic)
319: format(0, i, mnemonic);
320: if (f == 0)
321: return;
322: if (i->curr < i->end)
323: *i->curr++ = '\t';
324: for ( ; *f && i->curr < i->end; f++) {
325: if (*f != '%') {
326: *i->curr++ = *f;
327: continue;
328: }
329: switch (*++f) {
330:
331: case 's':
332: bprint(i, "%d", i->rs);
333: break;
334:
335: case 't':
336: bprint(i, "%d", i->rt);
337: break;
338:
339: case 'd':
340: bprint(i, "%d", i->rd);
341: break;
342:
343: case 'a':
344: bprint(i, "%d", i->sa);
345: break;
346:
347: case 'l':
348: if (i->rs == 30) {
349: i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
350: bprint(i, "(SB)");
351: } else
352: bprint(i, "%lx(r%d)", i->immediate, i->rs);
353: break;
354:
355: case 'i':
356: bprint(i, "$%lx", i->immediate);
357: break;
358:
359: case 'u':
360: *i->curr++ = '$';
361: i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
362: bprint(i, "(SB)");
363: break;
364:
365: case 'j':
366: i->curr += symoff(i->curr, i->end-i->curr,
367: (i->target<<2)|(i->addr & 0xF0000000), CANY);
368: bprint(i, "(SB)");
369: break;
370:
371: case 'b':
372: i->curr += symoff(i->curr, i->end-i->curr,
373: (i->immediate<<2)+i->addr+4, CANY);
374: break;
375:
376: case 'c':
377: bprint(i, "%lux", i->cofun);
378: break;
379:
380: case 'w':
381: bprint(i, "[%lux]", i->w0);
382: break;
383:
384: case 'f':
385: *i->curr++ = fsub[i->rs & 0x0F];
386: break;
387:
388: case '\0':
389: *i->curr++ = '%';
390: return;
391:
392: default:
393: bprint(i, "%%%c", *f);
394: break;
395: }
396: }
397: }
398:
399: static void
400: copz(int cop, Instr *i)
401: {
402: char *f, *m, buf[16];
403:
404: m = buf;
405: f = "%t,%d";
406: switch (i->rs) {
407:
408: case 0:
409: sprint(buf, "mfc%d", cop);
410: break;
411:
412: case 2:
413: sprint(buf, "cfc%d", cop);
414: break;
415:
416: case 4:
417: sprint(buf, "mtc%d", cop);
418: break;
419:
420: case 6:
421: sprint(buf, "ctc%d", cop);
422: break;
423:
424: case 8:
425: f = "%b";
426: switch (i->rt) {
427:
428: case 0:
429: sprint(buf, "bc%df", cop);
430: break;
431:
432: case 1:
433: sprint(buf, "bc%dt", cop);
434: break;
435:
436: case 2:
437: sprint(buf, "bc%dfl", cop);
438: break;
439:
440: case 3:
441: sprint(buf, "bc%dtl", cop);
442: break;
443:
444: default:
445: sprint(buf, "cop%d", cop);
446: f = mipscoxxx;
447: break;
448: }
449: break;
450:
451: default:
452: sprint(buf, "cop%d", cop);
453: if (i->rs & 0x10)
454: f = "function %c";
455: else
456: f = mipscoxxx;
457: break;
458: }
459: format(m, i, f);
460: }
461:
462: static void
463: cop0(Instr *i)
464: {
465: char *m = 0;
466:
467: if (i->rs >= 0x10) {
468: switch (i->cofun) {
469:
470: case 1:
471: m = "tlbr";
472: break;
473:
474: case 2:
475: m = "tlbwi";
476: break;
477:
478: case 6:
479: m = "tlbwr";
480: break;
481:
482: case 8:
483: m = "tlbp";
484: break;
485:
486: case 16:
487: m = "rfe";
488: break;
489:
490: case 32:
491: m = "eret";
492: break;
493: }
494: if (m) {
495: format(m, i, 0);
496: if (i->curr < i->end)
497: *i->curr++ = 0;
498: return;
499: }
500: }
501: copz(0, i);
502: }
503:
504: int
505: _mipscoinst(Map *map, ulong pc, char *buf, int n)
506: {
507: Instr i;
508: Opcode *o;
509: uchar op;
510:
511: i.curr = buf;
512: i.end = buf+n-1;
513: if (mkinstr(&i, map, pc) < 0)
514: return -1;
515: switch (i.op) {
516:
517: case 0x00: /* SPECIAL */
518: o = sopcodes;
519: op = i.function;
520: break;
521:
522: case 0x01: /* REGIMM */
523: o = ropcodes;
524: op = i.rt;
525: break;
526:
527: case 0x10: /* COP0 */
528: cop0(&i);
529: return 4;
530:
531: case 0x11: /* COP1 */
532: if (i.rs & 0x10) {
533: o = fopcodes;
534: op = i.function;
535: break;
536: }
537: /*FALLTHROUGH*/
538: case 0x12: /* COP2 */
539: case 0x13: /* COP3 */
540: copz(i.op-0x10, &i);
541: return 4;
542:
543: default:
544: o = opcodes;
545: op = i.op;
546: break;
547: }
548: format(o[op].mnemonic, &i, o[op].mipsco);
549: return 4;
550: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.