Rizin
unix-like reverse engineering framework and cli tools
arm_esil64.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_accessors64.h"
9 
10 #define REG64(x) rz_str_get_null(cs_reg_name(*handle, insn->detail->arm64.operands[x].reg))
11 #define MEMBASE64(x) rz_str_get_null(cs_reg_name(*handle, insn->detail->arm64.operands[x].mem.base))
12 #define MEMINDEX64(x) rz_str_get_null(cs_reg_name(*handle, insn->detail->arm64.operands[x].mem.index))
13 
14 static int arm64_reg_width(int reg) {
15  switch (reg) {
16  case ARM64_REG_W0:
17  case ARM64_REG_W1:
18  case ARM64_REG_W2:
19  case ARM64_REG_W3:
20  case ARM64_REG_W4:
21  case ARM64_REG_W5:
22  case ARM64_REG_W6:
23  case ARM64_REG_W7:
24  case ARM64_REG_W8:
25  case ARM64_REG_W9:
26  case ARM64_REG_W10:
27  case ARM64_REG_W11:
28  case ARM64_REG_W12:
29  case ARM64_REG_W13:
30  case ARM64_REG_W14:
31  case ARM64_REG_W15:
32  case ARM64_REG_W16:
33  case ARM64_REG_W17:
34  case ARM64_REG_W18:
35  case ARM64_REG_W19:
36  case ARM64_REG_W20:
37  case ARM64_REG_W21:
38  case ARM64_REG_W22:
39  case ARM64_REG_W23:
40  case ARM64_REG_W24:
41  case ARM64_REG_W25:
42  case ARM64_REG_W26:
43  case ARM64_REG_W27:
44  case ARM64_REG_W28:
45  case ARM64_REG_W29:
46  case ARM64_REG_W30:
47  return 32;
48  break;
49  default:
50  break;
51  }
52  return 64;
53 }
54 
55 static int decode_sign_ext(arm64_extender extender) {
56  switch (extender) {
57  case ARM64_EXT_UXTB:
58  case ARM64_EXT_UXTH:
59  case ARM64_EXT_UXTW:
60  case ARM64_EXT_UXTX:
61  return 0; // nothing needs to be done for unsigned
62  case ARM64_EXT_SXTB:
63  return 8;
64  case ARM64_EXT_SXTH:
65  return 16;
66  case ARM64_EXT_SXTW:
67  return 32;
68  case ARM64_EXT_SXTX:
69  return 64;
70  default:
71  break;
72  }
73 
74  return 0;
75 }
76 
77 #define EXT64(x) decode_sign_ext(insn->detail->arm64.operands[x].ext)
78 
79 static const char *decode_shift_64(arm64_shifter shift) {
80  const char *E_OP_SR = ">>";
81  const char *E_OP_SL = "<<";
82  const char *E_OP_RR = ">>>";
83  const char *E_OP_VOID = "";
84 
85  switch (shift) {
86  case ARM64_SFT_ASR:
87  case ARM64_SFT_LSR:
88  return E_OP_SR;
89 
90  case ARM64_SFT_LSL:
91  case ARM64_SFT_MSL:
92  return E_OP_SL;
93 
94  case ARM64_SFT_ROR:
95  return E_OP_RR;
96 
97  default:
98  break;
99  }
100  return E_OP_VOID;
101 }
102 
103 #define DECODE_SHIFT64(x) decode_shift_64(insn->detail->arm64.operands[x].shift.type)
104 
105 static int regsize64(cs_insn *insn, int n) {
106  unsigned int reg = insn->detail->arm64.operands[n].reg;
107  if ((reg >= ARM64_REG_S0 && reg <= ARM64_REG_S31) ||
108  (reg >= ARM64_REG_W0 && reg <= ARM64_REG_W30) ||
109  reg == ARM64_REG_WZR) {
110  return 4;
111  }
112  if (reg >= ARM64_REG_B0 && reg <= ARM64_REG_B31) {
113  return 1;
114  }
115  if (reg >= ARM64_REG_H0 && reg <= ARM64_REG_H31) {
116  return 2;
117  }
118  if (reg >= ARM64_REG_Q0 && reg <= ARM64_REG_Q31) {
119  return 16;
120  }
121  return 8;
122 }
123 
124 #define REGSIZE64(x) regsize64(insn, x)
125 
126 #define SHIFTED_REG64_APPEND(sb, n) shifted_reg64_append(sb, handle, insn, n)
127 
128 // do the sign extension here as well, but honestly this whole thing should maybe be redesigned
129 static void shifted_reg64_append(RzStrBuf *sb, csh *handle, cs_insn *insn, int n) {
130  int signext = EXT64(n);
131  const char *rn;
132 
133  if (HASMEMINDEX64(n)) {
134  rn = MEMINDEX64(n);
135  } else {
136  rn = REG64(n);
137  }
138 
139  if (LSHIFT2_64(n)) {
140  if (insn->detail->arm64.operands[n].shift.type != ARM64_SFT_ASR) {
141  if (signext) {
142  rz_strbuf_appendf(sb, "%d,%d,%s,~,%s", LSHIFT2_64(n), signext, rn, DECODE_SHIFT64(n));
143  } else {
144  rz_strbuf_appendf(sb, "%d,%s,%s", LSHIFT2_64(n), rn, DECODE_SHIFT64(n));
145  }
146  } else {
147  /* ASR: add the missing ones if negative */
148  ut8 index = LSHIFT2_64(n);
149  if (!index) {
150  return;
151  }
152  ut64 missing_ones = rz_num_bitmask(index) << (REGSIZE64(n) * 8 - LSHIFT2_64(n));
153  if (signext) {
154  rz_strbuf_appendf(sb, "%d,%d,%s,~,%s,1,%d,%s,~,<<<,1,&,?{,%" PFMT64u ",}{,0,},|",
155  LSHIFT2_64(n), signext, rn, DECODE_SHIFT64(n), signext, REG64(n), (ut64)missing_ones);
156  } else {
157  rz_strbuf_appendf(sb, "%d,%s,%s,1,%s,<<<,1,&,?{,%" PFMT64u ",}{,0,},|",
158  LSHIFT2_64(n), rn, DECODE_SHIFT64(n), rn, (ut64)missing_ones);
159  }
160  }
161  } else if (signext) {
162  rz_strbuf_appendf(sb, "%d,%s,~", signext, rn);
163  } else {
164  rz_strbuf_appendf(sb, "%s", rn);
165  }
166 }
167 
168 #define OPCALL(opchar) arm64math(a, op, addr, buf, len, handle, insn, opchar, 0)
169 #define OPCALL_NEG(opchar) arm64math(a, op, addr, buf, len, handle, insn, opchar, 1)
170 
171 // got rid of the opchar= pattern here because it caused missing operators to fail silently
172 // and makes things more complicated with very little benefit
173 static void arm64math(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, const char *opchar, int negate) {
174  const char *r0 = REG64(0);
175  const char *r1 = REG64(1);
176 
177  if (ISREG64(2)) {
178  if (LSHIFT2_64(2) || EXT64(2)) {
179  SHIFTED_REG64_APPEND(&op->esil, 2);
180  if (negate) {
181  rz_strbuf_appendf(&op->esil, ",-1,^");
182  }
183  rz_strbuf_appendf(&op->esil, ",%s,%s,%s,=", r1, opchar, r0);
184  } else {
185  const char *r2 = REG64(2);
186  if (negate) {
187  rz_strbuf_setf(&op->esil, "%s,-1,^,%s,%s,%s,=", r2, r1, opchar, r0);
188  } else {
189  rz_strbuf_setf(&op->esil, "%s,%s,%s,%s,=", r2, r1, opchar, r0);
190  }
191  }
192  } else {
193  ut64 i2 = IMM64(2) << LSHIFT2_64(2);
194  if (negate) {
195  rz_strbuf_setf(&op->esil, "%" PFMT64d ",-1,^,%s,%s,%s,=", i2, r1, opchar, r0);
196  } else {
197  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,%s,%s,=", i2, r1, opchar, r0);
198  }
199  }
200 }
201 
203  const char *postfix = NULL;
204 
205  rz_strbuf_init(&op->esil);
206  rz_strbuf_set(&op->esil, "");
207 
208  postfix = rz_arm_cs_esil_prefix_cond(op, insn->detail->arm64.cc);
209 
210  switch (insn->id) {
211  case ARM64_INS_REV:
212  // these REV* instructions were almost right, except in the cases like rev x0, x0
213  // where the use of |= caused copies of the value to be erroneously present
214  {
215  const char *r0 = REG64(0);
216  const char *r1 = REG64(1);
217  int size = REGSIZE64(1);
218 #if 0
219  rz_strbuf_setf (&op->esil,
220  "0,%s,=," // dst = 0
221  "%d," // initial counter = size
222  "DUP," // counter: size -> 0 (repeat here)
223  "DUP,1,SWAP,-,8,*," // counter to bits in source
224  "DUP,0xff,<<,%s,&,>>," // src byte moved to LSB
225  "SWAP,%d,-,8,*," // invert counter, calc dst bit
226  "SWAP,<<,%s,|=," // shift left to there and insert
227  "4,REPEAT", // goto 5th instruction
228  r0, size, r1, size, r0);
229 #endif
230  if (size == 8) {
231  rz_strbuf_setf(&op->esil,
232  "56,0xff,%s,&,<<,tmp,=,"
233  "48,0xff,8,%s,>>,&,<<,tmp,|=,"
234  "40,0xff,16,%s,>>,&,<<,tmp,|=,"
235  "32,0xff,24,%s,>>,&,<<,tmp,|=,"
236  "24,0xff,32,%s,>>,&,<<,tmp,|=,"
237  "16,0xff,40,%s,>>,&,<<,tmp,|=,"
238  "8,0xff,48,%s,>>,&,<<,tmp,|=,"
239  "0xff,56,%s,>>,&,tmp,|=,tmp,%s,=",
240  r1, r1, r1, r1,
241  r1, r1, r1, r1, r0);
242  } else {
243  rz_strbuf_setf(&op->esil,
244  "24,0xff,%s,&,<<,tmp,=,"
245  "16,0xff,8,%s,>>,&,<<,tmp,|=,"
246  "8,0xff,16,%s,>>,&,<<,tmp,|=,"
247  "0xff,24,%s,>>,&,tmp,|=,tmp,%s,=",
248  r1, r1, r1, r1, r0);
249  }
250  break;
251  }
252  case ARM64_INS_REV32: {
253  const char *r0 = REG64(0);
254  const char *r1 = REG64(1);
255  rz_strbuf_setf(&op->esil,
256  "24,0x000000ff000000ff,%s,&,<<,tmp,=,"
257  "16,0x000000ff000000ff,8,%s,>>,&,<<,tmp,|=,"
258  "8,0x000000ff000000ff,16,%s,>>,&,<<,tmp,|=,"
259  "0x000000ff000000ff,24,%s,>>,&,tmp,|=,tmp,%s,=",
260  r1, r1, r1, r1, r0);
261  break;
262  }
263  case ARM64_INS_REV16: {
264  const char *r0 = REG64(0);
265  const char *r1 = REG64(1);
266  rz_strbuf_setf(&op->esil,
267  "8,0xff00ff00ff00ff00,%s,&,>>,tmp,=,"
268  "8,0x00ff00ff00ff00ff,%s,&,<<,tmp,|=,tmp,%s,=",
269  r1, r1, r0);
270  break;
271  }
272  case ARM64_INS_ADR:
273  // TODO: must be 21bit signed
274  rz_strbuf_setf(&op->esil,
275  "%" PFMT64d ",%s,=", IMM64(1), REG64(0));
276  break;
277  case ARM64_INS_SMADDL: {
278  int size = REGSIZE64(1) * 8;
279  rz_strbuf_setf(&op->esil, "%d,%s,~,%d,%s,~,*,%s,+,%s,=",
280  size, REG64(2), size, REG64(1), REG64(3), REG64(0));
281  break;
282  }
283  case ARM64_INS_UMADDL:
284  case ARM64_INS_FMADD:
285  case ARM64_INS_MADD:
286  rz_strbuf_setf(&op->esil, "%s,%s,*,%s,+,%s,=",
287  REG64(2), REG64(1), REG64(3), REG64(0));
288  break;
289  case ARM64_INS_MSUB:
290  rz_strbuf_setf(&op->esil, "%s,%s,*,%s,-,%s,=",
291  REG64(2), REG64(1), REG64(3), REG64(0));
292  break;
293  case ARM64_INS_MNEG:
294  rz_strbuf_setf(&op->esil, "%s,%s,*,0,-,%s,=",
295  REG64(2), REG64(1), REG64(0));
296  break;
297  case ARM64_INS_ADD:
298  case ARM64_INS_ADC: // Add with carry.
299  // case ARM64_INS_ADCS: // Add with carry.
300  OPCALL("+");
301  break;
302  case ARM64_INS_SUB:
303  OPCALL("-");
304  break;
305  case ARM64_INS_SBC:
306  // TODO have to check this more, VEX does not work
307  rz_strbuf_setf(&op->esil, "%s,cf,+,%s,-,%s,=",
308  REG64(2), REG64(1), REG64(0));
309  break;
310  case ARM64_INS_SMULL: {
311  int size = REGSIZE64(1) * 8;
312  rz_strbuf_setf(&op->esil, "%d,%s,~,%d,%s,~,*,%s,=",
313  size, REG64(2), size, REG64(1), REG64(0));
314  break;
315  }
316  case ARM64_INS_MUL:
317  OPCALL("*");
318  break;
319  case ARM64_INS_AND:
320  OPCALL("&");
321  break;
322  case ARM64_INS_ORR:
323  OPCALL("|");
324  break;
325  case ARM64_INS_EOR:
326  OPCALL("^");
327  break;
328  case ARM64_INS_ORN:
329  OPCALL_NEG("|");
330  break;
331  case ARM64_INS_EON:
332  OPCALL_NEG("^");
333  break;
334  case ARM64_INS_LSR: {
335  const char *r0 = REG64(0);
336  const char *r1 = REG64(1);
337  const int size = REGSIZE64(0) * 8;
338 
339  if (ISREG64(2)) {
340  if (LSHIFT2_64(2) || EXT64(2)) {
341  SHIFTED_REG64_APPEND(&op->esil, 2);
342  rz_strbuf_appendf(&op->esil, ",%d,%%,%s,>>,%s,=", size, r1, r0);
343  } else {
344  const char *r2 = REG64(2);
345  rz_strbuf_setf(&op->esil, "%d,%s,%%,%s,>>,%s,=", size, r2, r1, r0);
346  }
347  } else {
348  ut64 i2 = IMM64(2);
349  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,>>,%s,=", i2 % (ut64)size, r1, r0);
350  }
351  break;
352  }
353  case ARM64_INS_LSL: {
354  const char *r0 = REG64(0);
355  const char *r1 = REG64(1);
356  const int size = REGSIZE64(0) * 8;
357 
358  if (ISREG64(2)) {
359  if (LSHIFT2_64(2) || EXT64(2)) {
360  SHIFTED_REG64_APPEND(&op->esil, 2);
361  rz_strbuf_appendf(&op->esil, ",%d,%%,%s,<<,%s,=", size, r1, r0);
362  } else {
363  const char *r2 = REG64(2);
364  rz_strbuf_setf(&op->esil, "%d,%s,%%,%s,<<,%s,=", size, r2, r1, r0);
365  }
366  } else {
367  ut64 i2 = IMM64(2);
368  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,<<,%s,=", i2 % (ut64)size, r1, r0);
369  }
370  break;
371  }
372  case ARM64_INS_ROR:
373  OPCALL(">>>");
374  break;
375  case ARM64_INS_NOP:
376  rz_strbuf_setf(&op->esil, ",");
377  break;
378  case ARM64_INS_FDIV:
379  break;
380  case ARM64_INS_SDIV: {
381  /* TODO: support WZR XZR to specify 32, 64bit op */
382  int size = REGSIZE64(1) * 8;
383  if (ISREG64(2)) {
384  rz_strbuf_setf(&op->esil, "%d,%s,~,%d,%s,~,~/,%s,=", size, REG64(2), size, REG64(1), REG64(0));
385  } else {
386  rz_strbuf_setf(&op->esil, "%d,%s,~,%d,%s,~,~/,%s,=", size, REG64(1), size, REG64(0), REG64(0));
387  }
388  break;
389  }
390  case ARM64_INS_UDIV:
391  /* TODO: support WZR XZR to specify 32, 64bit op */
392  if ISREG64 (2) {
393  rz_strbuf_setf(&op->esil, "%s,%s,/,%s,=", REG64(2), REG64(1), REG64(0));
394  } else {
395  rz_strbuf_setf(&op->esil, "%s,%s,/=", REG64(1), REG64(0));
396  }
397  break;
398  case ARM64_INS_BR:
399  rz_strbuf_setf(&op->esil, "%s,pc,=", REG64(0));
400  break;
401  case ARM64_INS_B:
402  /* capstone precompute resulting address, using PC + IMM */
403  rz_strbuf_appendf(&op->esil, "%" PFMT64d ",pc,=", IMM64(0));
404  break;
405  case ARM64_INS_BL:
406  rz_strbuf_setf(&op->esil, "pc,lr,=,%" PFMT64d ",pc,=", IMM64(0));
407  break;
408  case ARM64_INS_BLR:
409  rz_strbuf_setf(&op->esil, "pc,lr,=,%s,pc,=", REG64(0));
410  break;
411  case ARM64_INS_CLZ:;
412  int size = 8 * REGSIZE64(0);
413 
414  // expression is much more concise with GOTO, but GOTOs should be minimized
415  // rz_strbuf_setf (&op->esil, "%s,%s,=,0,DUP,%d,1,<<,%s,&,%d,>,&,?{,%s,=,}{,1,%s,<<=,1,+,4,GOTO,}",
416  // REG64 (1), REG64 (0), size*8 - 1, REG64 (0), REG64 (0), REG64 (0));
417 
418  /*
419  from https://en.wikipedia.org/wiki/Find_first_set modified for up to size 64
420  function clz3 (x)
421  if x = 0 return 32
422  n ← 0
423  if (x & 0xFFFF0000) = 0: n ← n + 16, x ← x << 16
424  if (x & 0xFF000000) = 0: n ← n + 8, x ← x << 8
425  if (x & 0xF0000000) = 0: n ← n + 4, x ← x << 4
426  if (x & 0xC0000000) = 0: n ← n + 2, x ← x << 2
427  if (x & 0x80000000) = 0: n ← n + 1
428  return n
429  */
430 
431  const char *r0 = REG64(0);
432  const char *r1 = REG64(1);
433 
434  if (size == 32) {
435  rz_strbuf_setf(&op->esil,
436  "%s,tmp,=,0,"
437  "tmp,0xffff0000,&,!,?{,16,tmp,<<=,16,+,},"
438  "tmp,0xff000000,&,!,?{,8,tmp,<<=,8,+,},"
439  "tmp,0xf0000000,&,!,?{,4,tmp,<<=,4,+,},"
440  "tmp,0xc0000000,&,!,?{,2,tmp,<<=,2,+,},"
441  "tmp,0x80000000,&,!,?{,1,+,},"
442  "%s,!,?{,32,%s,=,}{,%s,=,}",
443  r1, r1, r0, r0);
444  } else {
445  rz_strbuf_setf(&op->esil,
446  "%s,tmp,=,0,"
447  "tmp,0xffffffff00000000,&,!,?{,32,tmp,<<=,32,+,},"
448  "tmp,0xffff000000000000,&,!,?{,16,tmp,<<=,16,+,},"
449  "tmp,0xff00000000000000,&,!,?{,8,tmp,<<=,8,+,},"
450  "tmp,0xf000000000000000,&,!,?{,4,tmp,<<=,4,+,},"
451  "tmp,0xc000000000000000,&,!,?{,2,tmp,<<=,2,+,},"
452  "tmp,0x8000000000000000,&,!,?{,1,+,},"
453  "%s,!,?{,64,%s,=,}{,%s,=,}",
454  r1, r1, r0, r0);
455  }
456 
457  break;
458  case ARM64_INS_LDRH:
459  case ARM64_INS_LDUR:
460  case ARM64_INS_LDURB:
461  case ARM64_INS_LDURH:
462  case ARM64_INS_LDR:
463  // case ARM64_INS_LDRSB:
464  // case ARM64_INS_LDRSH:
465  case ARM64_INS_LDRB:
466  // case ARM64_INS_LDRSW:
467  // case ARM64_INS_LDURSW:
468  case ARM64_INS_LDXR:
469  case ARM64_INS_LDXRB:
470  case ARM64_INS_LDXRH:
471  case ARM64_INS_LDAXR:
472  case ARM64_INS_LDAXRB:
473  case ARM64_INS_LDAXRH:
474  case ARM64_INS_LDAR:
475  case ARM64_INS_LDARB:
476  case ARM64_INS_LDARH: {
477  int size = REGSIZE64(0);
478  switch (insn->id) {
479  case ARM64_INS_LDRB:
480  case ARM64_INS_LDARB:
481  case ARM64_INS_LDAXRB:
482  case ARM64_INS_LDXRB:
483  case ARM64_INS_LDURB:
484  size = 1;
485  break;
486  case ARM64_INS_LDRH:
487  case ARM64_INS_LDARH:
488  case ARM64_INS_LDXRH:
489  case ARM64_INS_LDAXRH:
490  case ARM64_INS_LDURH:
491  size = 2;
492  break;
493  case ARM64_INS_LDRSW:
494  case ARM64_INS_LDURSW:
495  size = 4;
496  break;
497  default:
498  break;
499  }
500 
501  if (ISMEM64(1)) {
502  if (HASMEMINDEX64(1)) {
503  if (LSHIFT2_64(1) || EXT64(1)) {
504  SHIFTED_REG64_APPEND(&op->esil, 1);
505  rz_strbuf_appendf(&op->esil, ",%s,+,[%d],%s,=", MEMBASE64(1), size, REG64(0));
506  } else {
507  rz_strbuf_appendf(&op->esil, "%s,%s,+,[%d],%s,=",
508  MEMBASE64(1), MEMINDEX64(1), size, REG64(0));
509  }
510  } else {
511  // I really don't like the DUP / tmp approach but its better than doubling the calculation
512  if (LSHIFT2_64(1)) {
513  rz_strbuf_appendf(&op->esil, "%s,%d,%" PFMT64d ",%s,+",
515  } else if ((int)MEMDISP64(1) < 0) {
516  rz_strbuf_appendf(&op->esil, "%" PFMT64d ",%s,-",
517  -(st64)MEMDISP64(1), MEMBASE64(1));
518  } else {
519  rz_strbuf_appendf(&op->esil, "%" PFMT64d ",%s,+",
520  MEMDISP64(1), MEMBASE64(1));
521  }
522 
523  rz_strbuf_append(&op->esil, ",DUP,tmp,=");
524 
525  // I assume the DUPs here previously were to handle preindexing
526  // but it was never finished?
527  if (ISPREINDEX64()) {
528  rz_strbuf_appendf(&op->esil, ",tmp,%s,=", REG64(1));
529  }
530 
531  rz_strbuf_appendf(&op->esil, ",[%d],%s,=", size, REG64(0));
532 
533  if (ISPOSTINDEX64()) {
534  if (ISREG64(2)) { // not sure if register valued post indexing exists?
535  rz_strbuf_appendf(&op->esil, ",tmp,%s,+,%s,=", REG64(2), REG64(1));
536  } else {
537  rz_strbuf_appendf(&op->esil, ",tmp,%" PFMT64d ",+,%s,=", IMM64(2), REG64(1));
538  }
539  }
540  }
541  op->refptr = 4;
542  } else {
543  if (ISREG64(1)) {
544  if (OPCOUNT64() == 2) {
545  rz_strbuf_setf(&op->esil, "%s,[%d],%s,=",
546  REG64(1), size, REG64(0));
547  } else if (OPCOUNT64() == 3) {
548  /*
549  This seems like a capstone bug:
550  instructions like
551  ldr x16, [x13, x9]
552  ldrb w2, [x19, x23]
553  are not detected as ARM64_OP_MEM type and
554  fall in this case instead.
555  */
556  if (ISREG64(2)) {
557  rz_strbuf_setf(&op->esil, "%s,%s,+,[%d],%s,=",
558  REG64(1), REG64(2), size, REG64(0));
559  }
560  }
561  } else {
562  rz_strbuf_setf(&op->esil, "%" PFMT64d ",[%d],%s,=",
563  IMM64(1), size, REG64(0));
564  }
565  }
566  break;
567  }
568  case ARM64_INS_LDRSB:
569  case ARM64_INS_LDRSH:
570  case ARM64_INS_LDRSW:
571  case ARM64_INS_LDURSB:
572  case ARM64_INS_LDURSH:
573  case ARM64_INS_LDURSW: {
574  // handle the sign extended instrs here
575  int size = REGSIZE64(0);
576  switch (insn->id) {
577  case ARM64_INS_LDRSB:
578  case ARM64_INS_LDURSB:
579  size = 1;
580  break;
581  case ARM64_INS_LDRSH:
582  case ARM64_INS_LDURSH:
583  size = 2;
584  break;
585  case ARM64_INS_LDRSW:
586  case ARM64_INS_LDURSW:
587  size = 4;
588  break;
589  default:
590  break;
591  }
592 
593  if (ISMEM64(1)) {
594  if (HASMEMINDEX64(1)) {
595  if (LSHIFT2_64(1) || EXT64(1)) {
596  rz_strbuf_appendf(&op->esil, "%d,%s,", size * 8, MEMBASE64(1));
597  SHIFTED_REG64_APPEND(&op->esil, 1);
598  rz_strbuf_appendf(&op->esil, ",+,[%d],~,%s,=", size, REG64(0));
599  } else {
600  rz_strbuf_appendf(&op->esil, "%d,%s,%s,+,[%d],~,%s,=",
601  size * 8, MEMBASE64(1), MEMINDEX64(1), size, REG64(0));
602  }
603  } else {
604  if (LSHIFT2_64(1)) {
605  rz_strbuf_appendf(&op->esil, "%d,%s,%d,%" PFMT64d ",%s",
606  size * 8, MEMBASE64(1), LSHIFT2_64(1), MEMDISP64(1), DECODE_SHIFT64(1));
607  } else if ((int)MEMDISP64(1) < 0) {
608  rz_strbuf_appendf(&op->esil, "%d,%" PFMT64d ",%s,-",
609  size * 8, -(st64)MEMDISP64(1), MEMBASE64(1));
610  } else {
611  rz_strbuf_appendf(&op->esil, "%d,%" PFMT64d ",%s,+",
612  size * 8, MEMDISP64(1), MEMBASE64(1));
613  }
614 
615  rz_strbuf_append(&op->esil, ",DUP,tmp,=");
616 
617  // I assume the DUPs here previously were to handle preindexing
618  // but it was never finished?
619  if (ISPREINDEX64()) {
620  rz_strbuf_appendf(&op->esil, ",tmp,%s,=", REG64(1));
621  }
622 
623  rz_strbuf_appendf(&op->esil, ",[%d],~,%s,=", size, REG64(0));
624 
625  if (ISPOSTINDEX64()) {
626  if (ISREG64(2)) { // not sure if register valued post indexing exists?
627  rz_strbuf_appendf(&op->esil, ",tmp,%s,+,%s,=", REG64(2), REG64(1));
628  } else {
629  rz_strbuf_appendf(&op->esil, ",tmp,%" PFMT64d ",+,%s,=", IMM64(2), REG64(1));
630  }
631  }
632  }
633  op->refptr = 4;
634  } else {
635  if (ISREG64(1)) {
636  if (OPCOUNT64() == 2) {
637  rz_strbuf_setf(&op->esil, "%d,%s,[%d],~,%s,=",
638  size * 8, REG64(1), size, REG64(0));
639  } else if (OPCOUNT64() == 3) {
640  /*
641  This seems like a capstone bug:
642  instructions like
643  ldr x16, [x13, x9]
644  ldrb w2, [x19, x23]
645  are not detected as ARM64_OP_MEM type and
646  fall in this case instead.
647  */
648  if (ISREG64(2)) {
649  rz_strbuf_setf(&op->esil, "%d,%s,%s,+,[%d],~,%s,=",
650  size * 8, REG64(1), REG64(2), size, REG64(0));
651  }
652  }
653  } else {
654  rz_strbuf_setf(&op->esil, "%d,%" PFMT64d ",[%d],~,%s,=",
655  size * 8, IMM64(1), size, REG64(0));
656  }
657  }
658  break;
659  }
660  case ARM64_INS_FCMP:
661  case ARM64_INS_CCMP:
662  case ARM64_INS_CCMN:
663  case ARM64_INS_TST: // cmp w8, 0xd
664  case ARM64_INS_CMP: // cmp w8, 0xd
665  case ARM64_INS_CMN: // cmp w8, 0xd
666  {
667  // update esil, cpu flags
668  int bits = arm64_reg_width(REGID64(0));
669  if (ISIMM64(1)) {
670  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,==,$z,zf,:=,%d,$s,nf,:=,%d,$b,!,cf,:=,%d,$o,vf,:=", IMM64(1) << LSHIFT2_64(1), REG64(0), bits - 1, bits, bits - 1);
671  } else {
672  // cmp w10, w11
673  SHIFTED_REG64_APPEND(&op->esil, 1);
674  rz_strbuf_appendf(&op->esil, ",%s,==,$z,zf,:=,%d,$s,nf,:=,%d,$b,!,cf,:=,%d,$o,vf,:=", REG64(0), bits - 1, bits, bits - 1);
675  }
676  break;
677  }
678  case ARM64_INS_FCSEL:
679  case ARM64_INS_CSEL: // csel Wd, Wn, Wm --> Wd := (cond) ? Wn : Wm
680  rz_strbuf_appendf(&op->esil, "%s,}{,%s,},%s,=", REG64(1), REG64(2), REG64(0));
681  postfix = "";
682  break;
683  case ARM64_INS_CSET: // cset Wd --> Wd := (cond) ? 1 : 0
684  rz_strbuf_appendf(&op->esil, "1,}{,0,},%s,=", REG64(0));
685  postfix = "";
686  break;
687  case ARM64_INS_CINC: // cinc Wd, Wn --> Wd := (cond) ? (Wn+1) : Wn
688  rz_strbuf_appendf(&op->esil, "1,%s,+,}{,%s,},%s,=", REG64(1), REG64(1), REG64(0));
689  postfix = "";
690  break;
691  case ARM64_INS_CSINC: // csinc Wd, Wn, Wm --> Wd := (cond) ? Wn : (Wm+1)
692  rz_strbuf_appendf(&op->esil, "%s,}{,1,%s,+,},%s,=", REG64(1), REG64(2), REG64(0));
693  postfix = "";
694  break;
695  case ARM64_INS_STXRB:
696  case ARM64_INS_STXRH:
697  case ARM64_INS_STXR: {
698  int size = REGSIZE64(1);
699  if (insn->id == ARM64_INS_STXRB) {
700  size = 1;
701  } else if (insn->id == ARM64_INS_STXRH) {
702  size = 2;
703  }
704  rz_strbuf_setf(&op->esil, "0,%s,=,%s,%s,%" PFMT64d ",+,=[%d]",
705  REG64(0), REG64(1), MEMBASE64(1), MEMDISP64(1), size);
706  break;
707  }
708  case ARM64_INS_STRB:
709  case ARM64_INS_STRH:
710  case ARM64_INS_STUR:
711  case ARM64_INS_STURB:
712  case ARM64_INS_STURH:
713  case ARM64_INS_STR: // str x6, [x6,0xf90]
714  {
715  int size = REGSIZE64(0);
716  if (insn->id == ARM64_INS_STRB || insn->id == ARM64_INS_STURB) {
717  size = 1;
718  } else if (insn->id == ARM64_INS_STRH || insn->id == ARM64_INS_STURH) {
719  size = 2;
720  }
721  if (ISMEM64(1)) {
722  if (HASMEMINDEX64(1)) {
723  if (LSHIFT2_64(1) || EXT64(1)) {
724  rz_strbuf_appendf(&op->esil, "%s,%s,", REG64(0), MEMBASE64(1));
725  SHIFTED_REG64_APPEND(&op->esil, 1);
726  rz_strbuf_appendf(&op->esil, ",+,=[%d]", size);
727  } else {
728  rz_strbuf_appendf(&op->esil, "%s,%s,%s,+,=[%d]",
729  REG64(0), MEMBASE64(1), MEMINDEX64(1), size);
730  }
731  } else {
732  if (LSHIFT2_64(1)) {
733  rz_strbuf_appendf(&op->esil, "%s,%s,%d,%" PFMT64d ",%s,+",
734  REG64(0), MEMBASE64(1), LSHIFT2_64(1), MEMDISP64(1), DECODE_SHIFT64(1));
735  } else if ((int)MEMDISP64(1) < 0) {
736  rz_strbuf_appendf(&op->esil, "%s,%" PFMT64d ",%s,-",
737  REG64(0), -(st64)MEMDISP64(1), MEMBASE64(1));
738  } else {
739  rz_strbuf_appendf(&op->esil, "%s,%" PFMT64d ",%s,+",
740  REG64(0), MEMDISP64(1), MEMBASE64(1));
741  }
742 
743  rz_strbuf_append(&op->esil, ",DUP,tmp,=");
744 
745  // I assume the DUPs here previously were to handle preindexing
746  // but it was never finished?
747  if (ISPREINDEX64()) {
748  rz_strbuf_appendf(&op->esil, ",tmp,%s,=", REG64(1));
749  }
750 
751  rz_strbuf_appendf(&op->esil, ",=[%d]", size);
752 
753  if (ISPOSTINDEX64()) {
754  if (ISREG64(2)) { // not sure if register valued post indexing exists?
755  rz_strbuf_appendf(&op->esil, ",tmp,%s,+,%s,=", REG64(2), REG64(1));
756  } else {
757  rz_strbuf_appendf(&op->esil, ",tmp,%" PFMT64d ",+,%s,=", IMM64(2), REG64(1));
758  }
759  }
760  }
761  op->refptr = 4;
762  } else {
763  if (ISREG64(1)) {
764  if (OPCOUNT64() == 2) {
765  rz_strbuf_setf(&op->esil, "%s,%s,=[%d]",
766  REG64(0), REG64(1), size);
767  } else if (OPCOUNT64() == 3) {
768  /*
769  This seems like a capstone bug:
770  instructions like
771  ldr x16, [x13, x9]
772  ldrb w2, [x19, x23]
773  are not detected as ARM64_OP_MEM type and
774  fall in this case instead.
775  */
776  if (ISREG64(2)) {
777  rz_strbuf_setf(&op->esil, "%s,%s,%s,+,=[%d]",
778  REG64(0), REG64(1), REG64(2), size);
779  }
780  }
781  } else {
782  rz_strbuf_setf(&op->esil, "%s,%" PFMT64d ",=[%d]",
783  REG64(0), IMM64(1), size);
784  }
785  }
786  break;
787  }
788  case ARM64_INS_BIC:
789  if (OPCOUNT64() == 2) {
790  if (REGSIZE64(0) == 4) {
791  rz_strbuf_appendf(&op->esil, "%s,0xffffffff,^,%s,&=", REG64(1), REG64(0));
792  } else {
793  rz_strbuf_appendf(&op->esil, "%s,0xffffffffffffffff,^,%s,&=", REG64(1), REG64(0));
794  }
795  } else {
796  if (REGSIZE64(0) == 4) {
797  rz_strbuf_appendf(&op->esil, "%s,0xffffffff,^,%s,&,%s,=", REG64(2), REG64(1), REG64(0));
798  } else {
799  rz_strbuf_appendf(&op->esil, "%s,0xffffffffffffffff,^,%s,&,%s,=", REG64(2), REG64(1), REG64(0));
800  }
801  }
802  break;
803  case ARM64_INS_CBZ:
804  rz_strbuf_setf(&op->esil, "%s,!,?{,%" PFMT64d ",pc,=,}",
805  REG64(0), IMM64(1));
806  break;
807  case ARM64_INS_CBNZ:
808  rz_strbuf_setf(&op->esil, "%s,?{,%" PFMT64d ",pc,=,}",
809  REG64(0), IMM64(1));
810  break;
811  case ARM64_INS_TBZ:
812  // tbnz x0, 4, label
813  // if ((1<<4) & x0) goto label;
814  rz_strbuf_setf(&op->esil, "%" PFMT64d ",1,<<,%s,&,!,?{,%" PFMT64d ",pc,=,}",
815  IMM64(1), REG64(0), IMM64(2));
816  break;
817  case ARM64_INS_TBNZ:
818  // tbnz x0, 4, label
819  // if ((1<<4) & x0) goto label;
820  rz_strbuf_setf(&op->esil, "%" PFMT64d ",1,<<,%s,&,?{,%" PFMT64d ",pc,=,}",
821  IMM64(1), REG64(0), IMM64(2));
822  break;
823  case ARM64_INS_STNP:
824  case ARM64_INS_STP: // stp x6, x7, [x6,0xf90]
825  {
826  int disp = (int)MEMDISP64(2);
827  char sign = disp >= 0 ? '+' : '-';
828  ut64 abs = disp >= 0 ? MEMDISP64(2) : -MEMDISP64(2);
829  int size = REGSIZE64(0);
830  // Pre-index case
831  if (ISPREINDEX64()) {
832  // "stp x2, x3, [x8, 0x20]!
833  // "32,x8,+=,x2,x8,=[8],x3,x8,8,+,=[8]",
834  rz_strbuf_setf(&op->esil,
835  "%" PFMT64d ",%s,%c=,%s,%s,=[%d],%s,%s,%d,+,=[%d]",
836  abs, MEMBASE64(2), sign,
837  REG64(0), MEMBASE64(2), size,
838  REG64(1), MEMBASE64(2), size, size);
839  // Post-index case
840  } else if (ISPOSTINDEX64()) {
841  int val = IMM64(3);
842  sign = val >= 0 ? '+' : '-';
843  abs = val >= 0 ? val : -val;
844  // "stp x4, x5, [x8], 0x10"
845  // "x4,x8,=[],x5,x8,8,+,=[],16,x8,+="
846  rz_strbuf_setf(&op->esil,
847  "%s,%s,=[%d],%s,%s,%d,+,=[%d],%" PFMT64d ",%s,%c=",
848  REG64(0), MEMBASE64(2), size,
849  REG64(1), MEMBASE64(2), size, size,
850  abs, MEMBASE64(2), sign);
851  // Everything else
852  } else {
853  rz_strbuf_setf(&op->esil,
854  "%s,%s,%" PFMT64d ",%c,=[%d],"
855  "%s,%s,%" PFMT64d ",%c,%d,+,=[%d]",
856  REG64(0), MEMBASE64(2), abs, sign, size,
857  REG64(1), MEMBASE64(2), abs, sign, size, size);
858  }
859  } break;
860  case ARM64_INS_LDP: // ldp x29, x30, [sp], 0x10
861  {
862  int disp = (int)MEMDISP64(2);
863  char sign = disp >= 0 ? '+' : '-';
864  ut64 abs = disp >= 0 ? MEMDISP64(2) : -MEMDISP64(2);
865  int size = REGSIZE64(0);
866  // Pre-index case
867  // x2,x8,32,+,=[8],x3,x8,32,+,8,+,=[8]
868  if (ISPREINDEX64()) {
869  // "ldp x0, x1, [x8, -0x10]!"
870  // 16,x8,-=,x8,[8],x0,=,x8,8,+,[8],x1,=
871  rz_strbuf_setf(&op->esil,
872  "%" PFMT64d ",%s,%c=,"
873  "%s,[%d],%s,=,"
874  "%d,%s,+,[%d],%s,=",
875  abs, MEMBASE64(2), sign,
876  MEMBASE64(2), size, REG64(0),
877  size, MEMBASE64(2), size, REG64(1));
878  // Post-index case
879  } else if (ISPOSTINDEX64()) {
880  int val = IMM64(3);
881  sign = val >= 0 ? '+' : '-';
882  abs = val >= 0 ? val : -val;
883  // ldp x4, x5, [x8], -0x10
884  // x8,[8],x4,=,x8,8,+,[8],x5,=,16,x8,+=
885  rz_strbuf_setf(&op->esil,
886  "%s,[%d],%s,=,"
887  "%s,%d,+,[%d],%s,=,"
888  "%" PFMT64d ",%s,%c=",
889  MEMBASE64(2), size, REG64(0),
890  MEMBASE64(2), size, size, REG64(1),
891  abs, MEMBASE64(2), sign);
892  } else {
893  rz_strbuf_setf(&op->esil,
894  "%" PFMT64d ",%s,%c,[%d],%s,=,"
895  "%d,%" PFMT64d ",%s,%c,+,[%d],%s,=",
896  abs, MEMBASE64(2), sign, size, REG64(0),
897  size, abs, MEMBASE64(2), sign, size, REG64(1));
898  }
899  } break;
900  case ARM64_INS_ADRP:
901  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,=",
902  IMM64(1), REG64(0));
903  break;
904  case ARM64_INS_MOV:
905  if (ISREG64(1)) {
906  rz_strbuf_setf(&op->esil, "%s,%s,=", REG64(1), REG64(0));
907  } else {
908  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,=", IMM64(1), REG64(0));
909  }
910  break;
911  case ARM64_INS_EXTR:
912  // from VEX
913  /*
914  01 | t0 = GET:I64(x4)
915  02 | t1 = GET:I64(x0)
916  03 | t4 = Shr64(t1,0x20)
917  04 | t5 = Shl64(t0,0x20)
918  05 | t3 = Or64(t5,t4)
919  06 | PUT(x4) = t3
920  */
921  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,>>,%" PFMT64d ",%s,<<,|,%s,=",
922  IMM64(3), REG64(2), IMM64(3), REG64(1), REG64(0));
923  break;
924  case ARM64_INS_RBIT:
925  // this expression reverses the bits. it does. do not scroll right.
926  // Derived from VEX
927  rz_strbuf_setf(&op->esil, "0xffffffff00000000,0x20,0xffff0000ffff0000,0x10,0xff00ff00ff00ff00,0x8,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,<<,&,0x8,0xff00ff00ff00ff00,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,&,>>,|,<<,&,0x10,0xffff0000ffff0000,0xff00ff00ff00ff00,0x8,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,<<,&,0x8,0xff00ff00ff00ff00,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,&,>>,|,&,>>,|,<<,&,0x20,0xffffffff00000000,0xffff0000ffff0000,0x10,0xff00ff00ff00ff00,0x8,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,<<,&,0x8,0xff00ff00ff00ff00,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,&,>>,|,<<,&,0x10,0xffff0000ffff0000,0xff00ff00ff00ff00,0x8,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,<<,&,0x8,0xff00ff00ff00ff00,0xf0f0f0f0f0f0f0f0,0x4,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,<<,&,0x4,0xf0f0f0f0f0f0f0f0,0xcccccccccccccccc,0x2,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,<<,&,0x2,0xcccccccccccccccc,0xaaaaaaaaaaaaaaaa,0x1,%1$s,<<,&,0x1,0xaaaaaaaaaaaaaaaa,%1$s,&,>>,|,&,>>,|,&,>>,|,&,>>,|,&,>>,|,&,>>,|,%2$s,=",
928  REG64(1), REG64(0));
929  break;
930  case ARM64_INS_MVN:
931  case ARM64_INS_MOVN:
932  if (ISREG64(1)) {
933  rz_strbuf_setf(&op->esil, "%d,%s,-1,^,<<,%s,=", LSHIFT2_64(1), REG64(1), REG64(0));
934  } else {
935  rz_strbuf_setf(&op->esil, "%d,%" PFMT64d ",<<,-1,^,%s,=", LSHIFT2_64(1), IMM64(1), REG64(0));
936  }
937  break;
938  case ARM64_INS_MOVK: // movk w8, 0x1290
939  {
940  ut64 shift = LSHIFT2_64(1);
941  if (shift < 0) {
942  shift = 0;
943  } else if (shift > 48) {
944  shift = 48;
945  }
946  ut64 shifted_imm = IMM64(1) << shift;
947  ut64 mask = ~(0xffffLL << shift);
948 
949  rz_strbuf_setf(&op->esil, "0x%" PFMT64x ",%s,&,%" PFMT64u ",|,%s,=",
950  mask,
951  REG64(0),
952  shifted_imm,
953  REG64(0));
954 
955  break;
956  }
957  case ARM64_INS_MOVZ:
958  rz_strbuf_setf(&op->esil, "%" PFMT64u ",%s,=",
959  IMM64(1) << LSHIFT2_64(1),
960  REG64(0));
961  break;
962  /* ASR, SXTB, SXTH and SXTW are alias for SBFM */
963  case ARM64_INS_ASR: {
964  // OPCALL(">>>>");
965  const char *r0 = REG64(0);
966  const char *r1 = REG64(1);
967  const int size = REGSIZE64(0) * 8;
968 
969  if (ISREG64(2)) {
970  if (LSHIFT2_64(2)) {
971  SHIFTED_REG64_APPEND(&op->esil, 2);
972  rz_strbuf_appendf(&op->esil, ",%d,%%,%s,>>>>,%s,=", size, r1, r0);
973  } else {
974  const char *r2 = REG64(2);
975  rz_strbuf_setf(&op->esil, "%d,%s,%%,%s,>>>>,%s,=", size, r2, r1, r0);
976  }
977  } else {
978  ut64 i2 = IMM64(2);
979  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,>>>>,%s,=", i2 % (ut64)size, r1, r0);
980  }
981  break;
982  }
983  case ARM64_INS_SXTB:
984  if (arm64_reg_width(REGID64(0)) == 32) {
985  rz_strbuf_setf(&op->esil, "0xffffffff,8,0xff,%s,&,~,&,%s,=",
986  REG64(1), REG64(0));
987  } else {
988  rz_strbuf_setf(&op->esil, "8,0xff,%s,&,~,%s,=",
989  REG64(1), REG64(0));
990  }
991  break;
992  case ARM64_INS_SXTH: /* halfword */
993  if (arm64_reg_width(REGID64(0)) == 32) {
994  rz_strbuf_setf(&op->esil, "0xffffffff,16,0xffff,%s,&,~,&,%s,=",
995  REG64(1), REG64(0));
996  } else {
997  rz_strbuf_setf(&op->esil, "16,0xffff,%s,&,~,%s,=",
998  REG64(1), REG64(0));
999  }
1000  break;
1001  case ARM64_INS_SXTW: /* word */
1002  rz_strbuf_setf(&op->esil, "32,0xffffffff,%s,&,~,%s,=",
1003  REG64(1), REG64(0));
1004  break;
1005  case ARM64_INS_UXTB:
1006  rz_strbuf_setf(&op->esil, "%s,0xff,&,%s,=", REG64(1), REG64(0));
1007  break;
1008  case ARM64_INS_UMULL:
1009  rz_strbuf_setf(&op->esil, "%s,%s,*,%s,=", REG64(1), REG64(2), REG64(0));
1010  break;
1011  case ARM64_INS_UXTH:
1012  rz_strbuf_setf(&op->esil, "%s,0xffff,&,%s,=", REG64(1), REG64(0));
1013  break;
1014  case ARM64_INS_RET:
1015  rz_strbuf_setf(&op->esil, "lr,pc,=");
1016  break;
1017  case ARM64_INS_ERET:
1018  rz_strbuf_setf(&op->esil, "lr,pc,=");
1019  break;
1020  case ARM64_INS_BFI: // bfi w8, w8, 2, 1
1021  case ARM64_INS_BFXIL: {
1022  if (OPCOUNT64() >= 3 && ISIMM64(3) && IMM64(3) > 0) {
1023  ut64 mask = rz_num_bitmask((ut8)IMM64(3));
1024  ut64 shift = IMM64(2);
1025  ut64 notmask = ~(mask << shift);
1026  // notmask,dst,&,lsb,mask,src,&,<<,|,dst,=
1027  rz_strbuf_setf(&op->esil, "%" PFMT64u ",%s,&,%" PFMT64u ",%" PFMT64u ",%s,&,<<,|,%s,=",
1028  notmask, REG64(0), shift, mask, REG64(1), REG64(0));
1029  }
1030  break;
1031  }
1032  case ARM64_INS_SBFIZ:
1033  if (IMM64(3) > 0 && IMM64(3) <= 64 - IMM64(2)) {
1034  rz_strbuf_appendf(&op->esil, "%" PFMT64d ",%" PFMT64d ",%s,%" PFMT64u ",&,~,<<,%s,=",
1035  IMM64(2), IMM64(3), REG64(1), rz_num_bitmask((ut8)IMM64(3)), REG64(0));
1036  }
1037  break;
1038  case ARM64_INS_UBFIZ:
1039  if (IMM64(3) > 0 && IMM64(3) <= 64 - IMM64(2)) {
1040  rz_strbuf_appendf(&op->esil, "%" PFMT64d ",%s,%" PFMT64u ",&,<<,%s,=",
1041  IMM64(2), REG64(1), rz_num_bitmask((ut8)IMM64(3)), REG64(0));
1042  }
1043  break;
1044  case ARM64_INS_SBFX:
1045  if (IMM64(3) > 0 && IMM64(3) <= 64 - IMM64(2)) {
1046  rz_strbuf_appendf(&op->esil, "%" PFMT64d ",%" PFMT64d ",%s,%" PFMT64d ",%" PFMT64u ",<<,&,>>,~,%s,=",
1047  IMM64(3), IMM64(2), REG64(1), IMM64(2), rz_num_bitmask((ut8)IMM64(3)), REG64(0));
1048  }
1049  break;
1050  case ARM64_INS_UBFX:
1051  if (IMM64(3) > 0 && IMM64(3) <= 64 - IMM64(2)) {
1052  rz_strbuf_appendf(&op->esil, "%" PFMT64d ",%s,%" PFMT64d ",%" PFMT64u ",<<,&,>>,%s,=",
1053  IMM64(2), REG64(1), IMM64(2), rz_num_bitmask((ut8)IMM64(3)), REG64(0));
1054  }
1055  break;
1056  case ARM64_INS_NEG:
1057 #if CS_API_MAJOR > 3
1058  case ARM64_INS_NEGS:
1059 #endif
1060  if (LSHIFT2_64(1)) {
1061  SHIFTED_REG64_APPEND(&op->esil, 1);
1062  } else {
1063  rz_strbuf_appendf(&op->esil, "%s", REG64(1));
1064  }
1065  rz_strbuf_appendf(&op->esil, ",0,-,%s,=", REG64(0));
1066  break;
1067  case ARM64_INS_SVC:
1068  rz_strbuf_setf(&op->esil, "%" PFMT64u ",$", IMM64(0));
1069  break;
1070  }
1071 
1072  rz_strbuf_append(&op->esil, postfix);
1073 
1074  return 0;
1075 }
size_t len
Definition: 6502dis.c:15
#define mask()
#define RZ_IPI
Definition: analysis_wasm.c:11
r2
Definition: arm-aliases.s.cs:2
#define OPCOUNT64()
#define IMM64(x)
#define REGID64(x)
#define LSHIFT2_64(x)
#define ISMEM64(x)
#define HASMEMINDEX64(x)
#define ISREG64(x)
#define MEMDISP64(x)
#define ISPREINDEX64()
#define ISIMM64(x)
#define ISPOSTINDEX64()
RZ_IPI const char * rz_arm_cs_esil_prefix_cond(RzAnalysisOp *op, int cond_type)
Definition: arm_esil32.c:63
static int decode_sign_ext(arm64_extender extender)
Definition: arm_esil64.c:55
#define OPCALL_NEG(opchar)
Definition: arm_esil64.c:169
#define OPCALL(opchar)
Definition: arm_esil64.c:168
static void shifted_reg64_append(RzStrBuf *sb, csh *handle, cs_insn *insn, int n)
Definition: arm_esil64.c:129
#define MEMBASE64(x)
Definition: arm_esil64.c:11
static void arm64math(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn, const char *opchar, int negate)
Definition: arm_esil64.c:173
static int regsize64(cs_insn *insn, int n)
Definition: arm_esil64.c:105
#define DECODE_SHIFT64(x)
Definition: arm_esil64.c:103
#define REG64(x)
Definition: arm_esil64.c:10
#define MEMINDEX64(x)
Definition: arm_esil64.c:12
static const char * decode_shift_64(arm64_shifter shift)
Definition: arm_esil64.c:79
#define EXT64(x)
Definition: arm_esil64.c:77
#define SHIFTED_REG64_APPEND(sb, n)
Definition: arm_esil64.c:126
#define REGSIZE64(x)
Definition: arm_esil64.c:124
RZ_IPI int rz_arm_cs_analysis_op_64_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn)
Definition: arm_esil64.c:202
static int arm64_reg_width(int reg)
Definition: arm_esil64.c:14
static RZ_NULLABLE RzILOpBitVector * shift(RzILOpBitVector *val, RZ_NULLABLE RzILOpBool **carry_out, arm_shifter type, RZ_OWN RzILOpBitVector *dist)
Definition: arm_il32.c:190
ut16 val
Definition: armass64_const.h:6
static mcore_handle handle
Definition: asm_mcore.c:8
static SblHeader sb
Definition: bin_mbn.c:26
int bits(struct state *s, int need)
Definition: blast.c:72
arm64_shifter
ARM64 shift type.
Definition: arm64.h:18
@ ARM64_SFT_LSL
Definition: arm64.h:20
@ ARM64_SFT_LSR
Definition: arm64.h:22
@ ARM64_SFT_ASR
Definition: arm64.h:23
@ ARM64_SFT_ROR
Definition: arm64.h:24
@ ARM64_SFT_MSL
Definition: arm64.h:21
@ ARM64_REG_W21
Definition: arm64.h:538
@ ARM64_REG_W29
Definition: arm64.h:546
@ ARM64_REG_W17
Definition: arm64.h:534
@ ARM64_REG_W2
Definition: arm64.h:519
@ ARM64_REG_W0
Definition: arm64.h:517
@ ARM64_REG_W11
Definition: arm64.h:528
@ ARM64_REG_W5
Definition: arm64.h:522
@ ARM64_REG_B0
Definition: arm64.h:357
@ ARM64_REG_W12
Definition: arm64.h:529
@ ARM64_REG_W7
Definition: arm64.h:524
@ ARM64_REG_H31
Definition: arm64.h:452
@ ARM64_REG_W20
Definition: arm64.h:537
@ ARM64_REG_W15
Definition: arm64.h:532
@ ARM64_REG_S0
Definition: arm64.h:485
@ ARM64_REG_W9
Definition: arm64.h:526
@ ARM64_REG_W14
Definition: arm64.h:531
@ ARM64_REG_B31
Definition: arm64.h:388
@ ARM64_REG_W23
Definition: arm64.h:540
@ ARM64_REG_H0
Definition: arm64.h:421
@ ARM64_REG_W8
Definition: arm64.h:525
@ ARM64_REG_W16
Definition: arm64.h:533
@ ARM64_REG_S31
Definition: arm64.h:516
@ ARM64_REG_W24
Definition: arm64.h:541
@ ARM64_REG_W3
Definition: arm64.h:520
@ ARM64_REG_W30
Definition: arm64.h:547
@ ARM64_REG_Q31
Definition: arm64.h:484
@ ARM64_REG_W10
Definition: arm64.h:527
@ ARM64_REG_W1
Definition: arm64.h:518
@ ARM64_REG_Q0
Definition: arm64.h:453
@ ARM64_REG_WZR
Definition: arm64.h:355
@ ARM64_REG_W6
Definition: arm64.h:523
@ ARM64_REG_W25
Definition: arm64.h:542
@ ARM64_REG_W4
Definition: arm64.h:521
@ ARM64_REG_W28
Definition: arm64.h:545
@ ARM64_REG_W27
Definition: arm64.h:544
@ ARM64_REG_W22
Definition: arm64.h:539
@ ARM64_REG_W26
Definition: arm64.h:543
@ ARM64_REG_W19
Definition: arm64.h:536
@ ARM64_REG_W18
Definition: arm64.h:535
@ ARM64_REG_W13
Definition: arm64.h:530
arm64_extender
ARM64 extender type.
Definition: arm64.h:28
@ ARM64_EXT_SXTW
Definition: arm64.h:36
@ ARM64_EXT_UXTB
Definition: arm64.h:30
@ ARM64_EXT_UXTW
Definition: arm64.h:32
@ ARM64_EXT_SXTH
Definition: arm64.h:35
@ ARM64_EXT_SXTB
Definition: arm64.h:34
@ ARM64_EXT_UXTX
Definition: arm64.h:33
@ ARM64_EXT_UXTH
Definition: arm64.h:31
@ ARM64_EXT_SXTX
Definition: arm64.h:37
@ ARM64_INS_BFI
Definition: arm64.h:1110
@ ARM64_INS_LDAR
Definition: arm64.h:828
@ ARM64_INS_STNP
Definition: arm64.h:1000
@ ARM64_INS_AND
Definition: arm64.h:687
@ ARM64_INS_CSINC
Definition: arm64.h:725
@ ARM64_INS_NOP
Definition: arm64.h:1099
@ ARM64_INS_MVN
Definition: arm64.h:1113
@ ARM64_INS_LDURH
Definition: arm64.h:851
@ ARM64_INS_RBIT
Definition: arm64.h:884
@ ARM64_INS_CCMN
Definition: arm64.h:701
@ ARM64_INS_TBNZ
Definition: arm64.h:1023
@ ARM64_INS_ORN
Definition: arm64.h:875
@ ARM64_INS_STUR
Definition: arm64.h:1009
@ ARM64_INS_LDRH
Definition: arm64.h:838
@ ARM64_INS_LDARH
Definition: arm64.h:827
@ ARM64_INS_ADC
Definition: arm64.h:675
@ ARM64_INS_ERET
Definition: arm64.h:737
@ ARM64_INS_SXTH
Definition: arm64.h:1121
@ ARM64_INS_SVC
Definition: arm64.h:1019
@ ARM64_INS_LDAXRB
Definition: arm64.h:830
@ ARM64_INS_CMN
Definition: arm64.h:1112
@ ARM64_INS_EON
Definition: arm64.h:735
@ ARM64_INS_CSEL
Definition: arm64.h:724
@ ARM64_INS_REV32
Definition: arm64.h:887
@ ARM64_INS_CCMP
Definition: arm64.h:702
@ ARM64_INS_UMADDL
Definition: arm64.h:1046
@ ARM64_INS_RET
Definition: arm64.h:885
@ ARM64_INS_TBZ
Definition: arm64.h:1025
@ ARM64_INS_LDXRH
Definition: arm64.h:857
@ ARM64_INS_FMADD
Definition: arm64.h:774
@ ARM64_INS_LDRSW
Definition: arm64.h:841
@ ARM64_INS_LDAXRH
Definition: arm64.h:831
@ ARM64_INS_STXR
Definition: arm64.h:1014
@ ARM64_INS_LDARB
Definition: arm64.h:826
@ ARM64_INS_STXRB
Definition: arm64.h:1012
@ ARM64_INS_CINC
Definition: arm64.h:1116
@ ARM64_INS_MOVK
Definition: arm64.h:865
@ ARM64_INS_MOVN
Definition: arm64.h:866
@ ARM64_INS_STURH
Definition: arm64.h:1010
@ ARM64_INS_UMULL
Definition: arm64.h:1061
@ ARM64_INS_SXTW
Definition: arm64.h:1122
@ ARM64_INS_ROR
Definition: arm64.h:890
@ ARM64_INS_CSET
Definition: arm64.h:1115
@ ARM64_INS_UXTH
Definition: arm64.h:1125
@ ARM64_INS_LDURB
Definition: arm64.h:849
@ ARM64_INS_FDIV
Definition: arm64.h:773
@ ARM64_INS_BFXIL
Definition: arm64.h:1111
@ ARM64_INS_LDURSB
Definition: arm64.h:852
@ ARM64_INS_REV
Definition: arm64.h:889
@ ARM64_INS_LDAXR
Definition: arm64.h:832
@ ARM64_INS_LDUR
Definition: arm64.h:850
@ ARM64_INS_LDXRB
Definition: arm64.h:856
@ ARM64_INS_UBFX
Definition: arm64.h:1109
@ ARM64_INS_ADR
Definition: arm64.h:681
@ ARM64_INS_SMULL
Definition: arm64.h:947
@ ARM64_INS_SMADDL
Definition: arm64.h:931
@ ARM64_INS_MSUB
Definition: arm64.h:870
@ ARM64_INS_ADRP
Definition: arm64.h:682
@ ARM64_INS_SBC
Definition: arm64.h:909
@ ARM64_INS_LDRSB
Definition: arm64.h:839
@ ARM64_INS_STRH
Definition: arm64.h:1004
@ ARM64_INS_CBNZ
Definition: arm64.h:699
@ ARM64_INS_LSL
Definition: arm64.h:859
@ ARM64_INS_LDR
Definition: arm64.h:837
@ ARM64_INS_FCSEL
Definition: arm64.h:755
@ ARM64_INS_SDIV
Definition: arm64.h:912
@ ARM64_INS_UXTB
Definition: arm64.h:1124
@ ARM64_INS_MADD
Definition: arm64.h:861
@ ARM64_INS_LDRB
Definition: arm64.h:836
@ ARM64_INS_REV16
Definition: arm64.h:886
@ ARM64_INS_B
Definition: arm64.h:689
@ ARM64_INS_STR
Definition: arm64.h:1003
@ ARM64_INS_MOVZ
Definition: arm64.h:867
@ ARM64_INS_NEG
Definition: arm64.h:873
@ ARM64_INS_SXTB
Definition: arm64.h:1120
@ ARM64_INS_SBFIZ
Definition: arm64.h:1106
@ ARM64_INS_LDURSW
Definition: arm64.h:854
@ ARM64_INS_EXTR
Definition: arm64.h:738
@ ARM64_INS_UDIV
Definition: arm64.h:1043
@ ARM64_INS_ADD
Definition: arm64.h:679
@ ARM64_INS_SBFX
Definition: arm64.h:1108
@ ARM64_INS_MOV
Definition: arm64.h:715
@ ARM64_INS_LDRSH
Definition: arm64.h:840
@ ARM64_INS_CLZ
Definition: arm64.h:705
@ ARM64_INS_BR
Definition: arm64.h:696
@ ARM64_INS_LSR
Definition: arm64.h:860
@ ARM64_INS_LDP
Definition: arm64.h:834
@ ARM64_INS_BL
Definition: arm64.h:694
@ ARM64_INS_BIC
Definition: arm64.h:691
@ ARM64_INS_EOR
Definition: arm64.h:736
@ ARM64_INS_CMP
Definition: arm64.h:1123
@ ARM64_INS_MNEG
Definition: arm64.h:1096
@ ARM64_INS_STXRH
Definition: arm64.h:1013
@ ARM64_INS_MUL
Definition: arm64.h:871
@ ARM64_INS_STURB
Definition: arm64.h:1008
@ ARM64_INS_FCMP
Definition: arm64.h:753
@ ARM64_INS_LDURSH
Definition: arm64.h:853
@ ARM64_INS_CBZ
Definition: arm64.h:700
@ ARM64_INS_ORR
Definition: arm64.h:876
@ ARM64_INS_BLR
Definition: arm64.h:695
@ ARM64_INS_STRB
Definition: arm64.h:1002
@ ARM64_INS_SUB
Definition: arm64.h:1017
@ ARM64_INS_TST
Definition: arm64.h:1114
@ ARM64_INS_LDXR
Definition: arm64.h:858
@ ARM64_INS_ASR
Definition: arm64.h:688
@ ARM64_INS_UBFIZ
Definition: arm64.h:1107
@ ARM64_INS_STP
Definition: arm64.h:1001
@ ARM64_INS_NEGS
Definition: arm64.h:1132
size_t csh
Definition: capstone.h:71
#define NULL
Definition: cris-opc.c:27
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
int n
Definition: mipsasm.c:19
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
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 PFMT64u
Definition: rz_types.h:395
#define PFMT64x
Definition: rz_types.h:393
#define st64
Definition: rz_types_base.h:10
static int
Definition: sfsocketcall.h:114
#define a(i)
Definition: sha256.c:41
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58