]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/vcodas.c
9bootfat: rename open() to fileinit and make it static as its really a internal funct...
[plan9front.git] / sys / src / libmach / vcodas.c
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         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 */
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, uvlong pc)
286 {
287         ulong 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 #pragma varargck        argpos  bprint          2
310
311 static void
312 bprint(Instr *i, char *fmt, ...)
313 {
314         va_list arg;
315
316         va_start(arg, fmt);
317         i->curr = vseprint(i->curr, i->end, fmt, arg);
318         va_end(arg);
319 }
320
321 static void
322 format(char *mnemonic, Instr *i, char *f)
323 {
324         if (mnemonic)
325                 format(0, i, mnemonic);
326         if (f == 0)
327                 return;
328         if (i->curr < i->end)
329                 *i->curr++ = '\t';
330         for ( ; *f && i->curr < i->end; f++) {
331                 if (*f != '%') {
332                         *i->curr++ = *f;
333                         continue;
334                 }
335                 switch (*++f) {
336
337                 case 's':
338                         bprint(i, "%d", i->rs);
339                         break;
340
341                 case 't':
342                         bprint(i, "%d", i->rt);
343                         break;
344
345                 case 'd':
346                         bprint(i, "%d", i->rd);
347                         break;
348
349                 case 'a':
350                         bprint(i, "%d", i->sa);
351                         break;
352
353                 case 'l':
354                         if (i->rs == 30) {
355                                 i->curr += symoff(i->curr, i->end-i->curr, i->immediate+mach->sb, CANY);
356                                 bprint(i, "(SB)");
357                         } else 
358                                 bprint(i, "%lx(r%d)", i->immediate, i->rs);
359                         break;
360
361                 case 'i':
362                         bprint(i, "$%lx", i->immediate);
363                         break;
364
365                 case 'u':
366                         *i->curr++ = '$';
367                         i->curr += symoff(i->curr, i->end-i->curr, i->immediate, CANY);
368                         bprint(i, "(SB)");
369                         break;
370
371                 case 'j':
372                         i->curr += symoff(i->curr, i->end-i->curr,
373                                 (i->target<<2)|(i->addr & 0xF0000000), CANY);
374                         bprint(i, "(SB)");
375                         break;
376
377                 case 'b':
378                         i->curr += symoff(i->curr, i->end-i->curr,
379                                 (i->immediate<<2)+i->addr+4, CANY);
380                         break;
381
382                 case 'c':
383                         bprint(i, "%lux", i->cofun);
384                         break;
385
386                 case 'w':
387                         bprint(i, "[%lux]", i->w0);
388                         break;
389
390                 case 'f':
391                         *i->curr++ = fsub[i->rs & 0x0F];
392                         break;
393
394                 case '\0':
395                         *i->curr++ = '%';
396                         return;
397
398                 default:
399                         bprint(i, "%%%c", *f);
400                         break;
401                 }
402         }
403 }
404
405 static void
406 copz(int cop, Instr *i)
407 {
408         char *f, *m, buf[16];
409
410         m = buf;
411         f = "%t,%d";
412         switch (i->rs) {
413
414         case 0:
415                 sprint(buf, "mfc%d", cop);
416                 break;
417
418         case 2:
419                 sprint(buf, "cfc%d", cop);
420                 break;
421
422         case 4:
423                 sprint(buf, "mtc%d", cop);
424                 break;
425
426         case 6:
427                 sprint(buf, "ctc%d", cop);
428                 break;
429
430         case 8:
431                 f = "%b";
432                 switch (i->rt) {
433
434                 case 0:
435                         sprint(buf, "bc%df", cop);
436                         break;
437
438                 case 1:
439                         sprint(buf, "bc%dt", cop);
440                         break;
441
442                 case 2:
443                         sprint(buf, "bc%dfl", cop);
444                         break;
445
446                 case 3:
447                         sprint(buf, "bc%dtl", cop);
448                         break;
449
450                 default:
451                         sprint(buf, "cop%d", cop);
452                         f = mipscoxxx;
453                         break;
454                 }
455                 break;
456
457         default:
458                 sprint(buf, "cop%d", cop);
459                 if (i->rs & 0x10)
460                         f = "function %c";
461                 else
462                         f = mipscoxxx;
463                 break;
464         }
465         format(m, i, f);
466 }
467
468 static void
469 cop0(Instr *i)
470 {
471         char *m = 0;
472
473         if (i->rs >= 0x10) {
474                 switch (i->cofun) {
475         
476                 case 1:
477                         m = "tlbr";
478                         break;
479         
480                 case 2:
481                         m = "tlbwi";
482                         break;
483         
484                 case 6:
485                         m = "tlbwr";
486                         break;
487         
488                 case 8:
489                         m = "tlbp";
490                         break;
491         
492                 case 16:
493                         m = "rfe";
494                         break;
495         
496                 case 32:
497                         m = "eret";
498                         break;
499                 }
500                 if (m) {
501                         format(m, i, 0);
502                         if (i->curr < i->end)
503                                 *i->curr++ = 0;
504                         return;
505                 }
506         }
507         copz(0, i);
508 }
509
510 int
511 _mipscoinst(Map *map, uvlong pc, char *buf, int n)
512 {
513         Instr i;
514         Opcode *o;
515         uchar op;
516
517         i.curr = buf;
518         i.end = buf+n-1;
519         if (mkinstr(&i, map, pc) < 0)
520                 return -1;
521         switch (i.op) {
522
523         case 0x00:                                      /* SPECIAL */
524                 o = sopcodes;
525                 op = i.function;
526                 break;
527
528         case 0x01:                                      /* REGIMM */
529                 o = ropcodes;
530                 op = i.rt;
531                 break;
532
533         case 0x10:                                      /* COP0 */
534                 cop0(&i);
535                 return 4;
536
537         case 0x11:                                      /* COP1 */
538                 if (i.rs & 0x10) {
539                         o = fopcodes;
540                         op = i.function;
541                         break;
542                 }
543                 /*FALLTHROUGH*/
544         case 0x12:                                      /* COP2 */
545         case 0x13:                                      /* COP3 */
546                 copz(i.op-0x10, &i);
547                 return 4;
548
549         default:
550                 o = opcodes;
551                 op = i.op;
552                 break;
553         }
554         format(o[op].mnemonic, &i, o[op].mipsco);
555         return 4;
556 }