8 #define BITS(a, b) ((1<<(b+1))-(1<<a))
10 #define LSR(v, s) ((ulong)(v) >> (s))
11 #define ASR(v, s) ((long)(v) >> (s))
12 #define ROR(v, s) (LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s))))
16 typedef struct Instr Instr;
22 uchar op; /* super opcode */
24 uchar cond; /* bits 28-31 */
25 uchar store; /* bit 20 */
27 uchar rd; /* bits 12-15 */
28 uchar rn; /* bits 16-19 */
29 uchar rs; /* bits 0-11 (shifter operand) */
31 long imm; /* rotated imm */
32 char* curr; /* fill point in buffer */
33 char* end; /* end of buffer */
34 char* err; /* error message */
37 typedef struct Opcode Opcode;
41 void (*fmt)(Opcode*, Instr*);
42 uvlong (*foll)(Map*, Rgetter, Instr*, uvlong);
46 static void format(char*, Instr*, char*);
47 static char FRAMENAME[] = ".frame";
50 * Arm-specific debugger interface
53 static char *armexcep(Map*, Rgetter);
54 static int armfoll(Map*, uvlong, Rgetter, uvlong*);
55 static int arminst(Map*, uvlong, char, char*, int);
56 static int armdas(Map*, uvlong, char*, int);
57 static int arminstlen(Map*, uvlong);
64 {0, 0, 0, 0xD}, /* break point */
65 4, /* break point size */
67 leswab, /* short to local byte order */
68 leswal, /* long to local byte order */
69 leswav, /* long to local byte order */
70 risctrace, /* C traceback */
71 riscframe, /* Frame finder */
72 armexcep, /* print exception */
73 0, /* breakpoint fixup */
74 0, /* single precision float printer */
75 0, /* double precision float printer */
76 armfoll, /* following addresses */
77 arminst, /* print instruction */
78 armdas, /* dissembler */
79 arminstlen, /* instruction size */
83 armexcep(Map *map, Rgetter rget)
87 c = (*rget)(map, "TYPE");
88 switch ((int)c&0x1f) {
90 return "Fiq interrupt";
92 return "Mirq interrupt";
94 return "SVC/SWI Exception";
96 return "Prefetch Abort/Data Abort";
100 return "Undefined instruction/Breakpoint";
104 return "Undefined trap";
111 "EQ", "NE", "CS", "CC",
112 "MI", "PL", "VS", "VC",
113 "HI", "LS", "GE", "LT",
120 "<<", ">>", "->", "@>"
126 "???", "HU", "B", "H"
140 op = (w >> 25) & 0x7;
142 case 0: /* data processing r,r,r */
143 op = ((w >> 4) & 0xf);
145 op = 48+16; /* mul */
152 if(w & (1<<23)) { /* mullu */
153 op = (48+24+4+4+2+2+4);
154 if(w & (1<<22)) /* mull */
161 if((op & 0x9) == 0x9) /* ld/st byte/half s/u */
163 op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
166 op = (w >> 21) & 0xf;
170 if((w & (31<<7)) || (w & (1<<5)))
173 case 1: /* data processing i,r,r */
174 op = (48) + ((w >> 21) & 0xf);
176 case 2: /* load/store byte/word i(r) */
177 op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
179 case 3: /* load/store byte/word (r)(r) */
180 op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
182 case 4: /* block data transfer (r)(r) */
183 op = (48+24+4+4) + ((w >> 20) & 0x1);
185 case 5: /* branch / branch link */
186 op = (48+24+4+4+2) + ((w >> 24) & 0x1);
188 case 7: /* coprocessor crap */
189 op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
192 op = (48+24+4+4+2+2+4+4);
199 decode(Map *map, uvlong pc, Instr *i)
203 if(get4(map, pc, &w) < 0) {
204 werrstr("can't read instruction: %r");
209 i->cond = (w >> 28) & 0xF;
215 #pragma varargck argpos bprint 2
218 bprint(Instr *i, char *fmt, ...)
223 i->curr = vseprint(i->curr, i->end, fmt, arg);
236 if(!findsym(i->addr, CTEXT, &s)) {
237 if(debug)fprint(2,"fn not found @%llux: %r\n", i->addr);
241 if (!findlocal(&s, FRAMENAME, &s)) {
242 if(debug)fprint(2,"%s.%s not found @%s: %r\n", fn, FRAMENAME, s.name);
245 if(s.value > i->imm) {
247 offset = s.value-i->imm;
251 offset = i->imm-s.value-4;
254 if(!getauto(&s, offset, class, &s)) {
255 if(debug)fprint(2,"%s %s not found @%ux: %r\n", fn,
256 class == CAUTO ? " auto" : "param", offset);
259 bprint(i, "%s%c%lld%s", s.name, class == CPARAM ? '+' : '-', s.value, reg);
264 * Print value v as name[+offset]
267 gsymoff(char *buf, int n, long v, int space)
273 r = delta = 0; /* to shut compiler up */
275 r = findsym(v, space, &s);
281 if (v == 0 || r == 0 || delta >= 4096)
282 return snprint(buf, n, "#%lux", v);
283 if (strcmp(s.name, ".string") == 0)
284 return snprint(buf, n, "#%lux", v);
286 return snprint(buf, n, "%s", s.name);
287 if (s.type != 't' && s.type != 'T')
288 return snprint(buf, n, "%s+%llux", s.name, v-s.value);
290 return snprint(buf, n, "#%lux", v);
294 armdps(Opcode *o, Instr *i)
296 i->store = (i->w >> 20) & 1;
297 i->rn = (i->w >> 16) & 0xf;
298 i->rd = (i->w >> 12) & 0xf;
299 i->rs = (i->w >> 0) & 0xf;
300 if(i->rn == 15 && i->rs == 0) {
302 format("MOVW", i,"CPSR, R%d");
306 format("MOVW", i,"SPSR, R%d");
310 if(i->rn == 9 && i->rd == 15) {
312 format("MOVW", i, "R%s, CPSR");
316 format("MOVW", i, "R%s, SPSR");
320 format(o->o, i, o->a);
324 armdpi(Opcode *o, Instr *i)
329 v = (i->w >> 0) & 0xff;
330 c = (i->w >> 8) & 0xf;
332 v = (v<<30) | (v>>2);
336 i->store = (i->w >> 20) & 1;
337 i->rn = (i->w >> 16) & 0xf;
338 i->rd = (i->w >> 12) & 0xf;
341 /* RET is encoded as ADD #0,R14,R15 */
342 if((i->w & 0x0fffffff) == 0x028ef000){
343 format("RET%C", i, "");
346 if((i->w & 0x0ff0ffff) == 0x0280f000){
347 format("B%C", i, "0(R%n)");
350 format(o->o, i, o->a);
354 armsdti(Opcode *o, Instr *i)
359 if(!(i->w & (1<<23)))
361 i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
363 i->rn = (i->w >> 16) & 0xf;
364 i->rd = (i->w >> 12) & 0xf;
365 /* RET is encoded as LW.P x,R13,R15 */
366 if ((i->w & 0x0ffff000) == 0x049df000)
368 format("RET%C%p", i, "%I");
371 format(o->o, i, o->a);
374 /* arm V4 ld/st halfword, signed byte */
376 armhwby(Opcode *o, Instr *i)
378 i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
379 i->imm = (i->w & 0xf) | ((i->w >> 8) & 0xf);
380 if (!(i->w & (1 << 23)))
382 i->rn = (i->w >> 16) & 0xf;
383 i->rd = (i->w >> 12) & 0xf;
384 i->rs = (i->w >> 0) & 0xf;
385 format(o->o, i, o->a);
389 armsdts(Opcode *o, Instr *i)
391 i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
392 i->rs = (i->w >> 0) & 0xf;
393 i->rn = (i->w >> 16) & 0xf;
394 i->rd = (i->w >> 12) & 0xf;
395 format(o->o, i, o->a);
399 armbdt(Opcode *o, Instr *i)
401 i->store = (i->w >> 21) & 0x3; /* S & W bits */
402 i->rn = (i->w >> 16) & 0xf;
403 i->imm = i->w & 0xffff;
404 if(i->w == 0xe8fd8000)
405 format("RFE", i, "");
407 format(o->o, i, o->a);
411 armund(Opcode *o, Instr *i)
413 format(o->o, i, o->a);
417 armcdt(Opcode *o, Instr *i)
419 format(o->o, i, o->a);
423 armunk(Opcode *o, Instr *i)
425 format(o->o, i, o->a);
429 armb(Opcode *o, Instr *i)
436 i->imm = (v<<2) + i->addr + 8;
437 format(o->o, i, o->a);
441 armco(Opcode *o, Instr *i) /* coprocessor instructions */
447 i->rn = (i->w >> 16) & 0xf;
448 i->rd = (i->w >> 12) & 0xf;
450 cp = (i->w >> 8) & 0xf;
451 p = (i->w >> 5) & 0x7;
453 op = (i->w >> 21) & 0x07;
454 snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x", cp, op, i->rd, i->rn, i->rs, p);
456 op = (i->w >> 20) & 0x0f;
457 snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x", cp, op, i->rd, i->rn, i->rs, p);
459 format(o->o, i, buf);
463 armcondpass(Map *map, Rgetter rget, uchar cond)
471 psr = rget(map, "PSR");
487 case 8: return c && !z;
488 case 9: return !c || z;
489 case 10: return n == v;
490 case 11: return n != v;
491 case 12: return !z && (n == v);
492 case 13: return z && (n != v);
499 armshiftval(Map *map, Rgetter rget, Instr *i)
501 if(i->w & (1 << 25)) { /* immediate */
502 ulong imm = i->w & BITS(0, 7);
503 ulong s = (i->w & BITS(8, 11)) >> 7; /* this contains the *2 */
508 ulong s = (i->w & BITS(7,11)) >> 7;
510 sprint(buf, "R%ld", i->w & 0xf);
513 switch((i->w & BITS(4, 6)) >> 4) {
518 sprint(buf, "R%lud", s >> 1);
519 s = rget(map, buf) & 0xFF;
520 if(s >= 32) return 0;
525 sprint(buf, "R%ld", s >> 1);
526 s = rget(map, buf) & 0xFF;
527 if(s >= 32) return 0;
531 if((v & (1U<<31)) == 0)
537 sprint(buf, "R%ld", s >> 1);
538 s = rget(map, buf) & 0xFF;
540 if((v & (1U<<31)) == 0)
547 ulong c = (rget(map, "PSR") >> 29) & 1;
549 return (c << 31) | LSR(v, 1);
553 sprint(buf, "R%ld", (s>>1)&0xF);
555 if(s == 0 || (s & 0xF) == 0)
557 return ROR(v, s & 0xF);
568 for(i=0; i < 32 ; i++) {
577 armmaddr(Map *map, Rgetter rget, Instr *i)
584 rn = (i->w >> 16) & 0xf;
585 sprint(buf,"R%ld", rn);
588 nb = nbits(i->w & ((1 << 15) - 1));
590 switch((i->w >> 23) & 3) {
592 case 0: return (v - (nb*4)) + 4;
594 case 2: return v - (nb*4);
595 case 3: return v + 4;
600 armaddr(Map *map, Rgetter rget, Instr *i)
605 sprint(buf, "R%ld", (i->w >> 16) & 0xf);
608 if((i->w & (1<<24)) == 0) { /* POSTIDX */
609 sprint(buf, "R%ld", rn);
610 return rget(map, buf);
613 if((i->w & (1<<25)) == 0) { /* OFFSET */
614 sprint(buf, "R%ld", rn);
616 return rget(map, buf) + (i->w & BITS(0,11));
617 return rget(map, buf) - (i->w & BITS(0,11));
618 } else { /* REGOFF */
623 sprint(buf, "R%ld", i->w & 0xf);
626 switch((i->w & BITS(5,6)) >> 5) {
627 case 0: index = rm << ((i->w & BITS(7,11)) >> 7); break;
628 case 1: index = LSR(rm, ((i->w & BITS(7,11)) >> 7)); break;
629 case 2: index = ASR(rm, ((i->w & BITS(7,11)) >> 7)); break;
631 if((i->w & BITS(7,11)) == 0) {
632 c = (rget(map, "PSR") >> 29) & 1;
633 index = c << 31 | LSR(rm, 1);
635 index = ROR(rm, ((i->w & BITS(7,11)) >> 7));
646 armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc)
651 r = (i->w >> 12) & 0xf;
652 if(r != 15 || !armcondpass(map, rget, (i->w >> 28) & 0xf))
655 r = (i->w >> 16) & 0xf;
656 sprint(buf, "R%d", r);
658 return rget(map, buf) + armshiftval(map, rget, i);
662 armfmovm(Map *map, Rgetter rget, Instr *i, uvlong pc)
668 if(!v || !armcondpass(map, rget, (i->w>>28)&0xf))
671 addr = armmaddr(map, rget, i) + nbits(i->w & BITS(0,15));
672 if(get4(map, addr, &v) < 0) {
673 werrstr("can't read addr: %r");
680 armfbranch(Map *map, Rgetter rget, Instr *i, uvlong pc)
682 if(!armcondpass(map, rget, (i->w >> 28) & 0xf))
685 return pc + (((signed long)i->w << 8) >> 6) + 8;
689 armfmov(Map *map, Rgetter rget, Instr *i, uvlong pc)
693 rd = (i->w >> 12) & 0xf;
694 if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf))
698 /* BUG: Needs LDH/B, too */
699 if(((i->w>>26)&0x3) == 1) {
700 if(get4(map, armaddr(map, rget, i), &v) < 0) {
701 werrstr("can't read instruction: %r");
708 v = armshiftval(map, rget, i);
713 static Opcode opcodes[] =
715 "AND%C%S", armdps, 0, "R%s,R%n,R%d",
716 "EOR%C%S", armdps, 0, "R%s,R%n,R%d",
717 "SUB%C%S", armdps, 0, "R%s,R%n,R%d",
718 "RSB%C%S", armdps, 0, "R%s,R%n,R%d",
719 "ADD%C%S", armdps, armfadd, "R%s,R%n,R%d",
720 "ADC%C%S", armdps, 0, "R%s,R%n,R%d",
721 "SBC%C%S", armdps, 0, "R%s,R%n,R%d",
722 "RSC%C%S", armdps, 0, "R%s,R%n,R%d",
723 "TST%C%S", armdps, 0, "R%s,R%n",
724 "TEQ%C%S", armdps, 0, "R%s,R%n",
725 "CMP%C%S", armdps, 0, "R%s,R%n",
726 "CMN%C%S", armdps, 0, "R%s,R%n",
727 "ORR%C%S", armdps, 0, "R%s,R%n,R%d",
728 "MOVW%C%S", armdps, armfmov, "R%s,R%d",
729 "BIC%C%S", armdps, 0, "R%s,R%n,R%d",
730 "MVN%C%S", armdps, 0, "R%s,R%d",
733 "AND%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
734 "EOR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
735 "SUB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
736 "RSB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
737 "ADD%C%S", armdps, armfadd, "(R%s%h%m),R%n,R%d",
738 "ADC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
739 "SBC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
740 "RSC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
741 "TST%C%S", armdps, 0, "(R%s%h%m),R%n",
742 "TEQ%C%S", armdps, 0, "(R%s%h%m),R%n",
743 "CMP%C%S", armdps, 0, "(R%s%h%m),R%n",
744 "CMN%C%S", armdps, 0, "(R%s%h%m),R%n",
745 "ORR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
746 "MOVW%C%S", armdps, armfmov, "(R%s%h%m),R%d",
747 "BIC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
748 "MVN%C%S", armdps, 0, "(R%s%h%m),R%d",
751 "AND%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
752 "EOR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
753 "SUB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
754 "RSB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
755 "ADD%C%S", armdps, armfadd, "(R%s%hR%M),R%n,R%d",
756 "ADC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
757 "SBC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
758 "RSC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
759 "TST%C%S", armdps, 0, "(R%s%hR%M),R%n",
760 "TEQ%C%S", armdps, 0, "(R%s%hR%M),R%n",
761 "CMP%C%S", armdps, 0, "(R%s%hR%M),R%n",
762 "CMN%C%S", armdps, 0, "(R%s%hR%M),R%n",
763 "ORR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
764 "MOVW%C%S", armdps, armfmov, "(R%s%hR%M),R%d",
765 "BIC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
766 "MVN%C%S", armdps, 0, "(R%s%hR%M),R%d",
769 "AND%C%S", armdpi, 0, "$#%i,R%n,R%d",
770 "EOR%C%S", armdpi, 0, "$#%i,R%n,R%d",
771 "SUB%C%S", armdpi, 0, "$#%i,R%n,R%d",
772 "RSB%C%S", armdpi, 0, "$#%i,R%n,R%d",
773 "ADD%C%S", armdpi, armfadd, "$#%i,R%n,R%d",
774 "ADC%C%S", armdpi, 0, "$#%i,R%n,R%d",
775 "SBC%C%S", armdpi, 0, "$#%i,R%n,R%d",
776 "RSC%C%S", armdpi, 0, "$#%i,R%n,R%d",
777 "TST%C%S", armdpi, 0, "$#%i,R%n",
778 "TEQ%C%S", armdpi, 0, "$#%i,R%n",
779 "CMP%C%S", armdpi, 0, "$#%i,R%n",
780 "CMN%C%S", armdpi, 0, "$#%i,R%n",
781 "ORR%C%S", armdpi, 0, "$#%i,R%n,R%d",
782 "MOVW%C%S", armdpi, armfmov, "$#%i,R%d",
783 "BIC%C%S", armdpi, 0, "$#%i,R%n,R%d",
784 "MVN%C%S", armdpi, 0, "$#%i,R%d",
787 "MUL%C%S", armdpi, 0, "R%M,R%s,R%n",
788 "MULA%C%S", armdpi, 0, "R%M,R%s,R%n,R%d",
789 "SWPW", armdpi, 0, "R%s,(R%n),R%d",
790 "SWPB", armdpi, 0, "R%s,(R%n),R%d",
793 "MOV%u%C%p", armhwby, 0, "R%d,(R%n%UR%M)",
794 "MOV%u%C%p", armhwby, 0, "R%d,%I",
795 "MOV%u%C%p", armhwby, armfmov, "(R%n%UR%M),R%d",
796 "MOV%u%C%p", armhwby, armfmov, "%I,R%d",
799 "MOVW%C%p", armsdti, 0, "R%d,%I",
800 "MOVB%C%p", armsdti, 0, "R%d,%I",
801 "MOVW%C%p", armsdti, armfmov, "%I,R%d",
802 "MOVBU%C%p", armsdti, armfmov, "%I,R%d",
804 "MOVW%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
805 "MOVB%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
806 "MOVW%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
807 "MOVBU%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
809 "MOVM%C%P%a", armbdt, armfmovm, "[%r],(R%n)",
810 "MOVM%C%P%a", armbdt, armfmovm, "(R%n),[%r]",
812 "B%C", armb, armfbranch, "%b",
813 "BL%C", armb, armfbranch, "%b",
815 "CDP%C", armco, 0, "",
816 "CDP%C", armco, 0, "",
817 "MCR%C", armco, 0, "",
818 "MRC%C", armco, 0, "",
820 /* 48+24+4+4+2+2+4 */
821 "MULLU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
822 "MULALU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
823 "MULL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
824 "MULAL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
826 /* 48+24+4+4+2+2+4+4 */
827 "UNK", armunk, 0, "",
834 i->curr += gsymoff(i->curr, i->end-i->curr, i->imm, CANY);
837 static char *mode[] = { 0, "IA", "DB", "IB" };
838 static char *pw[] = { "P", "PW", 0, "W" };
839 static char *sw[] = { 0, "W", "S", "SW" };
842 format(char *mnemonic, Instr *i, char *f)
849 format(0, i, mnemonic);
855 for ( ; *f && i->curr < i->end; f++) {
862 case 'C': /* .CONDITION */
864 bprint(i, ".%s", cond[i->cond]);
867 case 'S': /* .STORE */
872 case 'P': /* P & U bits for block move */
873 n = (i->w >>23) & 0x3;
875 bprint(i, ".%s", mode[n]);
878 case 'p': /* P & W bits for single data xfer*/
880 bprint(i, ".%s", pw[i->store]);
883 case 'a': /* S & W bits for single data xfer*/
885 bprint(i, ".%s", sw[i->store]);
889 bprint(i, "%d", i->rs & 0xf);
893 bprint(i, "%lud", (i->w>>8) & 0xf);
897 bprint(i, "%lud", (i->w>>7) & 0x1f);
901 bprint(i, shtype[(i->w>>5) & 0x3]);
904 case 'u': /* Signed/unsigned Byte/Halfword */
905 bprint(i, hb[(i->w>>5) & 0x3]);
916 /* convert load of offset(PC) to a load immediate */
917 if (get4(i->map, i->addr+i->imm+8, (ulong*)&i->imm) > 0)
928 if (get4(i->map, i->addr+4, &nxti) > 0) {
929 if ((nxti & 0x0e0f0fff) == 0x060c000b) {
946 bprint(i, fmt, i->rn);
949 bprint(i, fmt, i->imm, i->rn);
951 case 'U': /* Add/subtract from base */
952 bprint(i, addsub[(i->w >> 23) & 1]);
956 bprint(i, "%d", i->rn);
960 bprint(i, "%d", i->rd);
964 bprint(i, "%lux", i->imm);
968 i->curr += symoff(i->curr, i->end-i->curr,
973 i->curr += gsymoff(i->curr, i->end-i->curr,
993 bprint(i, "R%d-R%d", m, j-1);
1006 bprint(i, "%%%c", *f);
1014 printins(Map *map, uvlong pc, char *buf, int n)
1020 if(decode(map, pc, &i) < 0)
1023 (*opcodes[i.op].fmt)(&opcodes[i.op], &i);
1028 arminst(Map *map, uvlong pc, char modifier, char *buf, int n)
1031 return printins(map, pc, buf, n);
1035 armdas(Map *map, uvlong pc, char *buf, int n)
1041 if(decode(map, pc, &i) < 0)
1043 if(i.end-i.curr > 8)
1044 i.curr = _hexify(buf, i.w, 7);
1050 arminstlen(Map *map, uvlong pc)
1054 if(decode(map, pc, &i) < 0)
1060 armfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
1065 if(decode(map, pc, &i) < 0)
1068 if(opcodes[i.op].foll) {
1069 d = (*opcodes[i.op].foll)(map, rget, &i, pc);