Rizin
unix-like reverse engineering framework and cli tools
arm_esil32.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2013-2021 pancake <pancake@nopcode.org>
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 
10 #define REG(x) rz_str_get_null(cs_reg_name(*handle, insn->detail->arm.operands[x].reg))
11 #define MEMBASE(x) rz_str_get_null(cs_reg_name(*handle, insn->detail->arm.operands[x].mem.base))
12 #define MEMINDEX(x) rz_str_get_null(cs_reg_name(*handle, insn->detail->arm.operands[x].mem.index))
13 
14 static const char *decode_shift(arm_shifter shift) {
15  const char *E_OP_SR = ">>";
16  const char *E_OP_SL = "<<";
17  const char *E_OP_RR = ">>>";
18  const char *E_OP_ASR = ">>>>";
19  const char *E_OP_VOID = "";
20 
21  switch (shift) {
22  case ARM_SFT_ASR:
23  case ARM_SFT_ASR_REG:
24  return E_OP_ASR;
25 
26  case ARM_SFT_LSR:
27  case ARM_SFT_LSR_REG:
28  return E_OP_SR;
29 
30  case ARM_SFT_LSL:
31  case ARM_SFT_LSL_REG:
32  return E_OP_SL;
33 
34  case ARM_SFT_ROR:
35  case ARM_SFT_RRX:
36  case ARM_SFT_ROR_REG:
37  case ARM_SFT_RRX_REG:
38  return E_OP_RR;
39 
40  default:
41  break;
42  }
43  return E_OP_VOID;
44 }
45 
46 #define DECODE_SHIFT(x) decode_shift(insn->detail->arm.operands[x].shift.type)
47 
48 static unsigned int regsize32(cs_insn *insn, int n) {
49  rz_return_val_if_fail(n >= 0 && n < insn->detail->arm.op_count, 0);
50  unsigned int reg = insn->detail->arm.operands[n].reg;
51  if (reg >= ARM_REG_D0 && reg <= ARM_REG_D31) {
52  return 8;
53  }
54  if (reg >= ARM_REG_Q0 && reg <= ARM_REG_Q15) {
55  return 16;
56  }
57  return 4; // s0-s31, r0-r15
58 }
59 
60 #define REGSIZE32(x) regsize32(insn, x)
61 
62 // return postfix
63 RZ_IPI const char *rz_arm_cs_esil_prefix_cond(RzAnalysisOp *op, int cond_type) {
64  const char *close_cond[2];
65  close_cond[0] = "\0";
66  close_cond[1] = ",}\0";
67  int close_type = 0;
68  switch (cond_type) {
69  case ARM_CC_EQ:
70  close_type = 1;
71  rz_strbuf_setf(&op->esil, "zf,?{,");
72  break;
73  case ARM_CC_NE:
74  close_type = 1;
75  rz_strbuf_setf(&op->esil, "zf,!,?{,");
76  break;
77  case ARM_CC_HS:
78  close_type = 1;
79  rz_strbuf_setf(&op->esil, "cf,?{,");
80  break;
81  case ARM_CC_LO:
82  close_type = 1;
83  rz_strbuf_setf(&op->esil, "cf,!,?{,");
84  break;
85  case ARM_CC_MI:
86  close_type = 1;
87  rz_strbuf_setf(&op->esil, "nf,?{,");
88  break;
89  case ARM_CC_PL:
90  close_type = 1;
91  rz_strbuf_setf(&op->esil, "nf,!,?{,");
92  break;
93  case ARM_CC_VS:
94  close_type = 1;
95  rz_strbuf_setf(&op->esil, "vf,?{,");
96  break;
97  case ARM_CC_VC:
98  close_type = 1;
99  rz_strbuf_setf(&op->esil, "vf,!,?{,");
100  break;
101  case ARM_CC_HI:
102  close_type = 1;
103  rz_strbuf_setf(&op->esil, "cf,zf,!,&,?{,");
104  break;
105  case ARM_CC_LS:
106  close_type = 1;
107  rz_strbuf_setf(&op->esil, "cf,!,zf,|,?{,");
108  break;
109  case ARM_CC_GE:
110  close_type = 1;
111  rz_strbuf_setf(&op->esil, "nf,vf,^,!,?{,");
112  break;
113  case ARM_CC_LT:
114  close_type = 1;
115  rz_strbuf_setf(&op->esil, "nf,vf,^,?{,");
116  break;
117  case ARM_CC_GT:
118  // zf == 0 && nf == vf
119  close_type = 1;
120  rz_strbuf_setf(&op->esil, "zf,!,nf,vf,^,!,&,?{,");
121  break;
122  case ARM_CC_LE:
123  // zf == 1 || nf != vf
124  close_type = 1;
125  rz_strbuf_setf(&op->esil, "zf,nf,vf,^,|,?{,");
126  break;
127  case ARM_CC_AL:
128  // always executed
129  break;
130  default:
131  break;
132  }
133  return close_cond[close_type];
134 }
135 
136 static const char *arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n) {
137  buf[0] = 0;
138  switch (insn->detail->arm.operands[n].type) {
139  case ARM_OP_REG:
140  if (ISSHIFTED(n)) {
141  sprintf(buf, "%u,%s,%s",
142  LSHIFT2(n),
144  insn->detail->arm.operands[n].reg)),
145  DECODE_SHIFT(n));
146  } else {
147  sprintf(buf, "%s",
149  insn->detail->arm.operands[n].reg)));
150  }
151  break;
152  case ARM_OP_IMM:
153  if (a->bits == 64) {
154  // 64bit only
155  sprintf(buf, "%" PFMT64d, (ut64)insn->detail->arm.operands[n].imm);
156  } else {
157  // 32bit only
158  sprintf(buf, "%" PFMT64d, (ut64)(ut32)insn->detail->arm.operands[n].imm);
159  }
160  break;
161  case ARM_OP_MEM:
162  break;
163  case ARM_OP_FP:
164  sprintf(buf, "%lf", insn->detail->arm.operands[n].fp);
165  break;
166  default:
167  break;
168  }
169  return buf;
170 }
171 
172 #define ARG(x) arg(a, handle, insn, str[x], x)
173 
174 #define MATH32(opchar) arm32math(a, op, addr, buf, len, handle, insn, pcdelta, str, opchar, 0)
175 #define MATH32_NEG(opchar) arm32math(a, op, addr, buf, len, handle, insn, pcdelta, str, opchar, 1)
176 #define MATH32AS(opchar) arm32mathaddsub(a, op, addr, buf, len, handle, insn, pcdelta, str, opchar)
177 
178 static void arm32math(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, int pcdelta, char (*str)[32], const char *opchar, int negate) {
179  const char *dest = ARG(0);
180  const char *op1;
181  const char *op2;
182  bool rotate_imm = OPCOUNT() > 3;
183  if (OPCOUNT() > 2) {
184  op1 = ARG(1);
185  op2 = ARG(2);
186  } else {
187  op1 = dest;
188  op2 = ARG(1);
189  }
190  // right operand
191  if (rotate_imm) {
192  rz_strbuf_appendf(&op->esil, "%s,", ARG(3));
193  }
194  if (!strcmp(op2, "pc")) {
195  rz_strbuf_appendf(&op->esil, "%d,$$,+", pcdelta);
196  } else {
197  rz_strbuf_appendf(&op->esil, "%s", op2);
198  }
199  if (rotate_imm) {
200  rz_strbuf_appendf(&op->esil, ",>>>");
201  }
202  if (negate) {
203  rz_strbuf_appendf(&op->esil, ",-1,^");
204  }
205  if (!strcmp(op1, "pc")) {
206  rz_strbuf_appendf(&op->esil, ",%d,$$,+,%s,0xffffffff,&,%s,=", pcdelta, opchar, dest);
207  } else {
208  if (ISSHIFTED(1)) {
209  rz_strbuf_appendf(&op->esil, ",0xffffffff,&,%s,=", dest);
210  } else {
211  rz_strbuf_appendf(&op->esil, ",%s,%s,0xffffffff,&,%s,=", op1, opchar, dest);
212  }
213  }
214 }
215 
216 static void arm32mathaddsub(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, int pcdelta, char (*str)[32], const char *opchar) {
217  const char *dst = ARG(0);
218  const char *src;
219  bool noflags = false;
220  if (!strcmp(dst, "pc")) { // this is because strbuf_prepend doesn't exist and E_TOO_LAZY
221  // rz_strbuf_append (&op->esil, "$$,pc,=,");
222  noflags = true;
223  }
224  if (OPCOUNT() == 3) {
225  rz_strbuf_appendf(&op->esil, "%s,0xffffffff,&,%s,=,", ARG(1), dst);
226  src = ARG(2);
227  } else {
228  // src = (!strcmp (ARG(1), "pc"))? "$$": ARG(1);
229  src = ARG(1);
230  }
231  rz_strbuf_appendf(&op->esil, "%s,%s,%s,0xffffffff,&,%s,=", src, dst, opchar, dst);
232  if (noflags) {
233  return;
234  }
235  rz_strbuf_appendf(&op->esil, ",$z,zf,:=,%s,cf,:=,vf,=,0,nf,=",
236  (!strcmp(opchar, "+") ? "30,$c,31,$c,^,31,$c" : "30,$c,31,$c,^,32,$b"));
237 }
238 
239 RZ_IPI int rz_arm_cs_analysis_op_32_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, bool thumb) {
240  int i;
241  const char *postfix = NULL;
242  char str[32][32];
243  int msr_flags;
244  int pcdelta = (thumb ? 4 : 8);
245  ut32 mask = UT32_MAX;
246  int str_ldr_bytes = 4;
247  unsigned int width = 0;
248 
249  rz_strbuf_init(&op->esil);
250  rz_strbuf_set(&op->esil, "");
251  postfix = rz_arm_cs_esil_prefix_cond(op, insn->detail->arm.cc);
252 
253  switch (insn->id) {
254  case ARM_INS_CLZ:
255  rz_strbuf_appendf(&op->esil, "%s,!,?{,32,%s,=,BREAK,},0,%s,=,%s,%s,<<,0x80000000,&,!,?{,1,%s,+=,11,GOTO,}", REG(1), REG(0), REG(0), REG(0), REG(1), REG(0));
256  break;
257  case ARM_INS_IT:
258  rz_strbuf_appendf(&op->esil, "2,$$,+,pc,=");
259  break;
260  case ARM_INS_BKPT:
261  rz_strbuf_setf(&op->esil, "%d,%d,TRAP", IMM(0), IMM(0));
262  break;
263  case ARM_INS_NOP:
264  rz_strbuf_setf(&op->esil, ",");
265  break;
266  case ARM_INS_BL:
267  case ARM_INS_BLX:
268  rz_strbuf_appendf(&op->esil, "pc,%d,+,lr,=,", thumb);
269  /* fallthrough */
270  case ARM_INS_BX:
271  case ARM_INS_BXJ:
272  case ARM_INS_B:
273  if (ISREG(0) && REGID(0) == ARM_REG_PC) {
274  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",pc,=", (addr & ~3LL) + pcdelta);
275  } else {
276  if (ISIMM(0)) {
277  rz_strbuf_appendf(&op->esil, "%s,pc,=", ARG(0));
278  } else {
279  rz_strbuf_appendf(&op->esil, "%d,%s,-,pc,=", thumb, ARG(0));
280  }
281  }
282  break;
283  case ARM_INS_UDF:
284  rz_strbuf_setf(&op->esil, "%s,TRAP", ARG(0));
285  break;
286  case ARM_INS_SADD16:
287  case ARM_INS_SADD8:
288  MATH32AS("+");
289  break;
290  case ARM_INS_ADDW:
291  case ARM_INS_ADD:
292  MATH32("+");
293  break;
294  case ARM_INS_ADC:
295  if (OPCOUNT() == 2) {
296  rz_strbuf_appendf(&op->esil, "cf,%s,+=,%s,%s,+=", ARG(0), ARG(1), ARG(0));
297  } else {
298  rz_strbuf_appendf(&op->esil, "cf,%s,+=,%s,%s,+,%s,+=", ARG(0), ARG(2), ARG(1), ARG(0));
299  }
300  break;
301  case ARM_INS_SSUB16:
302  case ARM_INS_SSUB8:
303  MATH32AS("-");
304  break;
305  case ARM_INS_SUBW:
306  case ARM_INS_SUB:
307  MATH32("-");
308  break;
309  case ARM_INS_SBC:
310  if (OPCOUNT() == 2) {
311  rz_strbuf_appendf(&op->esil, "cf,%s,-=,%s,%s,-=", ARG(0), ARG(1), ARG(0));
312  } else {
313  rz_strbuf_appendf(&op->esil, "cf,%s,-=,%s,%s,+,%s,-=", ARG(0), ARG(2), ARG(1), ARG(0));
314  }
315  break;
316  case ARM_INS_MUL:
317  MATH32("*");
318  break;
319  case ARM_INS_AND:
320  MATH32("&");
321  break;
322  case ARM_INS_ORR:
323  MATH32("|");
324  break;
325  case ARM_INS_EOR:
326  MATH32("^");
327  break;
328  case ARM_INS_ORN:
329  MATH32_NEG("|");
330  break;
331  case ARM_INS_LSR:
332  if (insn->detail->arm.update_flags) {
333  if (OPCOUNT() == 2) {
334  rz_strbuf_appendf(&op->esil, "%s,!,!,?{,%s,1,%s,-,0x1,<<,&,!,!,cf,:=,},", ARG(1), ARG(0), ARG(1));
335  } else {
336  rz_strbuf_appendf(&op->esil, "%s,!,!,?{,%s,1,%s,-,0x1,<<,&,!,!,cf,:=,},", ARG(2), ARG(1), ARG(2));
337  }
338  }
339  MATH32(">>");
340  break;
341  case ARM_INS_LSL:
342  if (insn->detail->arm.update_flags) {
343  if (OPCOUNT() == 2) {
344  rz_strbuf_appendf(&op->esil, "%s,!,!,?{,%s,32,-,%s,>>,cf,:=,},", ARG(1), ARG(1), ARG(0));
345  } else {
346  rz_strbuf_appendf(&op->esil, "%s,!,!,?{,%s,32,-,%s,>>,cf,:=,},", ARG(2), ARG(2), ARG(1));
347  }
348  }
349  MATH32("<<");
350  break;
351  case ARM_INS_SVC:
352  rz_strbuf_setf(&op->esil, "%s,$", ARG(0));
353  break;
354  case ARM_INS_PUSH:
355 #if 0
356 PUSH { r4, r5, r6, r7, lr }
357 4,sp,-=,lr,sp,=[4],
358 4,sp,-=,r7,sp,=[4],
359 4,sp,-=,r6,sp,=[4],
360 4,sp,-=,r5,sp,=[4],
361 4,sp,-=,r4,sp,=[4]
362 
363 20,sp,-=,lr,r7,r6,r5,r4,5,sp,=[*]
364 #endif
365  rz_strbuf_appendf(&op->esil, "%d,sp,-=,",
366  4 * insn->detail->arm.op_count);
367  for (i = insn->detail->arm.op_count; i > 0; i--) {
368  rz_strbuf_appendf(&op->esil, "%s,", REG(i - 1));
369  }
370  rz_strbuf_appendf(&op->esil, "%d,sp,=[*]",
371  insn->detail->arm.op_count);
372  break;
373  case ARM_INS_STMDA:
374  case ARM_INS_STMDB:
375  case ARM_INS_STM:
376  case ARM_INS_STMIB: {
377  int direction = (insn->id == ARM_INS_STMDA || insn->id == ARM_INS_STMDB ? -1 : 1);
378  int offset = direction > 0 ? -1 : -insn->detail->arm.op_count;
379  if (insn->id == ARM_INS_STMDA || insn->id == ARM_INS_STMIB) {
380  offset++;
381  }
382  for (i = 1; i < insn->detail->arm.op_count; i++) {
383  rz_strbuf_appendf(&op->esil, "%s,%s,%d,+,=[4],",
384  REG(i), ARG(0), (i + offset) * 4);
385  }
386  if (insn->detail->arm.writeback == true) { // writeback, reg should be incremented
387  rz_strbuf_appendf(&op->esil, "%d,%s,+=,",
388  direction * (insn->detail->arm.op_count - 1) * 4, ARG(0));
389  }
390  break;
391  }
392  case ARM_INS_VSTMIA:
393  rz_strbuf_set(&op->esil, "");
394  width = 0;
395  for (i = 1; i < insn->detail->arm.op_count; i++) {
396  rz_strbuf_appendf(&op->esil, "%s,%d,%s,+,=[%d],",
397  REG(i), width, ARG(0), REGSIZE32(i));
398  width += REGSIZE32(i);
399  }
400  // increment if writeback
401  if (insn->detail->arm.writeback) {
402  rz_strbuf_appendf(&op->esil, "%d,%s,+=,", width, ARG(0));
403  }
404  break;
405  case ARM_INS_VSTMDB:
406  rz_strbuf_set(&op->esil, "");
407  width = 0;
408  for (i = insn->detail->arm.op_count - 1; i > 0; i--) {
409  width += REGSIZE32(i);
410  rz_strbuf_appendf(&op->esil, "%s,%d,%s,-,=[%d],",
411  REG(i), width, ARG(0), REGSIZE32(i));
412  }
413  // decrement writeback is mandatory for VSTMDB
414  rz_strbuf_appendf(&op->esil, "%d,%s,-=,", width, ARG(0));
415  break;
416  case ARM_INS_VLDMIA:
417  rz_strbuf_set(&op->esil, "");
418  width = 0;
419  for (i = 1; i < insn->detail->arm.op_count; i++) {
420  rz_strbuf_appendf(&op->esil, "%d,%s,+,[%d],%s,=,",
421  width, ARG(0), REGSIZE32(i), REG(i));
422  width += REGSIZE32(i);
423  }
424  // increment if writeback
425  if (insn->detail->arm.writeback) {
426  rz_strbuf_appendf(&op->esil, "%d,%s,+=,", width, ARG(0));
427  }
428  break;
429  case ARM_INS_VLDMDB:
430  rz_strbuf_set(&op->esil, "");
431  width = 0;
432  for (i = insn->detail->arm.op_count - 1; i > 0; i--) {
433  width += REGSIZE32(i);
434  rz_strbuf_appendf(&op->esil, "%d,%s,-,[%d],%s,=,",
435  width, ARG(0), REGSIZE32(i), REG(i));
436  }
437  // decrement writeback is mandatory for VLDMDB
438  rz_strbuf_appendf(&op->esil, "%d,%s,-=,", width, ARG(0));
439  break;
440  case ARM_INS_ASR:
441  // suffix 'S' forces conditional flag to be updated
442  if (insn->detail->arm.update_flags) {
443  if (OPCOUNT() == 2) {
444  rz_strbuf_appendf(&op->esil, "%s,!,!,?{,%s,1,%s,-,0x1,<<,&,!,!,cf,:=,},", ARG(1), ARG(0), ARG(1));
445  } else if (OPCOUNT() == 3) {
446  rz_strbuf_appendf(&op->esil, "%s,!,!,?{,%s,1,%s,-,0x1,<<,&,!,!,cf,:=,},", ARG(2), ARG(1), ARG(2));
447  }
448  }
449  if (OPCOUNT() == 2) {
450  if (ISSHIFTED(1)) {
451  rz_strbuf_appendf(&op->esil, "%s,%s,=", ARG(1), ARG(0));
452  } else {
453  rz_strbuf_appendf(&op->esil, "%s,%s,>>>>,%s,=", ARG(1), ARG(0), ARG(0));
454  }
455  } else if (OPCOUNT() == 3) {
456  rz_strbuf_appendf(&op->esil, "%s,%s,>>>>,%s,=", ARG(2), ARG(1), ARG(0));
457  }
458  break;
459  case ARM_INS_POP:
460 #if 0
461 POP { r4,r5, r6}
462 r6,r5,r4,3,sp,[*],12,sp,+=
463 #endif
464  for (i = insn->detail->arm.op_count; i > 0; i--) {
465  rz_strbuf_appendf(&op->esil, "%s,", REG(i - 1));
466  }
467  rz_strbuf_appendf(&op->esil, "%d,sp,[*],",
468  insn->detail->arm.op_count);
469  rz_strbuf_appendf(&op->esil, "%d,sp,+=",
470  4 * insn->detail->arm.op_count);
471  break;
472  case ARM_INS_LDMDA:
473  case ARM_INS_LDMDB:
474  case ARM_INS_LDM:
475  case ARM_INS_LDMIB: {
476  int direction = (insn->id == ARM_INS_LDMDA || insn->id == ARM_INS_LDMDB) ? -1 : 1;
477  int offset = direction > 0 ? -1 : -insn->detail->arm.op_count;
478  if (insn->id == ARM_INS_LDMDA || insn->id == ARM_INS_LDMIB) {
479  offset++;
480  }
481  for (i = 1; i < insn->detail->arm.op_count; i++) {
482  rz_strbuf_appendf(&op->esil, "%s,%d,+,[4],%s,=,", ARG(0), (i + offset) * 4, REG(i));
483  }
484  if (insn->detail->arm.writeback) {
485  rz_strbuf_appendf(&op->esil, "%d,%s,+=,",
486  direction * (insn->detail->arm.op_count - 1) * 4, ARG(0));
487  }
488  break;
489  }
490  case ARM_INS_CMP:
491  rz_strbuf_appendf(&op->esil, "%s,%s,==", ARG(1), ARG(0));
492  break;
493  case ARM_INS_CMN:
494  rz_strbuf_appendf(&op->esil, "%s,%s,^,!,!,zf,=", ARG(1), ARG(0));
495  break;
496  case ARM_INS_MOVT:
497  rz_strbuf_appendf(&op->esil, "16,%s,<<,%s,|=", ARG(1), REG(0));
498  break;
499  case ARM_INS_ADR:
500  rz_strbuf_appendf(&op->esil, "%d,$$,+,%s,+,0xfffffffc,&,%s,=",
501  pcdelta, ARG(1), REG(0));
502  break;
503  case ARM_INS_MOV:
504  case ARM_INS_VMOV:
505  case ARM_INS_MOVW:
506  rz_strbuf_appendf(&op->esil, "%s,%s,=", ARG(1), REG(0));
507  break;
508  case ARM_INS_CBZ:
509  rz_strbuf_appendf(&op->esil, "%s,!,?{,%" PFMT32u ",pc,=,}",
510  REG(0), IMM(1));
511  break;
512  case ARM_INS_CBNZ:
513  rz_strbuf_appendf(&op->esil, "%s,?{,%" PFMT32u ",pc,=,}",
514  REG(0), IMM(1));
515  break;
516  // Encapsulated STR/H/B into a code section
517  case ARM_INS_STRT:
518  case ARM_INS_STR:
519  case ARM_INS_STRHT:
520  case ARM_INS_STRH:
521  case ARM_INS_STRBT:
522  case ARM_INS_STRB:
523  case ARM_INS_STRD:
524  // case ARM_INS_STLXRB: // capstone has no STLXR?
525  switch (insn->id) {
526  case ARM_INS_STRD:
527  str_ldr_bytes = 8; // just an indication, won't be used in esil code
528  break;
529  case ARM_INS_STRHT:
530  case ARM_INS_STRH:
531  str_ldr_bytes = 2;
532  break;
533  case ARM_INS_STRBT:
534  case ARM_INS_STRB:
535  str_ldr_bytes = 1;
536  break;
537  default:
538  str_ldr_bytes = 4;
539  }
540  if (OPCOUNT() == 2) {
541  if (ISMEM(1) && !HASMEMINDEX(1)) {
542  int disp = MEMDISP(1);
543  char sign = disp >= 0 ? '+' : '-';
544  disp = disp >= 0 ? disp : -disp;
545  rz_strbuf_appendf(&op->esil, "%s,0x%x,%s,%c,0xffffffff,&,=[%d]",
546  REG(0), disp, MEMBASE(1), sign, str_ldr_bytes);
547  if (insn->detail->arm.writeback) {
548  rz_strbuf_appendf(&op->esil, ",%d,%s,%c,%s,=",
549  disp, MEMBASE(1), sign, MEMBASE(1));
550  }
551  }
552  if (HASMEMINDEX(1)) { // e.g. 'str r2, [r3, r1]'
553  if (ISSHIFTED(1)) { // e.g. 'str r2, [r3, r1, lsl 4]'
554  switch (SHIFTTYPE(1)) {
555  case ARM_SFT_LSL:
556  rz_strbuf_appendf(&op->esil, "%s,%s,%d,%s,<<,+,0xffffffff,&,=[%d]",
557  REG(0), MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), str_ldr_bytes);
558  if (insn->detail->arm.writeback) { // e.g. 'str r2, [r3, r1, lsl 4]!'
559  rz_strbuf_appendf(&op->esil, ",%s,%d,%s,<<,+,%s,=",
560  MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), MEMBASE(1));
561  }
562  break;
563  case ARM_SFT_LSR:
564  rz_strbuf_appendf(&op->esil, "%s,%s,%d,%s,>>,+,0xffffffff,&,=[%d]",
565  REG(0), MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), str_ldr_bytes);
566  if (insn->detail->arm.writeback) {
567  rz_strbuf_appendf(&op->esil, ",%s,%d,%s,>>,+,%s,=",
568  MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), MEMBASE(1));
569  }
570  break;
571  case ARM_SFT_ASR:
572  rz_strbuf_appendf(&op->esil, "%s,%s,%d,%s,>>>>,+,0xffffffff,&,=[%d]",
573  REG(0), MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), str_ldr_bytes);
574  if (insn->detail->arm.writeback) {
575  rz_strbuf_appendf(&op->esil, ",%s,%d,%s,>>>>,+,%s,=",
576  MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), MEMBASE(1));
577  }
578  break;
579  case ARM_SFT_ROR:
580  rz_strbuf_appendf(&op->esil, "%s,%s,%d,%s,>>>,+,0xffffffff,&,=[%d]",
581  REG(0), MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), str_ldr_bytes);
582  if (insn->detail->arm.writeback) {
583  rz_strbuf_appendf(&op->esil, ",%s,%d,%s,>>>,+,%s,=",
584  MEMBASE(1), SHIFTVALUE(1), MEMINDEX(1), MEMBASE(1));
585  }
586  break;
587  case ARM_SFT_RRX: // ROR with single bit shift, using previous cf rather than new cf
588  // TODO: r2 doesn't mark this as a shift, it falls through to no shift
589  break;
590  default:
591  // Hopefully nothing here
592  break;
593  }
594  } else { // No shift
595  rz_strbuf_appendf(&op->esil, "%s,%s,%s,+,0xffffffff,&,=[%d]",
596  REG(0), MEMINDEX(1), MEMBASE(1), str_ldr_bytes);
597  if (insn->detail->arm.writeback) {
598  rz_strbuf_appendf(&op->esil, ",%s,%s,+,%s,=",
599  MEMINDEX(1), MEMBASE(1), MEMBASE(1));
600  }
601  }
602  }
603  }
604  if (OPCOUNT() == 3) { // e.g. 'str r2, [r3], 4
605  if (ISIMM(2)) { // e.g. 'str r2, [r3], 4
606  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%d,%s,+=",
607  REG(0), MEMBASE(1), str_ldr_bytes, IMM(2), MEMBASE(1));
608  }
609  if (ISREG(2)) { // e.g. 'str r2, [r3], r1
610  if (ISSHIFTED(2)) { // e.g. 'str r2, [r3], r1, lsl 4'
611  switch (SHIFTTYPE(2)) {
612  case ARM_SFT_LSL:
613  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%s,%d,%s,<<,+,%s,=",
614  REG(0), MEMBASE(1), str_ldr_bytes, MEMBASE(1), SHIFTVALUE(2), REG(2), MEMBASE(1));
615  break;
616  case ARM_SFT_LSR:
617  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%s,%d,%s,>>,+,%s,=",
618  REG(0), MEMBASE(1), str_ldr_bytes, MEMBASE(1), SHIFTVALUE(2), REG(2), MEMBASE(1));
619  break;
620  case ARM_SFT_ASR:
621  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%s,%d,%s,>>>>,+,%s,=",
622  REG(0), MEMBASE(1), str_ldr_bytes, MEMBASE(1), SHIFTVALUE(2), REG(2), MEMBASE(1));
623  break;
624  case ARM_SFT_ROR:
625  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%s,%d,%s,>>>,+,%s,=",
626  REG(0), MEMBASE(1), str_ldr_bytes, MEMBASE(1), SHIFTVALUE(2), REG(2), MEMBASE(1));
627  break;
628  case ARM_SFT_RRX:
629  // TODO
630  break;
631  default:
632  // Hopefully nothing here
633  break;
634  }
635  } else { // No shift
636  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%s,%s,+=",
637  REG(0), MEMBASE(1), str_ldr_bytes, REG(2), MEMBASE(1));
638  }
639  }
640  if (ISREG(1) && str_ldr_bytes == 8) { // e.g. 'strd r2, r3, [r4]', normally should be the only case for ISREG(1).
641  if (!HASMEMINDEX(2)) {
642  int disp = MEMDISP(2);
643  char sign = disp >= 0 ? '+' : '-';
644  disp = disp >= 0 ? disp : -disp;
645  rz_strbuf_appendf(&op->esil, "%s,%d,%s,%c,0xffffffff,&,=[4],%s,4,%d,+,%s,%c,0xffffffff,&,=[4]",
646  REG(0), disp, MEMBASE(2), sign, REG(1), disp, MEMBASE(2), sign);
647  if (insn->detail->arm.writeback) {
648  rz_strbuf_appendf(&op->esil, ",%d,%s,%c,%s,=",
649  disp, MEMBASE(2), sign, MEMBASE(2));
650  }
651  } else {
652  if (ISSHIFTED(2)) {
653  // it seems strd does not support SHIFT which is good, but have a check nonetheless
654  } else {
655  rz_strbuf_appendf(&op->esil, "%s,%s,%s,+,0xffffffff,&,=[4],%s,4,%s,+,%s,+,0xffffffff,&,=[4]",
656  REG(0), MEMINDEX(2), MEMBASE(2), REG(1), MEMINDEX(2), MEMBASE(2));
657  if (insn->detail->arm.writeback) {
658  rz_strbuf_appendf(&op->esil, ",%s,%s,+,%s,=",
659  MEMINDEX(2), MEMBASE(2), MEMBASE(2));
660  }
661  }
662  }
663  }
664  }
665  if (OPCOUNT() == 4) { // e.g. 'strd r2, r3, [r4], 4' or 'strd r2, r3, [r4], r5'
666  if (ISIMM(3)) { // e.g. 'strd r2, r3, [r4], 4'
667  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%s,4,%s,+,0xffffffff,&,=[%d],%d,%s,+=,",
668  REG(0), MEMBASE(2), str_ldr_bytes, REG(1), MEMBASE(2), str_ldr_bytes, IMM(3), MEMBASE(2));
669  }
670  if (ISREG(3)) { // e.g. 'strd r2, r3, [r4], r5'
671  if (ISSHIFTED(3)) {
672  // same as above
673  } else {
674  rz_strbuf_appendf(&op->esil, "%s,%s,0xffffffff,&,=[%d],%s,4,%s,+,0xffffffff,&,=[%d],%s,%s,+=",
675  REG(0), MEMBASE(2), str_ldr_bytes, REG(1), MEMBASE(2), str_ldr_bytes, REG(3), MEMBASE(2));
676  }
677  }
678  }
679  break;
680  case ARM_INS_TST:
681  rz_strbuf_appendf(&op->esil, "0,%s,%s,&,==", ARG(1), ARG(0));
682  break;
683  case ARM_INS_LDRD:
684  addr &= ~3LL;
685  if (MEMDISP(2) < 0) {
686  const char *pc = "$$";
687  if (REGBASE(2) == ARM_REG_PC) {
688  op->refptr = 4;
689  op->ptr = addr + pcdelta + MEMDISP(2);
690  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",2,2,%s,%d,+,>>,<<,+,0xffffffff,&,DUP,[4],%s,=,4,+,[4],%s,=",
691  (ut64)MEMDISP(2), pc, pcdelta, REG(0), REG(1));
692  } else {
693  int disp = MEMDISP(2);
694  // not refptr, because we can't grab the reg value statically op->refptr = 4;
695  if (disp < 0) {
696  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",%s,-,0xffffffff,&,DUP,[4],%s,=,4,+,[4],%s,=",
697  (ut64)-disp, MEMBASE(2), REG(0), REG(1));
698  } else {
699  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",%s,+,0xffffffff,&,DUP,[4],%s,=,4,+,[4],%s,=",
700  (ut64)disp, MEMBASE(2), REG(0), REG(1));
701  }
702  }
703  } else {
704  if (REGBASE(2) == ARM_REG_PC) {
705  const char *pc = "$$";
706  op->refptr = 4;
707  op->ptr = addr + pcdelta + MEMDISP(2);
708  if (HASMEMINDEX(2) || ISREG(2)) {
709  const char op_index = ISMEMINDEXSUB(2) ? '-' : '+';
710  rz_strbuf_appendf(&op->esil, "%s,2,2,%d,%s,+,>>,<<,%c,0xffffffff,&,DUP,[4],%s,=,4,+,[4],%s,=",
711  MEMINDEX(2), pcdelta, pc, op_index, REG(0), REG(1));
712  } else {
713  rz_strbuf_appendf(&op->esil, "2,2,%d,%s,+,>>,<<,%d,+,0xffffffff,&,DUP,[4],%s,=,4,+,[4],%s,=",
714  pcdelta, pc, MEMDISP(2), REG(0), REG(1));
715  }
716  } else {
717  if (HASMEMINDEX(2)) { // e.g. `ldrd r2, r3 [r4, r1]`
718  const char op_index = ISMEMINDEXSUB(2) ? '-' : '+';
719  rz_strbuf_appendf(&op->esil, "%s,%s,%c,0xffffffff,&,DUP,[4],%s,=,4,+,[4],%s,=",
720  MEMINDEX(2), MEMBASE(2), op_index, REG(0), REG(1));
721  } else {
722  rz_strbuf_appendf(&op->esil, "%d,%s,+,0xffffffff,&,DUP,[4],%s,=,4,+,[4],%s,=",
723  MEMDISP(2), MEMBASE(2), REG(0), REG(1));
724  }
725  if (insn->detail->arm.writeback) {
726  if (ISPOSTINDEX32()) {
727  if (ISIMM(3)) {
728  rz_strbuf_appendf(&op->esil, ",%s,%d,+,%s,=",
729  MEMBASE(2), IMM(3), MEMBASE(2));
730  } else {
731  const char op_index = ISMEMINDEXSUB(3) ? '-' : '+';
732  rz_strbuf_appendf(&op->esil, ",%s,%s,%c,%s,=",
733  REG(3), MEMBASE(2), op_index, MEMBASE(2));
734  }
735  } else if (ISPREINDEX32()) {
736  if (HASMEMINDEX(2)) {
737  const char op_index = ISMEMINDEXSUB(2) ? '-' : '+';
738  rz_strbuf_appendf(&op->esil, ",%s,%s,%c,%s,=",
739  MEMINDEX(2), MEMBASE(2), op_index, MEMBASE(2));
740  } else {
741  rz_strbuf_appendf(&op->esil, ",%s,%d,+,%s,=",
742  MEMBASE(2), MEMDISP(2), MEMBASE(2));
743  }
744  }
745  }
746  }
747  }
748  break;
749  case ARM_INS_LDRB:
750  if (ISMEM(1) && LSHIFT2(1)) {
751  rz_strbuf_appendf(&op->esil, "%s,%d,%s,<<,+,0xffffffff,&,[1],0x%x,&,%s,=",
752  MEMBASE(1), LSHIFT2(1), MEMINDEX(1), mask, REG(0));
753  } else if (HASMEMINDEX(1)) {
754  rz_strbuf_appendf(&op->esil, "%s,%s,+,0xffffffff,&,[1],%s,=",
755  MEMINDEX(1), MEMBASE(1), REG(0));
756  } else {
757  rz_strbuf_appendf(&op->esil, "%s,%d,+,[1],%s,=",
758  MEMBASE(1), MEMDISP(1), REG(0));
759  }
760  if (insn->detail->arm.writeback) {
761  if (ISIMM(2)) {
762  rz_strbuf_appendf(&op->esil, ",%s,%d,+,%s,=",
763  MEMBASE(1), IMM(2), MEMBASE(1));
764  } else {
765  rz_strbuf_appendf(&op->esil, ",%s,%d,+,%s,=",
766  MEMBASE(1), MEMDISP(1), MEMBASE(1));
767  }
768  }
769  break;
770  case ARM_INS_SXTH:
771  rz_strbuf_appendf(&op->esil,
772  "15,%s,>>,1,&,?{,15,-1,<<,%s,0xffff,&,|,%s,:=,}{,%s,0xffff,%s,:=,}",
773  REG(1), REG(1), REG(0), REG(1), REG(0));
774  break;
775  case ARM_INS_SXTB:
776  rz_strbuf_appendf(&op->esil,
777  "7,%s,>>,1,&,?{,7,-1,<<,%s,0xff,&,|,%s,:=,}{,%s,0xff,&,%s,:=,}",
778  REG(1), REG(1), REG(0), REG(1), REG(0));
779  break;
780  case ARM_INS_LDREX:
781  case ARM_INS_LDREXB:
782  case ARM_INS_LDREXD:
783  case ARM_INS_LDREXH:
785  // intentional fallthrough
786  case ARM_INS_LDRHT:
787  case ARM_INS_LDRH:
788  case ARM_INS_LDRT:
789  case ARM_INS_LDRBT:
790  case ARM_INS_LDRSB:
791  case ARM_INS_LDRSBT:
792  case ARM_INS_LDRSH:
793  case ARM_INS_LDRSHT:
794  case ARM_INS_LDR:
795  switch (insn->id) {
796  case ARM_INS_LDRHT:
797  case ARM_INS_LDRH:
798  case ARM_INS_LDRSH:
799  case ARM_INS_LDRSHT:
800  mask = UT16_MAX;
801  break;
802  default:
803  mask = UT32_MAX;
804  break;
805  }
806  addr &= ~3LL;
807  if (MEMDISP(1) < 0) {
808  const char *pc = "$$";
809  if (REGBASE(1) == ARM_REG_PC) {
810  op->refptr = 4;
811  op->ptr = addr + pcdelta + MEMDISP(1);
812  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",2,2,%s,>>,<<,+,0xffffffff,&,[4],0x%x,&,%s,=",
813  (ut64)MEMDISP(1), pc, mask, REG(0));
814  } else {
815  int disp = MEMDISP(1);
816  // not refptr, because we can't grab the reg value statically op->refptr = 4;
817  if (disp < 0) {
818  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",%s,-,0xffffffff,&,[4],0x%x,&,%s,=",
819  (ut64)-disp, MEMBASE(1), mask, REG(0));
820  } else {
821  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",%s,+,0xffffffff,&,[4],0x%x,&,%s,=",
822  (ut64)disp, MEMBASE(1), mask, REG(0));
823  }
824  }
825  } else {
826  if (ISMEM(1) && REGBASE(1) == ARM_REG_PC) {
827  const char *pc = "$$";
828  if (HASMEMINDEX(1)) {
829  if (LSHIFT2(1)) {
830  rz_strbuf_appendf(&op->esil, "2,2,%d,%s,+,>>,<<,%d,%s,<<,+,0xffffffff,&,[4],0x%x,&,%s,=",
831  pcdelta, pc, LSHIFT2(1), MEMINDEX(1), mask, REG(0));
832  } else {
833  rz_strbuf_appendf(&op->esil, "2,2,%d,%s,+,>>,<<,%s,+,0xffffffff,&,[4],0x%x,&,%s,=",
834  pcdelta, pc, MEMINDEX(1), mask, REG(0));
835  }
836  } else {
837  op->refptr = 4;
838  op->ptr = addr + pcdelta + MEMDISP(1);
839  rz_strbuf_appendf(&op->esil, "2,2,%d,%s,+,>>,<<,%d,+,0xffffffff,&,[4],0x%x,&,%s,=",
840  pcdelta, pc, MEMDISP(1), mask, REG(0));
841  }
842  } else {
843  if (ISMEM(1) && LSHIFT2(1)) {
844  rz_strbuf_appendf(&op->esil, "%s,%d,%s,<<,+,0xffffffff,&,[4],0x%x,&,%s,=",
845  MEMBASE(1), LSHIFT2(1), MEMINDEX(1), mask, REG(0));
846  } else if (HASMEMINDEX(1)) { // e.g. `ldr r2, [r3, r1]`
847  rz_strbuf_appendf(&op->esil, "%s,%s,+,0xffffffff,&,[4],0x%x,&,%s,=",
848  MEMINDEX(1), MEMBASE(1), mask, REG(0));
849  } else {
850  rz_strbuf_appendf(&op->esil, "%d,%s,+,0xffffffff,&,[4],0x%x,&,%s,=",
851  MEMDISP(1), MEMBASE(1), mask, REG(0));
852  }
853  if (insn->detail->arm.writeback) {
854  if (ISIMM(2)) {
855  rz_strbuf_appendf(&op->esil, ",%s,%d,+,%s,=",
856  MEMBASE(1), IMM(2), MEMBASE(1));
857  } else {
858  rz_strbuf_appendf(&op->esil, ",%s,%d,+,%s,=",
859  MEMBASE(1), MEMDISP(1), MEMBASE(1));
860  }
861  }
862  }
863  }
864  break;
865  case ARM_INS_MRS:
866  // TODO: esil for MRS
867  break;
868  case ARM_INS_MSR:
869  msr_flags = insn->detail->arm.operands[0].reg >> 4;
870  rz_strbuf_appendf(&op->esil, "0,");
871  if (msr_flags & 1) {
872  rz_strbuf_appendf(&op->esil, "0xFF,|,");
873  }
874  if (msr_flags & 2) {
875  rz_strbuf_appendf(&op->esil, "0xFF00,|,");
876  }
877  if (msr_flags & 4) {
878  rz_strbuf_appendf(&op->esil, "0xFF0000,|,");
879  }
880  if (msr_flags & 8) {
881  rz_strbuf_appendf(&op->esil, "0xFF000000,|,");
882  }
883  rz_strbuf_appendf(&op->esil, "DUP,!,SWAP,&,%s,SWAP,cpsr,&,|,cpsr,=", REG(1));
884  break;
885  case ARM_INS_UBFX:
886  if (IMM(3) > 0 && IMM(3) <= 32 - IMM(2)) {
887  rz_strbuf_appendf(&op->esil, "%d,%s,%d,%" PFMT64u ",<<,&,>>,%s,=",
888  IMM(2), REG(1), IMM(2), rz_num_bitmask((ut8)IMM(3)), REG(0));
889  }
890  break;
891  case ARM_INS_UXTB:
892  rz_strbuf_appendf(&op->esil, "%s,0xff,&,%s,=", ARG(1), REG(0));
893  break;
894  case ARM_INS_RSB:
895  if (OPCOUNT() == 2) {
896  rz_strbuf_appendf(&op->esil, "%s,%s,-=", ARG(0), ARG(1));
897  } else if (OPCOUNT() == 3) {
898  rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", ARG(1), ARG(2), ARG(0));
899  }
900  break;
901  case ARM_INS_BIC:
902  if (OPCOUNT() == 2) {
903  rz_strbuf_appendf(&op->esil, "%s,0xffffffff,^,%s,&=", ARG(1), ARG(0));
904  } else {
905  rz_strbuf_appendf(&op->esil, "%s,0xffffffff,^,%s,&,%s,=", ARG(2), ARG(1), ARG(0));
906  }
907  break;
908  case ARM_INS_SMMLA:
909  rz_strbuf_appendf(&op->esil, "32,%s,%s,*,>>,%s,+,0xffffffff,&,%s,=",
910  REG(1), REG(2), REG(3), REG(0));
911  break;
912  case ARM_INS_SMMLAR:
913  rz_strbuf_appendf(&op->esil, "32,0x80000000,%s,%s,*,+,>>,%s,+,0xffffffff,&,%s,=",
914  REG(1), REG(2), REG(3), REG(0));
915  break;
916  case ARM_INS_UMULL:
917  rz_strbuf_appendf(&op->esil, "32,%s,%s,*,DUP,0xffffffff,&,%s,=,>>,%s,=",
918  REG(2), REG(3), REG(0), REG(1));
919  break;
920  case ARM_INS_MLS:
921  rz_strbuf_appendf(&op->esil, "%s,%s,*,%s,-,0xffffffff,&,%s,=",
922  REG(1), REG(2), REG(3), REG(0));
923  break;
924  case ARM_INS_MLA:
925  rz_strbuf_appendf(&op->esil, "%s,%s,*,%s,+,0xffffffff,&,%s,=",
926  REG(1), REG(2), REG(3), REG(0));
927  break;
928  case ARM_INS_MVN:
929  rz_strbuf_appendf(&op->esil, "-1,%s,^,0xffffffff,&,%s,=",
930  ARG(1), REG(0));
931  break;
932  case ARM_INS_BFI: {
933  if (OPCOUNT() >= 3 && ISIMM(3) && IMM(3) > 0 && IMM(3) < 64) {
934  ut64 mask = rz_num_bitmask((ut8)IMM(3));
935  ut64 shift = IMM(2);
936  ut64 notmask = ~(mask << shift);
937  // notmask,dst,&,lsb,mask,src,&,<<,|,dst,=
938  rz_strbuf_setf(&op->esil, "%" PFMT64u ",%s,&,%" PFMT64u ",%" PFMT64u ",%s,&,<<,|,0xffffffff,&,%s,=",
939  notmask, REG(0), shift, mask, REG(1), REG(0));
940  }
941  break;
942  }
943  case ARM_INS_BFC: {
944  if (OPCOUNT() >= 2 && ISIMM(2) && IMM(2) > 0 && IMM(2) < 64) {
945  ut64 mask = rz_num_bitmask((ut8)IMM(2));
946  ut64 shift = IMM(1);
947  ut64 notmask = ~(mask << shift);
948  // notmask,dst,&,dst,=
949  rz_strbuf_setf(&op->esil, "%" PFMT64u ",%s,&,0xffffffff,&,%s,=",
950  notmask, REG(0), REG(0));
951  }
952  break;
953  }
954  case ARM_INS_REV: {
955  const char *r0 = REG(0);
956  const char *r1 = REG(1);
957  rz_strbuf_setf(&op->esil,
958  "24,0xff,%s,&,<<,%s,=,"
959  "16,0xff,8,%s,>>,&,<<,%s,|=,"
960  "8,0xff,16,%s,>>,&,<<,%s,|=,"
961  "0xff,24,%s,>>,&,%s,|=,",
962  r1, r0, r1, r0, r1, r0, r1, r0);
963  break;
964  }
965  case ARM_INS_REV16: {
966  const char *r0 = REG(0);
967  const char *r1 = REG(1);
968  rz_strbuf_setf(&op->esil,
969  "8,0xff00ff00,%s,&,>>,%s,=,"
970  "8,0x00ff00ff,%s,&,<<,%s,|=,",
971  r1, r0, r1, r0);
972  break;
973  }
974  case ARM_INS_REVSH: {
975  const char *r0 = REG(0);
976  const char *r1 = REG(1);
977  rz_strbuf_setf(&op->esil,
978  "8,0xff00,%s,&,>>,%s,=,"
979  "8,0x00ff,%s,&,<<,%s,|=,"
980  "0x8000,%s,&,?{,"
981  "0xffff0000,%s,|=,"
982  "}",
983  r1, r0, r1, r0, r0, r0);
984  break;
985  }
986  case ARM_INS_TBB:
987  rz_strbuf_appendf(&op->esil, "%s,%s,+,0xffffffff,&,DUP,[1],1,SWAP,<<,+,pc,+=",
988  MEMBASE(0), MEMINDEX(0));
989  break;
990  case ARM_INS_TBH:
991  rz_strbuf_appendf(&op->esil, "%s,%d,%s,<<,+,0xffffffff,&,[2],1,SWAP,<<,pc,+=",
992  MEMBASE(0), LSHIFT2(0), MEMINDEX(0));
993  break;
994  default:
995  break;
996  }
997  // Update flags if required...TODO different instructions update different flags, but this should fix
998  // many errors
999  if (insn->detail->arm.update_flags) {
1000  switch (insn->id) {
1001  case ARM_INS_CMP:
1002  rz_strbuf_appendf(&op->esil, ",$z,zf,:=,31,$s,nf,:=,32,$b,!,cf,:=,31,$o,vf,:=");
1003  break;
1004  case ARM_INS_ADD:
1005  case ARM_INS_RSB:
1006  case ARM_INS_SUB:
1007  case ARM_INS_SBC:
1008  case ARM_INS_ADC:
1009  case ARM_INS_CMN:
1010  rz_strbuf_appendf(&op->esil, ",$z,zf,:=,31,$s,nf,:=,31,$c,cf,:=,31,$o,vf,:=");
1011  break;
1012  default:
1013  rz_strbuf_appendf(&op->esil, ",$z,zf,:=,31,$s,nf,:=");
1014  }
1015  }
1016 
1017  rz_strbuf_append(&op->esil, postfix);
1018 
1019  return 0;
1020 }
size_t len
Definition: 6502dis.c:15
#define mask()
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
#define ISREG(x)
#define ISMEMINDEXSUB(x)
#define HASMEMINDEX(x)
#define OPCOUNT()
#define MEMDISP(x)
#define ISSHIFTED(x)
#define IMM(x)
#define REGBASE(x)
#define SHIFTVALUE(x)
#define SHIFTTYPE(x)
#define ISIMM(x)
#define LSHIFT2(x)
#define ISPREINDEX32()
#define ISMEM(x)
#define ISPOSTINDEX32()
#define REGID(x)
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
#define ARG(x)
Definition: arm_esil32.c:172
RZ_IPI int rz_arm_cs_analysis_op_32_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, bool thumb)
Definition: arm_esil32.c:239
#define DECODE_SHIFT(x)
Definition: arm_esil32.c:46
#define MEMINDEX(x)
Definition: arm_esil32.c:12
RZ_IPI const char * rz_arm_cs_esil_prefix_cond(RzAnalysisOp *op, int cond_type)
Definition: arm_esil32.c:63
static void arm32math(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, int pcdelta, char(*str)[32], const char *opchar, int negate)
Definition: arm_esil32.c:178
static unsigned int regsize32(cs_insn *insn, int n)
Definition: arm_esil32.c:48
#define REGSIZE32(x)
Definition: arm_esil32.c:60
static void arm32mathaddsub(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, int pcdelta, char(*str)[32], const char *opchar)
Definition: arm_esil32.c:216
static const char * decode_shift(arm_shifter shift)
Definition: arm_esil32.c:14
#define MATH32_NEG(opchar)
Definition: arm_esil32.c:175
#define MATH32AS(opchar)
Definition: arm_esil32.c:176
#define MATH32(opchar)
Definition: arm_esil32.c:174
#define REG(x)
Definition: arm_esil32.c:10
#define MEMBASE(x)
Definition: arm_esil32.c:11
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
Definition: arm_il32.c:190
static mcore_handle handle
Definition: asm_mcore.c:8
@ ARM_INS_TBH
Definition: arm.h:865
@ ARM_INS_ADR
Definition: arm.h:448
@ ARM_INS_VLDMIA
Definition: arm.h:755
@ ARM_INS_SADD16
Definition: arm.h:564
@ ARM_INS_LDRSH
Definition: arm.h:517
@ ARM_INS_STR
Definition: arm.h:659
@ 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_VLDMDB
Definition: arm.h:754
@ ARM_INS_STRH
Definition: arm.h:656
@ ARM_INS_ADC
Definition: arm.h:446
@ ARM_INS_ORN
Definition: arm.h:860
@ ARM_INS_BX
Definition: arm.h:460
@ ARM_INS_LDRB
Definition: arm.h:507
@ ARM_INS_SUB
Definition: arm.h:660
@ ARM_INS_IT
Definition: arm.h:857
@ ARM_INS_ASR
Definition: arm.h:853
@ ARM_INS_LDRHT
Definition: arm.h:514
@ ARM_INS_MLS
Definition: arm.h:526
@ ARM_INS_RSB
Definition: arm.h:562
@ ARM_INS_UXTB
Definition: arm.h:704
@ ARM_INS_AND
Definition: arm.h:453
@ ARM_INS_STRB
Definition: arm.h:650
@ ARM_INS_LDRSBT
Definition: arm.h:516
@ 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_BKPT
Definition: arm.h:457
@ ARM_INS_MOVT
Definition: arm.h:528
@ ARM_INS_MOV
Definition: arm.h:527
@ ARM_INS_SADD8
Definition: arm.h:565
@ ARM_INS_LDRSB
Definition: arm.h:515
@ ARM_INS_LDRBT
Definition: arm.h:506
@ ARM_INS_LDM
Definition: arm.h:504
@ ARM_INS_SMMLA
Definition: arm.h:608
@ ARM_INS_STMDB
Definition: arm.h:646
@ ARM_INS_BFI
Definition: arm.h:455
@ ARM_INS_MRS
Definition: arm.h:534
@ ARM_INS_VSTMDB
Definition: arm.h:837
@ ARM_INS_UBFX
Definition: arm.h:676
@ ARM_INS_LSL
Definition: arm.h:858
@ ARM_INS_LSR
Definition: arm.h:859
@ ARM_INS_STRBT
Definition: arm.h:649
@ ARM_INS_UMULL
Definition: arm.h:687
@ ARM_INS_BIC
Definition: arm.h:456
@ ARM_INS_STMIB
Definition: arm.h:648
@ ARM_INS_REVSH
Definition: arm.h:557
@ ARM_INS_UDF
Definition: arm.h:677
@ ARM_INS_MUL
Definition: arm.h:536
@ ARM_INS_ADDW
Definition: arm.h:852
@ ARM_INS_LDRH
Definition: arm.h:513
@ ARM_INS_CBZ
Definition: arm.h:867
@ ARM_INS_REV16
Definition: arm.h:556
@ ARM_INS_LDREXD
Definition: arm.h:511
@ ARM_INS_EOR
Definition: arm.h:479
@ ARM_INS_NOP
Definition: arm.h:872
@ ARM_INS_LDMDA
Definition: arm.h:502
@ ARM_INS_STMDA
Definition: arm.h:645
@ ARM_INS_LDREX
Definition: arm.h:509
@ ARM_INS_ADD
Definition: arm.h:447
@ ARM_INS_LDRSHT
Definition: arm.h:518
@ ARM_INS_POP
Definition: arm.h:868
@ ARM_INS_BLX
Definition: arm.h:459
@ ARM_INS_STM
Definition: arm.h:647
@ ARM_INS_LDMIB
Definition: arm.h:505
@ ARM_INS_CMN
Definition: arm.h:467
@ ARM_INS_SMMLAR
Definition: arm.h:609
@ ARM_INS_LDR
Definition: arm.h:520
@ ARM_INS_STRT
Definition: arm.h:658
@ 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_LDREXH
Definition: arm.h:512
@ ARM_INS_MVN
Definition: arm.h:537
@ ARM_INS_SVC
Definition: arm.h:661
@ ARM_INS_BFC
Definition: arm.h:454
@ ARM_INS_B
Definition: arm.h:462
@ 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_CMP
Definition: arm.h:468
@ ARM_INS_LDRD
Definition: arm.h:508
@ ARM_INS_MOVW
Definition: arm.h:529
@ ARM_INS_LDREXB
Definition: arm.h:510
@ ARM_INS_VSTMIA
Definition: arm.h:838
@ ARM_INS_STRHT
Definition: arm.h:657
@ ARM_INS_SSUB8
Definition: arm.h:633
@ ARM_INS_ORR
Definition: arm.h:538
@ ARM_INS_CLZ
Definition: arm.h:466
@ ARM_INS_MSR
Definition: arm.h:535
@ ARM_INS_SXTB
Definition: arm.h:667
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_ASR_REG
shift with register
Definition: arm.h:25
@ 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_FP
= CS_OP_FP (Floating-Point operand).
Definition: arm.h:166
@ 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_Q0
Definition: arm.h:303
@ ARM_REG_Q15
Definition: arm.h:318
@ ARM_REG_D31
Definition: arm.h:298
@ ARM_REG_PC
Definition: arm.h:264
@ ARM_REG_D0
Definition: arm.h:267
size_t csh
Definition: capstone.h:71
#define NULL
Definition: cris-opc.c:27
CAPSTONE_EXPORT const char *CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
Definition: cs.c:1154
uint32_t ut32
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
sprintf
Definition: kernel.h:365
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
char * dst
Definition: lz4.h:724
char * dest
Definition: lz4.h:697
int n
Definition: mipsasm.c:19
@ RZ_ANALYSIS_OP_FAMILY_THREAD
Definition: rz_analysis.h:318
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
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
static const char * rz_str_get_null(const char *str)
Definition: rz_str.h:190
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API const char * rz_strbuf_setf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
#define PFMT64d
Definition: rz_types.h:394
#define PFMT32u
Definition: rz_types.h:409
#define PFMT64u
Definition: rz_types.h:395
#define PFMT64x
Definition: rz_types.h:393
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT16_MAX
#define a(i)
Definition: sha256.c:41
int width
Definition: main.c:10
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int sp
Definition: z80asm.c:91
static int addr
Definition: z80asm.c:58