Rizin
unix-like reverse engineering framework and cli tools
arm_il32.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2022 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_analysis.h>
5 #include <capstone/capstone.h>
6 
7 #include "arm_cs.h"
8 #include "arm_accessors32.h"
9 
11 
12 #include "arm_il_common.inc"
13 
17 static const char *regs_bound_32[] = {
18  "lr", "sp",
19  "qf", "vf", "cf", "zf", "nf", "gef",
20  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
21  "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
22  "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
23  NULL
24 };
25 
29 static const char *reg_var_name(arm_reg reg) {
30  switch (reg) {
31  case ARM_REG_LR: return "lr";
32  case ARM_REG_SP: return "sp";
33  case ARM_REG_D0: return "d0";
34  case ARM_REG_D1: return "d1";
35  case ARM_REG_D2: return "d2";
36  case ARM_REG_D3: return "d3";
37  case ARM_REG_D4: return "d4";
38  case ARM_REG_D5: return "d5";
39  case ARM_REG_D6: return "d6";
40  case ARM_REG_D7: return "d7";
41  case ARM_REG_D8: return "d8";
42  case ARM_REG_D9: return "d9";
43  case ARM_REG_D10: return "d10";
44  case ARM_REG_D11: return "d11";
45  case ARM_REG_D12: return "d12";
46  case ARM_REG_D13: return "d13";
47  case ARM_REG_D14: return "d14";
48  case ARM_REG_D15: return "d15";
49  case ARM_REG_D16: return "d16";
50  case ARM_REG_D17: return "d17";
51  case ARM_REG_D18: return "d18";
52  case ARM_REG_D19: return "d19";
53  case ARM_REG_D20: return "d20";
54  case ARM_REG_D21: return "d21";
55  case ARM_REG_D22: return "d22";
56  case ARM_REG_D23: return "d23";
57  case ARM_REG_D24: return "d24";
58  case ARM_REG_D25: return "d25";
59  case ARM_REG_D26: return "d26";
60  case ARM_REG_D27: return "d27";
61  case ARM_REG_D28: return "d28";
62  case ARM_REG_D29: return "d29";
63  case ARM_REG_D30: return "d30";
64  case ARM_REG_D31: return "d31";
65  case ARM_REG_R0: return "r0";
66  case ARM_REG_R1: return "r1";
67  case ARM_REG_R2: return "r2";
68  case ARM_REG_R3: return "r3";
69  case ARM_REG_R4: return "r4";
70  case ARM_REG_R5: return "r5";
71  case ARM_REG_R6: return "r6";
72  case ARM_REG_R7: return "r7";
73  case ARM_REG_R8: return "r8";
74  case ARM_REG_R9: return "r9";
75  case ARM_REG_R10: return "r10";
76  case ARM_REG_R11: return "r11";
77  case ARM_REG_R12: return "r12";
78  default: return NULL;
79  }
80 }
81 
83  if (reg >= ARM_REG_D0 && reg <= ARM_REG_D31) {
84  return 64;
85  }
86  if (reg >= ARM_REG_Q0 && reg <= ARM_REG_Q15) {
87  return 128;
88  }
89  return 32;
90 }
91 
96  if (reg == ARM_REG_PC) {
97  return U32(pc);
98  }
99  if (reg >= ARM_REG_S0 && reg <= ARM_REG_S31) {
100  ut32 idx = reg - ARM_REG_S0;
102  return UNSIGNED(32, idx % 2 ? SHIFTR0(var, UN(7, 32)) : var);
103  }
104  const char *var = reg_var_name(reg);
105  return var ? VARG(var) : NULL;
106 }
107 
108 #define PC(addr, is_thumb) (addr + (is_thumb ? 4 : 8))
109 #define PCALIGN(addr, is_thumb) (PC(addr, is_thumb) & ~3ul)
110 #define REG_VAL(id) read_reg(PC(insn->address, is_thumb), id)
111 #define REG(n) REG_VAL(REGID(n))
112 #define MEMBASE(x) REG_VAL(insn->detail->arm.operands[x].mem.base)
113 
119  if (reg >= ARM_REG_S0 && reg <= ARM_REG_S31) {
120  ut32 idx = reg - ARM_REG_S0;
121  arm_reg dreg = ARM_REG_D0 + idx / 2;
122  RzILOpBitVector *masked = LOGAND(read_reg(0, dreg), U64(idx % 2 ? 0xffffffffull : 0xffffffff00000000ull));
123  v = UNSIGNED(64, v);
124  if (idx % 2) {
125  v = SHIFTL0(v, UN(6, 32));
126  }
127  return SETG(reg_var_name(dreg), LOGOR(masked, v));
128  }
129  const char *var = reg_var_name(reg);
130  if (!var) {
132  return NULL;
133  }
134  return SETG(var, v);
135 }
136 
142  switch (c) {
143  case ARM_CC_EQ:
144  return VARG("zf");
145  case ARM_CC_NE:
146  return INV(VARG("zf"));
147  case ARM_CC_HS:
148  return VARG("cf");
149  case ARM_CC_LO:
150  return INV(VARG("cf"));
151  case ARM_CC_MI:
152  return VARG("nf");
153  case ARM_CC_PL:
154  return INV(VARG("nf"));
155  case ARM_CC_VS:
156  return VARG("vf");
157  case ARM_CC_VC:
158  return INV(VARG("vf"));
159  case ARM_CC_HI:
160  return AND(VARG("cf"), INV(VARG("zf")));
161  case ARM_CC_LS:
162  return OR(INV(VARG("cf")), VARG("zf"));
163  case ARM_CC_GE:
164  return INV(XOR(VARG("nf"), VARG("vf")));
165  case ARM_CC_LT:
166  return XOR(VARG("nf"), VARG("vf"));
167  case ARM_CC_GT:
168  return AND(INV(VARG("zf")), INV(XOR(VARG("nf"), VARG("vf"))));
169  case ARM_CC_LE:
170  return OR(VARG("zf"), XOR(VARG("nf"), VARG("vf")));
171  case ARM_CC_AL:
172  default:
173  return NULL;
174  }
175 }
176 
178  switch (type) {
179  case ARM_SFT_ASR_REG:
180  case ARM_SFT_LSL_REG:
181  case ARM_SFT_LSR_REG:
182  case ARM_SFT_ROR_REG:
183  case ARM_SFT_RRX_REG:
184  return true;
185  default:
186  return false;
187  }
188 }
189 
191  switch (type) {
192  case ARM_SFT_ASR:
193  case ARM_SFT_ASR_REG:
194  if (!dist) {
195  return val;
196  }
197  if (carry_out) {
198  *carry_out = LSB(SHIFTRA(APPEND(DUP(val), ITE(VARG("cf"), UN(1, 1), UN(1, 0))), DUP(dist)));
199  }
200  return SHIFTRA(val, dist);
201  case ARM_SFT_LSL:
202  case ARM_SFT_LSL_REG:
203  if (!dist) {
204  return val;
205  }
206  if (carry_out) {
207  *carry_out = MSB(SHIFTL0(APPEND(ITE(VARG("cf"), UN(1, 1), UN(1, 0)), DUP(val)), DUP(dist)));
208  }
209  return SHIFTL0(val, dist);
210  case ARM_SFT_LSR:
211  case ARM_SFT_LSR_REG:
212  if (!dist) {
213  return val;
214  }
215  if (carry_out) {
216  *carry_out = LSB(SHIFTR0(APPEND(DUP(val), ITE(VARG("cf"), UN(1, 1), UN(1, 0))), DUP(dist)));
217  }
218  return SHIFTR0(val, dist);
219  case ARM_SFT_ROR:
220  case ARM_SFT_ROR_REG:
221  if (!dist) {
222  return val;
223  }
224  if (dist->code == RZ_IL_OP_CAST) {
225  // this takes care of the mod 32 for register-based shifts which originally have 8 bits:
226  dist->op.cast.length = 5;
227  }
228  if (carry_out) {
229  *carry_out = ITE(IS_ZERO(DUP(dist)), VARG("cf"), MSB(SHIFTL0(DUP(val), NEG(DUP(dist)))));
230  }
231  return LOGOR(
232  SHIFTR0(val, dist),
233  SHIFTL0(DUP(val), NEG(DUP(dist))));
234  case ARM_SFT_RRX:
235  case ARM_SFT_RRX_REG:
236  if (carry_out) {
237  *carry_out = LSB(DUP(val));
238  }
239  rz_il_op_pure_free(dist);
240  return SHIFTR(VARG("cf"), val, UN(5, 1));
241  default:
242  rz_il_op_pure_free(dist);
243  return val;
244  }
245 }
246 
247 static RzILOpBitVector *arg_mem(RzILOpBitVector *base_plus_disp, cs_arm_op *op, RZ_NULLABLE RzILOpBool **carry_out) {
248  if (op->mem.index != ARM_REG_INVALID && op->mem.index != ARM_REG_PC) {
249  RzILOpBitVector *index = read_reg(0, op->mem.index);
250  return ADD(base_plus_disp, shift(index, carry_out, op->shift.type, UN(5, op->shift.value)));
251  }
252  return base_plus_disp;
253 }
254 
259 static RzILOpBitVector *arg(cs_insn *insn, bool is_thumb, int n, RZ_NULLABLE RzILOpBool **carry_out) {
260  if (carry_out) {
261  *carry_out = NULL;
262  }
263  cs_arm_op *op = &insn->detail->arm.operands[n];
264  switch (op->type) {
265  case ARM_OP_REG: {
266  RzILOpBitVector *r = REG(n);
267  if (!r) {
268  return NULL;
269  }
270  RzILOpBitVector *dist = NULL;
271  if (is_reg_shift(op->shift.type)) {
272  dist = read_reg(PC(insn->address, is_thumb), op->shift.value);
273  if (dist) {
274  dist = UNSIGNED(8, dist);
275  }
276  } else if (op->shift.type != ARM_SFT_INVALID) {
277  dist = UN(5, op->shift.value);
278  }
279  return r ? shift(r, carry_out, op->shift.type, dist) : NULL;
280  }
281  case ARM_OP_IMM: {
282  ut32 imm = IMM(n);
283  if (op->shift.type == ARM_SFT_INVALID && ISIMM(n + 1)) {
284  // sometimes capstone encoded the shift like this, see also comment below
285  ut32 ror = IMM(n + 1);
286  imm = (imm >> ror) | (imm << (32 - ror));
287  }
288  if (carry_out) {
289  // Some "movs"s leave c alone, some set it to the highest bit of the result.
290  // Determining which one it is from capstone's info is tricky:
291  // Arm defines that it is set when the imm12's rotate value is not 0.
292  // This is the case when:
293  // * capstone disassembles to something like "movs r0, 0, 2", giving us an explicit third operand
294  // * capstone disassembles to something like "movs r0, 0x4000000" without the third operand,
295  // but we can see that the value is larger than 8 bits, so there must be a shift.
296  if (ISIMM(n + 1) || imm > 0xff) {
297  *carry_out = (imm & (1ul << 31)) ? IL_TRUE : IL_FALSE;
298  }
299  }
300  return U32(imm);
301  }
302  case ARM_OP_MEM: {
304  int disp = MEMDISP(n);
305  if (disp > 0) {
306  addr = ADD(addr, U32(disp));
307  } else if (disp < 0) {
308  addr = SUB(addr, U32(-disp));
309  }
310  return arg_mem(addr, &insn->detail->arm.operands[n], carry_out);
311  }
312  default:
313  break;
314  }
315  return NULL;
316 }
317 
318 #define ARG_C(n, carry) arg(insn, is_thumb, n, carry)
319 #define ARG(n) ARG_C(n, NULL)
320 
326  return SEQ2(
327  SETG("zf", IS_ZERO(v)),
328  SETG("nf", MSB(DUP(v))));
329 }
330 
336  RzILOpEffect *setf = f ? SEQ5(
337  SETG("nf", INV(IS_ZERO(LOGAND(val, U32(1ul << 31))))),
338  SETG("zf", INV(IS_ZERO(LOGAND(DUP(val), U32(1ul << 30))))),
339  SETG("cf", INV(IS_ZERO(LOGAND(DUP(val), U32(1ul << 29))))),
340  SETG("vf", INV(IS_ZERO(LOGAND(DUP(val), U32(1ul << 28))))),
341  SETG("qf", INV(IS_ZERO(LOGAND(DUP(val), U32(1ul << 27))))))
342  : NULL;
343  RzILOpEffect *sets = s ? SETG("gef", UNSIGNED(4, SHIFTR0(setf ? DUP(val) : val, UN(5, 16)))) : NULL;
344  return setf && sets ? SEQ2(sets, setf) : (setf ? setf : sets);
345 }
346 
351 static RzILOpEffect *mov(cs_insn *insn, bool is_thumb) {
352  if (!ISREG(0) || (!ISIMM(1) && !ISREG(1)) || OPCOUNT() < 2) {
353  return NULL;
354  }
355  size_t base_op = 1;
356  // All of lsl, lsr, etc. are really just mov/movs, but capstone encodes them differently,
357  // with the shift distance as extra (third) operand. But it doesn't do that always, sometimes the shift is also still
358  // embedded in the second operand.
359  arm_shifter shift_alias = ARM_SFT_INVALID;
360  if (insn->detail->arm.operands[base_op].shift.type == ARM_SFT_INVALID) {
361  base_op = OPCOUNT() < 3 ? 0 : 1;
362  switch (insn->id) {
363  case ARM_INS_LSL:
364  shift_alias = ARM_SFT_LSL;
365  break;
366  case ARM_INS_LSR:
367  shift_alias = ARM_SFT_LSR;
368  break;
369  case ARM_INS_ASR:
370  shift_alias = ARM_SFT_ASR;
371  break;
372  case ARM_INS_RRX:
373  shift_alias = ARM_SFT_RRX;
374  base_op = 1;
375  break;
376  case ARM_INS_ROR:
377  shift_alias = ARM_SFT_ROR;
378  break;
379  default:
380  base_op = 1;
381  break;
382  }
383  }
384  bool update_flags = insn->detail->arm.update_flags;
385  RzILOpBool *carry = NULL;
386  RzILOpPure *val = ARG_C(base_op, update_flags && shift_alias == ARM_SFT_INVALID ? &carry : NULL);
387  if (!val) {
388  return NULL;
389  }
390  if (shift_alias != ARM_SFT_INVALID) {
391  RzILOpPure *dist = NULL;
392  if (shift_alias != ARM_SFT_RRX) {
393  dist = ARG(base_op + 1);
394  if (!dist) {
396  return NULL;
397  }
398  }
399  val = shift(val, update_flags ? &carry : NULL, shift_alias, dist ? UNSIGNED(8, dist) : NULL);
400  }
401  if (insn->id == ARM_INS_MVN) {
402  val = LOGNOT(val);
403  }
404  if (REGID(0) == ARM_REG_PC) {
405  if (update_flags) {
406  // ALUExceptionReturn()
407  goto err;
408  } else {
409  return JMP(val);
410  }
411  }
412  RzILOpEffect *eff = write_reg(REGID(0), val);
413  if (!eff) {
414  goto err;
415  }
416  if (update_flags) {
417  RzILOpEffect *zn = update_flags_zn(REG(0));
418  return carry
419  ? SEQ4(SETL("cf_tmp", carry), eff, SETG("cf", VARL("cf_tmp")), zn) // rrxs still needs the old carry
420  : SEQ2(eff, zn);
421  }
422  return eff;
423 err:
424  rz_il_op_pure_free(carry);
426  return NULL;
427 }
428 
433 static RzILOpEffect *movt(cs_insn *insn, bool is_thumb) {
434  if (!ISREG(0) || !ISIMM(1)) {
435  return NULL;
436  }
437  RzILOpPure *regval = REG(0);
438  if (!regval) {
439  return NULL;
440  }
441  return write_reg(REGID(0), APPEND(U16(IMM(1)), UNSIGNED(16, regval)));
442 }
443 
449 static RzILOpEffect *adr(cs_insn *insn, bool is_thumb) {
450  if (!ISREG(0)) {
451  return NULL;
452  }
453  st32 offset;
454  switch (insn->id) {
455  case ARM_INS_ADR:
456  offset = IMM(1);
457  break;
458  case ARM_INS_ADD:
459  case ARM_INS_ADDW:
460  offset = IMM(2);
461  break;
462  case ARM_INS_SUB:
463  case ARM_INS_SUBW:
464  offset = -IMM(2);
465  break;
466  default:
467  return NULL;
468  }
469  return write_reg(REGID(0), U32(PCALIGN(insn->address, is_thumb) + offset));
470 }
471 
476 static RzILOpEffect *add_sub(cs_insn *insn, bool is_thumb) {
477  if (!ISREG(0)) {
478  return NULL;
479  }
480  if ((insn->id == ARM_INS_ADD || insn->id == ARM_INS_ADDW || insn->id == ARM_INS_SUB || insn->id == ARM_INS_SUBW) &&
481  !insn->detail->arm.update_flags && OPCOUNT() == 3 && REGID(1) == ARM_REG_PC && ISIMM(2)) {
482  // alias for adr
483  return adr(insn, is_thumb);
484  }
485  bool is_sub = insn->id == ARM_INS_SUB || insn->id == ARM_INS_SUBW || insn->id == ARM_INS_RSB || insn->id == ARM_INS_RSC || insn->id == ARM_INS_SBC;
486  RzILOpBitVector *a = ARG(OPCOUNT() > 2 ? 1 : 0);
487  RzILOpBitVector *b = ARG(OPCOUNT() > 2 ? 2 : 1);
488  if (insn->id == ARM_INS_RSB || insn->id == ARM_INS_RSC) {
489  RzILOpBitVector *tmp = b;
490  b = a;
491  a = tmp;
492  }
493  if (!a || !b) {
496  return NULL;
497  }
498  RzILOpBitVector *res = is_sub ? SUB(a, b) : ADD(a, b);
499  bool with_carry = false;
500  if (insn->id == ARM_INS_ADC) {
501  res = ADD(res, ITE(VARG("cf"), U32(1), U32(0)));
502  with_carry = true;
503  } else if (insn->id == ARM_INS_RSC || insn->id == ARM_INS_SBC) {
504  res = SUB(res, ITE(VARG("cf"), U32(0), U32(1)));
505  with_carry = true;
506  }
507  if (REGID(0) == ARM_REG_PC) {
508  if (insn->detail->arm.update_flags) {
509  // ALUExceptionReturn()
510  rz_il_op_pure_free(res);
511  return NULL;
512  } else {
513  return JMP(res);
514  }
515  }
516  RzILOpEffect *set = write_reg(REGID(0), res);
517  bool update_flags = insn->detail->arm.update_flags;
518  if (!strcmp(insn->mnemonic, "adc") || !strcmp(insn->mnemonic, "rsc") || !strcmp(insn->mnemonic, "sbc") ||
519  !strcmp(insn->mnemonic, "adc.w") || !strcmp(insn->mnemonic, "sbc.w")) {
520  // capstone is wrong about this, only the <...>s variants set flags
521  update_flags = false;
522  }
523  if (update_flags) {
524  return SEQ6(
525  SETL("a", DUP(a)),
526  SETL("b", DUP(b)),
527  set,
528  SETG("cf", (is_sub ? sub_carry : add_carry)(VARL("a"), VARL("b"), with_carry, 32)),
529  SETG("vf", (is_sub ? sub_overflow : add_overflow)(VARL("a"), VARL("b"), REG(0))),
530  update_flags_zn(REG(0)));
531  }
532  return set;
533 }
534 
539 static RzILOpEffect *mul(cs_insn *insn, bool is_thumb) {
540  if (!ISREG(0)) {
541  return NULL;
542  }
543  RzILOpBitVector *a = ARG(OPCOUNT() > 2 ? 1 : 0);
544  RzILOpBitVector *b = ARG(OPCOUNT() > 2 ? 2 : 1);
545  if (!a || !b) {
548  return NULL;
549  }
550  RzILOpEffect *eff = write_reg(REGID(0), MUL(a, b));
551  if (!eff) {
552  return NULL;
553  }
554  return insn->detail->arm.update_flags ? SEQ2(eff, update_flags_zn(REG(0))) : eff;
555 }
556 
564 static RzILOpEffect *ldr(cs_insn *insn, bool is_thumb) {
565  bool is_double = insn->id == ARM_INS_LDRD || insn->id == ARM_INS_LDREXD;
566  size_t mem_idx = is_double ? 2 : 1;
567  if (!ISREG(0) || !ISMEM(mem_idx) || (is_double && (!ISREG(1) || REGID(0) == ARM_REG_PC || REGID(1) == ARM_REG_PC))) {
568  return NULL;
569  }
571  cs_arm_op *memop = &insn->detail->arm.operands[mem_idx];
572  if (memop->mem.base == ARM_REG_PC) {
573  // LDR (literal) is different in the sense that it aligns the pc value:
574  addr = arg_mem(U32(PCALIGN(insn->address, is_thumb) + MEMDISP(mem_idx)), memop, NULL);
575  } else {
576  addr = ARG(mem_idx);
577  }
578  if (!addr) {
579  return NULL;
580  }
581  bool writeback = insn->detail->arm.writeback;
582  if (ISIMM(mem_idx + 1)) {
583  // capstone incorrectly sets writeback to false for e.g. 0400b1e4 ldrt r0, [r1], 4
584  writeback = true;
585  }
586  RzILOpEffect *writeback_eff = NULL;
587  bool writeback_post = false;
588  if (writeback) {
589  arm_reg base = insn->detail->arm.operands[mem_idx].mem.base;
590  if (ISIMM(mem_idx + 1)) {
591  // "ldr r0, [r1], 4" is treated as an extra operand after the mem
592  addr = insn->detail->arm.operands[mem_idx + 1].subtracted
593  ? SUB(addr, ARG(mem_idx + 1))
594  : ADD(addr, ARG(mem_idx + 1));
595  writeback_post = true;
596  }
597  writeback_eff = write_reg(base, addr);
598  if (!writeback_eff) {
599  // 'ldrb r0, [pc, 0x104]!' (0401ffe5) for example is unpredictable. write_reg will return NULL for pc.
600  return NULL;
601  }
602  addr = MEMBASE(mem_idx);
603  }
604  RzILOpEffect *eff;
605  if (is_double) {
606  eff = SEQ2(
607  write_reg(REGID(0), LOADW(32, addr)),
608  write_reg(REGID(1), LOADW(32, ADD(DUP(addr), U32(4)))));
609  } else {
610  RzILOpBitVector *data;
611  switch (insn->id) {
612  case ARM_INS_LDRB:
613  case ARM_INS_LDRBT:
614  case ARM_INS_LDAB:
615  case ARM_INS_LDAEXB:
616  data = UNSIGNED(32, LOAD(addr));
617  break;
618  case ARM_INS_LDRH:
619  case ARM_INS_LDRHT:
620  case ARM_INS_LDAH:
621  case ARM_INS_LDAEXH:
622  data = UNSIGNED(32, LOADW(16, addr));
623  break;
624  case ARM_INS_LDRSB:
625  case ARM_INS_LDRSBT:
626  data = SIGNED(32, LOAD(addr));
627  break;
628  case ARM_INS_LDRSH:
629  case ARM_INS_LDRSHT:
630  data = SIGNED(32, LOADW(16, addr));
631  break;
632  default: // ARM_INS_LDR, ARM_INS_LDRT, ARM_INS_LDA, ARM_INS_LDAEX
633  data = LOADW(32, addr);
634  break;
635  }
636  if (REGID(0) == ARM_REG_PC) {
637  if (writeback_post) {
638  // can't have writeback after the jmp, so need to handle this special case with a local var
639  return SEQ3(
640  SETL("tgt", data),
641  writeback_eff,
642  JMP(VARL("tgt")));
643  } else {
644  eff = JMP(data);
645  }
646  } else {
647  eff = write_reg(REGID(0), data);
648  }
649  }
650  if (writeback_eff) {
651  return writeback_post ? SEQ2(eff, writeback_eff) : SEQ2(writeback_eff, eff);
652  }
653  return eff;
654 }
655 
661 static RzILOpEffect *str(cs_insn *insn, bool is_thumb) {
662  size_t mem_idx = insn->id == ARM_INS_STRD ? 2 : 1;
663  if (!ISREG(0) || !ISMEM(mem_idx)) {
664  return NULL;
665  }
666  RzILOpBitVector *addr = ARG(mem_idx);
667  if (!addr) {
668  return NULL;
669  }
670  bool writeback = insn->detail->arm.writeback;
671  if (ISIMM(mem_idx + 1)) {
672  // capstone incorrectly sets writeback to false for e.g. 04b0ade4 strt fp, [sp], 4
673  writeback = true;
674  }
675  RzILOpEffect *writeback_eff = NULL;
676  bool writeback_post = false;
677  if (writeback) {
678  arm_reg base = insn->detail->arm.operands[mem_idx].mem.base;
679  if (ISIMM(mem_idx + 1)) {
680  // "str r0, [r1], 4" is treated as an extra operand after the mem
681  addr = insn->detail->arm.operands[mem_idx + 1].subtracted
682  ? SUB(addr, ARG(mem_idx + 1))
683  : ADD(addr, ARG(mem_idx + 1));
684  writeback_post = true;
685  }
686  writeback_eff = write_reg(base, addr);
687  if (!writeback_eff) {
688  return NULL;
689  }
690  addr = MEMBASE(mem_idx);
691  }
692  RzILOpBitVector *val = ARG(0);
693  if (!val) {
695  return NULL;
696  }
697  RzILOpEffect *eff;
698  switch (insn->id) {
699  case ARM_INS_STRB:
700  case ARM_INS_STRBT:
701  case ARM_INS_STLB:
702  eff = STORE(addr, UNSIGNED(8, val));
703  break;
704  case ARM_INS_STRH:
705  case ARM_INS_STRHT:
706  case ARM_INS_STLH:
707  eff = STOREW(addr, UNSIGNED(16, val));
708  break;
709  case ARM_INS_STRD: {
710  RzILOpBitVector *val2 = ARG(1);
711  if (!val2) {
714  return NULL;
715  }
716  eff = SEQ2(
717  STOREW(addr, val),
718  STOREW(ADD(DUP(addr), U32(4)), val2));
719  break;
720  }
721  default: // ARM_INS_STR, ARM_INS_STRT, ARM_INS_STL
722  eff = STOREW(addr, val);
723  break;
724  }
725  if (writeback_eff) {
726  return writeback_post ? SEQ2(eff, writeback_eff) : SEQ2(writeback_eff, eff);
727  }
728  return eff;
729 }
730 
736 static RzILOpEffect *strex(cs_insn *insn, bool is_thumb) {
737  size_t mem_idx = insn->id == ARM_INS_STREXD || insn->id == ARM_INS_STLEXD ? 3 : 2;
738  if (!ISREG(0) || !ISMEM(mem_idx)) {
739  return NULL;
740  }
741  RzILOpBitVector *addr = ARG(mem_idx);
742  RzILOpBitVector *val = ARG(1);
743  // always return success of exclusive access while it's not represented in IL:
744  RzILOpEffect *ret_eff = write_reg(REGID(0), U32(0));
745  if (!addr || !val || !ret_eff) {
746  err:
749  rz_il_op_effect_free(ret_eff);
750  return NULL;
751  }
752  RzILOpEffect *eff;
753  switch (insn->id) {
754  case ARM_INS_STREXB:
755  case ARM_INS_STLEXB:
756  eff = STORE(addr, UNSIGNED(8, val));
757  break;
758  case ARM_INS_STREXH:
759  case ARM_INS_STLEXH:
760  eff = STOREW(addr, UNSIGNED(16, val));
761  break;
762  case ARM_INS_STREXD:
763  case ARM_INS_STLEXD: {
764  RzILOpBitVector *val2 = ARG(2);
765  if (!val2) {
766  goto err;
767  }
768  eff = SEQ2(
769  STOREW(addr, val),
770  STOREW(ADD(DUP(addr), U32(4)), val2));
771  break;
772  }
773  default: // ARM_INS_STREX, ARM_INS_STLEX
774  eff = STOREW(addr, val);
775  break;
776  }
777  return SEQ2(eff, ret_eff);
778 }
779 
784 static RzILOpEffect *bitwise(cs_insn *insn, bool is_thumb) {
785  if (!ISREG(0) || OPCOUNT() < 2) {
786  return NULL;
787  }
788  bool update_flags = insn->detail->arm.update_flags;
789  RzILOpBitVector *a = ARG(OPCOUNT() - 2);
790  RzILOpBool *carry = NULL;
791  RzILOpBitVector *b = ARG_C(OPCOUNT() - 1, update_flags ? &carry : NULL);
792  if (!a || !b) {
795  rz_il_op_pure_free(carry);
796  return NULL;
797  }
798  RzILOpBitVector *res;
799  switch (insn->id) {
800  case ARM_INS_AND:
801  res = LOGAND(a, b);
802  break;
803  case ARM_INS_ORR:
804  res = LOGOR(a, b);
805  break;
806  case ARM_INS_ORN:
807  res = LOGOR(a, LOGNOT(b));
808  break;
809  case ARM_INS_EOR:
810  res = LOGXOR(a, b);
811  break;
812  case ARM_INS_BIC:
813  res = LOGAND(a, LOGNOT(b));
814  break;
815  default:
818  rz_il_op_pure_free(carry);
819  return NULL;
820  }
821  if (REGID(0) == ARM_REG_PC) {
822  if (insn->detail->arm.update_flags) {
823  // ALUExceptionReturn()
824  rz_il_op_pure_free(res);
825  rz_il_op_pure_free(carry);
826  return NULL;
827  } else {
828  return JMP(res);
829  }
830  }
831  RzILOpEffect *eff = write_reg(REGID(0), res);
832  if (update_flags) {
833  if (carry) {
834  return SEQ3(
835  eff,
836  SETG("cf", carry),
837  update_flags_zn(REG(0)));
838  } else {
839  return SEQ2(eff, update_flags_zn(REG(0)));
840  }
841  }
842  return eff;
843 }
844 
849 static RzILOpEffect *tst(cs_insn *insn, bool is_thumb) {
850  RzILOpBitVector *a = ARG(0);
851  RzILOpBool *carry = NULL;
852  RzILOpBitVector *b = ARG_C(1, &carry);
853  if (!a || !b) {
856  rz_il_op_pure_free(carry);
857  return NULL;
858  }
859  RzILOpBitVector *res = insn->id == ARM_INS_TST ? LOGAND(a, b) : LOGOR(a, b);
860  if (carry) {
861  return SEQ2(
862  SETG("cf", carry),
863  update_flags_zn(res));
864  } else {
865  return update_flags_zn(res);
866  }
867 }
868 
874 static RzILOpEffect *uxt(cs_insn *insn, bool is_thumb) {
875  if (!ISREG(0)) {
876  return NULL;
877  }
878  bool is_add = insn->id == ARM_INS_UXTAB || insn->id == ARM_INS_UXTAH || insn->id == ARM_INS_SXTAB || insn->id == ARM_INS_SXTAH;
879  RzILOpBitVector *src = ARG(is_add ? 2 : 1);
880  if (!src) {
881  return NULL;
882  }
883  ut32 src_bits =
884  insn->id == ARM_INS_UXTH || insn->id == ARM_INS_UXTAH || insn->id == ARM_INS_SXTH || insn->id == ARM_INS_SXTAH
885  ? 16
886  : 8;
887  RzILOpBitVector *val = UNSIGNED(src_bits, src);
888  val = insn->id == ARM_INS_SXTB || insn->id == ARM_INS_SXTH || insn->id == ARM_INS_SXTAB || insn->id == ARM_INS_SXTAH
889  ? SIGNED(32, val)
890  : UNSIGNED(32, val);
891  if (is_add) {
892  RzILOpBitVector *b = ARG(1);
893  if (!b) {
895  return NULL;
896  }
897  val = ADD(b, val);
898  }
899  return write_reg(REGID(0), val);
900 }
901 
906 static RzILOpEffect *uxt16(cs_insn *insn, bool is_thumb) {
907  if (!ISREG(0)) {
908  return NULL;
909  }
910  bool is_add = insn->id == ARM_INS_UXTAB16 || insn->id == ARM_INS_SXTAB16;
911  RzILOpBitVector *src = ARG(is_add ? 2 : 1);
912  if (!src) {
913  return NULL;
914  }
915  RzILOpBitVector *l = UNSIGNED(8, VARLP("x"));
916  RzILOpBitVector *h = UNSIGNED(8, SHIFTR0(VARLP("x"), UN(5, 16)));
917  if (insn->id == ARM_INS_SXTB16 || insn->id == ARM_INS_SXTAB16) {
918  l = SIGNED(16, l);
919  h = SIGNED(16, h);
920  } else {
921  l = UNSIGNED(16, l);
922  h = UNSIGNED(16, h);
923  }
924  if (is_add) {
925  RzILOpBitVector *b = ARG(1);
926  if (!b) {
930  return NULL;
931  }
932  l = ADD(UNSIGNED(16, b), l);
933  h = ADD(UNSIGNED(16, SHIFTR0(DUP(b), UN(5, 16))), h);
934  }
935  return write_reg(REGID(0), LET("x", src, APPEND(h, l)));
936 }
937 
942 static RzILOpEffect *cmp(cs_insn *insn, bool is_thumb) {
943  if (!ISREG(0)) {
944  return NULL;
945  }
946  bool is_sub = insn->id == ARM_INS_CMP;
947  RzILOpBitVector *a = ARG(0);
948  RzILOpBitVector *b = ARG(1);
949  if (!a || !b) {
952  return NULL;
953  }
954  return SEQ6(
955  SETL("a", a),
956  SETL("b", b),
957  SETL("res", is_sub ? SUB(VARL("a"), VARL("b")) : ADD(VARL("a"), VARL("b"))),
958  SETG("cf", (is_sub ? sub_carry : add_carry)(VARL("a"), VARL("b"), false, 32)),
959  SETG("vf", (is_sub ? sub_overflow : add_overflow)(VARL("a"), VARL("b"), VARL("res"))),
960  update_flags_zn(VARL("res")));
961 }
962 
968 static RzILOpEffect *stm(cs_insn *insn, bool is_thumb) {
969  size_t op_first;
970  arm_reg ptr_reg;
971  bool writeback;
972  if (insn->id == ARM_INS_PUSH || insn->id == ARM_INS_VPUSH) {
973  op_first = 0;
974  ptr_reg = ARM_REG_SP;
975  writeback = true;
976  } else { // ARM_INS_STMDB.*
977  if (!ISREG(0)) {
978  return NULL;
979  }
980  op_first = 1;
981  ptr_reg = REGID(0);
982  writeback = insn->detail->arm.writeback;
983  }
984  size_t op_count = OPCOUNT() - op_first;
985  if (!op_count) {
986  return NOP();
987  }
988  RzILOpBitVector *ptr = REG_VAL(ptr_reg);
989  if (!ptr) {
990  return NULL;
991  }
992  bool decrement = insn->id == ARM_INS_STMDA || insn->id == ARM_INS_STMDB || insn->id == ARM_INS_PUSH ||
993  insn->id == ARM_INS_VSTMDB || insn->id == ARM_INS_VPUSH;
994  bool before = insn->id == ARM_INS_STMDB || insn->id == ARM_INS_PUSH || insn->id == ARM_INS_VSTMDB ||
995  insn->id == ARM_INS_STMIB || insn->id == ARM_INS_VPUSH;
996  ut32 regsize = reg_bits(REGID(op_first)) / 8;
997  RzILOpEffect *eff = NULL;
998  // build up in reverse order so the result recurses in the second arg of seq (for tail-call optimization)
999  if (writeback) {
1000  eff = write_reg(ptr_reg,
1001  decrement
1002  ? SUB(DUP(ptr), U32(op_count * regsize))
1003  : ADD(DUP(ptr), U32(op_count * regsize)));
1004  }
1005  for (size_t i = 0; i < op_count; i++) {
1006  size_t idx = op_first + (op_count - 1 - i);
1007  RzILOpPure *val;
1008  if (!ISREG(idx) || !(val = REG(idx))) {
1009  rz_il_op_pure_free(ptr);
1010  rz_il_op_effect_free(eff);
1011  return NULL;
1012  }
1013  RzILOpEffect *store = STOREW(
1014  decrement
1015  ? SUB(DUP(ptr), U32((i + (before ? 1 : 0)) * regsize))
1016  : ADD(DUP(ptr), U32((op_count - i - (before ? 0 : 1)) * regsize)),
1017  val);
1018  eff = eff ? SEQ2(store, eff) : store;
1019  }
1020  rz_il_op_pure_free(ptr);
1021  return eff;
1022 }
1023 
1029 static RzILOpEffect *ldm(cs_insn *insn, bool is_thumb) {
1030  size_t op_first;
1031  arm_reg ptr_reg;
1032  bool writeback;
1033  if (insn->id == ARM_INS_POP || insn->id == ARM_INS_VPOP) {
1034  op_first = 0;
1035  ptr_reg = ARM_REG_SP;
1036  writeback = true;
1037  } else { // ARM_INS_LDM.*
1038  if (!ISREG(0)) {
1039  return NULL;
1040  }
1041  op_first = 1;
1042  ptr_reg = REGID(0);
1043  writeback = insn->detail->arm.writeback;
1044  }
1045  size_t op_count = OPCOUNT() - op_first;
1046  if (!op_count) {
1047  return NOP();
1048  }
1049  RzILOpBitVector *ptr_initial = REG_VAL(ptr_reg);
1050  if (!ptr_initial) {
1051  return NULL;
1052  }
1053  RzILOpEffect *eff = NULL;
1054  // build up in reverse order so the result recurses in the second arg of seq (for tail-call optimization)
1055  for (size_t i = 0; i < op_count; i++) {
1056  size_t idx = op_first + (op_count - 1 - i);
1057  if (ISREG(idx) && REGID(idx) == ARM_REG_PC) {
1058  // jmp goes last
1059  eff = JMP(VARL("tgt"));
1060  }
1061  }
1062  bool decrement = insn->id == ARM_INS_LDMDA || insn->id == ARM_INS_LDMDB || insn->id == ARM_INS_VLDMDB;
1063  bool before = insn->id == ARM_INS_LDMDB || insn->id == ARM_INS_LDMIB || insn->id == ARM_INS_VLDMIA;
1064  ut32 regsize = reg_bits(REGID(op_first)) / 8;
1065  if (writeback) {
1066  RzILOpEffect *wb = write_reg(ptr_reg,
1067  decrement
1068  ? SUB(VARL("base"), U32(op_count * regsize))
1069  : ADD(VARL("base"), U32(op_count * regsize)));
1070  eff = eff ? SEQ2(wb, eff) : wb;
1071  }
1072  for (size_t i = 0; i < op_count; i++) {
1073  size_t idx = op_first + (op_count - 1 - i);
1074  if (!ISREG(idx)) {
1075  rz_il_op_pure_free(ptr_initial);
1076  rz_il_op_effect_free(eff);
1077  return NULL;
1078  }
1079  RzILOpPure *val = LOADW(regsize * 8,
1080  decrement
1081  ? SUB(VARL("base"), U32((i + (before ? 1 : 0)) * regsize))
1082  : ADD(VARL("base"), U32((op_count - i - (before ? 0 : 1)) * regsize)));
1083  RzILOpEffect *load;
1084  if (REGID(idx) == ARM_REG_PC) {
1085  load = SETL("tgt", val);
1086  } else {
1087  load = write_reg(REGID(idx), val);
1088  }
1089  eff = eff ? SEQ2(load, eff) : load;
1090  }
1091  return SEQ2(SETL("base", ptr_initial), eff);
1092 }
1093 
1098 static RzILOpEffect *bl(cs_insn *insn, bool is_thumb) {
1099  RzILOpBitVector *tgt = ARG(0);
1100  if (!tgt) {
1101  return NULL;
1102  }
1103  return SEQ2(
1104  SETG("lr", U32(((insn->address + insn->size) & ~1ul) | (is_thumb ? 1 : 0))),
1105  JMP(tgt));
1106 }
1107 
1112 static RzILOpEffect *clz(cs_insn *insn, bool is_thumb) {
1113  if (!ISREG(0)) {
1114  return NULL;
1115  }
1116  RzILOpBitVector *v = ARG(1);
1117  if (!v) {
1118  return NULL;
1119  }
1120  return SEQ4(
1121  SETL("v", v),
1122  SETL("i", U32(0x20)),
1123  REPEAT(INV(IS_ZERO(VARL("v"))),
1124  SEQ2(
1125  SETL("v", SHIFTR0(VARL("v"), UN(5, 1))),
1126  SETL("i", SUB(VARL("i"), U32(1))))),
1127  write_reg(REGID(0), VARL("i")));
1128 }
1129 
1134 static RzILOpEffect *svc(cs_insn *insn, bool is_thumb) {
1135  return GOTO("svc");
1136 }
1137 
1138 static void label_svc(RzILVM *vm, RzILOpEffect *op) {
1139  // stub, nothing to do here
1140 }
1141 
1142 #if CS_API_MAJOR > 3
1147 static RzILOpEffect *hvc(cs_insn *insn, bool is_thumb) {
1148  return GOTO("hvc");
1149 }
1150 #endif
1151 
1152 static void label_hvc(RzILVM *vm, RzILOpEffect *op) {
1153  // stub, nothing to do here
1154 }
1155 
1160 static RzILOpEffect *bfc(cs_insn *insn, bool is_thumb) {
1161  if (!ISREG(0) || !ISIMM(1) || !ISIMM(2)) {
1162  return NULL;
1163  }
1164  RzILOpBitVector *val = REG(0);
1165  if (!val) {
1166  return NULL;
1167  }
1168  return write_reg(REGID(0), LOGAND(val, U32(~(rz_num_bitmask(IMM(2)) << IMM(1)))));
1169 }
1170 
1175 static RzILOpEffect *bfi(cs_insn *insn, bool is_thumb) {
1176  if (!ISREG(0) || !ISIMM(2) || !ISIMM(3)) {
1177  return NULL;
1178  }
1179  RzILOpBitVector *dval = REG(0);
1180  RzILOpBitVector *nval = ARG(1);
1181  if (!dval || !nval) {
1182  rz_il_op_pure_free(dval);
1183  rz_il_op_pure_free(nval);
1184  return NULL;
1185  }
1186  ut32 lsb = IMM(2);
1187  ut32 mask = rz_num_bitmask(IMM(3));
1188  return write_reg(REGID(0),
1189  LOGOR(
1190  LOGAND(dval, U32(~(mask << lsb))),
1191  SHIFTL0(LOGAND(nval, U32(mask)), UN(5, lsb))));
1192 }
1193 
1198 static RzILOpEffect *cbz(cs_insn *insn, bool is_thumb) {
1199  RzILOpBitVector *val = ARG(0);
1200  RzILOpBitVector *dst = ARG(1);
1201  if (!val || !dst) {
1204  return NULL;
1205  }
1206  RzILOpBool *cond = IS_ZERO(val);
1207  if (insn->id == ARM_INS_CBNZ) {
1208  cond = INV(cond);
1209  }
1210  return BRANCH(cond, JMP(dst), NULL);
1211 }
1212 
1217 static RzILOpEffect *mla(cs_insn *insn, bool is_thumb) {
1218  if (!ISREG(0)) {
1219  return NULL;
1220  }
1221  RzILOpBitVector *op0 = ARG(1);
1222  RzILOpBitVector *op1 = ARG(2);
1223  RzILOpBitVector *addend = ARG(3);
1224  if (!op0 || !op1 || !addend) {
1225  rz_il_op_pure_free(op0);
1226  rz_il_op_pure_free(op1);
1227  rz_il_op_pure_free(addend);
1228  return NULL;
1229  }
1230  RzILOpBitVector *val = insn->id == ARM_INS_MLS
1231  ? SUB(addend, MUL(op0, op1))
1232  : ADD(MUL(op0, op1), addend);
1233  RzILOpEffect *eff = write_reg(REGID(0), val);
1234  if (!eff) {
1235  return NULL;
1236  }
1237  return insn->detail->arm.update_flags
1238  ? SEQ2(eff, update_flags_zn(REG(0)))
1239  : eff;
1240 }
1241 
1246 static RzILOpEffect *mrs(cs_insn *insn, bool is_thumb) {
1247  if (!ISREG(0) || !ISREG(1)) {
1248  return NULL;
1249  }
1250  if (REGID(1) != ARM_REG_CPSR && REGID(1) != ARM_REG_SPSR && REGID(1) != ARM_REG_APSR) {
1251  // only these regs supported
1252  return NULL;
1253  }
1254  // There are more bits in ARM, but this is all we have:
1255  return write_reg(REGID(0),
1256  LOGOR(ITE(VARG("nf"), U32(1ul << 31), U32(0)),
1257  LOGOR(ITE(VARG("zf"), U32(1ul << 30), U32(0)),
1258  LOGOR(ITE(VARG("cf"), U32(1ul << 29), U32(0)),
1259  LOGOR(ITE(VARG("vf"), U32(1ul << 28), U32(0)),
1260  LOGOR(ITE(VARG("qf"), U32(1ul << 27), U32(0)),
1261  SHIFTL0(UNSIGNED(32, VARG("gef")), UN(5, 16))))))));
1262 }
1263 
1268 static RzILOpEffect *msr(cs_insn *insn, bool is_thumb) {
1269  cs_arm_op *dst = &insn->detail->arm.operands[0];
1270  if (dst->type != ARM_OP_SYSREG) {
1271  return NULL;
1272  }
1273  // check if the reg+mask contains any of the flags we have:
1274  bool update_f = false;
1275  bool update_s = false;
1276  switch (dst->reg) {
1277  case ARM_SYSREG_APSR_NZCVQ:
1278  update_f = true;
1279  break;
1280  case ARM_SYSREG_APSR_G:
1281  update_s = true;
1282  break;
1284  update_f = true;
1285  update_s = true;
1286  break;
1287  default:
1288  update_f = (dst->reg & ARM_SYSREG_CPSR_F) || (dst->reg & ARM_SYSREG_SPSR_F);
1289  update_s = (dst->reg & ARM_SYSREG_CPSR_S) || (dst->reg & ARM_SYSREG_SPSR_S);
1290  break;
1291  }
1292  if (!update_f && !update_s) {
1293  // no flags we know
1294  return NULL;
1295  }
1296  RzILOpBitVector *val = ARG(1);
1297  if (!val) {
1298  return NULL;
1299  }
1300  return update_flags_from_cpsr(val, update_f, update_s);
1301 }
1302 
1307 static RzILOpEffect *pkhbt(cs_insn *insn, bool is_thumb) {
1308  if (!ISREG(0)) {
1309  return NULL;
1310  }
1311  RzILOpBitVector *hv = ARG(1);
1312  RzILOpBitVector *lv = ARG(2);
1313  if (!hv || !lv) {
1314  rz_il_op_pure_free(hv);
1315  rz_il_op_pure_free(lv);
1316  return NULL;
1317  }
1318  hv = UNSIGNED(16, SHIFTR0(hv, UN(5, 16)));
1319  lv = UNSIGNED(16, lv);
1320  bool tbform = insn->id == ARM_INS_PKHTB;
1321  return write_reg(REGID(0), tbform ? APPEND(hv, lv) : APPEND(lv, hv));
1322 }
1323 
1332 static RzILOpEffect *saturate_signed_to_range(const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q, st64 min, st64 max) {
1333  return SEQ2(
1334  SETL("er", val),
1335  BRANCH(SGT(VARL("er"), SN(ext_bits, max)),
1336  set_q ? SEQ2(SETL(dst, SN(bits, max)), SETG("qf", IL_TRUE)) : SETL(dst, SN(bits, max)),
1337  BRANCH(SLT(VARL("er"), SN(ext_bits, min)),
1338  set_q ? SEQ2(SETL(dst, SN(bits, min)), SETG("qf", IL_TRUE)) : SETL(dst, SN(bits, min)),
1339  SETL(dst, UNSIGNED(bits, VARL("er"))))));
1340 }
1341 
1342 static RzILOpEffect *saturate_signed(bool to_signed, const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q) {
1343  st64 max = to_signed ? (1ull << (bits - 1)) - 1 : (1ull << bits) - 1;
1344  st64 min = to_signed ? -max - 1 : 0;
1345  return saturate_signed_to_range(dst, bits, val, ext_bits, set_q, min, max);
1346 }
1347 
1355 static RzILOpEffect *saturate_unsigned(bool is_sub, const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q) {
1356  ut64 max = (1ull << bits) - 1;
1357  ut64 min = 0;
1358  return SEQ2(
1359  SETL("er", val),
1360  BRANCH(UGT(VARL("er"), UN(ext_bits, max)),
1361  set_q ? SEQ2(SETL(dst, UN(bits, max)), SETG("qf", IL_TRUE)) : SETL(dst, UN(bits, is_sub ? min : max)),
1362  SETL(dst, UNSIGNED(bits, VARL("er")))));
1363 }
1364 
1365 static RzILOpEffect *saturate(bool sign, bool is_sub, const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q) {
1366  return sign
1367  ? saturate_signed(true, dst, bits, val, ext_bits, set_q)
1368  : saturate_unsigned(is_sub, dst, bits, val, ext_bits, set_q);
1369 }
1370 
1375 static RzILOpEffect *ssat(cs_insn *insn, bool is_thumb) {
1376  if (!ISREG(0) || !ISIMM(1)) {
1377  return NULL;
1378  }
1379  RzILOpPure *src = ARG(2);
1380  bool is_signed = insn->id == ARM_INS_SSAT;
1381  RzILOpEffect *eff = write_reg(REGID(0), is_signed ? SIGNED(32, VARL("r")) : UNSIGNED(32, VARL("r")));
1382  if (!src || !eff) {
1384  rz_il_op_effect_free(eff);
1385  return NULL;
1386  }
1387  return SEQ2(
1388  saturate_signed(is_signed, "r", IMM(1), src, 32, true),
1389  eff);
1390 }
1391 
1396 static RzILOpEffect *ssat16(cs_insn *insn, bool is_thumb) {
1397  if (!ISREG(0) || !ISIMM(1)) {
1398  return NULL;
1399  }
1400  RzILOpPure *src = ARG(2);
1401  bool is_signed = insn->id == ARM_INS_SSAT16;
1402  RzILOpEffect *eff = write_reg(REGID(0),
1403  APPEND(
1404  is_signed ? SIGNED(16, VARL("rh")) : UNSIGNED(16, VARL("rh")),
1405  is_signed ? SIGNED(16, VARL("rl")) : UNSIGNED(16, VARL("rl"))));
1406  if (!src || !eff) {
1408  rz_il_op_effect_free(eff);
1409  return NULL;
1410  }
1411  return SEQ3(
1412  saturate_signed(is_signed, "rl", IMM(1), UNSIGNED(16, src), 16, true),
1413  saturate_signed(is_signed, "rh", IMM(1), UNSIGNED(16, SHIFTR0(DUP(src), UN(5, 16))), 16, true),
1414  eff);
1415 }
1416 
1421 static RzILOpEffect *qadd(cs_insn *insn, bool is_thumb) {
1422  if (!ISREG(0)) {
1423  return NULL;
1424  }
1425  RzILOpBitVector *a = ARG(1);
1426  RzILOpBitVector *b = ARG(2);
1427  if (!a || !b) {
1430  return NULL;
1431  }
1432  RzILOpEffect *eff = write_reg(REGID(0), VARL("r"));
1433  if (!eff) {
1434  return NULL;
1435  }
1436  RzILOpEffect *dbl = NULL;
1437  if (insn->id == ARM_INS_QDADD || insn->id == ARM_INS_QDSUB) {
1438  b = SIGNED(33, b);
1439  dbl = saturate_signed(true, "dbl", 32, ADD(b, DUP(b)), 33, true);
1440  b = VARL("dbl");
1441  }
1442  eff = SEQ2(
1443  saturate_signed(true, "r", 32,
1444  (insn->id == ARM_INS_QSUB || insn->id == ARM_INS_QDSUB)
1445  ? SUB(SIGNED(33, a), SIGNED(33, b))
1446  : ADD(SIGNED(33, a), SIGNED(33, b)),
1447  33, true),
1448  eff);
1449  return dbl ? SEQ2(dbl, eff) : eff;
1450 }
1451 
1457 static RzILOpEffect *qadd16(cs_insn *insn, bool is_thumb) {
1458  if (!ISREG(0)) {
1459  return NULL;
1460  }
1461  RzILOpBitVector *a = ARG(1);
1462  RzILOpBitVector *b = ARG(2);
1463  if (!a || !b) {
1466  return NULL;
1467  }
1468  RzILOpEffect *eff = write_reg(REGID(0), APPEND(VARL("rh"), VARL("rl")));
1469  if (!eff) {
1470  return NULL;
1471  }
1472  bool is_signed = insn->id == ARM_INS_QADD16 || insn->id == ARM_INS_QSUB16 || insn->id == ARM_INS_QASX || insn->id == ARM_INS_QSAX;
1474  RzILOpBitVector *al = cast(17, UNSIGNED(16, a));
1475  RzILOpBitVector *ah = cast(17, UNSIGNED(16, SHIFTR0(DUP(a), UN(5, 16))));
1476  RzILOpBitVector *bl = cast(17, UNSIGNED(16, b));
1477  RzILOpBitVector *bh = cast(17, UNSIGNED(16, SHIFTR0(DUP(b), UN(5, 16))));
1478  bool l_sub, h_sub;
1479  RzILOpBitVector *l, *h;
1480  switch (insn->id) {
1481  case ARM_INS_QSUB16:
1482  case ARM_INS_UQSUB16:
1483  l_sub = true;
1484  h_sub = true;
1485  l = SUB(al, bl);
1486  h = SUB(ah, bh);
1487  break;
1488  case ARM_INS_QASX:
1489  case ARM_INS_UQASX:
1490  l_sub = true;
1491  h_sub = false;
1492  l = SUB(al, bh);
1493  h = ADD(ah, bl);
1494  break;
1495  case ARM_INS_QSAX:
1496  case ARM_INS_UQSAX:
1497  l_sub = false;
1498  h_sub = true;
1499  l = ADD(al, bh);
1500  h = SUB(ah, bl);
1501  break;
1502  default: // ARM_INS_QADD16, ARM_INS_UQADD16
1503  l_sub = false;
1504  h_sub = false;
1505  l = ADD(al, bl);
1506  h = ADD(ah, bh);
1507  break;
1508  }
1509  return SEQ3(saturate(is_signed, l_sub, "rl", 16, l, 17, false), saturate(is_signed, h_sub, "rh", 16, h, 17, false), eff);
1510 }
1511 
1516 static RzILOpEffect *qadd8(cs_insn *insn, bool is_thumb) {
1517  if (!ISREG(0)) {
1518  return NULL;
1519  }
1520  RzILOpBitVector *a = ARG(1);
1521  RzILOpBitVector *b = ARG(2);
1522  if (!a || !b) {
1525  return NULL;
1526  }
1527  RzILOpEffect *eff = write_reg(REGID(0), APPEND(APPEND(VARL("rb3"), VARL("rb2")), APPEND(VARL("rb1"), VARL("rb0"))));
1528  if (!eff) {
1529  return NULL;
1530  }
1531  bool is_signed = insn->id == ARM_INS_QADD8 || insn->id == ARM_INS_QSUB8;
1532  bool is_sub = insn->id == ARM_INS_QSUB8 || insn->id == ARM_INS_UQSUB8;
1534  return SEQ5(
1535  saturate(is_signed, is_sub, "rb0", 8,
1536  is_sub
1537  ? SUB(cast(9, UNSIGNED(8, a)), cast(9, UNSIGNED(8, b)))
1538  : ADD(cast(9, UNSIGNED(8, a)), cast(9, UNSIGNED(8, b))),
1539  9, false),
1540  saturate(is_signed, is_sub, "rb1", 8,
1541  is_sub
1542  ? SUB(cast(9, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 8)))), cast(9, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 8)))))
1543  : ADD(cast(9, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 8)))), cast(9, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 8))))),
1544  9, false),
1545  saturate(is_signed, is_sub, "rb2", 8,
1546  is_sub
1547  ? SUB(cast(9, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 16)))), cast(9, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 16)))))
1548  : ADD(cast(9, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 16)))), cast(9, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 16))))),
1549  9, false),
1550  saturate(is_signed, is_sub, "rb3", 8,
1551  is_sub
1552  ? SUB(cast(9, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 24)))), cast(9, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 24)))))
1553  : ADD(cast(9, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 24)))), cast(9, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 24))))),
1554  9, false),
1555  eff);
1556 }
1557 
1562 static RzILOpEffect *rbit(cs_insn *insn, bool is_thumb) {
1563  if (!ISREG(0)) {
1564  return NULL;
1565  }
1566  RzILOpBitVector *v = ARG(1);
1567  if (!v) {
1568  return NULL;
1569  }
1570  RzILOpEffect *eff = write_reg(REGID(0), VARL("r"));
1571  if (!eff) {
1572  return NULL;
1573  }
1574  return SEQ5(
1575  SETL("v", v),
1576  SETL("i", U32(0x20)),
1577  SETL("r", U32(0x0)),
1578  REPEAT(INV(IS_ZERO(VARL("v"))),
1579  SEQ3(
1580  SETL("i", SUB(VARL("i"), U32(1))),
1581  SETL("r", LOGOR(VARL("r"), ITE(LSB(VARL("v")), SHIFTL0(U32(1), VARL("i")), U32(0)))),
1582  SETL("v", SHIFTR0(VARL("v"), UN(5, 1))))),
1583  eff);
1584 }
1585 
1590 static RzILOpEffect *rev(cs_insn *insn, bool is_thumb) {
1591  if (!ISREG(0)) {
1592  return NULL;
1593  }
1594  RzILOpBitVector *v = ARG(1);
1595  if (!v) {
1596  return NULL;
1597  }
1598  RzILOpBitVector *l = APPEND(UNSIGNED(8, v), UNSIGNED(8, SHIFTR0(DUP(v), UN(5, 8))));
1599  RzILOpBitVector *h = APPEND(UNSIGNED(8, SHIFTR0(DUP(v), UN(5, 16))), UNSIGNED(8, SHIFTR0(DUP(v), UN(5, 24))));
1600  return write_reg(REGID(0),
1601  insn->id == ARM_INS_REV
1602  ? APPEND(l, h)
1603  : APPEND(h, l));
1604 }
1605 
1610 static RzILOpEffect *revsh(cs_insn *insn, bool is_thumb) {
1611  if (!ISREG(0)) {
1612  return NULL;
1613  }
1614  RzILOpBitVector *v = ARG(1);
1615  if (!v) {
1616  return NULL;
1617  }
1618  return write_reg(REGID(0), LET("r", APPEND(UNSIGNED(8, v), UNSIGNED(8, SHIFTR0(DUP(v), UN(5, 8)))), SIGNED(32, VARLP("r"))));
1619 }
1620 
1625 static RzILOpEffect *rfe(cs_insn *insn, bool is_thumb) {
1626  if (!ISREG(0)) {
1627  return NULL;
1628  }
1629  RzILOpBitVector *base = REG(0);
1630  if (!base) {
1631  return NULL;
1632  }
1633  RzILOpEffect *wb = NULL;
1634  bool wordhigher = insn->id == ARM_INS_RFEDA || insn->id == ARM_INS_RFEIB;
1635  bool increment = insn->id == ARM_INS_RFEIA || insn->id == ARM_INS_RFEIB;
1636  if (insn->detail->arm.writeback) {
1637  wb = write_reg(REGID(0),
1638  increment ? ADD(DUP(base), U32(8)) : SUB(DUP(base), U32(8)));
1639  if (!wb) {
1640  rz_il_op_pure_free(base);
1641  return NULL;
1642  }
1643  }
1644  RzILOpBitVector *addr = increment ? base : SUB(base, U32(8));
1645  if (wordhigher) {
1646  addr = ADD(addr, U32(4));
1647  }
1648  return SEQ5(
1649  SETL("addr", addr),
1650  SETL("tgt", LOADW(32, VARL("addr"))),
1651  SETL("spsr", LOADW(32, ADD(VARL("addr"), U32(4)))),
1652  update_flags_from_cpsr(VARL("spsr"), true, true),
1653  wb ? SEQ2(wb, JMP(VARL("tgt"))) : JMP(VARL("tgt")));
1654 }
1655 
1664 static RzILOpEffect *sadd16(cs_insn *insn, bool is_thumb) {
1665  if (!ISREG(0)) {
1666  return NULL;
1667  }
1668  RzILOpBitVector *a = ARG(1);
1669  RzILOpBitVector *b = ARG(2);
1670  if (!a || !b) {
1673  return NULL;
1674  }
1675  RzILOpBitVector *al = UNSIGNED(16, a);
1676  RzILOpBitVector *ah = UNSIGNED(16, SHIFTR0(DUP(a), UN(5, 16)));
1677  RzILOpBitVector *bl = UNSIGNED(16, b);
1678  RzILOpBitVector *bh = UNSIGNED(16, SHIFTR0(DUP(b), UN(5, 16)));
1679  bool is_signed = insn->id == ARM_INS_SADD16 || insn->id == ARM_INS_SHADD16 || insn->id == ARM_INS_SASX ||
1680  insn->id == ARM_INS_SSAX || insn->id == ARM_INS_SHASX || insn->id == ARM_INS_SHSAX ||
1681  insn->id == ARM_INS_SSUB16 || insn->id == ARM_INS_SHSUB16;
1683  al = cast(17, al);
1684  ah = cast(17, ah);
1685  bl = cast(17, bl);
1686  bh = cast(17, bh);
1687  RzILOpBitVector *l, *h;
1688  bool halve = false;
1689  switch (insn->id) {
1690  case ARM_INS_SHSAX:
1691  case ARM_INS_UHSAX:
1692  halve = true;
1693  // fallthrough
1694  case ARM_INS_SASX:
1695  case ARM_INS_UASX:
1696  l = SUB(al, bh);
1697  h = ADD(ah, bl);
1698  break;
1699 
1700  case ARM_INS_SHASX:
1701  case ARM_INS_UHASX:
1702  halve = true;
1703  // fallthrough
1704  case ARM_INS_SSAX:
1705  case ARM_INS_USAX:
1706  l = ADD(al, bh);
1707  h = SUB(ah, bl);
1708  break;
1709 
1710  case ARM_INS_SHSUB16:
1711  case ARM_INS_UHSUB16:
1712  halve = true;
1713  // fallthrough
1714  case ARM_INS_SSUB16:
1715  case ARM_INS_USUB16:
1716  l = SUB(al, bl);
1717  h = SUB(ah, bh);
1718  break;
1719 
1720  case ARM_INS_SHADD16:
1721  case ARM_INS_UHADD16:
1722  halve = true;
1723  // fallthrough
1724  default: // ARM_INS_SADD16, ARM_INS_SHADD16, ARM_INS_UADD16, ARM_INS_UHADD16
1725  l = ADD(al, bl);
1726  h = ADD(ah, bh);
1727  break;
1728  }
1729  bool set_ge = !halve;
1730  RzILOpBitVector *res = halve
1731  ? APPEND(UNSIGNED(16, SHIFTRA(VARL("res1"), UN(4, 1))), UNSIGNED(16, SHIFTRA(VARL("res0"), UN(4, 1))))
1732  : APPEND(UNSIGNED(16, VARL("res1")), UNSIGNED(16, VARL("res0")));
1733  RzILOpEffect *eff = write_reg(REGID(0), res);
1734  if (!eff) {
1735  rz_il_op_pure_free(l);
1737  return NULL;
1738  }
1739  if (set_ge) {
1740  ut64 tval = is_signed ? 0 : 3;
1741  ut64 fval = 3 - tval;
1742  eff = SEQ2(
1743  SETL("gef",
1744  APPEND(
1745  ITE(MSB(VARL("res1")), UN(2, tval), UN(2, fval)),
1746  ITE(MSB(VARL("res0")), UN(2, tval), UN(2, fval)))),
1747  eff);
1748  }
1749  return SEQ3(SETL("res0", l), SETL("res1", h), eff);
1750 }
1751 
1757 static RzILOpEffect *sadd8(cs_insn *insn, bool is_thumb) {
1758  if (!ISREG(0)) {
1759  return NULL;
1760  }
1761  RzILOpBitVector *a = ARG(1);
1762  RzILOpBitVector *b = ARG(2);
1763  if (!a || !b) {
1766  return NULL;
1767  }
1768  RzILOpBitVector *a0 = UNSIGNED(8, a);
1769  RzILOpBitVector *a1 = UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 8)));
1770  RzILOpBitVector *a2 = UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 16)));
1771  RzILOpBitVector *a3 = UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 24)));
1772  RzILOpBitVector *b0 = UNSIGNED(8, b);
1773  RzILOpBitVector *b1 = UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 8)));
1774  RzILOpBitVector *b2 = UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 16)));
1775  RzILOpBitVector *b3 = UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 24)));
1776  RzILOpBitVector *r0, *r1, *r2, *r3;
1777  bool halve = false;
1778  switch (insn->id) {
1779  case ARM_INS_SHSUB8:
1780  case ARM_INS_UHSUB8:
1781  halve = true;
1782  // fallthrough
1783  case ARM_INS_SSUB8:
1784  case ARM_INS_USUB8:
1785  r0 = SUB(a0, b0);
1786  r1 = SUB(a1, b1);
1787  r2 = SUB(a2, b2);
1788  r3 = SUB(a3, b3);
1789  break;
1790 
1791  case ARM_INS_SHADD8:
1792  case ARM_INS_UHADD8:
1793  halve = true;
1794  // fallthrough
1795  default: // ARM_INS_SADD8, ARM_INS_UADD8
1796  r0 = ADD(a0, b0);
1797  r1 = ADD(a1, b1);
1798  r2 = ADD(a2, b2);
1799  r3 = ADD(a3, b3);
1800  break;
1801  }
1802  bool set_ge = !halve;
1803  bool is_signed = insn->id == ARM_INS_SADD8 || insn->id == ARM_INS_SHADD8 || insn->id == ARM_INS_SSUB8 || insn->id == ARM_INS_SHSUB8;
1804  if (set_ge) {
1805  // Retroactively patch the ops to extend to 8 before the calculation because this is needed for ge
1806  // Note: add/sub members here use the same structure, so using just `.add` is fine.
1808  r0->op.add.x = cast(9, r0->op.add.x);
1809  r0->op.add.y = cast(9, r0->op.add.y);
1810  r1->op.add.x = cast(9, r1->op.add.x);
1811  r1->op.add.y = cast(9, r1->op.add.y);
1812  r2->op.add.x = cast(9, r2->op.add.x);
1813  r2->op.add.y = cast(9, r2->op.add.y);
1814  r3->op.add.x = cast(9, r3->op.add.x);
1815  r3->op.add.y = cast(9, r3->op.add.y);
1816  }
1817  RzILOpBitVector *res;
1818  if (halve) {
1819  res = APPEND(
1820  APPEND(
1821  SHIFTRA(VARL("res3"), UN(3, 1)),
1822  SHIFTRA(VARL("res2"), UN(3, 1))),
1823  APPEND(
1824  SHIFTRA(VARL("res1"), UN(3, 1)),
1825  SHIFTRA(VARL("res0"), UN(3, 1))));
1826  } else {
1827  res = APPEND(
1828  APPEND(
1829  UNSIGNED(8, VARL("res3")),
1830  UNSIGNED(8, VARL("res2"))),
1831  APPEND(
1832  UNSIGNED(8, VARL("res1")),
1833  UNSIGNED(8, VARL("res0"))));
1834  }
1835  RzILOpEffect *eff = write_reg(REGID(0), res);
1836  if (!eff) {
1841  return NULL;
1842  }
1843  if (set_ge) {
1844  ut64 tval = is_signed ? 0 : 1;
1845  ut64 fval = 1 - tval;
1846  eff = SEQ2(
1847  SETL("gef",
1848  APPEND(
1849  APPEND(
1850  ITE(MSB(VARL("res3")), UN(1, tval), UN(1, fval)),
1851  ITE(MSB(VARL("res2")), UN(1, tval), UN(1, fval))),
1852  APPEND(
1853  ITE(MSB(VARL("res1")), UN(1, tval), UN(1, fval)),
1854  ITE(MSB(VARL("res0")), UN(1, tval), UN(1, fval))))),
1855  eff);
1856  }
1857  return SEQ5(
1858  SETL("res0", r0),
1859  SETL("res1", r1),
1860  SETL("res2", r2),
1861  SETL("res3", r3),
1862  eff);
1863 }
1864 
1869 static RzILOpEffect *sel(cs_insn *insn, bool is_thumb) {
1870  if (!ISREG(0)) {
1871  return NULL;
1872  }
1873  RzILOpBitVector *a = ARG(1);
1874  RzILOpBitVector *b = ARG(2);
1875  if (!a || !b) {
1878  return NULL;
1879  }
1880  return write_reg(REGID(0),
1881  APPEND(
1882  APPEND(
1883  UNSIGNED(8, SHIFTR0(ITE(IS_ZERO(LOGAND(VARG("gef"), UN(4, 1 << 3))), b, a), UN(5, 24))),
1884  UNSIGNED(8, SHIFTR0(ITE(IS_ZERO(LOGAND(VARG("gef"), UN(4, 1 << 2))), DUP(b), DUP(a)), UN(5, 16)))),
1885  APPEND(
1886  UNSIGNED(8, SHIFTR0(ITE(IS_ZERO(LOGAND(VARG("gef"), UN(4, 1 << 1))), DUP(b), DUP(a)), UN(5, 8))),
1887  UNSIGNED(8, ITE(IS_ZERO(LOGAND(VARG("gef"), UN(4, 1))), DUP(b), DUP(a))))));
1888 }
1889 
1894 static RzILOpEffect *sbfx(cs_insn *insn, bool is_thumb) {
1895  if (!ISREG(0) || !ISIMM(2) || !ISIMM(3)) {
1896  return NULL;
1897  }
1898  RzILOpBitVector *val = REG(1);
1899  if (!val) {
1900  return NULL;
1901  }
1902  val = UNSIGNED(IMM(3), SHIFTR0(val, UN(5, IMM(2))));
1903  val = insn->id == ARM_INS_SBFX ? SIGNED(32, val) : UNSIGNED(32, val);
1904  return write_reg(REGID(0), val);
1905 }
1906 
1911 static RzILOpEffect *sdiv(cs_insn *insn, bool is_thumb) {
1912  if (!ISREG(0)) {
1913  return NULL;
1914  }
1915  RzILOpBitVector *a = ARG(1);
1916  RzILOpBitVector *b = ARG(2);
1917  if (!a || !b) {
1920  return NULL;
1921  }
1922  return write_reg(REGID(0),
1923  ITE(EQ(b, U32(0)), U32(0),
1924  ITE(AND(EQ(a, U32(0x80000000)), EQ(DUP(b), U32(0xffffffff))),
1925  U32(0x80000000),
1926  SDIV(DUP(a), DUP(b)))));
1927 }
1928 
1933 static RzILOpEffect *udiv(cs_insn *insn, bool is_thumb) {
1934  if (!ISREG(0)) {
1935  return NULL;
1936  }
1937  RzILOpBitVector *a = ARG(1);
1938  RzILOpBitVector *b = ARG(2);
1939  if (!a || !b) {
1942  return NULL;
1943  }
1944  return write_reg(REGID(0),
1945  ITE(EQ(b, U32(0)), U32(0),
1946  DIV(a, DUP(b))));
1947 }
1948 
1953 static RzILOpEffect *umaal(cs_insn *insn, bool is_thumb) {
1954  if (!ISREG(0) || !ISREG(1)) {
1955  return NULL;
1956  }
1957  RzILOpBitVector *dl = ARG(0);
1958  RzILOpBitVector *dh = ARG(1);
1959  RzILOpBitVector *a = ARG(2);
1960  RzILOpBitVector *b = ARG(3);
1961  RzILOpEffect *wl = write_reg(REGID(0), UNSIGNED(32, VARL("res")));
1962  RzILOpEffect *wh = write_reg(REGID(1), UNSIGNED(32, SHIFTR0(VARL("res"), UN(6, 32))));
1963  if (!dl || !dh || !a || !b || !wl || !wh) {
1964  rz_il_op_pure_free(dl);
1965  rz_il_op_pure_free(dh);
1970  return NULL;
1971  }
1972  return SEQ3(
1973  SETL("res", ADD(ADD(MUL(UNSIGNED(64, a), UNSIGNED(64, b)), UNSIGNED(64, dl)), UNSIGNED(64, dh))),
1974  wl, wh);
1975 }
1976 
1981 static RzILOpEffect *umull(cs_insn *insn, bool is_thumb) {
1982  if (!ISREG(0) || !ISREG(1)) {
1983  return NULL;
1984  }
1985  RzILOpBitVector *a = ARG(2);
1986  RzILOpBitVector *b = ARG(3);
1987  RzILOpEffect *wl = write_reg(REGID(0), UNSIGNED(32, VARL("res")));
1988  RzILOpEffect *wh = write_reg(REGID(1), UNSIGNED(32, SHIFTR0(VARL("res"), UN(6, 32))));
1989  if (!a || !b || !wl || !wh) {
1994  return NULL;
1995  }
1996  if (insn->detail->arm.update_flags) {
1997  return SEQ4(
1998  SETL("res", MUL(UNSIGNED(64, a), UNSIGNED(64, b))),
1999  wl, wh, update_flags_zn(VARL("res")));
2000  } else {
2001  return SEQ3(SETL("res", MUL(UNSIGNED(64, a), UNSIGNED(64, b))), wl, wh);
2002  }
2003 }
2004 
2006  return LET("a", a, LET("b", b, ITE(ULE(VARLP("a"), VARLP("b")), SUB(VARLP("b"), VARLP("a")), SUB(VARLP("a"), VARLP("b")))));
2007 }
2008 
2013 static RzILOpEffect *usad8(cs_insn *insn, bool is_thumb) {
2014  if (!ISREG(0)) {
2015  return NULL;
2016  }
2017  bool have_acc = insn->id == ARM_INS_USADA8;
2018  RzILOpBitVector *a = ARG(1);
2019  RzILOpBitVector *b = ARG(2);
2020  RzILOpBitVector *acc = have_acc ? ARG(3) : NULL;
2021  if (!a || !b || (have_acc && !acc)) {
2024  return NULL;
2025  }
2026  RzILOpBitVector *a0 = UNSIGNED(32, UNSIGNED(8, a));
2027  RzILOpBitVector *a1 = UNSIGNED(32, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 8))));
2028  RzILOpBitVector *a2 = UNSIGNED(32, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 16))));
2029  RzILOpBitVector *a3 = UNSIGNED(32, UNSIGNED(8, SHIFTR0(DUP(a), UN(5, 24))));
2030  RzILOpBitVector *b0 = UNSIGNED(32, UNSIGNED(8, b));
2031  RzILOpBitVector *b1 = UNSIGNED(32, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 8))));
2032  RzILOpBitVector *b2 = UNSIGNED(32, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 16))));
2033  RzILOpBitVector *b3 = UNSIGNED(32, UNSIGNED(8, SHIFTR0(DUP(b), UN(5, 24))));
2034  RzILOpBitVector *sum = ADD(absdiff(a0, b0), ADD(absdiff(a1, b1), ADD(absdiff(a2, b2), absdiff(a3, b3))));
2035  if (have_acc) {
2036  sum = ADD(acc, sum);
2037  }
2038  return write_reg(REGID(0), sum);
2039 }
2040 
2045 static RzILOpEffect *smlabb(cs_insn *insn, bool is_thumb) {
2046  if (!ISREG(0)) {
2047  return NULL;
2048  }
2049  RzILOpBitVector *ra = ARG(1);
2050  RzILOpBitVector *rb = ARG(2);
2051  RzILOpBitVector *acc = ARG(3);
2052  if (!ra || !rb || !acc) {
2053  rz_il_op_pure_free(ra);
2054  rz_il_op_pure_free(rb);
2055  rz_il_op_pure_free(acc);
2056  return NULL;
2057  }
2058  RzILOpBitVector *a = ra;
2059  RzILOpBitVector *b = rb;
2060  bool exchange_b = insn->id == ARM_INS_SMLADX || insn->id == ARM_INS_SMLSDX;
2061  if (insn->id == ARM_INS_SMLATB || insn->id == ARM_INS_SMLATT) {
2062  a = SHIFTR0(ra, UN(5, 16));
2063  }
2064  if (insn->id == ARM_INS_SMLABT || insn->id == ARM_INS_SMLATT || exchange_b) {
2065  b = SHIFTR0(rb, UN(5, 16));
2066  }
2067  a = UNSIGNED(16, a);
2068  b = UNSIGNED(16, b);
2069  RzILOpBitVector *product;
2070  ut32 extend_bits;
2071  if (insn->id == ARM_INS_SMLAD || insn->id == ARM_INS_SMLADX || insn->id == ARM_INS_SMLSD || insn->id == ARM_INS_SMLSDX) {
2072  extend_bits = 34; // need more bits for the larger range that can be reached here
2073  RzILOpBitVector *ah = SIGNED(extend_bits, UNSIGNED(16, SHIFTR0(DUP(ra), UN(5, 16))));
2074  RzILOpBitVector *bh = SIGNED(extend_bits, UNSIGNED(16, exchange_b ? DUP(rb) : SHIFTR0(DUP(rb), UN(5, 16))));
2075  RzILOpBitVector *proda = MUL(SIGNED(extend_bits, a), SIGNED(extend_bits, b));
2076  RzILOpBitVector *prodb = MUL(ah, bh);
2077  product = insn->id == ARM_INS_SMLSD || insn->id == ARM_INS_SMLSDX
2078  ? SUB(proda, prodb)
2079  : ADD(proda, prodb);
2080  } else {
2081  extend_bits = 33;
2082  product = MUL(SIGNED(extend_bits, a), SIGNED(extend_bits, b));
2083  }
2084  RzILOpEffect *eff = write_reg(REGID(0), UNSIGNED(32, VARL("res")));
2085  if (!eff) {
2088  rz_il_op_pure_free(acc);
2089  return NULL;
2090  }
2091  return SEQ3(
2092  SETL("res", ADD(product, SIGNED(extend_bits, acc))),
2093  eff,
2094  BRANCH(INV(EQ(VARL("res"), SIGNED(extend_bits, REG(0)))), SETG("qf", IL_TRUE), NULL));
2095 }
2096 
2102 static RzILOpEffect *smlal(cs_insn *insn, bool is_thumb) {
2103  if (!ISREG(0) || !ISREG(1)) {
2104  return NULL;
2105  }
2106  RzILOpBitVector *dl = ARG(0);
2107  RzILOpBitVector *dh = ARG(1);
2108  RzILOpBitVector *ra = ARG(2);
2109  RzILOpBitVector *rb = ARG(3);
2110  RzILOpEffect *wl = write_reg(REGID(0), UNSIGNED(32, VARL("res")));
2111  RzILOpEffect *wh = write_reg(REGID(1), UNSIGNED(32, SHIFTR0(VARL("res"), UN(6, 32))));
2112  if (!dl || !dh || !ra || !rb || !wl || !wh) {
2113  rz_il_op_pure_free(dl);
2114  rz_il_op_pure_free(dh);
2115  rz_il_op_pure_free(ra);
2116  rz_il_op_pure_free(rb);
2119  return NULL;
2120  }
2121  RzILOpBitVector *a = ra;
2122  RzILOpBitVector *b = rb;
2123  bool exchange_b = insn->id == ARM_INS_SMLALDX || insn->id == ARM_INS_SMLSLDX;
2124  if (insn->id == ARM_INS_SMLALTB || insn->id == ARM_INS_SMLALTT) {
2125  a = SHIFTR0(ra, UN(5, 16));
2126  }
2127  if (insn->id == ARM_INS_SMLALBT || insn->id == ARM_INS_SMLALTT || exchange_b) {
2128  b = SHIFTR0(rb, UN(5, 16));
2129  }
2130  if (insn->id == ARM_INS_SMLALBB || insn->id == ARM_INS_SMLALBT || insn->id == ARM_INS_SMLALTB ||
2131  insn->id == ARM_INS_SMLALTT || insn->id == ARM_INS_SMLALD || insn->id == ARM_INS_SMLALDX ||
2132  insn->id == ARM_INS_SMLSLD || insn->id == ARM_INS_SMLSLDX) {
2133  a = UNSIGNED(16, a);
2134  b = UNSIGNED(16, b);
2135  }
2136  if (insn->id == ARM_INS_UMLAL) {
2137  a = UNSIGNED(64, a);
2138  b = UNSIGNED(64, b);
2139  } else {
2140  a = SIGNED(64, a);
2141  b = SIGNED(64, b);
2142  }
2143  RzILOpBitVector *product;
2144  if (insn->id == ARM_INS_SMLALD || insn->id == ARM_INS_SMLALDX || insn->id == ARM_INS_SMLSLD || insn->id == ARM_INS_SMLSLDX) {
2145  RzILOpBitVector *ah = SIGNED(64, UNSIGNED(16, SHIFTR0(DUP(ra), UN(5, 16))));
2146  RzILOpBitVector *bh = SIGNED(64, UNSIGNED(16, exchange_b ? DUP(rb) : SHIFTR0(DUP(rb), UN(5, 16))));
2147  product = insn->id == ARM_INS_SMLSLD || insn->id == ARM_INS_SMLSLDX
2148  ? SUB(MUL(a, b), MUL(ah, bh))
2149  : ADD(MUL(a, b), MUL(ah, bh));
2150  } else {
2151  product = MUL(a, b);
2152  }
2153  RzILOpBitVector *res = ADD(product, APPEND(dh, dl));
2154  return insn->detail->arm.update_flags
2155  ? SEQ4(SETL("res", res), update_flags_zn(VARL("res")), wl, wh)
2156  : SEQ3(SETL("res", res), wl, wh);
2157 }
2158 
2163 static RzILOpEffect *smlaw(cs_insn *insn, bool is_thumb) {
2164  if (!ISREG(0)) {
2165  return NULL;
2166  }
2167  RzILOpBitVector *a = ARG(1);
2168  RzILOpBitVector *b = ARG(2);
2169  RzILOpBitVector *acc = ARG(3);
2170  RzILOpBitVector *rres = ARG(0);
2171  RzILOpEffect *eff = write_reg(REGID(0), UNSIGNED(32, VARL("res")));
2172  if (!a || !b || !acc || !rres || !eff) {
2175  rz_il_op_pure_free(acc);
2176  rz_il_op_pure_free(rres);
2177  rz_il_op_effect_free(eff);
2178  return NULL;
2179  }
2180  a = SIGNED(64, a);
2181  b = SIGNED(64, insn->id == ARM_INS_SMLAWT ? SHIFTRA(b, UN(5, 16)) : UNSIGNED(16, b));
2182  acc = SIGNED(64, acc);
2183  return SEQ3(
2184  SETL("res", ADD(SHIFTR0(MUL(a, b), UN(6, 16)), acc)),
2185  eff,
2186  BRANCH(INV(EQ(UNSIGNED(48, VARL("res")), SIGNED(48, rres))), SETG("qf", IL_TRUE), NULL));
2187 }
2188 
2193 static RzILOpEffect *smmla(cs_insn *insn, bool is_thumb) {
2194  if (!ISREG(0)) {
2195  return NULL;
2196  }
2197  RzILOpBitVector *a = ARG(1);
2198  RzILOpBitVector *b = ARG(2);
2199  RzILOpBitVector *acc = ARG(3);
2200  if (!a || !b || !acc) {
2203  rz_il_op_pure_free(acc);
2204  return NULL;
2205  }
2206  RzILOpBitVector *res = insn->id == ARM_INS_SMMLS || insn->id == ARM_INS_SMMLSR
2207  ? SUB(APPEND(acc, U32(0)), MUL(SIGNED(64, a), SIGNED(64, b)))
2208  : ADD(MUL(SIGNED(64, a), SIGNED(64, b)), APPEND(acc, U32(0)));
2209  if (insn->id == ARM_INS_SMMLAR || insn->id == ARM_INS_SMMLSR) {
2210  res = ADD(res, U64(0x80000000));
2211  }
2212  return write_reg(REGID(0), UNSIGNED(32, SHIFTR0(res, UN(6, 32))));
2213 }
2214 
2219 static RzILOpEffect *smmul(cs_insn *insn, bool is_thumb) {
2220  if (!ISREG(0)) {
2221  return NULL;
2222  }
2223  RzILOpBitVector *a = ARG(1);
2224  RzILOpBitVector *b = ARG(2);
2225  if (!a || !b) {
2228  return NULL;
2229  }
2230  RzILOpBitVector *res = MUL(SIGNED(64, a), SIGNED(64, b));
2231  if (insn->id == ARM_INS_SMMULR) {
2232  res = ADD(res, U64(0x80000000));
2233  }
2234  return write_reg(REGID(0), UNSIGNED(32, SHIFTR0(res, UN(6, 32))));
2235 }
2236 
2241 static RzILOpEffect *smuad(cs_insn *insn, bool is_thumb) {
2242  if (!ISREG(0)) {
2243  return NULL;
2244  }
2245  RzILOpBitVector *ra = ARG(1);
2246  RzILOpBitVector *rb = ARG(2);
2247  RzILOpEffect *eff = write_reg(REGID(0), UNSIGNED(32, VARL("res")));
2248  if (!ra || !rb || !eff) {
2249  rz_il_op_pure_free(ra);
2250  rz_il_op_pure_free(rb);
2251  rz_il_op_effect_free(eff);
2252  return NULL;
2253  }
2254  RzILOpBitVector *al = SIGNED(33, UNSIGNED(16, ra));
2255  RzILOpBitVector *ah = SIGNED(33, UNSIGNED(16, SHIFTR0(DUP(ra), UN(5, 16))));
2256  RzILOpBitVector *bl = SIGNED(33, UNSIGNED(16, rb));
2257  RzILOpBitVector *bh = SIGNED(33, UNSIGNED(16, SHIFTR0(DUP(rb), UN(5, 16))));
2258  if (insn->id == ARM_INS_SMUADX) {
2259  RzILOpBitVector *tmp = bl;
2260  bl = bh;
2261  bh = tmp;
2262  }
2263  return SEQ3(
2264  SETL("res", ADD(MUL(al, bl), MUL(ah, bh))),
2265  eff,
2266  BRANCH(XOR(MSB(VARL("res")), MSB(REG(0))), SETG("qf", IL_TRUE), NULL));
2267 }
2268 
2273 static RzILOpEffect *smulbb(cs_insn *insn, bool is_thumb) {
2274  if (!ISREG(0)) {
2275  return NULL;
2276  }
2277  RzILOpBitVector *ra = ARG(1);
2278  RzILOpBitVector *rb = ARG(2);
2279  if (!ra || !rb) {
2280  rz_il_op_pure_free(ra);
2281  rz_il_op_pure_free(rb);
2282  return NULL;
2283  }
2284  RzILOpBitVector *a = ra;
2285  RzILOpBitVector *b = rb;
2286  if (insn->id == ARM_INS_SMULTB || insn->id == ARM_INS_SMULTT) {
2287  a = SHIFTR0(a, UN(5, 16));
2288  }
2289  if (insn->id == ARM_INS_SMULBT || insn->id == ARM_INS_SMULTT || insn->id == ARM_INS_SMUSDX) {
2290  b = SHIFTR0(b, UN(5, 16));
2291  }
2292  a = UNSIGNED(16, a);
2293  b = UNSIGNED(16, b);
2294  RzILOpBitVector *res = MUL(SIGNED(32, a), SIGNED(32, b));
2295  if (insn->id == ARM_INS_SMUSD || insn->id == ARM_INS_SMUSDX) {
2296  res = SUB(res,
2297  MUL(
2298  SIGNED(32, UNSIGNED(16, SHIFTR0(DUP(ra), UN(5, 16)))),
2299  SIGNED(32, UNSIGNED(16, insn->id == ARM_INS_SMUSDX ? DUP(rb) : SHIFTR0(DUP(rb), UN(5, 16))))));
2300  }
2301  return write_reg(REGID(0), res);
2302 }
2303 
2308 static RzILOpEffect *tbb(cs_insn *insn, bool is_thumb) {
2309  RzILOpBitVector *addr = ARG(0);
2310  if (!addr) {
2311  return NULL;
2312  }
2313  RzILOpBitVector *off = insn->id == ARM_INS_TBB ? LOAD(addr) : LOADW(16, addr);
2314  return JMP(ADD(U32(PC(insn->address, is_thumb)), SHIFTL0(UNSIGNED(32, off), UN(5, 1))));
2315 }
2316 
2321 static RzILOpEffect *vmov(cs_insn *insn, bool is_thumb) {
2322  if (OPCOUNT() != 2 || !ISREG(0) || !ISREG(1)) {
2323  // for now, only support vmov rt, rn
2324  return NULL;
2325  }
2326  RzILOpBitVector *val = ARG(1);
2327  if (!val) {
2328  return NULL;
2329  }
2330  return write_reg(REGID(0), val);
2331 }
2332 
2354 static RzILOpEffect *il_unconditional(csh *handle, cs_insn *insn, bool is_thumb) {
2355  switch (insn->id) {
2356  // --
2357  // Base Instruction Set
2358  case ARM_INS_DBG:
2359  case ARM_INS_NOP:
2360  case ARM_INS_PLD:
2361  case ARM_INS_PLDW:
2362  case ARM_INS_PLI:
2363  case ARM_INS_YIELD:
2364  // barriers/synchronization
2365  case ARM_INS_DMB:
2366  case ARM_INS_DSB:
2367  case ARM_INS_ISB:
2368  return NOP();
2369  case ARM_INS_B:
2370  case ARM_INS_BX:
2371  case ARM_INS_BXJ: {
2372  RzILOpBitVector *dst = ARG(0);
2373  return dst ? JMP(dst) : NULL;
2374  }
2375  case ARM_INS_BL:
2376  case ARM_INS_BLX:
2377  return bl(insn, is_thumb);
2378  case ARM_INS_MOV:
2379  case ARM_INS_MOVW:
2380  case ARM_INS_LSL:
2381  case ARM_INS_LSR:
2382  case ARM_INS_ASR:
2383  case ARM_INS_RRX:
2384  case ARM_INS_ROR:
2385  case ARM_INS_MVN:
2386  return mov(insn, is_thumb);
2387  case ARM_INS_MOVT:
2388  return movt(insn, is_thumb);
2389  case ARM_INS_ADR:
2390  return adr(insn, is_thumb);
2391  case ARM_INS_ADD:
2392  case ARM_INS_ADDW:
2393  case ARM_INS_ADC:
2394  case ARM_INS_SUB:
2395  case ARM_INS_SUBW:
2396  case ARM_INS_RSB:
2397  case ARM_INS_RSC:
2398  case ARM_INS_SBC:
2399  return add_sub(insn, is_thumb);
2400  case ARM_INS_MUL:
2401  return mul(insn, is_thumb);
2402  case ARM_INS_LDR:
2403  case ARM_INS_LDREX:
2404  case ARM_INS_LDRB:
2405  case ARM_INS_LDRH:
2406  case ARM_INS_LDRT:
2407  case ARM_INS_LDRBT:
2408  case ARM_INS_LDRHT:
2409  case ARM_INS_LDA:
2410  case ARM_INS_LDAB:
2411  case ARM_INS_LDAH:
2412  case ARM_INS_LDAEX:
2413  case ARM_INS_LDAEXB:
2414  case ARM_INS_LDAEXH:
2415  case ARM_INS_LDRD:
2416  case ARM_INS_LDREXD:
2417  case ARM_INS_LDRSB:
2418  case ARM_INS_LDRSBT:
2419  case ARM_INS_LDRSH:
2420  case ARM_INS_LDRSHT:
2421  return ldr(insn, is_thumb);
2422  case ARM_INS_STR:
2423  case ARM_INS_STRB:
2424  case ARM_INS_STRH:
2425  case ARM_INS_STRT:
2426  case ARM_INS_STRBT:
2427  case ARM_INS_STRHT:
2428  case ARM_INS_STL:
2429  case ARM_INS_STLB:
2430  case ARM_INS_STLH:
2431  case ARM_INS_STRD:
2432  return str(insn, is_thumb);
2433  case ARM_INS_STREX:
2434  case ARM_INS_STREXB:
2435  case ARM_INS_STREXD:
2436  case ARM_INS_STREXH:
2437  case ARM_INS_STLEX:
2438  case ARM_INS_STLEXB:
2439  case ARM_INS_STLEXD:
2440  case ARM_INS_STLEXH:
2441  return strex(insn, is_thumb);
2442  case ARM_INS_AND:
2443  case ARM_INS_ORR:
2444  case ARM_INS_ORN:
2445  case ARM_INS_EOR:
2446  case ARM_INS_BIC:
2447  return bitwise(insn, is_thumb);
2448  case ARM_INS_TST:
2449  case ARM_INS_TEQ:
2450  return tst(insn, is_thumb);
2451  case ARM_INS_UXTB:
2452  case ARM_INS_UXTAB:
2453  case ARM_INS_UXTH:
2454  case ARM_INS_UXTAH:
2455  case ARM_INS_SXTB:
2456  case ARM_INS_SXTAB:
2457  case ARM_INS_SXTH:
2458  case ARM_INS_SXTAH:
2459  return uxt(insn, is_thumb);
2460  case ARM_INS_UXTB16:
2461  case ARM_INS_UXTAB16:
2462  case ARM_INS_SXTB16:
2463  case ARM_INS_SXTAB16:
2464  return uxt16(insn, is_thumb);
2465  case ARM_INS_CMP:
2466  case ARM_INS_CMN:
2467  return cmp(insn, is_thumb);
2468  case ARM_INS_STM:
2469  case ARM_INS_STMDA:
2470  case ARM_INS_STMDB:
2471  case ARM_INS_PUSH:
2472  case ARM_INS_STMIB:
2473  return stm(insn, is_thumb);
2474  case ARM_INS_POP:
2475  case ARM_INS_LDM:
2476  case ARM_INS_LDMDA:
2477  case ARM_INS_LDMDB:
2478  case ARM_INS_LDMIB:
2479  return ldm(insn, is_thumb);
2480  case ARM_INS_CLZ:
2481  return clz(insn, is_thumb);
2482  case ARM_INS_SVC:
2483  return svc(insn, is_thumb);
2484 #if CS_API_MAJOR > 3
2485  case ARM_INS_HVC:
2486  return hvc(insn, is_thumb);
2487 #endif
2488  case ARM_INS_BFC:
2489  return bfc(insn, is_thumb);
2490  case ARM_INS_BFI:
2491  return bfi(insn, is_thumb);
2492  case ARM_INS_CBZ:
2493  case ARM_INS_CBNZ:
2494  return cbz(insn, is_thumb);
2495  case ARM_INS_MLA:
2496  case ARM_INS_MLS:
2497  return mla(insn, is_thumb);
2498  case ARM_INS_MRS:
2499  return mrs(insn, is_thumb);
2500  case ARM_INS_MSR:
2501  return msr(insn, is_thumb);
2502  case ARM_INS_PKHBT:
2503  case ARM_INS_PKHTB:
2504  return pkhbt(insn, is_thumb);
2505  case ARM_INS_SSAT:
2506  case ARM_INS_USAT:
2507  return ssat(insn, is_thumb);
2508  case ARM_INS_SSAT16:
2509  case ARM_INS_USAT16:
2510  return ssat16(insn, is_thumb);
2511  case ARM_INS_QADD:
2512  case ARM_INS_QSUB:
2513  case ARM_INS_QDADD:
2514  case ARM_INS_QDSUB:
2515  return qadd(insn, is_thumb);
2516  case ARM_INS_QADD16:
2517  case ARM_INS_QSUB16:
2518  case ARM_INS_QASX:
2519  case ARM_INS_QSAX:
2520  case ARM_INS_UQADD16:
2521  case ARM_INS_UQSUB16:
2522  case ARM_INS_UQASX:
2523  case ARM_INS_UQSAX:
2524  return qadd16(insn, is_thumb);
2525  case ARM_INS_QADD8:
2526  case ARM_INS_QSUB8:
2527  case ARM_INS_UQADD8:
2528  case ARM_INS_UQSUB8:
2529  return qadd8(insn, is_thumb);
2530  case ARM_INS_RBIT:
2531  return rbit(insn, is_thumb);
2532  case ARM_INS_REV:
2533  case ARM_INS_REV16:
2534  return rev(insn, is_thumb);
2535  case ARM_INS_REVSH:
2536  return revsh(insn, is_thumb);
2537  case ARM_INS_RFEDA:
2538  case ARM_INS_RFEDB:
2539  case ARM_INS_RFEIA:
2540  case ARM_INS_RFEIB:
2541  return rfe(insn, is_thumb);
2542  case ARM_INS_SADD16:
2543  case ARM_INS_SHADD16:
2544  case ARM_INS_SASX:
2545  case ARM_INS_SSAX:
2546  case ARM_INS_SHASX:
2547  case ARM_INS_SHSAX:
2548  case ARM_INS_SSUB16:
2549  case ARM_INS_SHSUB16:
2550  case ARM_INS_UADD16:
2551  case ARM_INS_UHADD16:
2552  case ARM_INS_UASX:
2553  case ARM_INS_USAX:
2554  case ARM_INS_UHASX:
2555  case ARM_INS_UHSAX:
2556  case ARM_INS_USUB16:
2557  case ARM_INS_UHSUB16:
2558  return sadd16(insn, is_thumb);
2559  case ARM_INS_SADD8:
2560  case ARM_INS_SHADD8:
2561  case ARM_INS_SSUB8:
2562  case ARM_INS_SHSUB8:
2563  case ARM_INS_UADD8:
2564  case ARM_INS_UHADD8:
2565  case ARM_INS_USUB8:
2566  case ARM_INS_UHSUB8:
2567  return sadd8(insn, is_thumb);
2568  case ARM_INS_SEL:
2569  return sel(insn, is_thumb);
2570  case ARM_INS_SBFX:
2571  case ARM_INS_UBFX:
2572  return sbfx(insn, is_thumb);
2573  case ARM_INS_SDIV:
2574  return sdiv(insn, is_thumb);
2575  case ARM_INS_UDIV:
2576  return udiv(insn, is_thumb);
2577  case ARM_INS_UMAAL:
2578  return umaal(insn, is_thumb);
2579  case ARM_INS_UMULL:
2580  return umull(insn, is_thumb);
2581  case ARM_INS_USAD8:
2582  case ARM_INS_USADA8:
2583  return usad8(insn, is_thumb);
2584  case ARM_INS_SMLABB:
2585  case ARM_INS_SMLABT:
2586  case ARM_INS_SMLATB:
2587  case ARM_INS_SMLATT:
2588  case ARM_INS_SMLAD:
2589  case ARM_INS_SMLADX:
2590  case ARM_INS_SMLSD:
2591  case ARM_INS_SMLSDX:
2592  return smlabb(insn, is_thumb);
2593  case ARM_INS_SMLAL:
2594  case ARM_INS_SMLALBB:
2595  case ARM_INS_SMLALBT:
2596  case ARM_INS_SMLALTB:
2597  case ARM_INS_SMLALTT:
2598  case ARM_INS_SMLALD:
2599  case ARM_INS_SMLALDX:
2600  case ARM_INS_SMLSLD:
2601  case ARM_INS_SMLSLDX:
2602  case ARM_INS_UMLAL:
2603  return smlal(insn, is_thumb);
2604  case ARM_INS_SMLAWB:
2605  case ARM_INS_SMLAWT:
2606  return smlaw(insn, is_thumb);
2607  case ARM_INS_SMMLA:
2608  case ARM_INS_SMMLAR:
2609  case ARM_INS_SMMLS:
2610  case ARM_INS_SMMLSR:
2611  return smmla(insn, is_thumb);
2612  case ARM_INS_SMMUL:
2613  case ARM_INS_SMMULR:
2614  return smmul(insn, is_thumb);
2615  case ARM_INS_SMUAD:
2616  case ARM_INS_SMUADX:
2617  return smuad(insn, is_thumb);
2618  case ARM_INS_SMULBB:
2619  case ARM_INS_SMULBT:
2620  case ARM_INS_SMULTB:
2621  case ARM_INS_SMULTT:
2622  case ARM_INS_SMUSD:
2623  case ARM_INS_SMUSDX:
2624  return smulbb(insn, is_thumb);
2625  case ARM_INS_TBB:
2626  case ARM_INS_TBH:
2627  return tbb(insn, is_thumb);
2628 
2629  // --
2630  // Advanced SIMD and Floating-point
2631  case ARM_INS_VSTMIA:
2632  case ARM_INS_VSTMDB:
2633  case ARM_INS_VPUSH:
2634  return stm(insn, is_thumb);
2635  case ARM_INS_VLDMIA:
2636  case ARM_INS_VLDMDB:
2637  case ARM_INS_VPOP:
2638  return ldm(insn, is_thumb);
2639  case ARM_INS_VMOV:
2640  return vmov(insn, is_thumb);
2641 
2642  default:
2643  return NULL;
2644  }
2645 }
2646 
2647 RZ_IPI RzILOpEffect *rz_arm_cs_32_il(csh *handle, cs_insn *insn, bool thumb) {
2648  if (insn->id == ARM_INS_IT) {
2649  // Note: IT is **not** a conditional branch!
2650  // It's currently handled in analysis_arm_cs.c using ArmCSContext as a hack to turn the following instructions
2651  // into conditional ones. So in the IL, we don't do anything for IT.
2652  return NOP();
2653  }
2654  RzILOpEffect *eff = il_unconditional(handle, insn, thumb);
2655  if (!eff) {
2656  return NULL;
2657  }
2658  RzILOpBool *c = cond(insn->detail->arm.cc);
2659  if (c) {
2660  return BRANCH(c, eff, NOP());
2661  }
2662  return eff;
2663 }
2664 
2665 #include <rz_il/rz_il_opbuilder_end.h>
2666 
2668  RzAnalysisILConfig *r = rz_analysis_il_config_new(32, big_endian, 32);
2669  r->reg_bindings = regs_bound_32;
2671  svc_label->hook = label_svc;
2672  rz_analysis_il_config_add_label(r, svc_label);
2674  hvc_label->hook = label_hvc;
2675  rz_analysis_il_config_add_label(r, hvc_label);
2676  return r;
2677 }
#define mask()
#define imm
RZ_API void rz_analysis_il_config_add_label(RZ_NONNULL RzAnalysisILConfig *cfg, RZ_NONNULL RZ_OWN RzILEffectLabel *label)
Definition: analysis_il.c:77
RZ_API RZ_OWN RzAnalysisILConfig * rz_analysis_il_config_new(ut32 pc_size, bool big_endian, ut32 mem_key_size)
Definition: analysis_il.c:53
static void update_flags(RzAnalysisOp *op, int flags)
Definition: analysis_v810.c:20
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
#define BRANCH
#define cast(x, y)
Definition: arch_53.h:166
r3
Definition: arm-aliases.s.cs:3
r2
Definition: arm-aliases.s.cs:2
#define ISREG(x)
#define OPCOUNT()
#define MEMDISP(x)
#define IMM(x)
#define ISIMM(x)
#define ISMEM(x)
#define REGID(x)
static RzILOpEffect * bfi(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1175
static RzILOpEffect * mrs(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1246
static RzILOpEffect * strex(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:736
static RzILOpEffect * vmov(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2321
static RzILOpEffect * bitwise(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:784
static RzILOpEffect * sadd16(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1664
#define ARG_C(n, carry)
Definition: arm_il32.c:318
static RzILOpEffect * rfe(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1625
static RzILOpEffect * clz(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1112
static RzILOpEffect * smlal(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2102
static RzILOpEffect * write_reg(arm_reg reg, RZ_OWN RZ_NONNULL RzILOpBitVector *v)
Definition: arm_il32.c:117
static RzILOpEffect * adr(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:449
static const char * regs_bound_32[]
Definition: arm_il32.c:17
static RzILOpEffect * msr(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1268
static RzILOpEffect * sbfx(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1894
static RzILOpEffect * sdiv(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1911
static RzILOpEffect * uxt16(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:906
static RzILOpEffect * qadd8(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1516
static RzILOpEffect * cmp(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:942
#define REG_VAL(id)
Definition: arm_il32.c:110
static RzILOpEffect * rev(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1590
static RzILOpEffect * smlaw(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2163
static RzILOpEffect * ssat16(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1396
static RzILOpEffect * sadd8(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1757
static RzILOpBitVector * absdiff(RzILOpBitVector *a, RzILOpBitVector *b)
Definition: arm_il32.c:2005
static RzILOpBitVector * read_reg(ut64 pc, arm_reg reg)
Definition: arm_il32.c:95
static void label_hvc(RzILVM *vm, RzILOpEffect *op)
Definition: arm_il32.c:1152
static RzILOpEffect * uxt(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:874
static RzILOpEffect * smmla(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2193
static RzILOpBitVector * arg_mem(RzILOpBitVector *base_plus_disp, cs_arm_op *op, RZ_NULLABLE RzILOpBool **carry_out)
Definition: arm_il32.c:247
static RzILOpEffect * movt(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:433
static RzILOpEffect * tst(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:849
static RzILOpEffect * svc(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1134
static RzILOpEffect * mla(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1217
#define PCALIGN(addr, is_thumb)
Definition: arm_il32.c:109
static RzILOpEffect * smlabb(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2045
static RzILOpEffect * tbb(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2308
static RzILOpEffect * smulbb(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2273
static bool is_reg_shift(arm_shifter type)
Definition: arm_il32.c:177
static RzILOpEffect * smmul(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2219
static RzILOpEffect * udiv(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1933
static RzILOpEffect * saturate_signed_to_range(const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q, st64 min, st64 max)
Definition: arm_il32.c:1332
RZ_IPI RzAnalysisILConfig * rz_arm_cs_32_il_config(bool big_endian)
Definition: arm_il32.c:2667
static RzILOpEffect * saturate_signed(bool to_signed, const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q)
Definition: arm_il32.c:1342
static void label_svc(RzILVM *vm, RzILOpEffect *op)
Definition: arm_il32.c:1138
static RzILOpEffect * bl(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1098
static RzILOpEffect * bfc(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1160
static RzILOpEffect * revsh(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1610
static RzILOpEffect * usad8(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2013
static RzILOpEffect * str(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:661
static RzILOpEffect * ldm(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1029
static RzILOpEffect * qadd(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1421
#define ARG(n)
Definition: arm_il32.c:319
static RzILOpEffect * il_unconditional(csh *handle, cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2354
static const char * reg_var_name(arm_reg reg)
Definition: arm_il32.c:29
static RzILOpEffect * ldr(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:564
static RzILOpEffect * saturate(bool sign, bool is_sub, const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q)
Definition: arm_il32.c:1365
static RzILOpEffect * umull(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1981
static RzILOpEffect * update_flags_from_cpsr(RzILOpBitVector *val, bool f, bool s)
Definition: arm_il32.c:335
static RzILOpEffect * add_sub(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:476
static RZ_NULLABLE RzILOpBool * cond(arm_cc c)
Definition: arm_il32.c:141
static RzILOpEffect * ssat(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1375
static RzILOpBitVector * arg(cs_insn *insn, bool is_thumb, int n, RZ_NULLABLE RzILOpBool **carry_out)
Definition: arm_il32.c:259
RZ_IPI RzILOpEffect * rz_arm_cs_32_il(csh *handle, cs_insn *insn, bool thumb)
Definition: arm_il32.c:2647
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
Definition: arm_il32.c:190
#define PC(addr, is_thumb)
Definition: arm_il32.c:108
static ut32 reg_bits(arm_reg reg)
Definition: arm_il32.c:82
static RzILOpEffect * qadd16(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1457
static RzILOpEffect * sel(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1869
static RzILOpEffect * mov(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:351
static RzILOpEffect * saturate_unsigned(bool is_sub, const char *dst, ut32 bits, RzILOpBitVector *val, ut32 ext_bits, bool set_q)
Definition: arm_il32.c:1355
static RzILOpEffect * pkhbt(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1307
static RzILOpEffect * umaal(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1953
#define REG(n)
Definition: arm_il32.c:111
static RzILOpEffect * cbz(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1198
static RzILOpEffect * rbit(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1562
static RzILOpEffect * update_flags_zn(RzILOpBitVector *v)
Definition: arm_il32.c:325
#define MEMBASE(x)
Definition: arm_il32.c:112
static RzILOpEffect * stm(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:968
static RzILOpEffect * mul(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:539
static RzILOpEffect * smuad(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:2241
static RzILOpEffect * writeback(cs_insn *insn, size_t addr_op, RZ_BORROW RzILOpBitVector *addr)
Definition: arm_il64.c:1024
static RzILOpEffect * hvc(cs_insn *insn)
Definition: arm_il64.c:999
ut16 val
Definition: armass64_const.h:6
static bool err
Definition: armass.c:435
static mcore_handle handle
Definition: asm_mcore.c:8
int bits(struct state *s, int need)
Definition: blast.c:72
@ ARM_INS_RFEIA
Definition: arm.h:560
@ ARM_INS_SMLAD
Definition: arm.h:591
@ ARM_INS_SMLSLD
Definition: arm.h:606
@ ARM_INS_TBH
Definition: arm.h:865
@ ARM_INS_ADR
Definition: arm.h:448
@ ARM_INS_QADD8
Definition: arm.h:546
@ ARM_INS_USAX
Definition: arm.h:698
@ ARM_INS_VPOP
Definition: arm.h:879
@ ARM_INS_QADD16
Definition: arm.h:545
@ ARM_INS_USADA8
Definition: arm.h:695
@ ARM_INS_SEL
Definition: arm.h:570
@ ARM_INS_SHSAX
Definition: arm.h:585
@ ARM_INS_SHSUB8
Definition: arm.h:587
@ ARM_INS_TEQ
Definition: arm.h:670
@ ARM_INS_SXTB16
Definition: arm.h:668
@ ARM_INS_SMMUL
Definition: arm.h:612
@ ARM_INS_VLDMIA
Definition: arm.h:755
@ ARM_INS_LDAEXH
Definition: arm.h:496
@ ARM_INS_SADD16
Definition: arm.h:564
@ ARM_INS_QSUB
Definition: arm.h:551
@ ARM_INS_SHSUB16
Definition: arm.h:586
@ ARM_INS_UADD8
Definition: arm.h:674
@ ARM_INS_SMLATT
Definition: arm.h:601
@ ARM_INS_LDRSH
Definition: arm.h:517
@ ARM_INS_STR
Definition: arm.h:659
@ ARM_INS_UMAAL
Definition: arm.h:685
@ ARM_INS_STLEXH
Definition: arm.h:643
@ ARM_INS_VMOV
Definition: arm.h:481
@ ARM_INS_LDRT
Definition: arm.h:519
@ ARM_INS_TBB
Definition: arm.h:864
@ ARM_INS_BXJ
Definition: arm.h:461
@ ARM_INS_SHADD8
Definition: arm.h:583
@ ARM_INS_SXTAH
Definition: arm.h:666
@ ARM_INS_SMLALBT
Definition: arm.h:595
@ ARM_INS_VLDMDB
Definition: arm.h:754
@ ARM_INS_RFEIB
Definition: arm.h:561
@ ARM_INS_STRH
Definition: arm.h:656
@ ARM_INS_USAT16
Definition: arm.h:697
@ ARM_INS_STLH
Definition: arm.h:644
@ ARM_INS_ADC
Definition: arm.h:446
@ ARM_INS_SASX
Definition: arm.h:566
@ ARM_INS_DMB
Definition: arm.h:477
@ ARM_INS_ORN
Definition: arm.h:860
@ ARM_INS_UXTB16
Definition: arm.h:705
@ ARM_INS_BX
Definition: arm.h:460
@ ARM_INS_SMLALD
Definition: arm.h:596
@ ARM_INS_LDRB
Definition: arm.h:507
@ ARM_INS_SUB
Definition: arm.h:660
@ ARM_INS_UQSUB8
Definition: arm.h:693
@ ARM_INS_STREXH
Definition: arm.h:655
@ ARM_INS_IT
Definition: arm.h:857
@ ARM_INS_ASR
Definition: arm.h:853
@ ARM_INS_ISB
Definition: arm.h:490
@ ARM_INS_LDRHT
Definition: arm.h:514
@ ARM_INS_MLS
Definition: arm.h:526
@ ARM_INS_SMLSD
Definition: arm.h:604
@ ARM_INS_LDAH
Definition: arm.h:497
@ ARM_INS_RSB
Definition: arm.h:562
@ ARM_INS_UXTB
Definition: arm.h:704
@ ARM_INS_AND
Definition: arm.h:453
@ ARM_INS_SMLALTB
Definition: arm.h:598
@ ARM_INS_STRB
Definition: arm.h:650
@ ARM_INS_UHASX
Definition: arm.h:681
@ ARM_INS_LDRSBT
Definition: arm.h:516
@ ARM_INS_SHADD16
Definition: arm.h:582
@ ARM_INS_SSUB16
Definition: arm.h:632
@ ARM_INS_TST
Definition: arm.h:672
@ ARM_INS_SXTH
Definition: arm.h:669
@ ARM_INS_PUSH
Definition: arm.h:869
@ ARM_INS_MOVT
Definition: arm.h:528
@ ARM_INS_MOV
Definition: arm.h:527
@ ARM_INS_QSAX
Definition: arm.h:550
@ ARM_INS_QDSUB
Definition: arm.h:549
@ ARM_INS_PLD
Definition: arm.h:542
@ ARM_INS_SADD8
Definition: arm.h:565
@ ARM_INS_SMMLS
Definition: arm.h:610
@ ARM_INS_UQADD16
Definition: arm.h:688
@ ARM_INS_SHASX
Definition: arm.h:584
@ ARM_INS_UXTAH
Definition: arm.h:703
@ ARM_INS_SSAT
Definition: arm.h:629
@ ARM_INS_UHADD16
Definition: arm.h:679
@ ARM_INS_UHSUB8
Definition: arm.h:684
@ ARM_INS_LDRSB
Definition: arm.h:515
@ ARM_INS_SSAT16
Definition: arm.h:630
@ ARM_INS_STREXD
Definition: arm.h:654
@ ARM_INS_LDRBT
Definition: arm.h:506
@ ARM_INS_SSAX
Definition: arm.h:631
@ ARM_INS_SMLABT
Definition: arm.h:590
@ ARM_INS_SMULTT
Definition: arm.h:620
@ ARM_INS_PKHBT
Definition: arm.h:539
@ ARM_INS_UQASX
Definition: arm.h:690
@ ARM_INS_LDM
Definition: arm.h:504
@ ARM_INS_PLI
Definition: arm.h:543
@ ARM_INS_SMMLA
Definition: arm.h:608
@ ARM_INS_SMLSDX
Definition: arm.h:605
@ ARM_INS_SBFX
Definition: arm.h:568
@ ARM_INS_STMDB
Definition: arm.h:646
@ ARM_INS_BFI
Definition: arm.h:455
@ ARM_INS_QASX
Definition: arm.h:547
@ ARM_INS_VPUSH
Definition: arm.h:878
@ ARM_INS_SMMLSR
Definition: arm.h:611
@ ARM_INS_MRS
Definition: arm.h:534
@ ARM_INS_LDAEX
Definition: arm.h:493
@ ARM_INS_VSTMDB
Definition: arm.h:837
@ ARM_INS_RFEDA
Definition: arm.h:558
@ ARM_INS_UHSUB16
Definition: arm.h:683
@ ARM_INS_LDAEXB
Definition: arm.h:494
@ ARM_INS_UBFX
Definition: arm.h:676
@ ARM_INS_LSL
Definition: arm.h:858
@ ARM_INS_UQSUB16
Definition: arm.h:692
@ ARM_INS_LSR
Definition: arm.h:859
@ ARM_INS_LDAB
Definition: arm.h:492
@ ARM_INS_DSB
Definition: arm.h:478
@ ARM_INS_SMUSD
Definition: arm.h:623
@ ARM_INS_USUB16
Definition: arm.h:699
@ ARM_INS_STRBT
Definition: arm.h:649
@ ARM_INS_SMLAWB
Definition: arm.h:602
@ ARM_INS_SMLALTT
Definition: arm.h:599
@ ARM_INS_UMULL
Definition: arm.h:687
@ ARM_INS_BIC
Definition: arm.h:456
@ ARM_INS_RFEDB
Definition: arm.h:559
@ ARM_INS_RBIT
Definition: arm.h:554
@ ARM_INS_STMIB
Definition: arm.h:648
@ ARM_INS_SMLSLDX
Definition: arm.h:607
@ ARM_INS_SMLALDX
Definition: arm.h:597
@ ARM_INS_REVSH
Definition: arm.h:557
@ ARM_INS_STL
Definition: arm.h:638
@ ARM_INS_DBG
Definition: arm.h:476
@ ARM_INS_MUL
Definition: arm.h:536
@ ARM_INS_SMLABB
Definition: arm.h:589
@ ARM_INS_ADDW
Definition: arm.h:852
@ ARM_INS_LDRH
Definition: arm.h:513
@ ARM_INS_QSUB16
Definition: arm.h:552
@ ARM_INS_SMUAD
Definition: arm.h:614
@ ARM_INS_CBZ
Definition: arm.h:867
@ ARM_INS_UHADD8
Definition: arm.h:680
@ ARM_INS_UMLAL
Definition: arm.h:686
@ ARM_INS_REV16
Definition: arm.h:556
@ ARM_INS_LDREXD
Definition: arm.h:511
@ ARM_INS_UQSAX
Definition: arm.h:691
@ ARM_INS_SXTAB16
Definition: arm.h:665
@ ARM_INS_SMLADX
Definition: arm.h:592
@ ARM_INS_HVC
Definition: arm.h:489
@ ARM_INS_EOR
Definition: arm.h:479
@ ARM_INS_SMULBB
Definition: arm.h:616
@ ARM_INS_NOP
Definition: arm.h:872
@ ARM_INS_STLEXB
Definition: arm.h:641
@ ARM_INS_LDMDA
Definition: arm.h:502
@ ARM_INS_UDIV
Definition: arm.h:678
@ ARM_INS_SXTAB
Definition: arm.h:664
@ ARM_INS_STMDA
Definition: arm.h:645
@ ARM_INS_LDREX
Definition: arm.h:509
@ ARM_INS_UHSAX
Definition: arm.h:682
@ ARM_INS_UASX
Definition: arm.h:675
@ ARM_INS_SMULTB
Definition: arm.h:619
@ ARM_INS_ADD
Definition: arm.h:447
@ ARM_INS_LDRSHT
Definition: arm.h:518
@ ARM_INS_QDADD
Definition: arm.h:548
@ ARM_INS_SMLALBB
Definition: arm.h:594
@ ARM_INS_POP
Definition: arm.h:868
@ ARM_INS_BLX
Definition: arm.h:459
@ ARM_INS_STM
Definition: arm.h:647
@ ARM_INS_RSC
Definition: arm.h:563
@ ARM_INS_SMUSDX
Definition: arm.h:624
@ ARM_INS_LDMIB
Definition: arm.h:505
@ ARM_INS_SMLAWT
Definition: arm.h:603
@ ARM_INS_SMMULR
Definition: arm.h:613
@ ARM_INS_CMN
Definition: arm.h:467
@ ARM_INS_SMUADX
Definition: arm.h:615
@ ARM_INS_SMMLAR
Definition: arm.h:609
@ ARM_INS_UQADD8
Definition: arm.h:689
@ ARM_INS_ROR
Definition: arm.h:861
@ ARM_INS_LDR
Definition: arm.h:520
@ ARM_INS_STRT
Definition: arm.h:658
@ ARM_INS_PLDW
Definition: arm.h:541
@ ARM_INS_STREXB
Definition: arm.h:653
@ ARM_INS_REV
Definition: arm.h:555
@ ARM_INS_STRD
Definition: arm.h:651
@ ARM_INS_SBC
Definition: arm.h:567
@ ARM_INS_CBNZ
Definition: arm.h:866
@ ARM_INS_STLEXD
Definition: arm.h:642
@ ARM_INS_STLB
Definition: arm.h:639
@ ARM_INS_SDIV
Definition: arm.h:569
@ ARM_INS_MVN
Definition: arm.h:537
@ ARM_INS_UXTAB
Definition: arm.h:701
@ ARM_INS_SMLAL
Definition: arm.h:593
@ ARM_INS_SVC
Definition: arm.h:661
@ ARM_INS_BFC
Definition: arm.h:454
@ ARM_INS_B
Definition: arm.h:462
@ ARM_INS_STLEX
Definition: arm.h:640
@ ARM_INS_UXTAB16
Definition: arm.h:702
@ ARM_INS_MLA
Definition: arm.h:525
@ ARM_INS_SUBW
Definition: arm.h:863
@ ARM_INS_BL
Definition: arm.h:458
@ ARM_INS_LDMDB
Definition: arm.h:503
@ ARM_INS_STREX
Definition: arm.h:652
@ ARM_INS_CMP
Definition: arm.h:468
@ ARM_INS_USUB8
Definition: arm.h:700
@ ARM_INS_SMULBT
Definition: arm.h:617
@ ARM_INS_UXTH
Definition: arm.h:706
@ ARM_INS_QADD
Definition: arm.h:544
@ ARM_INS_USAT
Definition: arm.h:696
@ ARM_INS_LDRD
Definition: arm.h:508
@ ARM_INS_QSUB8
Definition: arm.h:553
@ ARM_INS_MOVW
Definition: arm.h:529
@ ARM_INS_USAD8
Definition: arm.h:694
@ ARM_INS_VSTMIA
Definition: arm.h:838
@ ARM_INS_SMLATB
Definition: arm.h:600
@ ARM_INS_STRHT
Definition: arm.h:657
@ ARM_INS_SSUB8
Definition: arm.h:633
@ ARM_INS_YIELD
Definition: arm.h:873
@ ARM_INS_RRX
Definition: arm.h:862
@ ARM_INS_ORR
Definition: arm.h:538
@ ARM_INS_CLZ
Definition: arm.h:466
@ ARM_INS_LDA
Definition: arm.h:491
@ ARM_INS_MSR
Definition: arm.h:535
@ ARM_INS_PKHTB
Definition: arm.h:540
@ ARM_INS_SXTB
Definition: arm.h:667
@ ARM_INS_UADD16
Definition: arm.h:673
arm_shifter
ARM shift type.
Definition: arm.h:18
@ ARM_SFT_ROR_REG
shift with register
Definition: arm.h:28
@ ARM_SFT_ASR
shift with immediate const
Definition: arm.h:20
@ ARM_SFT_LSR_REG
shift with register
Definition: arm.h:27
@ ARM_SFT_LSL_REG
shift with register
Definition: arm.h:26
@ ARM_SFT_ROR
shift with immediate const
Definition: arm.h:23
@ ARM_SFT_LSL
shift with immediate const
Definition: arm.h:21
@ ARM_SFT_RRX_REG
shift with register
Definition: arm.h:29
@ ARM_SFT_LSR
shift with immediate const
Definition: arm.h:22
@ ARM_SFT_RRX
shift with immediate const
Definition: arm.h:24
@ ARM_SFT_INVALID
Definition: arm.h:19
@ ARM_SFT_ASR_REG
shift with register
Definition: arm.h:25
@ ARM_SYSREG_APSR_NZCVQG
Definition: arm.h:72
@ ARM_SYSREG_SPSR_S
Definition: arm.h:59
@ ARM_SYSREG_APSR_G
Definition: arm.h:70
@ ARM_SYSREG_CPSR_S
Definition: arm.h:65
@ ARM_SYSREG_APSR_NZCVQ
Definition: arm.h:71
@ ARM_SYSREG_SPSR_F
Definition: arm.h:60
@ ARM_SYSREG_CPSR_F
Definition: arm.h:66
@ ARM_OP_IMM
= CS_OP_IMM (Immediate operand).
Definition: arm.h:164
@ ARM_OP_REG
= CS_OP_REG (Register operand).
Definition: arm.h:163
@ ARM_OP_MEM
= CS_OP_MEM (Memory operand).
Definition: arm.h:165
@ ARM_OP_SYSREG
MSR/MRS special register operand.
Definition: arm.h:170
arm_cc
ARM condition code.
Definition: arm.h:33
@ ARM_CC_GT
Greater than Greater than.
Definition: arm.h:47
@ ARM_CC_LE
Less than or equal <, ==, or unordered.
Definition: arm.h:48
@ ARM_CC_AL
Always (unconditional) Always (unconditional)
Definition: arm.h:49
@ ARM_CC_HI
Unsigned higher Greater than, or unordered.
Definition: arm.h:43
@ ARM_CC_VC
No overflow Not unordered.
Definition: arm.h:42
@ ARM_CC_LS
Unsigned lower or same Less than or equal.
Definition: arm.h:44
@ ARM_CC_GE
Greater than or equal Greater than or equal.
Definition: arm.h:45
@ ARM_CC_VS
Overflow Unordered.
Definition: arm.h:41
@ ARM_CC_PL
Plus, positive or zero >, ==, or unordered.
Definition: arm.h:40
@ ARM_CC_NE
Not equal Not equal, or unordered.
Definition: arm.h:36
@ ARM_CC_LO
Carry clear Less than.
Definition: arm.h:38
@ ARM_CC_EQ
Equal Equal.
Definition: arm.h:35
@ ARM_CC_LT
Less than Less than, or unordered.
Definition: arm.h:46
@ ARM_CC_HS
Carry set >, ==, or unordered.
Definition: arm.h:37
@ ARM_CC_MI
Minus, negative Less than.
Definition: arm.h:39
arm_reg
ARM registers.
Definition: arm.h:252
@ ARM_REG_D4
Definition: arm.h:271
@ ARM_REG_R12
Definition: arm.h:331
@ ARM_REG_D12
Definition: arm.h:279
@ ARM_REG_S0
Definition: arm.h:332
@ ARM_REG_R5
Definition: arm.h:324
@ ARM_REG_D15
Definition: arm.h:282
@ ARM_REG_D25
Definition: arm.h:292
@ ARM_REG_R8
Definition: arm.h:327
@ ARM_REG_R4
Definition: arm.h:323
@ ARM_REG_R2
Definition: arm.h:321
@ ARM_REG_Q0
Definition: arm.h:303
@ ARM_REG_D19
Definition: arm.h:286
@ ARM_REG_R10
Definition: arm.h:329
@ ARM_REG_INVALID
Definition: arm.h:253
@ ARM_REG_D3
Definition: arm.h:270
@ ARM_REG_R6
Definition: arm.h:325
@ ARM_REG_D7
Definition: arm.h:274
@ ARM_REG_D26
Definition: arm.h:293
@ ARM_REG_R11
Definition: arm.h:330
@ ARM_REG_R3
Definition: arm.h:322
@ ARM_REG_D2
Definition: arm.h:269
@ ARM_REG_D30
Definition: arm.h:297
@ ARM_REG_CPSR
Definition: arm.h:256
@ ARM_REG_LR
Definition: arm.h:263
@ ARM_REG_D16
Definition: arm.h:283
@ ARM_REG_D9
Definition: arm.h:276
@ ARM_REG_D17
Definition: arm.h:284
@ ARM_REG_APSR
Definition: arm.h:254
@ ARM_REG_R0
Definition: arm.h:319
@ ARM_REG_Q15
Definition: arm.h:318
@ ARM_REG_SPSR
Definition: arm.h:266
@ ARM_REG_D11
Definition: arm.h:278
@ ARM_REG_D21
Definition: arm.h:288
@ ARM_REG_D31
Definition: arm.h:298
@ ARM_REG_SP
Definition: arm.h:265
@ ARM_REG_D29
Definition: arm.h:296
@ ARM_REG_PC
Definition: arm.h:264
@ ARM_REG_D18
Definition: arm.h:285
@ ARM_REG_D8
Definition: arm.h:275
@ ARM_REG_D24
Definition: arm.h:291
@ ARM_REG_R1
Definition: arm.h:320
@ ARM_REG_D5
Definition: arm.h:272
@ ARM_REG_D0
Definition: arm.h:267
@ ARM_REG_D1
Definition: arm.h:268
@ ARM_REG_D28
Definition: arm.h:295
@ ARM_REG_D13
Definition: arm.h:280
@ ARM_REG_R9
Definition: arm.h:328
@ ARM_REG_D27
Definition: arm.h:294
@ ARM_REG_D6
Definition: arm.h:273
@ ARM_REG_D14
Definition: arm.h:281
@ ARM_REG_D10
Definition: arm.h:277
@ ARM_REG_D22
Definition: arm.h:289
@ ARM_REG_S31
Definition: arm.h:363
@ ARM_REG_D23
Definition: arm.h:290
@ ARM_REG_R7
Definition: arm.h:326
@ ARM_REG_D20
Definition: arm.h:287
size_t csh
Definition: capstone.h:71
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
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 static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
uint32_t ut32
const char * v
Definition: dsignal.c:12
@ GOTO
Definition: egg_lang.c:71
int max
Definition: enough.c:225
RZ_API void rz_il_op_pure_free(RZ_NULLABLE RzILOpPure *op)
Definition: il_opcodes.c:928
RZ_API RZ_OWN RzILOpBitVector * rz_il_op_new_signed(ut32 length, RZ_NONNULL RzILOpBitVector *val)
Extend val to length bits, filling up with val's most significant bit.
Definition: il_opcodes.c:363
RZ_API void rz_il_op_effect_free(RZ_NULLABLE RzILOpEffect *op)
Definition: il_opcodes.c:1036
RZ_API RZ_OWN RzILOpBitVector * rz_il_op_new_unsigned(ut32 length, RZ_NONNULL RzILOpBitVector *val)
Extend val to length bits, filling up with zeroes.
Definition: il_opcodes.c:353
a0
Definition: insn-good.s.cs:704
voidpf uLong offset
Definition: ioapi.h:144
RZ_API RzILEffectLabel * rz_il_effect_label_new(RZ_NONNULL const char *name, RzILEffectLabelType type)
Definition: label.c:6
@ EFFECT_LABEL_SYSCALL
Definition: label.h:19
#define reg(n)
#define SIGNED
Definition: ansidecl.h:248
#define AND
Definition: ansidecl.h:254
char * dst
Definition: lz4.h:724
static bool is_thumb(RzBinFile *bf)
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
int off
Definition: pal.c:13
void * load(const char *name, size_t *len)
Definition: pufftest.c:60
#define min(a, b)
Definition: qsort.h:83
#define SLT
Definition: rsp_idec.c:216
#define OR
Definition: rsp_idec.c:210
#define XOR
Definition: rsp_idec.c:212
#define NOP
Definition: rsp_idec.c:182
#define ADD
Definition: rsp_idec.c:200
static RzSocket * s
Definition: rtr.c:28
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
Syntax Macros for RzIL Lifting.
#define LOAD(addr)
#define LOGOR(x, y)
#define UGT(x, y)
#define LOGNOT(x)
#define IS_ZERO(x)
#define SHIFTR0(v, dist)
#define LOADW(n, addr)
#define SDIV(x, y)
#define MUL(x, y)
#define U16(val)
#define LSB(x)
#define VARLP(name)
#define APPEND(high, low)
#define LET(name, v, body)
#define UN(l, val)
#define DIV(x, y)
#define U32(val)
#define IL_FALSE
#define REPEAT(c, b)
#define ULE(x, y)
#define EQ(x, y)
#define SEQ3(e0, e1, e2)
#define STOREW(addr, val)
#define SEQ5(e0, e1, e2, e3, e4)
#define SETL(name, v)
#define SEQ4(e0, e1, e2, e3)
#define SHIFTR(f, v, dist)
#define IL_TRUE
#define INV(x)
#define SEQ2(e0, e1)
#define ITE(c, t, f)
#define LOGXOR(x, y)
#define NEG(x)
#define UNSIGNED(n, x)
#define U64(val)
#define SN(l, val)
#define SEQ6(e0, e1, e2, e3, e4, e5)
#define SHIFTL0(v, dist)
#define SHIFTRA(v, dist)
#define VARL(name)
#define SGT(x, y)
#define MSB(x)
#define LOGAND(x, y)
#define STORE(addr, val)
#define VARG(name)
#define JMP(tgt)
#define SETG(name, v)
@ RZ_IL_OP_CAST
static ut64 rz_num_bitmask(ut8 width)
Get the 64-bit value that has exactly its width lowest bits set to 1. e.g. rz_num_bitmask(2) == 0b11 ...
Definition: rz_num.h:134
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
#define st64
Definition: rz_types_base.h:10
#define st32
Definition: rz_types_base.h:12
@ DUP
Definition: packet.c:12
#define SUB(ns, call)
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
#define h(i)
Definition: sha256.c:48
arm_reg base
base register
Definition: arm.h:381
Instruction operand.
Definition: arm.h:391
arm_op_mem mem
base/index/scale/disp value for MEM operand
Definition: arm.h:405
Description of the global context of an RzAnalysisILVM.
Definition: rz_analysis.h:1134
void * hook
Function pointer if EFFECT_LABEL_SYSCALL / EFFECT_LABEL_HOOK.
Definition: label.h:28
An IL op performing a pure computation, 'a pure.
Low-level VM to execute raw IL code.
Definition: rz_il_vm.h:37
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58