]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmach/7db.c
webfs: preauth support
[plan9front.git] / sys / src / libmach / 7db.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 /*
6  * Alpha-specific debugger interface
7  */
8
9 static  char    *alphaexcep(Map*, Rgetter);
10 static  int     alphafoll(Map*, uvlong, Rgetter, uvlong*);
11 static  int     alphainst(Map*, uvlong, char, char*, int);
12 static  int     alphadas(Map*, uvlong, char*, int);
13 static  int     alphainstlen(Map*, uvlong);
14 /*
15  *      Debugger interface
16  */
17 Machdata alphamach =
18 {
19         {0x80, 0, 0, 0},                /* break point */
20         4,                      /* break point size */
21
22         leswab,                 /* short to local byte order */
23         leswal,                 /* long to local byte order */
24         leswav,                 /* vlong to local byte order */
25         risctrace,              /* C traceback */
26         riscframe,              /* Frame finder */
27         alphaexcep,             /* print exception */
28         0,                      /* breakpoint fixup */
29         leieeesftos,            /* single precision float printer */
30         leieeedftos,            /* double precisioin float printer */
31         alphafoll,              /* following addresses */
32         alphainst,              /* print instruction */
33         alphadas,               /* dissembler */
34         alphainstlen,           /* instruction size */
35 };
36
37 static char *illegaltype[] = {
38         "breakpoint",
39         "bugchk",
40         "gentrap",
41         "fen",
42         "illegal instruction",
43 };
44
45 static char *
46 alphaexcep(Map *map, Rgetter rget)
47 {
48         ulong type, a0, a1;
49         static char buf[256];
50
51         type = (*rget)(map, "TYPE");
52         a0 = (*rget)(map, "A0");
53         a1 = (*rget)(map, "A1");
54 /*      a2 = (*rget)(map, "A2"); */
55
56         switch (type) {
57         case 1: /* arith */
58                 sprint(buf, "trap: arithmetic trap 0x%lux", a0);
59                 break;
60         case 2: /* bad instr or FEN */
61                 if (a0 <= 4)
62                         return illegaltype[a0];
63                 else
64                         sprint(buf, "illegal instr trap, unknown type %lud", a0);
65                 break;
66         case 3: /* intr */
67                 sprint(buf, "interrupt type %lud", a0);
68                 break;
69         case 4: /* memory fault */
70                 sprint(buf, "fault %s addr=0x%lux", (a1&1)?"write":"read", a0);
71                 break;
72         case 5: /* syscall() */
73                 return "system call";
74         case 6: /* alignment fault */
75                 sprint(buf, "unaligned op 0x%lux addr 0x%lux", a1, a0);
76                 break;
77         default:        /* cannot happen */
78                 sprint(buf, "unknown exception type %lud", type);
79                 break;
80         }
81         return buf;
82 }
83
84         /* alpha disassembler and related functions */
85
86 static  char FRAMENAME[] = ".frame";
87
88 typedef struct {
89         uvlong addr;
90         uchar op;                       /* bits 31-26 */
91         uchar ra;                       /* bits 25-21 */
92         uchar rb;                       /* bits 20-16 */
93         uchar rc;                       /* bits 4-0 */
94         long mem;                       /* bits 15-0 */
95         long branch;                    /* bits 20-0 */
96         uchar function;                 /* bits 11-5 */
97         uchar literal;                  /* bits 20-13 */
98         uchar islit;                    /* bit 12 */
99         uchar fpfn;                     /* bits 10-5 */
100         uchar fpmode;                   /* bits 15-11 */
101         long w0;
102         long w1;
103         int size;                       /* instruction size */
104         char *curr;                     /* fill point in buffer */
105         char *end;                      /* end of buffer */
106         char *err;                      /* error message */
107 } Instr;
108
109 static Map *mymap;
110
111 static int
112 decode(uvlong pc, Instr *i)
113 {
114         ulong w;
115
116         if (get4(mymap, pc, &w) < 0) {
117                 werrstr("can't read instruction: %r");
118                 return -1;
119         }
120         i->addr = pc;
121         i->size = 1;
122         i->op = (w >> 26) & 0x3F;
123         i->ra = (w >> 21) & 0x1F;
124         i->rb = (w >> 16) & 0x1F;
125         i->rc = w & 0x1F;
126         i->function = (w >> 5) & 0x7F;
127         i->mem = w & 0xFFFF;
128         if (i->mem & 0x8000)
129                 i->mem -= 0x10000;
130         i->branch = w & 0x1FFFFF;
131         if (i->branch & 0x100000)
132                 i->branch -= 0x200000;
133         i->function = (w >> 5) & 0x7F;
134         i->literal = (w >> 13) & 0xFF;
135         i->islit = (w >> 12) & 0x01;
136         i->fpfn = (w >> 5) & 0x3F;
137         i->fpmode = (w >> 11) & 0x1F;
138         i->w0 = w;
139         return 1;
140 }
141
142 static int
143 mkinstr(uvlong pc, Instr *i)
144 {
145 /*      Instr x; */
146
147         if (decode(pc, i) < 0)
148                 return -1;
149
150 #ifdef  frommips
151 /* we probably want to do something like this for alpha... */
152         /*
153          * if it's a LUI followed by an ORI,
154          * it's an immediate load of a large constant.
155          * fix the LUI immediate in any case.
156          */
157         if (i->op == 0x0F) {
158                 if (decode(pc+4, &x) < 0)
159                         return 0;
160                 i->immediate <<= 16;
161                 if (x.op == 0x0D && x.rs == x.rt && x.rt == i->rt) {
162                         i->immediate |= (x.immediate & 0xFFFF);
163                         i->w1 = x.w0;
164                         i->size++;
165                         return 1;
166                 }
167         }
168 #endif
169         return 1;
170 }
171
172 #pragma varargck        argpos  bprint          2
173
174 static void
175 bprint(Instr *i, char *fmt, ...)
176 {
177         va_list arg;
178
179         va_start(arg, fmt);
180         i->curr = vseprint(i->curr, i->end, fmt, arg);
181         va_end(arg);
182 }
183
184 typedef struct Opcode Opcode;
185
186 struct Opcode {
187         char *mnemonic;
188         void (*f)(Opcode *, Instr *);
189         char *ken;
190 };
191
192 static void format(char *, Instr *, char *);
193
194 static int
195 plocal(Instr *i, char *m, char r, int store)
196 {
197         int offset;
198         char *reg;
199         Symbol s;
200
201         if (!findsym(i->addr, CTEXT, &s) || !findlocal(&s, FRAMENAME, &s))
202                 return 0;
203         if (s.value > i->mem) {
204                 if(!getauto(&s, s.value-i->mem, CAUTO, &s))
205                         return 0;
206                 reg = "(SP)";
207                 offset = i->mem;
208         } else {
209                 offset = i->mem-s.value-8;
210                 if (!getauto(&s, offset, CPARAM, &s))
211                         return 0;
212                 reg = "(FP)";
213         }
214         if (store)
215                 bprint(i, "%s\t%c%d,%s+%d%s", m, r, i->ra, s.name, offset, reg);
216         else
217                 bprint(i, "%s\t%s+%d%s,%c%d", m, s.name, offset, reg, r, i->ra);
218         return 1;
219 }
220
221 static void
222 _load(Opcode *o, Instr *i, char r)
223 {
224         char *m;
225
226         m = o->mnemonic;
227         if (i->rb == 30 && plocal(i, m, r, 0))
228                 return;
229         if (i->rb == 29 && mach->sb) {
230                 bprint(i, "%s\t", m);
231                 i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
232                 bprint(i, "(SB),%c%d", r, i->ra);
233                 return;
234         }
235         format(m, i, o->ken);
236 }
237
238 static void
239 load(Opcode *o, Instr *i)
240 {
241         _load(o, i, 'R');
242 }
243
244 static void
245 loadf(Opcode *o, Instr *i)
246 {
247         _load(o, i, 'F');
248 }
249
250 static void
251 _store(Opcode *o, Instr *i, char r)
252 {
253         char *m;
254
255         m = o->mnemonic;
256         if (i->rb == 30 && plocal(i, m, r, 1))
257                 return;
258         if (i->rb == 29 && mach->sb) {
259                 bprint(i, "%s\t%c%d,", m, r, i->ra);
260                 i->curr += symoff(i->curr, i->end-i->curr, i->mem+mach->sb, CANY);
261                 bprint(i, "(SB)");
262                 return;
263         }
264         format(o->mnemonic, i, o->ken);
265 }
266
267 static void
268 store(Opcode *o, Instr *i)
269 {
270         _store(o, i, 'R');
271 }
272
273 static void
274 storef(Opcode *o, Instr *i)
275 {
276         _store(o, i, 'F');
277 }
278
279 static void
280 misc(Opcode *o, Instr *i)
281 {
282         char *f;
283
284         USED(o);
285         switch (i->mem&0xFFFF) {
286         case 0x0000:
287                 f = "TRAPB";
288                 break;
289         case 0x4000:
290                 f = "MB";
291                 break;
292         case 0x8000:
293                 f = "FETCH\t0(R%b)";
294                 break;
295         case 0xA000:
296                 f = "FETCH_M\t0(R%b)";
297                 break;
298         case 0xC000:
299                 f = "RPCC\tR%a";
300                 break;
301         case 0xE000:
302                 f = "RC\tR%a";
303                 break;
304         case 0xF000:
305                 f = "RS\tR%a";
306                 break;
307         default:
308                 f = "%w";
309         }
310         format(0, i, f);
311 }
312
313 static char     *jmpcode[4] = { "JMP", "JSR", "RET", "JSR_COROUTINE" };
314
315 static void
316 jmp(Opcode *o, Instr *i)
317 {
318         int hint;
319         char *m;
320
321         USED(o);
322         hint = (i->mem >> 14) & 3;
323         m = jmpcode[hint];
324         if (i->ra == 31) {
325                 if (hint == 2 && i->rb == 29)
326                         bprint(i, m);
327                 else
328                         format(m, i, "(R%b)");
329         }
330         else
331                 format(m, i, "R%a,(R%b)");
332 }
333
334 static void
335 br(Opcode *o, Instr *i)
336 {
337         if (i->ra == 31)
338                 format(o->mnemonic, i, "%B");
339         else
340                 format(o->mnemonic, i, o->ken);
341 }
342
343 static void
344 bsr(Opcode *o, Instr *i)
345 {
346         if (i->ra == 26)
347                 format(o->mnemonic, i, "%B");
348         else
349                 format(o->mnemonic, i, o->ken);
350 }
351
352 static void
353 mult(Opcode *o, Instr *i)
354 {
355         char *m;
356
357         switch (i->function) {
358         case 0x00:
359                 m = "MULL";
360                 break;
361         case 0x20:
362                 m = "MULQ";
363                 break;
364         case 0x40:
365                 m = "MULL/V";
366                 break;
367         case 0x60:
368                 m = "MULQ/V";
369                 break;
370         case 0x30:
371                 m = "UMULH";
372                 break;
373         default:
374                 format("???", i, "%w");
375                 return;
376         }
377         format(m, i, o->ken);
378 }
379
380 static char     alphaload[] = "%l,R%a";
381 static char     alphafload[] = "%l,F%a";
382 static char     alphastore[] = "R%a,%l";
383 static char     alphafstore[] = "F%a,%l";
384 static char     alphabranch[] = "R%a,%B";
385 static char     alphafbranch[] = "F%a,%B";
386 static char     alphaint[] = "%v,R%a,R%c";
387 static char     alphafp[] = "F%b,F%a,F%c";
388 static char     alphafp2[] = "F%b,F%c";
389 static char     alphaxxx[] = "%w";
390
391 static Opcode opcodes[64] = {
392         "PAL",          0,      alphaxxx,
393         "OPC01",        0,      alphaxxx,
394         "OPC02",        0,      alphaxxx,
395         "OPC03",        0,      alphaxxx,
396         "OPC04",        0,      alphaxxx,
397         "OPC05",        0,      alphaxxx,
398         "OPC06",        0,      alphaxxx,
399         "OPC07",        0,      alphaxxx,
400         "MOVQA",        load,   alphaload,
401         "MOVQAH",       load,   alphaload,
402         "MOVBU",        load,   alphaload,              /* v 3 */
403         "MOVQU",        load,   alphaload,
404         "MOVWU",        load,   alphaload,              /* v 3 */
405         "MOVWU",        store,  alphastore,             /* v 3 */
406         "MOVBU",        store,  alphastore,             /* v 3 */
407         "MOVQU",        store,  alphastore,
408         0,              0,      0,                      /* int arith */
409         0,              0,      0,                      /* logical */
410         0,              0,      0,                      /* shift */
411         0,              mult,   alphaint,
412         "OPC14",        0,      alphaxxx,
413         "vax",          0,      alphafp,                /* vax */
414         0,              0,      0,                      /* ieee */
415         0,              0,      0,                      /* fp */
416         0,              misc,   alphaxxx,
417         "PAL19 [HW_MFPR]",0,    alphaxxx,
418         "JSR",          jmp,    0,
419         "PAL1B [HW_LD]",0,      alphaxxx,
420         "OPC1C",        0,      alphaxxx,
421         "PAL1D [HW_MTPR]",0,    alphaxxx,
422         "PAL1E [HW_REI]",0,     alphaxxx,
423         "PAL1F [HW_ST]",0,      alphaxxx,
424         "MOVF",         loadf,  alphafload,
425         "MOVG",         loadf,  alphafload,
426         "MOVS",         loadf,  alphafload,
427         "MOVT",         loadf,  alphafload,
428         "MOVF",         storef, alphafstore,
429         "MOVG",         storef, alphafstore,
430         "MOVS",         storef, alphafstore,
431         "MOVT",         storef, alphafstore,
432         "MOVL",         load,   alphaload,
433         "MOVQ",         load,   alphaload,
434         "MOVLL",        load,   alphaload,
435         "MOVQL",        load,   alphaload,
436         "MOVL",         store,  alphastore,
437         "MOVQ",         store,  alphastore,
438         "MOVLC",        store,  alphastore,
439         "MOVQC",        store,  alphastore,
440         "JMP",          br,     alphabranch,
441         "FBEQ",         0,      alphafbranch,
442         "FBLT",         0,      alphafbranch,
443         "FBLE",         0,      alphafbranch,
444         "JSR",          bsr,    alphabranch,
445         "FBNE",         0,      alphafbranch,
446         "FBGE",         0,      alphafbranch,
447         "FBGT",         0,      alphafbranch,
448         "BLBC",         0,      alphafbranch,
449         "BEQ",          0,      alphabranch,
450         "BLT",          0,      alphabranch,
451         "BLE",          0,      alphabranch,
452         "BLBS",         0,      alphabranch,
453         "BNE",          0,      alphabranch,
454         "BGE",          0,      alphabranch,
455         "BGT",          0,      alphabranch,
456 };
457
458 static Opcode fpopcodes[64] = {
459         "???",          0,      alphaxxx,
460         "???",          0,      alphaxxx,
461         "???",          0,      alphaxxx,
462         "???",          0,      alphaxxx,
463         "???",          0,      alphaxxx,
464         "???",          0,      alphaxxx,
465         "???",          0,      alphaxxx,
466         "???",          0,      alphaxxx,
467         "???",          0,      alphaxxx,
468         "???",          0,      alphaxxx,
469         "???",          0,      alphaxxx,
470         "???",          0,      alphaxxx,
471         "???",          0,      alphaxxx,
472         "???",          0,      alphaxxx,
473         "???",          0,      alphaxxx,
474         "???",          0,      alphaxxx,
475
476         "CVTLQ",        0,      alphafp2,
477         "???",          0,      alphaxxx,
478         "???",          0,      alphaxxx,
479         "???",          0,      alphaxxx,
480         "???",          0,      alphaxxx,
481         "???",          0,      alphaxxx,
482         "???",          0,      alphaxxx,
483         "???",          0,      alphaxxx,
484         "???",          0,      alphaxxx,
485         "???",          0,      alphaxxx,
486         "???",          0,      alphaxxx,
487         "???",          0,      alphaxxx,
488         "???",          0,      alphaxxx,
489         "???",          0,      alphaxxx,
490         "???",          0,      alphaxxx,
491         "???",          0,      alphaxxx,
492
493         "CPYS",         0,      alphafp,
494         "CPYSN",        0,      alphafp,
495         "CPYSE",        0,      alphafp,
496         "???",          0,      alphaxxx,
497         "MOVT",         0,      "FPCR,F%a",
498         "MOVT",         0,      "F%a,FPCR",
499         "???",          0,      alphaxxx,
500         "???",          0,      alphaxxx,
501         "???",          0,      alphaxxx,
502         "???",          0,      alphaxxx,
503         "FCMOVEQ",      0,      alphafp,
504         "FCMOVNE",      0,      alphafp,
505         "FCMOVLT",      0,      alphafp,
506         "FCMOVGE",      0,      alphafp,
507         "FCMOVLE",      0,      alphafp,
508         "FCMOVGT",      0,      alphafp,
509
510         "CVTQL",        0,      alphafp2,
511         "???",          0,      alphaxxx,
512         "???",          0,      alphaxxx,
513         "???",          0,      alphaxxx,
514         "???",          0,      alphaxxx,
515         "???",          0,      alphaxxx,
516         "???",          0,      alphaxxx,
517         "???",          0,      alphaxxx,
518         "???",          0,      alphaxxx,
519         "???",          0,      alphaxxx,
520         "???",          0,      alphaxxx,
521         "???",          0,      alphaxxx,
522         "???",          0,      alphaxxx,
523         "???",          0,      alphaxxx,
524         "???",          0,      alphaxxx,
525         "???",          0,      alphaxxx,
526 };
527
528 static Opcode ieeeopcodes[64] = {
529         "ADDS",         0,      alphafp,
530         "SUBS",         0,      alphafp,
531         "MULS",         0,      alphafp,
532         "DIVS",         0,      alphafp,
533         "???",          0,      alphaxxx,
534         "???",          0,      alphaxxx,
535         "???",          0,      alphaxxx,
536         "???",          0,      alphaxxx,
537         "???",          0,      alphaxxx,
538         "???",          0,      alphaxxx,
539         "???",          0,      alphaxxx,
540         "???",          0,      alphaxxx,
541         "???",          0,      alphaxxx,
542         "???",          0,      alphaxxx,
543         "???",          0,      alphaxxx,
544         "???",          0,      alphaxxx,
545
546         "???",          0,      alphaxxx,
547         "???",          0,      alphaxxx,
548         "???",          0,      alphaxxx,
549         "???",          0,      alphaxxx,
550         "???",          0,      alphaxxx,
551         "???",          0,      alphaxxx,
552         "???",          0,      alphaxxx,
553         "???",          0,      alphaxxx,
554         "???",          0,      alphaxxx,
555         "???",          0,      alphaxxx,
556         "???",          0,      alphaxxx,
557         "???",          0,      alphaxxx,
558         "???",          0,      alphaxxx,
559         "???",          0,      alphaxxx,
560         "???",          0,      alphaxxx,
561         "???",          0,      alphaxxx,
562
563         "ADDT",         0,      alphafp,
564         "SUBT",         0,      alphafp,
565         "MULT",         0,      alphafp,
566         "DIVT",         0,      alphafp,
567         "CMPTUN",       0,      alphafp,
568         "CMPTEQ",       0,      alphafp,
569         "CMPTLT",       0,      alphafp,
570         "CMPTLE",       0,      alphafp,
571         "???",          0,      alphaxxx,
572         "???",          0,      alphaxxx,
573         "???",          0,      alphaxxx,
574         "???",          0,      alphaxxx,
575         "CVTTS",        0,      alphafp2,
576         "???",          0,      alphaxxx,
577         "???",          0,      alphaxxx,
578         "CVTTQ",        0,      alphafp2,
579
580         "???",          0,      alphaxxx,
581         "???",          0,      alphaxxx,
582         "???",          0,      alphaxxx,
583         "???",          0,      alphaxxx,
584         "???",          0,      alphaxxx,
585         "???",          0,      alphaxxx,
586         "???",          0,      alphaxxx,
587         "???",          0,      alphaxxx,
588         "???",          0,      alphaxxx,
589         "???",          0,      alphaxxx,
590         "???",          0,      alphaxxx,
591         "???",          0,      alphaxxx,
592         "CVTQS",        0,      alphafp2,
593         "???",          0,      alphaxxx,
594         "CVTQT",        0,      alphafp2,
595         "???",          0,      alphaxxx,
596 };
597
598 static uchar    amap[128] = {
599         [0x00]  1,
600         [0x40]  2,
601         [0x20]  3,
602         [0x60]  4,
603         [0x09]  5,
604         [0x49]  6,
605         [0x29]  7,
606         [0x69]  8,
607         [0x2D]  9,
608         [0x4D]  10,
609         [0x6D]  11,
610         [0x1D]  12,     
611         [0x3D]  13,     
612         [0x0F]  14,     
613         [0x02]  15,     
614         [0x0B]  16,     
615         [0x12]  17,     
616         [0x1B]  18,
617         [0x22]  19,     
618         [0x2B]  20,     
619         [0x32]  21,     
620         [0x3B]  22,
621 };
622
623 static Opcode arithopcodes[64] = {
624         "???",          0,      alphaxxx,
625         "ADDL",         0,      alphaint,
626         "ADDL/V",       0,      alphaint,
627         "ADDQ",         0,      alphaint,
628         "ADDQ/V",       0,      alphaint,
629         "SUBL",         0,      alphaint,
630         "SUBL/V",       0,      alphaint,
631         "SUBQ",         0,      alphaint,
632         "SUBQ/V",       0,      alphaint,
633         "CMPEQ",        0,      alphaint,
634         "CMPLT",        0,      alphaint,
635         "CMPLE",        0,      alphaint,
636         "CMPULT",       0,      alphaint,
637         "CMPULE",       0,      alphaint,
638         "CMPBGE",       0,      alphaint,
639         "S4ADDL",       0,      alphaint,
640         "S4SUBL",       0,      alphaint,
641         "S8ADDL",       0,      alphaint,
642         "S8SUBL",       0,      alphaint,
643         "S4ADDQ",       0,      alphaint,
644         "S4SUBQ",       0,      alphaint,
645         "S8ADDQ",       0,      alphaint,
646         "S8SUBQ",       0,      alphaint,
647 };
648
649 static uchar    lmap[128] = {
650         [0x00]  1,
651         [0x20]  2,
652         [0x40]  3,
653         [0x08]  4,
654         [0x28]  5,
655         [0x48]  6,
656         [0x24]  7,
657         [0x44]  8,
658         [0x64]  9,
659         [0x26]  7,
660         [0x46]  8,
661         [0x66]  9,
662         [0x14]  10,
663         [0x16]  11,
664 };
665
666 static Opcode logicalopcodes[64] = {
667         "???",          0,      alphaxxx,
668         "AND",          0,      alphaint,
669         "OR",           0,      alphaint,
670         "XOR",          0,      alphaint,
671         "ANDNOT",       0,      alphaint,
672         "ORNOT",        0,      alphaint,
673         "XORNOT",       0,      alphaint,
674         "CMOVEQ",       0,      alphaint,
675         "CMOVLT",       0,      alphaint,
676         "CMOVLE",       0,      alphaint,
677         "CMOVNE",       0,      alphaint,
678         "CMOVGE",       0,      alphaint,
679         "CMOVGT",       0,      alphaint,
680         "CMOVLBS",      0,      alphaint,
681         "CMOVLBC",      0,      alphaint,
682 };
683
684 static uchar    smap[128] = {
685         [0x39]  1,
686         [0x3C]  2,
687         [0x34]  3,
688         [0x06]  4,
689         [0x16]  5,
690         [0x26]  6,
691         [0x36]  7,
692         [0x5A]  8,
693         [0x6A]  9,
694         [0x7A]  10,
695         [0x0B]  11,
696         [0x1B]  12,
697         [0x2B]  13,
698         [0x3B]  14,
699         [0x57]  15,
700         [0x67]  16,
701         [0x77]  17,
702         [0x02]  18,
703         [0x12]  19,
704         [0x22]  20,
705         [0x32]  21,
706         [0x52]  22,
707         [0x62]  23,
708         [0x72]  24,
709         [0x30]  25,
710         [0x31]  26,
711 };
712
713 static Opcode shiftopcodes[64] = {
714         "???",          0,      alphaxxx,
715         "SLLQ",         0,      alphaint,
716         "SRAQ",         0,      alphaint,
717         "SRLQ",         0,      alphaint,
718         "EXTBL",        0,      alphaint,
719         "EXTWL",        0,      alphaint,
720         "EXTLL",        0,      alphaint,
721         "EXTQL",        0,      alphaint,
722         "EXTWH",        0,      alphaint,
723         "EXTLH",        0,      alphaint,
724         "EXTQH",        0,      alphaint,
725         "INSBL",        0,      alphaint,
726         "INSWL",        0,      alphaint,
727         "INSLL",        0,      alphaint,
728         "INSQL",        0,      alphaint,
729         "INSWH",        0,      alphaint,
730         "INSLH",        0,      alphaint,
731         "INSQH",        0,      alphaint,
732         "MSKBL",        0,      alphaint,
733         "MSKWL",        0,      alphaint,
734         "MSKLL",        0,      alphaint,
735         "MSKQL",        0,      alphaint,
736         "MSKWH",        0,      alphaint,
737         "MSKLH",        0,      alphaint,
738         "MSKQH",        0,      alphaint,
739         "ZAP",          0,      alphaint,
740         "ZAPNOT",       0,      alphaint,
741 };
742
743 static void
744 format(char *mnemonic, Instr *i, char *f)
745 {
746         if (mnemonic)
747                 format(0, i, mnemonic);
748         if (f == 0)
749                 return;
750         if (mnemonic)
751                 if (i->curr < i->end)
752                         *i->curr++ = '\t';
753         for ( ; *f && i->curr < i->end; f++) {
754                 if (*f != '%') {
755                         *i->curr++ = *f;
756                         continue;
757                 }
758                 switch (*++f) {
759
760                 case 'a':
761                         bprint(i, "%d", i->ra);
762                         break;
763
764                 case 'b':
765                         bprint(i, "%d", i->rb);
766                         break;
767
768                 case 'c':
769                         bprint(i, "%d", i->rc);
770                         break;
771
772                 case 'v':
773                         if (i->islit)
774                                 bprint(i, "$%ux", i->literal);
775                         else
776                                 bprint(i, "R%d", i->rb);
777                         break;
778
779                 case 'l':
780                         bprint(i, "%lx(R%d)", i->mem, i->rb);
781                         break;
782
783                 case 'i':
784                         bprint(i, "$%lx", i->mem);
785                         break;
786
787                 case 'B':
788                         i->curr += symoff(i->curr, i->end-i->curr,
789                                 (i->branch<<2)+i->addr+4, CANY);
790                         break;
791
792                 case 'w':
793                         bprint(i, "[%lux]", i->w0);
794                         break;
795
796                 case '\0':
797                         *i->curr++ = '%';
798                         return;
799
800                 default:
801                         bprint(i, "%%%c", *f);
802                         break;
803                 }
804         }
805         *i->curr = 0;
806 }
807
808 static int
809 printins(Map *map, uvlong pc, char *buf, int n)
810 {
811         Instr i;
812         Opcode *o;
813         uchar op;
814
815         i.curr = buf;
816         i.end = buf+n-1;
817         mymap = map;
818         if (mkinstr(pc, &i) < 0)
819                 return -1;
820         switch (i.op) {
821
822         case 0x10:                                      /* INTA */
823                 o = arithopcodes;
824                 op = amap[i.function];
825                 break;
826
827         case 0x11:                                      /* INTL */
828                 o = logicalopcodes;
829                 op = lmap[i.function];
830                 break;
831
832         case 0x12:                                      /* INTS */
833                 o = shiftopcodes;
834                 op = smap[i.function];
835                 break;
836
837         case 0x16:                                      /* FLTI */
838                 o = ieeeopcodes;
839                 op = i.fpfn;
840                 break;
841
842         case 0x17:                                      /* FLTL */
843                 o = fpopcodes;
844                 op = i.fpfn;
845                 break;
846
847         default:
848                 o = opcodes;
849                 op = i.op;
850                 break;
851         }
852         if (o[op].f)
853                 (*o[op].f)(&o[op], &i);
854         else
855                 format(o[op].mnemonic, &i, o[op].ken);
856         return i.size*4;
857 }
858
859 static int
860 alphainst(Map *map, uvlong pc, char modifier, char *buf, int n)
861 {
862         USED(modifier);
863         return printins(map, pc, buf, n);
864 }
865
866 static int
867 alphadas(Map *map, uvlong pc, char *buf, int n)
868 {
869         Instr i;
870
871         i.curr = buf;
872         i.end = buf+n;
873         mymap = map;
874         if (mkinstr(pc, &i) < 0)
875                 return -1;
876         if (i.end-i.curr > 8)
877                 i.curr = _hexify(buf, i.w0, 7);
878         if (i.size == 2 && i.end-i.curr > 9) {
879                 *i.curr++ = ' ';
880                 i.curr = _hexify(i.curr, i.w1, 7);
881         }
882         *i.curr = 0;
883         return i.size*4;
884 }
885
886 static int
887 alphainstlen(Map *map, uvlong pc)
888 {
889         Instr i;
890
891         mymap = map;
892         if (mkinstr(pc, &i) < 0)
893                 return -1;
894         return i.size*4;
895 }
896
897 static int
898 alphafoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
899 {
900         char buf[8];
901         Instr i;
902
903         mymap = map;
904         if (mkinstr(pc, &i) < 0)
905                 return -1;
906
907         switch(i.op) {
908         case 0x1A:                              /* JMP/JSR/RET */
909                 sprint(buf, "R%d", i.rb);
910                 foll[0] = (*rget)(map, buf);
911                 return 1;
912         case 0x30:                              /* BR */
913         case 0x34:                              /* BSR */
914                 foll[0] = pc+4 + (i.branch<<2);
915                 return 1;
916         default:
917                 if (i.op > 0x30) {              /* cond */
918                         foll[0] = pc+4;
919                         foll[1] = pc+4 + (i.branch<<2);
920                         return 2;
921                 }
922                 foll[0] = pc+i.size*4;
923                 return 1;
924         }
925 }