1 /* radare - LGPL - Copyright 2015-2018 - pancake */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <stdlib.h>
7 #include <r_util.h>
8
9 typedef enum optype_t {
10 ARM_NOTYPE = -1,
11 ARM_GPR = 1,
12 ARM_CONSTANT = 2,
13 ARM_FP = 4,
14 ARM_MEM_OPT = 8,
15 ARM_SHIFT = 16,
16 ARM_EXTEND = 32
17 } OpType;
18
19 typedef enum regtype_t {
20 ARM_UNDEFINED = -1,
21 ARM_REG64 = 1,
22 ARM_REG32 = 2,
23 ARM_SP = 4,
24 ARM_PC = 8,
25 ARM_SIMD = 16
26 } RegType;
27
28 typedef enum shifttype_t {
29 ARM_LSL = 0,
30 ARM_LSR = 1,
31 ARM_ASR = 2,
32 ARM_ROR = 3,
33 ARM_UXTB,
34 ARM_UXTH,
35 ARM_UXTW,
36 ARM_UXTX,
37 ARM_SXTB,
38 ARM_SXTH,
39 ARM_SXTW,
40 ARM_SXTX
41 } ShiftType;
42
43 typedef enum logicalop_t {
44 ARM_AND = 0,
45 ARM_ORR = 1,
46 ARM_EOR = 2,
47 ARM_ANDS = 3
48 } LogicalOp;
49
50 typedef struct operand_t {
51 OpType type;
52 union {
53 struct {
54 int reg;
55 RegType reg_type;
56 ut16 sp_val;
57 };
58 struct {
59 ut64 immediate;
60 bool sign;
61 bool preindex;
62 };
63 struct {
64 ut64 shift_amount;
65 ShiftType shift;
66 bool amount_present;
67 };
68 struct {
69 ut32 mem_option;
70 };
71 };
72 } Operand;
73
74 #define MAX_OPERANDS 7
75
76 typedef struct Opcode_t {
77 char *mnemonic;
78 ut32 op[3];
79 size_t op_len;
80 ut8 opcode[3];
81 bool writeback;
82 int operands_count;
83 Operand operands[MAX_OPERANDS];
84 } ArmOp;
85
86 #define check_cond(cond) if (!(cond)) { return data; }
87
get_mem_option(char * token)88 static int get_mem_option(char *token) {
89 // values 4, 8, 12, are unused. XXX to adjust
90 const char *options[] = {"sy", "st", "ld", "xxx", "ish", "ishst",
91 "ishld", "xxx", "nsh", "nshst", "nshld",
92 "xxx", "osh", "oshst", "oshld", NULL};
93 int i = 0;
94 while (options[i]) {
95 if (!r_str_casecmp (token, options[i])) {
96 return 15 - i;
97 }
98 i++;
99 }
100 return -1;
101 }
102
countLeadingZeros(ut64 x)103 static int countLeadingZeros(ut64 x) {
104 int count = 64;
105 while (x) {
106 x >>= 1;
107 --count;
108 }
109 return count;
110 }
111
countTrailingZeros(ut64 x)112 static int countTrailingZeros(ut64 x) {
113 int count = 0;
114 while (x && !(x & 1)) {
115 count++;
116 x >>= 1;
117 }
118 return count;
119 }
120
calcNegOffset(int n,int shift)121 static int calcNegOffset(int n, int shift) {
122 int a = n >> shift;
123 if (a == 0) {
124 return 0xff;
125 }
126 // find first set bit then invert it and all
127 // bits below it
128 int t = 0x400;
129 while (!(t & a) && a != 0 && t != 0) {
130 t = t >> 1;
131 }
132 t = t & (t - 1);
133 a = a ^ t;
134 // If bits below 32 are set
135 if (countTrailingZeros(n) > shift) {
136 a--;
137 }
138 return 0xff & (0xff - a);
139 }
140
countLeadingOnes(ut64 x)141 static int countLeadingOnes(ut64 x) {
142 return countLeadingZeros (~x);
143 }
144
countTrailingOnes(ut64 x)145 static int countTrailingOnes(ut64 x) {
146 return countTrailingZeros (~x);
147 }
148
isMask(ut64 value)149 static bool isMask(ut64 value) {
150 return value && ((value + 1) & value) == 0;
151 }
152
isShiftedMask(ut64 value)153 static bool isShiftedMask (ut64 value) {
154 return value && isMask ((value - 1) | value);
155 }
156
157 // https://llvm.org/doxygen/AArch64AddressingModes_8h_source.html
encodeBitMasksWithSize(ut64 imm,ut32 reg_size)158 static ut32 encodeBitMasksWithSize(ut64 imm, ut32 reg_size) {
159 if (imm == 0 || imm == UT64_MAX || (reg_size != 64
160 && (imm >> reg_size != 0 || imm == (~0ULL >> (64 - reg_size))))) {
161 return UT32_MAX;
162 }
163 // get element size
164 ut32 size = reg_size;
165 do {
166 size >>= 1;
167 ut64 mask = (1ull << size) - 1;
168 if ((imm & mask) != ((imm >> size) & mask)) {
169 size <<= 1;
170 break;
171 }
172 } while (size > 2);
173 // determine rot to make element be 0^m 1^n
174 ut32 cto, i;
175 ut64 mask = UT64_MAX >> (64 - size);
176 imm &= mask;
177
178 if (isShiftedMask (imm)) {
179 i = countTrailingZeros (imm);
180 cto = countTrailingOnes (imm >> i);
181 } else {
182 imm |= ~mask;
183 if (!isShiftedMask (~imm)) {
184 return UT32_MAX;
185 }
186
187 ut32 clo = countLeadingOnes (imm);
188 i = 64 - clo;
189 cto = clo + countTrailingOnes (imm) - (64 - size);
190 }
191
192 // Encode in Immr the number of RORs it would take to get *from* 0^m 1^n
193 // to our target value, where I is the number of RORs to go the opposite
194 // direction
195 ut32 immr = (size - i) & (size - 1);
196 // If size has a 1 in the n'th bit, create a value that has zeroes in
197 // bits [0, n] and ones above that.
198 ut64 nimms = ~(size - 1) << 1;
199 // Or the cto value into the low bits, which must be below the Nth bit
200 // bit mentioned above.
201 nimms |= (cto - 1);
202 // Extract and toggle seventh bit to make N field.
203 ut32 n = ((nimms >> 6) & 1) ^ 1;
204 ut32 encoding = (n << 12) | (immr << 6) | (nimms & 0x3f);
205 return encoding;
206 }
207
encode1reg(ArmOp * op)208 static inline ut32 encode1reg(ArmOp *op) {
209 return op->operands[0].reg << 24;
210 }
211
encode2regs(ArmOp * op)212 static inline ut32 encode2regs(ArmOp *op) {
213 return (op->operands[1].reg & 0x7) << 29 | (op->operands[1].reg & 0x18) << 13
214 | encode1reg (op);
215 }
216
encodeImm9(ut32 n)217 static inline ut32 encodeImm9(ut32 n) {
218 return (n & 0x1f0) << 4 | (n & 0xf) << 20;
219 }
220
mov(ArmOp * op)221 static ut32 mov(ArmOp *op) {
222 ut32 k = 0;
223 ut32 data = UT32_MAX;
224 check_cond (op->operands_count >= 2);
225 check_cond (op->operands[0].type == ARM_GPR);
226 int bits = (op->operands[0].reg_type & ARM_REG64) ? 64 : 32;
227 if (bits == 64) {
228 k = 0x0080;
229 }
230 k |= encode1reg (op);
231 if (!strcmp (op->mnemonic, "mov")) {
232 check_cond (op->operands_count == 2);
233 if (op->operands[1].type == ARM_GPR) {
234 check_cond (bits == ((op->operands[1].reg_type & ARM_REG64) ? 64 : 32));
235 if (op->operands[0].reg_type & ARM_SP || op->operands[1].reg_type & ARM_SP) { // alias of add
236 k |= 0x0011;
237 data = k | encode2regs (op);
238 return data;
239 }
240 k |= 0xe003002a; // alias of orr
241 data = k | op->operands[1].reg << 8;
242 return data;
243 }
244 check_cond (op->operands[1].type & ARM_CONSTANT);
245 ut64 imm = op->operands[1].immediate;
246 ut64 imm_inverse = ~imm;
247 if (bits == 32) {
248 check_cond (imm <= 0xffffffff || imm_inverse <= 0xffffffff);
249 imm &= 0xffffffff;
250 imm_inverse &= 0xffffffff;
251 }
252 int shift;
253 ut64 mask = 0xffff;
254 for (shift = 0; shift < bits; shift += 16, mask <<= 16) {
255 if (imm == (imm & mask)) { // movz
256 data = k | 0x00008052;
257 imm >>= shift;
258 data |= (imm & 7) << 29 | (imm & 0x7f8) << 13 | (imm & 0xf800) >> 3;
259 data |= shift << 9;
260 return data;
261 }
262 }
263 mask = 0xffff;
264 for (shift = 0; shift < bits; shift += 16, mask <<= 16) {
265 if (imm_inverse == (imm_inverse & mask)) { // movn
266 data = k | 0x00008012;
267 imm_inverse >>= shift;
268 data |= (imm_inverse & 7) << 29 | (imm_inverse & 0x7f8) << 13 | (imm_inverse & 0xf800) >> 3;
269 data |= shift << 9;
270 return data;
271 }
272 }
273 ut32 bitmask = encodeBitMasksWithSize (op->operands[1].immediate, bits); // orr
274 check_cond (bitmask != UT32_MAX);
275 data = k | 0xe0030032;
276 data |= (bitmask & 0x3f) << 18 | (bitmask & 0x1fc0) << 2;
277 return data;
278 }
279 if (!strcmp (op->mnemonic, "movz")) {
280 k |= 0x8052;
281 } else if (!strcmp (op->mnemonic, "movk")) {
282 k |= 0x8072;
283 } else if (!strcmp (op->mnemonic, "movn")) {
284 k |= 0x8012;
285 } else {
286 return data;
287 }
288 check_cond (op->operands[1].type == ARM_CONSTANT);
289 ut64 imm = op->operands[1].immediate;
290 check_cond (imm <= 0xffff);
291 int shift = 0;
292 if (op->operands_count >= 3) {
293 check_cond (op->operands_count == 3);
294 check_cond (op->operands[2].type == ARM_SHIFT);
295 check_cond (op->operands[2].shift == ARM_LSL);
296 shift = op->operands[2].shift_amount;
297 check_cond (!(shift & 0xf));
298 check_cond (shift < bits);
299 }
300 data = k;
301 data |= (imm & 7) << 29; // arg(1)
302 data |= (imm & 0x7f8) << 13; // arg(1)
303 data |= (imm & 0xf800) >> 3; // arg(1)
304 data |= shift << 9; // arg(2)
305 return data;
306 }
307
cb(ArmOp * op)308 static ut32 cb(ArmOp *op) {
309 ut32 data = UT32_MAX;
310 int k = 0;
311 if (!strncmp (op->mnemonic, "cbnz", 4)) {
312 if (op->operands[0].reg_type & ARM_REG64) {
313 k = 0x000000b5;
314 } else if (op->operands[0].reg_type & ARM_REG32) {
315 k = 0x00000035;
316 } else {
317 return UT32_MAX;
318 }
319 } else if (!strncmp (op->mnemonic, "cbz", 3)) {
320 if (op->operands[0].reg_type & ARM_REG64) {
321 k = 0x000000b4;
322 } else if (op->operands[0].reg_type & ARM_REG32) {
323 k = 0x00000034;
324 } else {
325 return UT32_MAX;
326 }
327 } else {
328 return UT32_MAX;
329 }
330 //printf ("%s %d, %llu\n", op->mnemonic, op->operands[0].reg, op->operands[1].immediate);
331 ut32 imm = op->operands[1].immediate;
332 data = k | encode1reg (op) | ((imm & 0x1c) << 27) | ((imm & 0x1fe0) << 11);
333 data = data | ((imm & 0x1fe000) >> 5);
334
335 return data;
336 }
337
338
cmp(ArmOp * op)339 static ut32 cmp(ArmOp *op) {
340 ut32 data = UT32_MAX;
341 int k = 0;
342 if (op->operands[0].reg_type & ARM_REG64 && op->operands[1].reg_type & ARM_REG64) {
343 k = 0x1f0000eb;
344 } else if (op->operands[0].reg_type & ARM_REG32 && op->operands[1].reg_type & ARM_REG32) {
345 if (op->operands[2].shift_amount > 31) {
346 return UT32_MAX;
347 }
348 k = 0x1f00006b;
349 } else {
350 return UT32_MAX;
351 }
352
353 data = k | (op->operands[0].reg & 0x18) << 13 | op->operands[0].reg << 29 | op->operands[1].reg << 8;
354
355 if (op->operands[2].type != ARM_SHIFT) {
356 data |= op->operands[2].shift_amount << 18 | op->operands[2].shift << 14;
357 }
358 return data;
359 }
360
361
regsluop(ArmOp * op,int k)362 static ut32 regsluop(ArmOp *op, int k) {
363 ut32 data = UT32_MAX;
364
365 if (op->operands[1].reg_type & ARM_REG32) {
366 return data;
367 }
368 if (op->operands[0].reg_type & ARM_REG32) {
369 k -= 0x40;
370 }
371 if (op->operands[2].type & ARM_GPR) {
372 return data;
373 }
374
375 int n = op->operands[2].immediate;
376 if (n > 0xff || n < -0x100) {
377 return data;
378 }
379
380 data = k | encode2regs (op);
381
382 if (n < 0) {
383 n *= -1;
384 data |= ( 0xf & (0xf - (n - 1)) ) << 20;
385
386 if (countTrailingZeros(n) > 3) {
387 data |= (0x1f - ((n >> 4) - 1)) << 8;
388 } else {
389 data |= (0x1f - (n >> 4)) << 8;
390 }
391 } else {
392 data |= (0xf & (n & 63)) << 20;
393 if (countTrailingZeros(n) < 4) {
394 data |= (n >> 4) << 8;
395 } else {
396 data |= (0xff & n) << 4;
397 }
398 data |= (n >> 8) << 8;
399 }
400
401 return data;
402 }
403
404 // Register Load/store ops
reglsop(ArmOp * op,int k)405 static ut32 reglsop(ArmOp *op, int k) {
406 ut32 data = UT32_MAX;
407
408 if (op->operands[1].reg_type & ARM_REG32) {
409 return data;
410 }
411 if (op->operands[0].reg_type & ARM_REG32) {
412 k -= 0x40;
413 }
414 if (op->operands[2].type & ARM_GPR) {
415 k += 0x00682000;
416 data = k | encode2regs (op);
417 data |= op->operands[2].reg << 8;
418 } else {
419 int n = op->operands[2].immediate;
420 if (n > 0x100 || n < -0x100) {
421 return UT32_MAX;
422 }
423
424 if (n == 0 || (n > 0 && countTrailingZeros(n) >= 4)) {
425 k ++;
426 }
427 data = k | encode2regs (op);
428
429 if (n < 0) {
430 n *= -1;
431 data |= ( 0xf & (0xf - (n - 1)) ) << 20;
432 if (countTrailingZeros(n) > 3) {
433 data |= (0x1f - ((n >> 4) - 1)) << 8;
434 } else {
435 data |= (0x1f - (n >> 4)) << 8;
436 }
437 } else {
438 if (op->operands[0].reg_type & ARM_REG32) {
439 if (countTrailingZeros(n) < 2) {
440 data |= (0xf & (n & 63)) << 20;
441 data |= (n >> 4) << 8;
442 } else {
443 data++;
444 data |= (0xff & n) << 16;
445 }
446 data |= (n >> 8) << 8;
447 } else {
448 data |= (0xf & (n & 63)) << 20;
449 if (countTrailingZeros(n) < 4) {
450 data |= (n >> 4) << 8;
451 } else {
452 data |= (0xff & n) << 15;
453 }
454 data |= (n >> 8) << 23;
455 }
456 }
457 }
458 return data;
459 }
460
461 // load/store ops
lsop(ArmOp * op,int k,ut64 addr)462 static ut32 lsop(ArmOp *op, int k, ut64 addr) {
463 ut32 data = UT32_MAX;
464 int op_count = op->operands_count;
465 if (k == 0x00000098) { // ldrsw
466 if (op->operands[0].type & ARM_GPR
467 && op->operands[1].type & ARM_CONSTANT) { // (literal)
468 st64 offset = op->operands[1].immediate - addr;
469 check_cond (op->operands[0].reg_type & ARM_REG64);
470 check_cond (!(offset & 0x3));
471 check_cond (-0x100000 <= offset && offset < 0x100000);
472 offset >>= 2;
473 data = k | (offset & 0x7f800) >> 3 | (offset & 0x7f8) << 13
474 | (offset & 0x7) << 29 | encode1reg (op);
475 return data;
476 }
477 k = 0x000080b8;
478 }
479 check_cond (op->operands[0].type == ARM_GPR);
480 check_cond (op->operands[1].type == ARM_GPR);
481 check_cond (op->operands[1].reg_type & ARM_REG64);
482 k |= encode2regs (op);
483 if (!strcmp (op->mnemonic, "ldrb") || !strcmp (op->mnemonic, "ldrh")
484 || !strcmp (op->mnemonic, "strb") || !strcmp (op->mnemonic, "strh")) {
485 check_cond (op->operands[0].reg_type & ARM_REG32);
486 } else if (!strcmp (op->mnemonic, "ldrsw")) {
487 check_cond (op->operands[0].reg_type & ARM_REG64);
488 } else { // ldrsh, ldrsb
489 if (op->operands[0].reg_type & ARM_REG32) {
490 k |= 0x00004000;
491 }
492 }
493 char width = op->mnemonic[strlen (op->mnemonic) - 1];
494 if (op->operands[2].type & ARM_GPR) {
495 k |= 0x00482000;
496 if (op->operands[3].type == ARM_EXTEND) {
497 switch (op->operands[3].shift) {
498 case ARM_SXTW:
499 k |= 0x00800000;
500 // fall through
501 case ARM_UXTW:
502 check_cond (op->operands[2].reg_type & ARM_REG32);
503 break;
504 case ARM_SXTX:
505 k |= 0x00a00000;
506 check_cond (op->operands[2].reg_type & ARM_REG64);
507 break;
508 default:
509 return data;
510 }
511 } else if (op->operands[3].type == ARM_SHIFT) {
512 check_cond (op->operands[3].shift == ARM_LSL);
513 check_cond (op->operands[2].reg_type & ARM_REG64);
514 k |= 0x00200000;
515 }
516 if (op->operands[3].type == ARM_EXTEND || op->operands[3].type == ARM_SHIFT) {
517 if (width == 'b') {
518 check_cond (op->operands[3].shift_amount == 0);
519 if (op->operands[3].amount_present) {
520 k |= 0x00100000;
521 }
522 } else if (width == 'h') {
523 switch (op->operands[3].shift_amount) {
524 case 1:
525 k |= 0x00100000;
526 // fall through
527 case 0:
528 break;
529 default:
530 return data;
531 }
532 } else { // w
533 switch (op->operands[3].shift_amount) {
534 case 2:
535 k |= 0x00100000;
536 // fall through
537 case 0:
538 break;
539 default:
540 return data;
541 }
542 }
543 } else { // lsl 0 by default
544 check_cond (op->operands[2].reg_type & ARM_REG64);
545 k |= 0x00200000;
546 }
547 data = k | op->operands[2].reg << 8;
548 return data;
549 }
550 check_cond (op_count == 2 || op->operands[2].type == ARM_CONSTANT);
551 check_cond (!op->writeback || op->operands[2].preindex);
552 int n = op_count == 2 ? 0 : op->operands[2].immediate;
553 if (!op->writeback && (op_count == 2 || op->operands[2].preindex)) { // unsigned offset
554 check_cond (n >= 0);
555 if (width == 'b') {
556 check_cond (n <= 0xfff);
557 } else if (width == 'h') {
558 check_cond (n <= 0x1ffe && !(n & 1))
559 n >>= 1;
560 } else { // w
561 check_cond (n <= 0x3ffc && !(n & 3));
562 n >>= 2;
563 }
564 data = k | (n & 0x3f) << 18 | (n & 0xfc0) << 2 | 1;
565 return data;
566 }
567 check_cond (-0x100 <= n && n < 0x100)
568 if (op->operands[2].preindex) {
569 k |= 0x00080000;
570 }
571 data = k | encodeImm9 (n) | 0x00040000;
572 return data;
573 }
574
branch(ArmOp * op,ut64 addr,int k)575 static ut32 branch(ArmOp *op, ut64 addr, int k) {
576 ut32 data = UT32_MAX;
577 ut64 n = 0;
578 if (op->operands[0].type & ARM_CONSTANT) {
579 n = op->operands[0].immediate;
580 if (!(n & 0x3)) {
581 if (n >= addr) {
582 n -= addr;
583 } else {
584 n -= addr;
585 n = n & 0xfffffff;
586 k |= 3;
587 }
588 n = n >> 2;
589 int t = (n & 0xff000000) >> 24;
590 int h = (n & 0xff0000) >> 16;
591 int m = (n & 0xff00) >> 8;
592 n &= 0xff;
593 data = k;
594 data |= n << 24;
595 data |= m << 16;
596 data |= h << 8;
597 data |= t;
598 }
599 } else {
600 n = op->operands[0].reg;
601 if (n >= 31) {
602 return -1;
603 }
604 n = n << 5;
605 int h = n >> 8;
606 n &= 0xff;
607 data = k;
608 data |= n << 24;
609 data |= h << 16;
610 }
611 return data;
612 }
613
bdot(ArmOp * op,ut64 addr,int k)614 static ut32 bdot(ArmOp *op, ut64 addr, int k) {
615 ut32 data = UT32_MAX;
616 int n = 0;
617 int a = 0;
618 n = op->operands[0].immediate;
619 // I am sure there's a logical way to do negative offsets,
620 // but I was unable to find any sensible docs so I did my best
621 if (!(n & 0x3 || n > 0x7ffffff)) {
622 n -= addr;
623 data = k;
624 if (n < 0) {
625 n *= -1;
626 a = (n << 3) - 1;
627 data |= (0xff - a) << 24;
628
629 a = calcNegOffset(n, 5);
630 data |= a << 16;
631
632 a = calcNegOffset(n, 13);
633 data |= a << 8;
634 } else {
635 data |= (n & 31) << 27;
636 data |= (0xff & (n >> 5)) << 16;
637 data |= (0xff & (n >> 13)) << 8;
638 }
639 }
640
641 return data;
642 }
643
mem_barrier(ArmOp * op,ut64 addr,int k)644 static ut32 mem_barrier(ArmOp *op, ut64 addr, int k) {
645 ut32 data = UT32_MAX;
646 data = k;
647 if (!strncmp (op->mnemonic, "isb", 3)) {
648 if (op->operands[0].mem_option == 15 || op->operands[0].type == ARM_NOTYPE) {
649 return data;
650 } else {
651 return UT32_MAX;
652 }
653 }
654 if (op->operands[0].type == ARM_MEM_OPT) {
655 data |= op->operands[0].mem_option << 16;
656 } else if (op->operands_count == 1 && op->operands[0].type == ARM_CONSTANT) {
657 data |= (op->operands[0].immediate << 16);
658 }
659 return data;
660 }
661
662 #include "armass64_const.h"
663
msr(ArmOp * op,int w)664 static ut32 msr(ArmOp *op, int w) {
665 ut32 data = UT32_MAX;
666 ut32 seq_data = UT32_MAX;
667 int is_immediate = 0;
668 int i;
669 ut32 r, b;
670 /* handle swapped args */
671 if (w) {
672 if (op->operands[1].reg_type != (ARM_REG64 | ARM_SP)) {
673 if (op->operands[1].type == ARM_CONSTANT) {
674 for (i = 0; msr_const[i].name; i++) {
675 if (op->operands[1].immediate == msr_const[i].val) {
676 op->operands[1].sp_val = msr_const[i].val;
677 op->operands[1].reg = op->operands[1].immediate;
678 break;
679 }
680 }
681 } else {
682 return data;
683 }
684 }
685 r = op->operands[0].reg;
686 b = op->operands[1].sp_val;
687 } else {
688 if (op->operands[0].reg_type != (ARM_REG64 | ARM_SP)) {
689 if (op->operands[0].type == ARM_CONSTANT) {
690 for (i = 0; msr_const[i].name; i++) {
691 if (op->operands[0].immediate == msr_const[i].val) {
692 op->operands[0].sp_val = msr_const[i].val;
693 op->operands[0].reg = op->operands[0].immediate;
694 break;
695 }
696 }
697 } else {
698 return data;
699 }
700 }
701 r = op->operands[1].reg;
702 if ( op->operands[1].sp_val == 0xfffe ) {
703 is_immediate = 1;
704 r = op->operands[1].immediate;
705 }
706 b = op->operands[0].sp_val;
707 }
708 data = 0x00000000;
709
710 if (is_immediate) {
711 //only msr has immediate mode
712 data = 0xd500401f;
713 if (b == 0xc210) { //op0 is SPSel
714 b = 0x05; //set to immediate mode encoding
715 }
716
717 data |= (b & 0xf0) << 12; //op1
718 data |= (b & 0x0f) << 5; //op2
719 data |= (r & 0xf) << 8; //CRm(#imm)
720
721 } else {
722 if (w) {
723 /* mrs */
724 data |= 0xd5200000;
725 } else {
726 data |= 0xd5000000;
727 }
728 data |= b << 5;
729 data |= r;
730 }
731 seq_data = 0x00000000;
732 seq_data |= (data & 0xff) << 8*3;
733 seq_data |= (data & 0xff00) << 8*1;
734 seq_data |= (data & 0xff0000) >> 8*1;
735 seq_data |= (data & 0xff000000) >> 8*3;
736 /*
737 if (op->operands[1].reg_type == ARM_REG64) {
738 data |= op->operands[1].reg << 24;
739 }
740 */
741 return seq_data;
742 }
743
logical(ArmOp * op,bool invert,LogicalOp opc)744 static ut32 logical(ArmOp *op, bool invert, LogicalOp opc) {
745 ut32 data = UT32_MAX;
746 RegType reg_type = op->operands[0].reg_type;
747
748 // Reg types need to match
749 if (!(reg_type == op->operands[1].reg_type)) {
750 return data;
751 }
752
753 OpType op2_type = op->operands[2].type;
754 if (op2_type == ARM_CONSTANT) {
755 if (invert) {
756 /* there aren't inverted immediates in arm64 */
757 return UT32_MAX;
758 }
759 if (reg_type & ARM_REG64) {
760 data = 0x92000000;
761 } else if (reg_type & ARM_REG32) {
762 data = 0x12000000;
763 } else {
764 return UT32_MAX;
765 }
766
767 bool is64bit = reg_type & ARM_REG64;
768
769 data |= op->operands[0].reg;
770 data |= op->operands[1].reg << 5;
771 data |= (opc & 3) << 29;
772
773 ut32 imm_orig = op->operands[2].immediate;
774 ut32 imm = encodeBitMasksWithSize (invert? ~imm_orig: imm_orig, is64bit? 64: 32);
775 if (imm == UT32_MAX) {
776 return UT32_MAX;
777 }
778 data |= (imm & 0x1fff) << 10;
779 } else if (op2_type == ARM_GPR) {
780 if (reg_type & ARM_REG64) {
781 data = 0x8a000000;
782 } else if (reg_type & ARM_REG32) {
783 data = 0x0a000000;
784 } else {
785 return UT32_MAX;
786 }
787
788 data |= op->operands[0].reg;
789 data |= op->operands[1].reg << 5;
790 data |= op->operands[2].reg << 16;
791 data |= (opc & 3) << 29;
792
793 if (op->operands_count == 4) {
794 Operand shift_op = op->operands[3];
795 if (shift_op.type == ARM_SHIFT) {
796 data |= (shift_op.shift_amount & 0x3f) << 10;
797 data |= (shift_op.shift & 0x3) << 22;
798 }
799 }
800
801 if (invert) {
802 data |= 1 << 21;
803 }
804 } else {
805 return UT32_MAX;
806 }
807
808 return r_read_be32 (&data);
809 }
810
adrp(ArmOp * op,ut64 addr,ut32 k)811 static ut32 adrp(ArmOp *op, ut64 addr, ut32 k) { //, int reg, ut64 dst) {
812 ut64 at = 0LL;
813 ut32 data = k;
814 if (op->operands[0].type == ARM_GPR) {
815 data |= encode1reg (op);
816 } else {
817 eprintf ("Usage: adrp x0, addr\n");
818 return UT32_MAX;
819 }
820 if (op->operands[1].type == ARM_CONSTANT) {
821 // XXX what about negative values?
822 at = op->operands[1].immediate - addr;
823 at /= 4;
824 } else {
825 eprintf ("Usage: adrp, x0, addr\n");
826 return UT32_MAX;
827 }
828 ut8 b0 = at;
829 ut8 b1 = (at >> 3) & 0xff;
830
831 #if 0
832 ut8 b2 = (at >> (8 + 7)) & 0xff;
833 data += b0 << 29;
834 data += b1 << 16;
835 data += b2 << 24;
836 #endif
837 data += b0 << 16;
838 data += b1 << 8;
839 return data;
840 }
841
adr(ArmOp * op,int addr)842 static ut32 adr(ArmOp *op, int addr) {
843 ut32 data = UT32_MAX;
844 ut64 at = 0LL;
845
846 if (op->operands[1].type & ARM_CONSTANT) {
847 // XXX what about negative values?
848 at = op->operands[1].immediate - addr;
849 at /= 4;
850 }
851 data = 0x00000030;
852 data |= encode1reg (op);
853 ut8 b0 = at;
854 ut8 b1 = (at >> 3) & 0xff;
855 ut8 b2 = (at >> (8 + 7)) & 0xff;
856 data += b0 << 29;
857 data += b1 << 16;
858 data += b2 << 24;
859 return data;
860 }
861
stp(ArmOp * op,int k)862 static ut32 stp(ArmOp *op, int k) {
863 ut32 data = UT32_MAX;
864
865 if (op->operands[3].immediate & 0x7) {
866 return data;
867 }
868 if (k == 0x000040a9 && (op->operands[0].reg == op->operands[1].reg)) {
869 return data;
870 }
871
872 data = k;
873 data |= encode2regs (op);
874 data += (op->operands[3].immediate & 0x8) << 20;
875 data += (op->operands[3].immediate >> 4) << 8;
876 return data;
877 }
878
exception(ArmOp * op,ut32 k)879 static ut32 exception(ArmOp *op, ut32 k) {
880 ut32 data = UT32_MAX;
881
882 if (op->operands[0].type == ARM_CONSTANT) {
883 int n = op->operands[0].immediate;
884 data = k;
885 data += (((n / 8) & 0xff) << 16);
886 data += n << 29;//((n >> 8) << 8);
887 }
888 return data;
889 }
890
arithmetic(ArmOp * op,int k)891 static ut32 arithmetic(ArmOp *op, int k) {
892 ut32 data = UT32_MAX;
893 if (op->operands_count < 3) {
894 return data;
895 }
896
897 if (!(op->operands[0].type & ARM_GPR &&
898 op->operands[1].type & ARM_GPR)) {
899 return data;
900 }
901 if (op->operands[2].type & ARM_GPR) {
902 k -= 6;
903 }
904
905 data = k;
906 data += encode1reg (op);
907 data += (op->operands[1].reg & 7) << (24 + 5);
908 data += (op->operands[1].reg >> 3) << 16;
909 if (op->operands[2].type & ARM_GPR) {
910 data += op->operands[2].reg << 8;
911 } else {
912 data += (op->operands[2].reg & 0x3f) << 18;
913 data += (op->operands[2].reg >> 6) << 8;
914 }
915 return data;
916 }
917
neg(ArmOp * op)918 static ut32 neg(ArmOp *op) {
919 if (op->operands_count < 2) {
920 return -1;
921 }
922 op->operands_count++;
923 op->operands[2] = op->operands[1];
924 op->operands[1].reg = 31; // xzr
925
926 return arithmetic (op, 0xd1); // sub reg0, xzr, reg1
927 }
928
bitfield(ArmOp * op,int k)929 static ut32 bitfield(ArmOp *op, int k) {
930 ut32 data = UT32_MAX;
931 check_cond (op->operands_count == 4);
932 check_cond (op->operands[0].type == ARM_GPR);
933 check_cond (op->operands[1].type == ARM_GPR);
934 check_cond (op->operands[0].reg_type == op->operands[1].reg_type);
935 check_cond (op->operands[2].type == ARM_CONSTANT);
936 check_cond (op->operands[3].type == ARM_CONSTANT);
937 int bits = (op->operands[0].reg_type & ARM_REG64) ? 64 : 32;
938 // unalias
939 if (!strcmp (op->mnemonic, "sbfx") || !strcmp (op->mnemonic, "ubfx")) {
940 op->operands[3].immediate += op->operands[2].immediate - 1;
941 } else if (!strcmp (op->mnemonic, "sbfiz") || !strcmp (op->mnemonic, "ubfiz")) {
942 check_cond (op->operands[2].immediate < bits);
943 int temp = bits - op->operands[2].immediate;
944 check_cond (op->operands[3].immediate <= temp);
945 op->operands[2].immediate = temp & (bits - 1);
946 op->operands[3].immediate--;
947 }
948 check_cond (op->operands[2].immediate < bits);
949 check_cond (op->operands[3].immediate < bits);
950 if (bits == 64) {
951 k |= 0x00004080;
952 }
953 k |= op->operands[2].immediate << 8 | op->operands[3].immediate << 18;
954 data = k | encode2regs (op);
955 return data;
956 }
957
parseOperands(char * str,ArmOp * op)958 static bool parseOperands(char* str, ArmOp *op) {
959 char *t = strdup (str);
960 int operand = 0;
961 char *token = t;
962 char *x;
963 int imm_count = 0;
964 int mem_opt = 0;
965 int msr_op_index = 0;
966 size_t index_bound = strcspn (t, "]");
967 if (!token) {
968 return false;
969 }
970
971 while (token) {
972 char *next = strchr (token, ',');
973 if (next) {
974 // Change the ',' in token to null byte
975 // essentialy split the token by commas
976 *next++ = '\0';
977 }
978 while (token[0] == ' ') {
979 token++;
980 }
981 if (operand >= MAX_OPERANDS) {
982 eprintf ("Too many operands\n");
983 return false;
984 }
985 op->operands[operand].type = ARM_NOTYPE;
986 op->operands[operand].reg_type = ARM_UNDEFINED;
987
988 //parse MSR (immediate) operand 1
989 if (strcmp (op->mnemonic, "msr") == 0 && operand == 1) {
990
991 //operand 1 must be a immediate
992 if ( token[0] == '#' || (token[0] >= '0' && token[0] <= '9')) {
993 //immediate operand found.
994 op->operands[operand].sp_val = 0xfffe; //not regiter, but a immediate
995 op->operands[operand].immediate = r_num_math (NULL, token[0]=='#'?token+1:token);
996 operand ++;
997 token = next;
998 continue;
999 }
1000 }
1001
1002 //parse system registers
1003 if ((strcmp (op->mnemonic, "mrs") == 0 && operand == 1) || (strcmp (op->mnemonic, "msr") == 0 && operand == 0)) {
1004 for(msr_op_index = 0; msr_const[msr_op_index].name; msr_op_index++) {
1005 if (strcasecmp (token, msr_const[msr_op_index].name) == 0) {
1006 op->operands_count ++;
1007 op->operands[operand].type = ARM_CONSTANT;
1008 op->operands[operand].immediate = msr_const[msr_op_index].val;
1009 imm_count++;
1010 break;
1011 }
1012 }
1013 if (msr_const[msr_op_index].name) {
1014 operand ++;
1015 token = next;
1016 continue;
1017 }
1018 }
1019
1020 while (token[0] == ' ' || token[0] == '[' || token[0] == ']') {
1021 token ++;
1022 }
1023
1024 if (!strncmp (token, "lsl", 3)) {
1025 op->operands[operand].type = ARM_SHIFT;
1026 op->operands[operand].shift = ARM_LSL;
1027 } else if (!strncmp (token, "lsr", 3)) {
1028 op->operands[operand].type = ARM_SHIFT;
1029 op->operands[operand].shift = ARM_LSR;
1030 } else if (!strncmp (token, "asr", 3)) {
1031 op->operands[operand].type = ARM_SHIFT;
1032 op->operands[operand].shift = ARM_ASR;
1033 } else if (!strncmp (token, "ror", 3)) {
1034 op->operands[operand].type = ARM_SHIFT;
1035 op->operands[operand].shift = ARM_ROR;
1036 } else if (!strncmp (token, "uxtb", 4)) {
1037 op->operands[operand].type = ARM_EXTEND;
1038 op->operands[operand].shift = ARM_UXTB;
1039 } else if (!strncmp (token, "uxth", 4)) {
1040 op->operands[operand].type = ARM_EXTEND;
1041 op->operands[operand].shift = ARM_UXTH;
1042 } else if (!strncmp (token, "uxtw", 4)) {
1043 op->operands[operand].type = ARM_EXTEND;
1044 op->operands[operand].shift = ARM_UXTW;
1045 } else if (!strncmp (token, "uxtx", 4)) {
1046 op->operands[operand].type = ARM_EXTEND;
1047 op->operands[operand].shift = ARM_UXTX;
1048 } else if (!strncmp (token, "sxtb", 4)) {
1049 op->operands[operand].type = ARM_EXTEND;
1050 op->operands[operand].shift = ARM_SXTB;
1051 } else if (!strncmp (token, "sxth", 4)) {
1052 op->operands[operand].type = ARM_EXTEND;
1053 op->operands[operand].shift = ARM_SXTH;
1054 } else if (!strncmp (token, "sxtw", 4)) {
1055 op->operands[operand].type = ARM_EXTEND;
1056 op->operands[operand].shift = ARM_SXTW;
1057 } else if (!strncmp (token, "sxtx", 4)) {
1058 op->operands[operand].type = ARM_EXTEND;
1059 op->operands[operand].shift = ARM_SXTX;
1060 }
1061 if (op->operands[operand].type == ARM_SHIFT) {
1062 op->operands_count ++;
1063 token += 3;
1064 while (*token && *token == ' ') {
1065 token++;
1066 }
1067 if (*token == '#') {
1068 token++;
1069 }
1070 if (!*token || !isdigit((unsigned char)*token)) {
1071 return false;
1072 }
1073 op->operands[operand].shift_amount = r_num_math (NULL, token);
1074 op->operands[operand].amount_present = true;
1075 if (op->operands[operand].shift_amount > 63) {
1076 free (t);
1077 return false;
1078 }
1079 operand ++;
1080 token = next;
1081 continue;
1082 }
1083 if (op->operands[operand].type == ARM_EXTEND) {
1084 op->operands_count++;
1085 token += 4;
1086 while (*token && *token == ' ') {
1087 token++;
1088 }
1089 bool present = false;
1090 if (*token == '#') {
1091 present = true;
1092 ++token;
1093 }
1094 if (!*token || !isdigit((unsigned char)*token)) {
1095 if (present) {
1096 return false;
1097 }
1098 op->operands[operand].shift_amount = 0;
1099 op->operands[operand].amount_present = false;
1100 } else {
1101 op->operands[operand].shift_amount = r_num_math (NULL, token);
1102 op->operands[operand].amount_present = true;
1103 }
1104 operand++;
1105 token = next;
1106 continue;
1107 }
1108
1109 switch (token[0]) {
1110 case 'x':
1111 x = strchr (token, ',');
1112 if (x) {
1113 x[0] = '\0';
1114 }
1115 op->operands_count ++;
1116 op->operands[operand].type = ARM_GPR;
1117 op->operands[operand].reg_type = ARM_REG64;
1118
1119 if (!strncmp(token + 1, "zr", 2)) {
1120 // XZR
1121 op->operands[operand].reg = 31;
1122 } else {
1123 op->operands[operand].reg = r_num_math (NULL, token + 1);
1124 }
1125
1126 if (op->operands[operand].reg > 31) {
1127 free (t);
1128 return false;
1129 }
1130 break;
1131 case 'w':
1132 op->operands_count ++;
1133 op->operands[operand].type = ARM_GPR;
1134 op->operands[operand].reg_type = ARM_REG32;
1135
1136 if (!strncmp(token + 1, "zr", 2)) {
1137 // WZR
1138 op->operands[operand].reg = 31;
1139 } else if (!strncmp(token + 1, "sp", 2)) {
1140 // WSP
1141 op->operands[operand].reg = 31;
1142 op->operands[operand].reg_type |= ARM_SP;
1143 } else {
1144 op->operands[operand].reg = r_num_math (NULL, token + 1);
1145 }
1146
1147 if (op->operands[operand].reg > 31) {
1148 free (t);
1149 return false;
1150 }
1151 break;
1152 case 'v':
1153 op->operands_count ++;
1154 op->operands[operand].type = ARM_FP;
1155 op->operands[operand].reg = r_num_math (NULL, token + 1);
1156 break;
1157 case 's':
1158 case 'S':
1159 if (token[1] == 'P' || token [1] == 'p') {
1160 int i;
1161 for (i = 0; msr_const[i].name; i++) {
1162 if (!r_str_ncasecmp (token, msr_const[i].name, strlen (msr_const[i].name))) {
1163 op->operands[operand].sp_val = msr_const[i].val;
1164 break;
1165 }
1166 }
1167 op->operands_count ++;
1168 op->operands[operand].type = ARM_GPR;
1169 op->operands[operand].reg_type = ARM_SP | ARM_REG64;
1170 op->operands[operand].reg = 31;
1171 break;
1172 }
1173 mem_opt = get_mem_option (token);
1174 if (mem_opt != -1) {
1175 op->operands_count ++;
1176 op->operands[operand].type = ARM_MEM_OPT;
1177 op->operands[operand].mem_option = mem_opt;
1178 }
1179 break;
1180 case 'L':
1181 case 'l':
1182 case 'I':
1183 case 'i':
1184 case 'N':
1185 case 'n':
1186 case 'O':
1187 case 'o':
1188 case 'p':
1189 case 'P':
1190 mem_opt = get_mem_option (token);
1191 if (mem_opt != -1) {
1192 op->operands_count ++;
1193 op->operands[operand].type = ARM_MEM_OPT;
1194 op->operands[operand].mem_option = mem_opt;
1195 }
1196 break;
1197 case '#':
1198 if (token[1] == '-') {
1199 op->operands[operand].sign = -1;
1200 }
1201 op->operands_count ++;
1202 op->operands[operand].type = ARM_CONSTANT;
1203 op->operands[operand].immediate = r_num_math (NULL, token + 1);
1204 op->operands[operand].preindex = token - t < index_bound;
1205 imm_count++;
1206 break;
1207 case '-':
1208 op->operands[operand].sign = -1;
1209 // falthru
1210 default:
1211 op->operands_count ++;
1212 op->operands[operand].type = ARM_CONSTANT;
1213 op->operands[operand].immediate = r_num_math (NULL, token);
1214 op->operands[operand].preindex = token - t < index_bound;
1215 imm_count++;
1216 break;
1217 }
1218 token = next;
1219
1220 operand ++;
1221 if (operand > MAX_OPERANDS) {
1222 free (t);
1223 return false;
1224 }
1225 }
1226 free (t);
1227 return true;
1228 }
1229
parseOpcode(const char * str,ArmOp * op)1230 static bool parseOpcode(const char *str, ArmOp *op) {
1231 char *in = strdup (str);
1232 char *space = strchr (in, ' ');
1233 if (!space) {
1234 op->operands[0].type = ARM_NOTYPE;
1235 op->mnemonic = in;
1236 return true;
1237 }
1238 space[0] = '\0';
1239 op->mnemonic = in;
1240 space ++;
1241 op->writeback = strstr (space, "]!") != NULL;
1242 return parseOperands (space, op);
1243 }
1244
handlePAC(ut32 * op,const char * str)1245 static bool handlePAC(ut32 *op, const char *str) {
1246 if (!strcmp (str, "autiasp")) {
1247 *op = 0xbf2303d5;
1248 return true;
1249 }
1250 if (!strcmp (str, "autiaz")) {
1251 *op = 0x9f2303d5;
1252 return true;
1253 }
1254 if (!strcmp (str, "autibsp")) {
1255 *op = 0xff2303d5;
1256 return true;
1257 }
1258 if (!strcmp (str, "autibz")) {
1259 *op = 0xdf2303d5;
1260 return true;
1261 }
1262 if (!strcmp (str, "paciaz")) {
1263 *op = 0x1f2303d5;
1264 return true;
1265 }
1266 if (!strcmp (str, "pacibz")) {
1267 *op = 0x5f2303d5;
1268 return true;
1269 }
1270 if (!strcmp (str, "paciasp")) {
1271 *op = 0x3f2303d5;
1272 return true;
1273 }
1274 if (!strcmp (str, "pacibsp")) {
1275 *op = 0x7f2303d5;
1276 return true;
1277 }
1278 if (!strcmp (str, "retab")) {
1279 *op = 0xff0f5fd6;
1280 return true;
1281 }
1282 return false;
1283 }
1284
arm64ass(const char * str,ut64 addr,ut32 * op)1285 bool arm64ass(const char *str, ut64 addr, ut32 *op) {
1286 ArmOp ops = {0};
1287 if (!parseOpcode (str, &ops)) {
1288 free (ops.mnemonic);
1289 return false;
1290 }
1291 /* TODO: write tests for this and move out the regsize logic into the mov */
1292 if (!strncmp (str, "mov", 3)) {
1293 *op = mov (&ops);
1294 } else if (!strncmp (str, "cb", 2)) {
1295 *op = cb (&ops);
1296 } else if (!strncmp (str, "cmp", 3)) {
1297 *op = cmp (&ops);
1298 } else if (!strncmp (str, "ldrb", 4)) {
1299 *op = lsop (&ops, 0x00004038, -1);
1300 } else if (!strncmp (str, "ldrh", 4)) {
1301 *op = lsop (&ops, 0x00004078, -1);
1302 } else if (!strncmp (str, "ldrsh", 5)) {
1303 *op = lsop (&ops, 0x00008078, -1);
1304 } else if (!strncmp (str, "ldrsw", 5)) {
1305 *op = lsop (&ops, 0x00000098, addr);
1306 } else if (!strncmp (str, "ldrsb", 5)) {
1307 *op = lsop (&ops, 0x00008038, -1);
1308 } else if (!strncmp (str, "strb", 4)) {
1309 *op = lsop (&ops, 0x00000038, -1);
1310 } else if (!strncmp (str, "strh", 4)) {
1311 *op = lsop (&ops, 0x00000078, -1);
1312 } else if (!strncmp (str, "ldr", 3)) {
1313 *op = reglsop (&ops, 0x000040f8);
1314 } else if (!strncmp (str, "stur", 4)) {
1315 *op = regsluop (&ops, 0x000000f8);
1316 } else if (!strncmp (str, "ldur", 4)) {
1317 *op = regsluop (&ops, 0x000040f8);
1318 } else if (!strncmp (str, "str", 3)) {
1319 *op = reglsop (&ops, 0x000000f8);
1320 } else if (!strncmp (str, "stp", 3)) {
1321 *op = stp (&ops, 0x000000a9);
1322 } else if (!strncmp (str, "ldp", 3)) {
1323 *op = stp (&ops, 0x000040a9);
1324 } else if (!strncmp (str, "sub", 3)) { // w
1325 *op = arithmetic (&ops, 0xd1);
1326 } else if (!strncmp (str, "add x", 5)) {
1327 *op = arithmetic (&ops, 0x91);
1328 } else if (!strncmp (str, "add w", 5)) {
1329 *op = arithmetic (&ops, 0x11);
1330 } else if (!strncmp (str, "adr x", 5)) { // w
1331 *op = adr (&ops, addr);
1332 } else if (!strncmp (str, "adrp x", 6)) {
1333 *op = adrp (&ops, addr, 0x00000090);
1334 } else if (!strncmp (str, "neg", 3)) {
1335 *op = neg (&ops);
1336 } else if (!strcmp (str, "isb")) {
1337 *op = 0xdf3f03d5;
1338 } else if (handlePAC (op, str)) { // PAC
1339 free (ops.mnemonic);
1340 return true;
1341 } else if (!strcmp (str, "nop")) {
1342 *op = 0x1f2003d5;
1343 } else if (!strcmp (str, "ret")) {
1344 *op = 0xc0035fd6;
1345 } else if (!strncmp (str, "msr ", 4)) {
1346 *op = msr (&ops, 0);
1347 } else if (!strncmp (str, "mrs ", 4)) {
1348 *op = msr (&ops, 1);
1349 } else if (!strncmp (str, "ands ", 5)) {
1350 *op = logical (&ops, false, ARM_ANDS);
1351 } else if (!strncmp (str, "and ", 4)) {
1352 *op = logical (&ops, false, ARM_AND);
1353 } else if (!strncmp (str, "bics ", 5)) {
1354 *op = logical (&ops, true, ARM_ANDS);
1355 } else if (!strncmp (str, "bic ", 4)) {
1356 *op = logical (&ops, true, ARM_AND);
1357 } else if (!strncmp (str, "eon ", 4)) {
1358 *op = logical (&ops, true, ARM_EOR);
1359 } else if (!strncmp (str, "eor ", 4)) {
1360 *op = logical (&ops, false, ARM_EOR);
1361 } else if (!strncmp (str, "orn ", 4)) {
1362 *op = logical (&ops, true, ARM_ORR);
1363 } else if (!strncmp (str, "orr ", 4)) {
1364 *op = logical (&ops, false, ARM_ORR);
1365 } else if (!strncmp (str, "svc ", 4)) { // system level exception
1366 *op = exception (&ops, 0x010000d4);
1367 } else if (!strncmp (str, "hvc ", 4)) { // hypervisor level exception
1368 *op = exception (&ops, 0x020000d4);
1369 } else if (!strncmp (str, "smc ", 4)) { // secure monitor exception
1370 *op = exception (&ops, 0x030000d4);
1371 } else if (!strncmp (str, "brk ", 4)) { // breakpoint
1372 *op = exception (&ops, 0x000020d4);
1373 } else if (!strncmp (str, "hlt ", 4)) { // halt
1374 *op = exception (&ops, 0x000040d4);
1375 } else if (!strncmp (str, "b ", 2)) {
1376 *op = branch (&ops, addr, 0x14);
1377 } else if (!strncmp (str, "b.eq ", 5)) {
1378 *op = bdot (&ops, addr, 0x00000054);
1379 } else if (!strncmp (str, "b.hs ", 5)) {
1380 *op = bdot (&ops, addr, 0x02000054);
1381 } else if (!strncmp (str, "bl ", 3)) {
1382 *op = branch (&ops, addr, 0x94);
1383 } else if (!strncmp (str, "br x", 4)) {
1384 *op = branch (&ops, addr, 0x1fd6);
1385 } else if (!strncmp (str, "blr x", 5)) {
1386 *op = branch (&ops, addr, 0x3fd6);
1387 } else if (!strncmp (str, "dmb ", 4)) {
1388 *op = mem_barrier (&ops, addr, 0xbf3003d5);
1389 } else if (!strncmp (str, "dsb ", 4)) {
1390 *op = mem_barrier (&ops, addr, 0x9f3003d5);
1391 } else if (!strncmp (str, "isb", 3)) {
1392 *op = mem_barrier (&ops, addr, 0xdf3f03d5);
1393 } else if (!strncmp (str, "sbfiz ", 6) || !strncmp (str, "sbfm ", 5)
1394 || !strncmp (str, "sbfx ", 5)) {
1395 *op = bitfield (&ops, 0x00000013);
1396 } else if (!strncmp (str, "ubfiz ", 6) || !strncmp (str, "ubfm ", 5)
1397 || !strncmp (str, "ubfx ", 5)) {
1398 *op = bitfield (&ops, 0x00000053);
1399 }
1400 free (ops.mnemonic);
1401 return *op != UT32_MAX;
1402 }
1403