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