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 {0x70, 0x00, 0x20, 0xE1}, /* break point */ /* E1200070 */
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/Breakpoint";
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 if((w & 0x0ff00080) == 0x01200000) {
147 else if (op > 0 && op < 4)
148 op += 124; /* bx, blx */
153 op = ((w >> 4) & 0xf);
155 op = 48+16; /* mul, swp or *rex */
156 if((w & 0x0ff00fff) == 0x01900f9f) {
160 if((w & 0x0ff00ff0) == 0x01800f90) {
170 if(w & (1<<23)) { /* mullu */
171 op = (48+24+4+4+2+2+4);
172 if(w & (1<<22)) /* mull */
179 if((op & 0x9) == 0x9) /* ld/st byte/half s/u */
181 op = (48+16+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
184 op = (w >> 21) & 0xf;
188 if(w & (31<<7 | 3<<5))
191 case 1: /* data processing i,r,r */
192 op = (48) + ((w >> 21) & 0xf);
194 case 2: /* load/store byte/word i(r) */
195 if ((w & 0xffffff8f) == 0xf57ff00f) { /* barriers, clrex */
197 switch ((w >> 4) & 7) {
217 op = (48+24) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
219 case 3: /* load/store byte/word (r)(r) */
220 op = (48+24+4) + ((w >> 22) & 0x1) + ((w >> 19) & 0x2);
222 case 4: /* block data transfer (r)(r) */
223 if ((w & 0xfe50ffff) == 0xf8100a00) { /* v7 RFE */
227 op = (48+24+4+4) + ((w >> 20) & 0x1);
229 case 5: /* branch / branch link */
230 op = (48+24+4+4+2) + ((w >> 24) & 0x1);
232 case 7: /* coprocessor crap */
234 if(cp == 10 || cp == 11){ /* vfp */
236 /* vfp register transfer */
237 switch((w >> 21) & 0x7){
239 op = 118 + ((w >> 20) & 0x1);
242 op = 118+2 + ((w >> 20) & 0x1);
245 op = (48+24+4+4+2+2+4+4);
250 /* vfp data processing */
251 if(((w >> 23) & 0x1) == 0){
252 op = 100 + ((w >> 19) & 0x6) + ((w >> 6) & 0x1);
255 switch(((w >> 19) & 0x6) + ((w >> 6) & 0x1)){
260 if(((w >> 19) & 0x1) == 0){
261 if(((w >> 17) & 0x1) == 0)
262 op = 109 + ((w >> 16) & 0x4) +
265 else if(((w >> 16) & 0x7) == 0x7)
269 switch((w >> 16) & 0x7){
279 op = (48+24+4+4+2+2+4+4);
282 op = (48+24+4+4+2+2) + ((w >> 3) & 0x2) + ((w >> 20) & 0x1);
284 case 6: /* vfp load / store */
285 if(((w >> 21) &0x9) == 0x8){
286 op = 122 + ((w >> 20) & 0x1);
291 op = (48+24+4+4+2+2+4+4);
298 decode(Map *map, uvlong pc, Instr *i)
302 if(get4(map, pc, &w) < 0) {
303 werrstr("can't read instruction: %r");
308 i->cond = (w >> 28) & 0xF;
314 #pragma varargck argpos bprint 2
317 bprint(Instr *i, char *fmt, ...)
322 i->curr = vseprint(i->curr, i->end, fmt, arg);
335 if(!findsym(i->addr, CTEXT, &s)) {
336 if(debug)fprint(2,"fn not found @%llux: %r\n", i->addr);
340 if (!findlocal(&s, FRAMENAME, &s)) {
341 if(debug)fprint(2,"%s.%s not found @%s: %r\n", fn, FRAMENAME, s.name);
344 if(s.value > i->imm) {
346 offset = s.value-i->imm;
350 offset = i->imm-s.value-4;
353 if(!getauto(&s, offset, class, &s)) {
354 if(debug)fprint(2,"%s %s not found @%ux: %r\n", fn,
355 class == CAUTO ? " auto" : "param", offset);
358 bprint(i, "%s%c%lld%s", s.name, class == CPARAM ? '+' : '-', s.value, reg);
363 * Print value v as name[+offset]
366 gsymoff(char *buf, int n, ulong v, int space)
372 r = delta = 0; /* to shut compiler up */
374 r = findsym(v, space, &s);
380 if (v == 0 || r == 0 || delta >= 4096)
381 return snprint(buf, n, "#%lux", v);
382 if (strcmp(s.name, ".string") == 0)
383 return snprint(buf, n, "#%lux", v);
385 return snprint(buf, n, "%s", s.name);
386 if (s.type != 't' && s.type != 'T')
387 return snprint(buf, n, "%s+%llux", s.name, v-s.value);
389 return snprint(buf, n, "#%lux", v);
393 armdps(Opcode *o, Instr *i)
395 i->store = (i->w >> 20) & 1;
396 i->rn = (i->w >> 16) & 0xf;
397 i->rd = (i->w >> 12) & 0xf;
398 i->rs = (i->w >> 0) & 0xf;
399 if(i->rn == 15 && i->rs == 0) {
401 format("MOVW", i,"CPSR, R%d");
405 format("MOVW", i,"SPSR, R%d");
409 if(i->rn == 9 && i->rd == 15) {
411 format("MOVW", i, "R%s, CPSR");
415 format("MOVW", i, "R%s, SPSR");
421 format("MOVW", i, "PSR, %x");
425 format("MOVW", i, "%x, PSR");
429 format(o->o, i, o->a);
433 armdpi(Opcode *o, Instr *i)
438 v = (i->w >> 0) & 0xff;
439 c = (i->w >> 8) & 0xf;
441 v = (v<<30) | (v>>2);
445 i->store = (i->w >> 20) & 1;
446 i->rn = (i->w >> 16) & 0xf;
447 i->rd = (i->w >> 12) & 0xf;
450 /* RET is encoded as ADD #0,R14,R15 */
451 if((i->w & 0x0fffffff) == 0x028ef000){
452 format("RET%C", i, "");
455 if((i->w & 0x0ff0ffff) == 0x0280f000){
456 format("B%C", i, "0(R%n)");
459 format(o->o, i, o->a);
463 armsdti(Opcode *o, Instr *i)
468 if(!(i->w & (1<<23)))
470 i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
472 i->rn = (i->w >> 16) & 0xf;
473 i->rd = (i->w >> 12) & 0xf;
474 /* RET is encoded as LW.P x,R13,R15 */
475 if ((i->w & 0x0ffff000) == 0x049df000)
477 format("RET%C%p", i, "%I");
480 format(o->o, i, o->a);
484 armvstdi(Opcode *o, Instr *i)
488 v = (i->w & 0xff) << 2;
489 if(!(i->w & (1<<23)))
492 i->rn = (i->w >> 16) & 0xf;
493 i->rd = (i->w >> 12) & 0xf;
494 format(o->o, i, o->a);
497 /* arm V4 ld/st halfword, signed byte */
499 armhwby(Opcode *o, Instr *i)
501 i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
502 i->imm = (i->w & 0xf) | ((i->w >> 4) & 0xf0);
503 if (!(i->w & (1 << 23)))
505 i->rn = (i->w >> 16) & 0xf;
506 i->rd = (i->w >> 12) & 0xf;
507 i->rs = (i->w >> 0) & 0xf;
508 format(o->o, i, o->a);
512 armsdts(Opcode *o, Instr *i)
514 i->store = ((i->w >> 23) & 0x2) | ((i->w >>21) & 0x1);
515 i->rs = (i->w >> 0) & 0xf;
516 i->rn = (i->w >> 16) & 0xf;
517 i->rd = (i->w >> 12) & 0xf;
518 format(o->o, i, o->a);
522 armbdt(Opcode *o, Instr *i)
524 i->store = (i->w >> 21) & 0x3; /* S & W bits */
525 i->rn = (i->w >> 16) & 0xf;
526 i->imm = i->w & 0xffff;
527 if(i->w == 0xe8fd8000)
528 format("RFE", i, "");
530 format(o->o, i, o->a);
534 armund(Opcode *o, Instr *i)
536 format(o->o, i, o->a);
540 armcdt(Opcode *o, Instr *i)
542 format(o->o, i, o->a);
546 armunk(Opcode *o, Instr *i)
548 format(o->o, i, o->a);
552 armb(Opcode *o, Instr *i)
559 i->imm = (v<<2) + i->addr + 8;
560 format(o->o, i, o->a);
564 armbpt(Opcode *o, Instr *i)
566 i->imm = ((i->w >> 4) & 0xfff0) | (i->w &0xf);
567 format(o->o, i, o->a);
571 armco(Opcode *o, Instr *i) /* coprocessor instructions */
577 i->rn = (i->w >> 16) & 0xf;
578 i->rd = (i->w >> 12) & 0xf;
580 cp = (i->w >> 8) & 0xf;
581 p = (i->w >> 5) & 0x7;
583 op = (i->w >> 21) & 0x07;
584 snprint(buf, sizeof(buf), "#%x, #%x, R%d, C(%d), C(%d), #%x", cp, op, i->rd, i->rn, i->rs, p);
586 op = (i->w >> 20) & 0x0f;
587 snprint(buf, sizeof(buf), "#%x, #%x, C(%d), C(%d), C(%d), #%x", cp, op, i->rd, i->rn, i->rs, p);
589 format(o->o, i, buf);
593 armcondpass(Map *map, Rgetter rget, uchar cond)
601 psr = rget(map, "PSR");
617 case 8: return c && !z;
618 case 9: return !c || z;
619 case 10: return n == v;
620 case 11: return n != v;
621 case 12: return !z && (n == v);
622 case 13: return z || (n != v);
629 armshiftval(Map *map, Rgetter rget, Instr *i)
631 if(i->w & (1 << 25)) { /* immediate */
632 ulong imm = i->w & BITS(0, 7);
633 ulong s = (i->w & BITS(8, 11)) >> 7; /* this contains the *2 */
638 ulong s = (i->w & BITS(7,11)) >> 7;
640 sprint(buf, "R%ld", i->w & 0xf);
643 switch((i->w & BITS(4, 6)) >> 4) {
648 sprint(buf, "R%lud", s >> 1);
649 s = rget(map, buf) & 0xFF;
650 if(s >= 32) return 0;
655 sprint(buf, "R%ld", s >> 1);
656 s = rget(map, buf) & 0xFF;
657 if(s >= 32) return 0;
661 if((v & (1U<<31)) == 0)
667 sprint(buf, "R%ld", s >> 1);
668 s = rget(map, buf) & 0xFF;
670 if((v & (1U<<31)) == 0)
677 ulong c = (rget(map, "PSR") >> 29) & 1;
679 return (c << 31) | LSR(v, 1);
683 sprint(buf, "R%ld", s >> 1);
684 s = rget(map, buf) & 0x1F;
698 for(i=0; i < 32 ; i++) {
707 armmaddr(Map *map, Rgetter rget, Instr *i)
714 rn = (i->w >> 16) & 0xf;
715 sprint(buf,"R%ld", rn);
718 nb = nbits(i->w & ((1 << 15) - 1));
720 switch((i->w >> 23) & 3) {
722 case 0: return (v - (nb*4)) + 4;
724 case 2: return v - (nb*4);
725 case 3: return v + 4;
730 armaddr(Map *map, Rgetter rget, Instr *i)
735 snprint(buf, sizeof(buf), "R%ld", (i->w >> 16) & 0xf);
738 if((i->w & (1<<24)) == 0) /* POSTIDX */
741 if((i->w & (1<<25)) == 0) { /* OFFSET */
743 return rn + (i->w & BITS(0,11));
744 return rn - (i->w & BITS(0,11));
745 } else { /* REGOFF */
750 sprint(buf, "R%ld", i->w & 0xf);
753 switch((i->w & BITS(5,6)) >> 5) {
754 case 0: index = rm << ((i->w & BITS(7,11)) >> 7); break;
755 case 1: index = LSR(rm, ((i->w & BITS(7,11)) >> 7)); break;
756 case 2: index = ASR(rm, ((i->w & BITS(7,11)) >> 7)); break;
758 if((i->w & BITS(7,11)) == 0) {
759 c = (rget(map, "PSR") >> 29) & 1;
760 index = c << 31 | LSR(rm, 1);
762 index = ROR(rm, ((i->w & BITS(7,11)) >> 7));
773 armfadd(Map *map, Rgetter rget, Instr *i, uvlong pc)
778 r = (i->w >> 12) & 0xf;
779 if(r != 15 || !armcondpass(map, rget, (i->w >> 28) & 0xf))
782 r = (i->w >> 16) & 0xf;
783 sprint(buf, "R%d", r);
785 return rget(map, buf) + armshiftval(map, rget, i);
789 armfbx(Map *map, Rgetter rget, Instr *i, uvlong pc)
794 if(!armcondpass(map, rget, (i->w>>28)&0xf))
796 r = (i->w >> 0) & 0xf;
797 sprint(buf, "R%d", r);
798 return rget(map, buf);
802 armfmovm(Map *map, Rgetter rget, Instr *i, uvlong pc)
808 if(!v || !armcondpass(map, rget, (i->w>>28)&0xf))
811 addr = armmaddr(map, rget, i) + nbits(i->w & BITS(0,15));
812 if(get4(map, addr, &v) < 0) {
813 werrstr("can't read addr: %r");
820 armfbranch(Map *map, Rgetter rget, Instr *i, uvlong pc)
822 if(!armcondpass(map, rget, (i->w >> 28) & 0xf))
825 return pc + (((signed long)i->w << 8) >> 6) + 8;
829 armfmov(Map *map, Rgetter rget, Instr *i, uvlong pc)
833 rd = (i->w >> 12) & 0xf;
834 if(rd != 15 || !armcondpass(map, rget, (i->w>>28)&0xf))
838 /* BUG: Needs LDH/B, too */
839 if(((i->w>>26)&0x3) == 1) {
840 if(get4(map, armaddr(map, rget, i), &v) < 0) {
841 werrstr("can't read instruction: %r");
848 v = armshiftval(map, rget, i);
853 static Opcode opcodes[] =
855 "AND%C%S", armdps, 0, "R%s,R%n,R%d",
856 "EOR%C%S", armdps, 0, "R%s,R%n,R%d",
857 "SUB%C%S", armdps, 0, "R%s,R%n,R%d",
858 "RSB%C%S", armdps, 0, "R%s,R%n,R%d",
859 "ADD%C%S", armdps, armfadd, "R%s,R%n,R%d",
860 "ADC%C%S", armdps, 0, "R%s,R%n,R%d",
861 "SBC%C%S", armdps, 0, "R%s,R%n,R%d",
862 "RSC%C%S", armdps, 0, "R%s,R%n,R%d",
863 "TST%C%S", armdps, 0, "R%s,R%n",
864 "TEQ%C%S", armdps, 0, "R%s,R%n",
865 "CMP%C%S", armdps, 0, "R%s,R%n",
866 "CMN%C%S", armdps, 0, "R%s,R%n",
867 "ORR%C%S", armdps, 0, "R%s,R%n,R%d",
868 "MOVW%C%S", armdps, armfmov, "R%s,R%d",
869 "BIC%C%S", armdps, 0, "R%s,R%n,R%d",
870 "MVN%C%S", armdps, 0, "R%s,R%d",
873 "AND%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
874 "EOR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
875 "SUB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
876 "RSB%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
877 "ADD%C%S", armdps, armfadd, "(R%s%h%m),R%n,R%d",
878 "ADC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
879 "SBC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
880 "RSC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
881 "TST%C%S", armdps, 0, "(R%s%h%m),R%n",
882 "TEQ%C%S", armdps, 0, "(R%s%h%m),R%n",
883 "CMP%C%S", armdps, 0, "(R%s%h%m),R%n",
884 "CMN%C%S", armdps, 0, "(R%s%h%m),R%n",
885 "ORR%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
886 "MOVW%C%S", armdps, armfmov, "(R%s%h%m),R%d",
887 "BIC%C%S", armdps, 0, "(R%s%h%m),R%n,R%d",
888 "MVN%C%S", armdps, 0, "(R%s%h%m),R%d",
891 "AND%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
892 "EOR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
893 "SUB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
894 "RSB%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
895 "ADD%C%S", armdps, armfadd, "(R%s%hR%M),R%n,R%d",
896 "ADC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
897 "SBC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
898 "RSC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
899 "TST%C%S", armdps, 0, "(R%s%hR%M),R%n",
900 "TEQ%C%S", armdps, 0, "(R%s%hR%M),R%n",
901 "CMP%C%S", armdps, 0, "(R%s%hR%M),R%n",
902 "CMN%C%S", armdps, 0, "(R%s%hR%M),R%n",
903 "ORR%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
904 "MOVW%C%S", armdps, armfmov, "(R%s%hR%M),R%d",
905 "BIC%C%S", armdps, 0, "(R%s%hR%M),R%n,R%d",
906 "MVN%C%S", armdps, 0, "(R%s%hR%M),R%d",
909 "AND%C%S", armdpi, 0, "$#%i,R%n,R%d",
910 "EOR%C%S", armdpi, 0, "$#%i,R%n,R%d",
911 "SUB%C%S", armdpi, 0, "$#%i,R%n,R%d",
912 "RSB%C%S", armdpi, 0, "$#%i,R%n,R%d",
913 "ADD%C%S", armdpi, armfadd, "$#%i,R%n,R%d",
914 "ADC%C%S", armdpi, 0, "$#%i,R%n,R%d",
915 "SBC%C%S", armdpi, 0, "$#%i,R%n,R%d",
916 "RSC%C%S", armdpi, 0, "$#%i,R%n,R%d",
917 "TST%C%S", armdpi, 0, "$#%i,R%n",
918 "TEQ%C%S", armdpi, 0, "$#%i,R%n",
919 "CMP%C%S", armdpi, 0, "$#%i,R%n",
920 "CMN%C%S", armdpi, 0, "$#%i,R%n",
921 "ORR%C%S", armdpi, 0, "$#%i,R%n,R%d",
922 "MOVW%C%S", armdpi, armfmov, "$#%i,R%d",
923 "BIC%C%S", armdpi, 0, "$#%i,R%n,R%d",
924 "MVN%C%S", armdpi, 0, "$#%i,R%d",
927 "MUL%C%S", armdpi, 0, "R%M,R%s,R%n",
928 "MULA%C%S", armdpi, 0, "R%M,R%s,R%n,R%d",
929 "SWPW", armdpi, 0, "R%s,(R%n),R%d",
930 "SWPB", armdpi, 0, "R%s,(R%n),R%d",
933 "MOV%u%C%p", armhwby, 0, "R%d,(R%n%UR%s)",
934 "MOV%u%C%p", armhwby, 0, "R%d,%I",
935 "MOV%u%C%p", armhwby, armfmov, "(R%n%UR%s),R%d",
936 "MOV%u%C%p", armhwby, armfmov, "%I,R%d",
939 "MOVW%C%p", armsdti, 0, "R%d,%I",
940 "MOVB%C%p", armsdti, 0, "R%d,%I",
941 "MOVW%C%p", armsdti, armfmov, "%I,R%d",
942 "MOVBU%C%p", armsdti, armfmov, "%I,R%d",
944 "MOVW%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
945 "MOVB%C%p", armsdts, 0, "R%d,(R%s%h%m)(R%n)",
946 "MOVW%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
947 "MOVBU%C%p", armsdts, armfmov, "(R%s%h%m)(R%n),R%d",
949 "MOVM%C%P%a", armbdt, armfmovm, "[%r],(R%n)",
950 "MOVM%C%P%a", armbdt, armfmovm, "(R%n),[%r]",
952 "B%C", armb, armfbranch, "%b",
953 "BL%C", armb, armfbranch, "%b",
955 "CDP%C", armco, 0, "",
956 "CDP%C", armco, 0, "",
957 "MCR%C", armco, 0, "",
958 "MRC%C", armco, 0, "",
960 /* 48+24+4+4+2+2+4 */
961 "MULLU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
962 "MULALU%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
963 "MULL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
964 "MULAL%C%S", armdpi, 0, "R%M,R%s,(R%n,R%d)",
966 /* 48+24+4+4+2+2+4+4 = 92 */
967 "UNK", armunk, 0, "",
969 /* new v7 arch instructions */
971 "LDREX", armdpi, 0, "(R%n),R%d",
972 "STREX", armdpi, 0, "R%s,(R%n),R%d",
973 "CLREX", armunk, 0, "",
976 "DSB", armunk, 0, "",
977 "DMB", armunk, 0, "",
978 "ISB", armunk, 0, "",
981 "RFEV7%P%a", armbdt, 0, "(R%n)",
984 "MLA%f%C", armdps, 0, "F%s,F%n,F%d",
985 "MLS%f%C", armdps, 0, "F%s,F%n,F%d",
986 "NMLS%f%C", armdps, 0, "F%s,F%n,F%d",
987 "NMLA%f%C", armdps, 0, "F%s,F%n,F%d",
988 "MUL%f%C", armdps, 0, "F%s,F%n,F%d",
989 "NMUL%f%C", armdps, 0, "F%s,F%n,F%d",
990 "ADD%f%C", armdps, 0, "F%s,F%n,F%d",
991 "SUB%f%C", armdps, 0, "F%s,F%n,F%d",
992 "DIV%f%C", armdps, 0, "F%s,F%n,F%d",
995 "MOV%f%C", armdps, 0, "F%s,F%d",
996 "ABS%f%C", armdps, 0, "F%s,F%d",
997 "NEG%f%C", armdps, 0, "F%s,F%d",
998 "SQRT%f%C", armdps, 0, "F%s,F%d",
999 "CMP%f%C", armdps, 0, "F%s,F%d",
1000 "CMPE%f%C", armdps, 0, "F%s,F%d",
1001 "CMP%f%C", armdps, 0, "$0.0,F%d",
1002 "CMPE%f%C", armdps, 0, "$0.0,F%d",
1005 "MOV%F%R%C", armdps, 0, "F%s,F%d",
1008 "MOVW%C", armdps, 0, "R%d,F%n",
1009 "MOVW%C", armdps, 0, "F%n,R%d",
1010 "MOVW%C", armdps, 0, "R%d,%x",
1011 "MOVW%C", armdps, 0, "%x,R%d",
1014 "MOV%f%C", armvstdi, 0, "F%d,%I",
1015 "MOV%f%C", armvstdi, 0, "%I,F%d",
1018 "BKPT%C", armbpt, 0, "$#%i",
1019 "BX%C", armdps, armfbx, "(R%s)",
1020 "BXJ%C", armdps, armfbx, "(R%s)",
1021 "BLX%C", armdps, armfbx, "(R%s)",
1028 i->curr += gsymoff(i->curr, i->end-i->curr, i->imm, CANY);
1031 static char *mode[] = { 0, "IA", "DB", "IB" };
1032 static char *pw[] = { "P", "PW", 0, "W" };
1033 static char *sw[] = { 0, "W", "S", "SW" };
1036 format(char *mnemonic, Instr *i, char *f)
1043 format(0, i, mnemonic);
1047 if(i->curr < i->end)
1049 for ( ; *f && i->curr < i->end; f++) {
1056 case 'C': /* .CONDITION */
1058 bprint(i, ".%s", cond[i->cond]);
1061 case 'S': /* .STORE */
1066 case 'P': /* P & U bits for block move */
1067 n = (i->w >>23) & 0x3;
1069 bprint(i, ".%s", mode[n]);
1072 case 'p': /* P & W bits for single data xfer*/
1074 bprint(i, ".%s", pw[i->store]);
1077 case 'a': /* S & W bits for single data xfer*/
1079 bprint(i, ".%s", sw[i->store]);
1083 bprint(i, "%d", i->rs & 0xf);
1087 bprint(i, "%lud", (i->w>>8) & 0xf);
1091 n = (i->w>>7) & 0x1f;
1092 if (n == 0 && (i->w & (3<<5)) != 0)
1098 bprint(i, shtype[(i->w>>5) & 0x3]);
1101 case 'u': /* Signed/unsigned Byte/Halfword */
1102 bprint(i, hb[(i->w>>5) & 0x3]);
1113 /* convert load of offset(PC) to a load immediate */
1114 if (get4(i->map, i->addr+i->imm+8, (ulong*)&i->imm) > 0)
1125 if (get4(i->map, i->addr+4, &nxti) > 0) {
1126 if ((nxti & 0x0e0f0fff) == 0x060c000b) {
1143 bprint(i, fmt, i->rn);
1146 bprint(i, fmt, i->imm, i->rn);
1148 case 'U': /* Add/subtract from base */
1149 bprint(i, addsub[(i->w >> 23) & 1]);
1153 bprint(i, "%d", i->rn);
1157 bprint(i, "%d", i->rd);
1161 bprint(i, "%lux", i->imm);
1165 i->curr += symoff(i->curr, i->end-i->curr,
1166 (ulong)i->imm, CTEXT);
1170 i->curr += gsymoff(i->curr, i->end-i->curr,
1175 switch((i->w >> 8) & 0xF){
1186 switch(((i->w >> 15) & 0xE) + ((i->w >> 8) & 0x1)){
1188 bprint(i, ((i->w >> 7) & 0x1)? "WF" : "WF.U");
1191 bprint(i, ((i->w >> 7) & 0x1)? "WD" : "WD.U");
1215 if(((i->w >> 7) & 0x1) == 0)
1231 bprint(i, "FPS(%d)", i->rn);
1250 bprint(i, "R%d", m);
1252 bprint(i, "R%d-R%d", m, j-1);
1265 bprint(i, "%%%c", *f);
1273 printins(Map *map, uvlong pc, char *buf, int n)
1279 if(decode(map, pc, &i) < 0)
1282 (*opcodes[i.op].fmt)(&opcodes[i.op], &i);
1287 arminst(Map *map, uvlong pc, char modifier, char *buf, int n)
1290 return printins(map, pc, buf, n);
1294 armdas(Map *map, uvlong pc, char *buf, int n)
1300 if(decode(map, pc, &i) < 0)
1302 if(i.end-i.curr > 8)
1303 i.curr = _hexify(buf, i.w, 7);
1309 arminstlen(Map *map, uvlong pc)
1313 if(decode(map, pc, &i) < 0)
1319 armfoll(Map *map, uvlong pc, Rgetter rget, uvlong *foll)
1324 if(decode(map, pc, &i) < 0)
1327 if(opcodes[i.op].foll) {
1328 d = (*opcodes[i.op].foll)(map, rget, &i, pc);