8 static char* shtype[4] =
15 static char* cond[16] =
17 ".EQ", ".NE", ".HS", ".LO",
18 ".MI", ".PL", ".VS", ".VC",
19 ".HI", ".LS", ".GE", ".LT",
20 ".GT", ".LE", "", ".NO",
35 void Ilsm(ulong inst);
44 { Idp0, "AND", Iarith }, /* 00 - r,r,r */
45 { Idp0, "EOR", Iarith }, /* 01 */
46 { Idp0, "SUB", Iarith }, /* 02 */
47 { Idp0, "RSB", Iarith }, /* 03 */
48 { Idp0, "ADD", Iarith }, /* 04 */
49 { Idp0, "ADC", Iarith }, /* 05 */
50 { Idp0, "SBC", Iarith }, /* 06 */
51 { Idp0, "RSC", Iarith }, /* 07 */
52 { Idp0, "TST", Iarith }, /* 08 */
53 { Idp0, "TEQ", Iarith }, /* 09 */
55 { Idp0, "CMP", Iarith }, /* 10 */
56 { Idp0, "CMN", Iarith }, /* 11 */
57 { Idp0, "ORR", Iarith }, /* 12 */
58 { Idp0, "MOV", Iarith }, /* 13 */
59 { Idp0, "BIC", Iarith }, /* 14 */
60 { Idp0, "MVN", Iarith }, /* 15 */
61 { Idp1, "AND", Iarith }, /* 16 */
62 { Idp1, "EOR", Iarith }, /* 17 */
63 { Idp1, "SUB", Iarith }, /* 18 */
64 { Idp1, "RSB", Iarith }, /* 19 */
66 { Idp1, "ADD", Iarith }, /* 20 */
67 { Idp1, "ADC", Iarith }, /* 21 */
68 { Idp1, "SBC", Iarith }, /* 22 */
69 { Idp1, "RSC", Iarith }, /* 23 */
70 { Idp1, "TST", Iarith }, /* 24 */
71 { Idp1, "TEQ", Iarith }, /* 25 */
72 { Idp1, "CMP", Iarith }, /* 26 */
73 { Idp1, "CMN", Iarith }, /* 27 */
74 { Idp1, "ORR", Iarith }, /* 28 */
75 { Idp1, "MOV", Iarith }, /* 29 */
77 { Idp1, "BIC", Iarith }, /* 30 */
78 { Idp1, "MVN", Iarith }, /* 31 */
79 { Idp2, "AND", Iarith }, /* 32 */
80 { Idp2, "EOR", Iarith }, /* 33 */
81 { Idp2, "SUB", Iarith }, /* 34 */
82 { Idp2, "RSB", Iarith }, /* 35 */
83 { Idp2, "ADD", Iarith }, /* 36 */
84 { Idp2, "ADC", Iarith }, /* 37 */
85 { Idp2, "SBC", Iarith }, /* 38 */
86 { Idp2, "RSC", Iarith }, /* 39 */
88 { Idp2, "TST", Iarith }, /* 40 */
89 { Idp2, "TEQ", Iarith }, /* 41 */
90 { Idp2, "CMP", Iarith }, /* 42 */
91 { Idp2, "CMN", Iarith }, /* 43 */
92 { Idp2, "ORR", Iarith }, /* 44 */
93 { Idp2, "MOV", Iarith }, /* 45 */
94 { Idp2, "BIC", Iarith }, /* 46 */
95 { Idp2, "MVN", Iarith }, /* 47 */
96 { Idp3, "AND", Iarith }, /* 48 - i,r,r */
97 { Idp3, "EOR", Iarith }, /* 49 */
99 { Idp3, "SUB", Iarith }, /* 50 */
100 { Idp3, "RSB", Iarith }, /* 51 */
101 { Idp3, "ADD", Iarith }, /* 52 */
102 { Idp3, "ADC", Iarith }, /* 53 */
103 { Idp3, "SBC", Iarith }, /* 54 */
104 { Idp3, "RSC", Iarith }, /* 55 */
105 { Idp3, "TST", Iarith }, /* 56 */
106 { Idp3, "TEQ", Iarith }, /* 57 */
107 { Idp3, "CMP", Iarith }, /* 58 */
108 { Idp3, "CMN", Iarith }, /* 59 */
110 { Idp3, "ORR", Iarith }, /* 60 */
111 { Idp3, "MOV", Iarith }, /* 61 */
112 { Idp3, "BIC", Iarith }, /* 62 */
113 { Idp3, "MVN", Iarith }, /* 63 */
114 { Imul, "MUL", Iarith }, /* 64 */
115 { Imula, "MULA", Iarith }, /* 65 */
117 { Iswap, "SWPW", Imem }, /* 66 */
118 { Iswap, "SWPBU", Imem }, /* 67 */
120 { Imem2, "MOV", Imem }, /* 68 load/store h/sb */
121 { Imem2, "MOV", Imem }, /* 69 */
122 { Imem2, "MOV", Imem }, /* 70 */
123 { Imem2, "MOV", Imem }, /* 71 */
125 { Imem1, "MOVW", Imem }, /* 72 load/store w/ub i,r */
126 { Imem1, "MOVB", Imem }, /* 73 */
127 { Imem1, "MOVW", Imem }, /* 74 */
128 { Imem1, "MOVB", Imem }, /* 75 */
129 { Imem1, "MOVW", Imem }, /* 76 load/store r,r */
130 { Imem1, "MOVB", Imem }, /* 77 */
131 { Imem1, "MOVW", Imem }, /* 78 */
132 { Imem1, "MOVB", Imem }, /* 79 */
134 { Ilsm, "LDM", Imem }, /* 80 block move r,r */
135 { Ilsm, "STM", Imem }, /* 81 */
136 { Ib, "B", Ibranch }, /* 82 branch */
137 { Ibl, "BL", Ibranch }, /* 83 */
138 { Ssyscall, "SWI", Isyscall }, /* 84 co processor */
139 { undef, "undef" }, /* 85 */
140 { undef, "undef" }, /* 86 */
141 { undef, "undef" }, /* 87 */
142 { Imull, "MULLU", Iarith }, /* 88 */
143 { Imull, "MULALU", Iarith }, /* 89 */
144 { Imull, "MULL", Iarith }, /* 90 */
145 { Imull, "MULAL", Iarith }, /* 91 */
146 { undef, "undef" }, /* 92 */
155 case 0x0: /* eq */ return (reg.cc1 == reg.cc2);
156 case 0x1: /* ne */ return (reg.cc1 != reg.cc2);
157 case 0x2: /* hs */ return ((ulong)reg.cc1 >= (ulong)reg.cc2);
158 case 0x3: /* lo */ return ((ulong)reg.cc1 < (ulong)reg.cc2);
159 case 0x4: /* mi */ return (reg.cc1 - reg.cc2 < 0);
160 case 0x5: /* pl */ return (reg.cc1 - reg.cc2 >= 0);
161 case 0x8: /* hi */ return ((ulong)reg.cc1 > (ulong)reg.cc2);
162 case 0x9: /* ls */ return ((ulong)reg.cc1 <= (ulong)reg.cc2);
163 case 0xa: /* ge */ return (reg.cc1 >= reg.cc2);
164 case 0xb: /* lt */ return (reg.cc1 < reg.cc2);
165 case 0xc: /* gt */ return (reg.cc1 > reg.cc2);
166 case 0xd: /* le */ return (reg.cc1 <= reg.cc2);
167 case 0xe: /* al */ return 1;
168 case 0xf: /* nv */ return 0;
170 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
171 reg.cond, reg.cc1, reg.cc2);
180 long res = reg.cc1 ^ reg.cc2;
182 case 0x0: /* eq */ return res == 0;
183 case 0x1: /* ne */ return res != 0;
184 case 0x4: /* mi */ return (res & SIGNBIT) != 0;
185 case 0x5: /* pl */ return (res & SIGNBIT) == 0;
186 case 0xe: /* al */ return 1;
187 case 0xf: /* nv */ return 0;
189 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
190 reg.cond, reg.cc1, reg.cc2);
199 long res = reg.cc1 & reg.cc2;
201 case 0x0: /* eq */ return res == 0;
202 case 0x1: /* ne */ return res != 0;
203 case 0x4: /* mi */ return (res & SIGNBIT) != 0;
204 case 0x5: /* pl */ return (res & SIGNBIT) == 0;
205 case 0xe: /* al */ return 1;
206 case 0xf: /* nv */ return 0;
208 Bprint(bioout, "unimplemented condition prefix %x (%ld %ld)\n",
209 reg.cond, reg.cc1, reg.cc2);
223 reg.ar = reg.r[REGPC];
224 reg.ir = ifetch(reg.ar);
225 reg.class = armclass(reg.ir);
226 reg.ip = &itab[reg.class];
227 reg.cond = (reg.ir>>28) & 0xf;
228 switch(reg.compare_op) {
239 Bprint(bioout, "unimplemented compare operation %x\n",
246 (*reg.ip->func)(reg.ir);
249 itrace("%s%s IGNORED",
250 reg.ip->name, cond[reg.cond]);
254 brkchk(reg.r[REGPC], Instruction);
261 Bprint(bioout, "undefined instruction trap pc #%lux inst %.8lux class %d\n",
262 reg.r[REGPC], inst, reg.class);
267 shift(long v, int st, int sc, int isreg)
271 case 0: /* logical left */
274 case 1: /* logical right */
275 reg.cout = (v >> 31) & 1;
277 case 2: /* arith right */
280 case 3: /* rotate right */
286 v = ((ulong)v >> 1) | (reg.cbit << 31);
292 case 0: /* logical left */
293 reg.cout = (v >> (32 - sc)) & 1;
296 case 1: /* logical right */
297 reg.cout = (v >> (sc - 1)) & 1;
300 case 2: /* arith right */
302 reg.cout = (v >> 31) & 1;
309 reg.cout = (v >> (sc - 1)) & 1;
313 case 3: /* rotate right */
314 reg.cout = (v >> (sc - 1)) & 1;
315 v = (v << (32-sc)) | ((ulong)v >> sc);
323 dpex(long inst, long o1, long o2, int rd)
328 switch((inst>>21) & 0xf) {
343 reg.compare_op = CCcmp;
351 reg.compare_op = CCcmp;
355 if(calltree && rd == REGPC && o2 == 0) {
358 findsym(o1 + o2, CTEXT, &s);
359 Bprint(bioout, "%8lux return to %lux %s r0=%lux\n",
360 reg.r[REGPC], o1 + o2, s.name, reg.r[REGRET]);
364 if(((uvlong)(ulong)o1 + (uvlong)(ulong)o2) & (1LL << 32))
370 reg.compare_op = CCcmp;
381 reg.compare_op = CCtst;
388 reg.compare_op = CCteq;
395 reg.compare_op = CCcmp;
407 reg.r[rd] = o1 & ~o2;
420 reg.compare_op = CCcmp;
425 * data processing instruction R,R,R
433 rn = (inst>>16) & 0xf;
434 rd = (inst>>12) & 0xf;
443 dpex(inst, o1, o2, rd);
445 itrace("%s%s\tR%d,R%d,R%d =#%x",
446 reg.ip->name, cond[reg.cond],
454 * data processing instruction (R<>#),R,R
459 int rn, rd, rm, st, sc;
462 rn = (inst>>16) & 0xf;
463 rd = (inst>>12) & 0xf;
465 st = (inst>>5) & 0x3;
466 sc = (inst>>7) & 0x1f;
473 o2 = shift(o2, st, sc, 0);
474 dpex(inst, o1, o2, rd);
476 itrace("%s%s\tR%d%s%d,R%d,R%d =#%x",
477 reg.ip->name, cond[reg.cond], rm, shtype[st], sc, rn, rd,
484 * data processing instruction (R<>R),R,R
489 int rn, rd, rm, rs, st;
492 rn = (inst>>16) & 0xf;
493 rd = (inst>>12) & 0xf;
495 st = (inst>>5) & 0x3;
496 rs = (inst>>8) & 0xf;
506 o2 = shift(o2, st, o3, 1);
507 dpex(inst, o1, o2, rd);
509 itrace("%s%s\tR%d%sR%d=%d,R%d,R%d =#%x",
510 reg.ip->name, cond[reg.cond], rm, shtype[st], rs, o3, rn, rd,
517 * data processing instruction #<>#,R,R
525 rn = (inst>>16) & 0xf;
526 rd = (inst>>12) & 0xf;
531 sc = (inst>>7) & 0x1e;
532 o2 = (o2 >> sc) | (o2 << (32 - sc));
534 dpex(inst, o1, o2, rd);
536 itrace("%s%s\t#%x,R%d,R%d =#%x",
537 reg.ip->name, cond[reg.cond], o2, rn, rd,
548 rd = (inst>>16) & 0xf;
549 rs = (inst>>8) & 0xf;
552 if(rd == REGPC || rs == REGPC || rm == REGPC || rd == rm)
555 reg.r[rd] = reg.r[rm]*reg.r[rs];
558 itrace("%s%s\tR%d,R%d,R%d =#%x",
559 reg.ip->name, cond[reg.cond], rs, rm, rd,
569 rd = (inst>>16) & 0xf;
570 rn = (inst>>12) & 0xf;
571 rs = (inst>>8) & 0xf;
574 if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC
575 || rd == rm || rn == rm || rd == rn)
579 v = (vlong)reg.r[rm] * (vlong)reg.r[rs];
583 v = (uvlong)(ulong)reg.r[rm] * (uvlong)(ulong)reg.r[rs];
585 v += (ulong)reg.r[rn];
591 itrace("%s%s\tR%d,R%d,(R%d,R%d) =#%llx",
592 reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
601 rd = (inst>>16) & 0xf;
602 rn = (inst>>12) & 0xf;
603 rs = (inst>>8) & 0xf;
606 if(rd == REGPC || rn == REGPC || rs == REGPC || rm == REGPC || rd == rm)
609 reg.r[rd] = reg.r[rm]*reg.r[rs] + reg.r[rn];
612 itrace("%s%s\tR%d,R%d,R%d,R%d =#%x",
613 reg.ip->name, cond[reg.cond], rs, rm, rn, rd,
621 ulong address, value, bbit;
623 bbit = inst & (1<<22);
624 rn = (inst>>16) & 0xf;
625 rd = (inst>>12) & 0xf;
626 rm = (inst>>0) & 0xf;
630 value = getmem_b(address);
631 putmem_b(address, reg.r[rm]);
633 value = getmem_w(address);
634 putmem_w(address, reg.r[rm]);
644 dotc = cond[reg.cond];
646 itrace("SWP%s%s\t#%x(R%d),R%d #%lux=#%x",
654 * load/store word/byte
659 int rn, rd, off, rm, sc, st;
660 ulong address, value, pbit, ubit, bbit, wbit, lbit, bit25;
662 bit25 = inst & (1<<25);
663 pbit = inst & (1<<24);
664 ubit = inst & (1<<23);
665 bbit = inst & (1<<22);
666 wbit = inst & (1<<21);
667 lbit = inst & (1<<20);
668 rn = (inst>>16) & 0xf;
669 rd = (inst>>12) & 0xf;
676 st = (inst>>5) & 0x3;
677 sc = (inst>>7) & 0x1f;
681 off = shift(off, st, sc, 0);
696 value = getmem_b(address);
698 value = getmem_w(address);
707 putmem_b(address, value);
709 putmem_w(address, value);
715 char *bw, *dotp, *dotc;
723 dotc = cond[reg.cond];
727 itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
732 itrace("MOV%s%s%s\t(R%d%s%d)(R%d),R%d #%lux=#%x",
734 rm, shtype[st], sc, rn, rd,
738 itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
743 itrace("MOV%s%s%s\tR%d,(R%d%s%d)(R%d) #%lux=#%x",
745 rd, rm, shtype[st], sc, rn,
752 * load/store unsigned byte/half word
758 ulong address, value, pbit, ubit, hbit, sbit, wbit, lbit, bit22;
760 pbit = inst & (1<<24);
761 ubit = inst & (1<<23);
762 bit22 = inst & (1<<22);
763 wbit = inst & (1<<21);
764 lbit = inst & (1<<20);
765 sbit = inst & (1<<6);
766 hbit = inst & (1<<5);
767 rn = (inst>>16) & 0xf;
768 rd = (inst>>12) & 0xf;
772 off = ((inst>>4) & 0xf0) | (inst & 0xf);
790 value = getmem_h(address);
791 if(sbit && (value & 0x8000))
794 value = getmem_b(address);
806 putmem_h(address, value);
808 putmem_b(address, value);
815 char *hb, *dotp, *dotc;
823 dotc = cond[reg.cond];
827 itrace("MOV%s%s%s\t#%x(R%d),R%d #%lux=#%x",
832 itrace("MOV%s%s%s\t(R%d)(R%d),R%d #%lux=#%x",
838 itrace("MOV%s%s%s\tR%d,#%x(R%d) #%lux=#%x",
843 itrace("MOV%s%s%s\tR%d,(R%d)(R%d) #%lux=#%x",
854 char pbit, ubit, sbit, wbit, lbit;
856 ulong address, predelta, postdelta;
858 pbit = (inst>>24) & 0x1;
859 ubit = (inst>>23) & 0x1;
860 sbit = (inst>>22) & 0x1;
861 wbit = (inst>>21) & 0x1;
862 lbit = (inst>>20) & 0x1;
863 rn = (inst>>16) & 0xf;
864 reglist = inst & 0xffff;
881 for (i = 0; i < 16; ++i) {
882 if(!(reglist & (1 << i)))
886 reg.r[i] = getmem_w(address);
888 putmem_w(address, reg.r[i]);
889 address += postdelta;
892 for (i = 15; 0 <= i; --i) {
893 if(!(reglist & (1 << i)))
897 reg.r[i] = getmem_w(address);
899 putmem_w(address, reg.r[i]);
900 address -= postdelta;
908 itrace("%s.%c%c\tR%d=%lux%s, <%lux>",
909 (lbit ? "LDM" : "STM"), (ubit ? 'I' : 'D'), (pbit ? 'B' : 'A'),
910 rn, reg.r[rn], (wbit ? "!" : ""), reglist);
920 v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
922 itrace("B%s\t#%lux", cond[reg.cond], v);
923 reg.r[REGPC] = v - 4;
933 v = reg.r[REGPC] + 8 + ((v << 8) >> 6);
935 itrace("BL%s\t#%lux", cond[reg.cond], v);
938 findsym(v, CTEXT, &s);
939 Bprint(bioout, "%8lux %s(", reg.r[REGPC], s.name);
940 printparams(&s, reg.r[13]);
941 Bprint(bioout, "from ");
942 printsource(reg.r[REGPC]);
946 reg.r[REGLINK] = reg.r[REGPC] + 4;
947 reg.r[REGPC] = v - 4;