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 *
alphaexcep(Map * map,Rgetter rget)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
decode(uvlong pc,Instr * i)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
mkinstr(uvlong pc,Instr * i)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
bprint(Instr * i,char * fmt,...)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
plocal(Instr * i,char * m,char r,int store)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
_load(Opcode * o,Instr * i,char r)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
load(Opcode * o,Instr * i)239 load(Opcode *o, Instr *i)
240 {
241 _load(o, i, 'R');
242 }
243
244 static void
loadf(Opcode * o,Instr * i)245 loadf(Opcode *o, Instr *i)
246 {
247 _load(o, i, 'F');
248 }
249
250 static void
_store(Opcode * o,Instr * i,char r)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
store(Opcode * o,Instr * i)268 store(Opcode *o, Instr *i)
269 {
270 _store(o, i, 'R');
271 }
272
273 static void
storef(Opcode * o,Instr * i)274 storef(Opcode *o, Instr *i)
275 {
276 _store(o, i, 'F');
277 }
278
279 static void
misc(Opcode * o,Instr * i)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
jmp(Opcode * o,Instr * i)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
br(Opcode * o,Instr * i)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
bsr(Opcode * o,Instr * i)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
mult(Opcode * o,Instr * i)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
format(char * mnemonic,Instr * i,char * f)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
printins(Map * map,uvlong pc,char * buf,int n)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
alphainst(Map * map,uvlong pc,char modifier,char * buf,int n)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
alphadas(Map * map,uvlong pc,char * buf,int n)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
alphainstlen(Map * map,uvlong pc)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
alphafoll(Map * map,uvlong pc,Rgetter rget,uvlong * foll)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 }
926