Rizin
unix-like reverse engineering framework and cli tools
analysis_xtensa.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2016-2018 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <string.h>
5 #include <rz_types.h>
6 #include <rz_lib.h>
7 #include <rz_asm.h>
8 #include <rz_analysis.h>
9 
10 #include <xtensa-isa.h>
11 
12 #define CM ","
13 #define XTENSA_MAX_LENGTH 8
14 
15 static int xtensa_length(const ut8 *insn) {
16  static int length_table[16] = { 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 8, 8 };
17  return length_table[*insn & 0xf];
18 }
19 
20 static inline ut64 xtensa_offset(ut64 addr, const ut8 *buf) {
21  ut32 offset = ((buf[0] >> 4) & 0xc) | (((ut32)buf[1]) << 4) | (((ut32)buf[2]) << 12);
22  if (offset & 0x80000) {
23  return (addr + 4 + offset - 0x100000) & ~3;
24  }
25  return (addr + 4 + offset) & ~3;
26 }
27 
28 static inline ut64 xtensa_imm18s(ut64 addr, const ut8 *buf) {
29  ut32 offset = (buf[0] >> 6) | (((ut32)buf[1]) << 2) | (((ut32)buf[2]) << 10);
30  if (offset & 0x20000) {
31  return addr + 4 + offset - 0x40000;
32  }
33  return addr + 4 + offset;
34 }
35 
36 static inline ut64 xtensa_imm6s(ut64 addr, const ut8 *buf) {
37  ut8 imm6 = (buf[1] >> 4) | (buf[0] & 0x30);
38  return (addr + 4 + imm6);
39 }
40 
41 static inline ut64 xtensa_imm8s(ut64 addr, ut8 imm8) {
42  if (imm8 & 0x80) {
43  return (addr + 4 + imm8 - 0x100);
44  }
45  return (addr + 4 + imm8);
46 }
47 
48 static inline ut64 xtensa_imm12s(ut64 addr, const ut8 *buf) {
49  ut16 imm12 = (buf[1] >> 4) | (((ut16)buf[2]) << 4);
50  if (imm12 & 0x800) {
51  return (addr + 4 + imm12 - 0x1000);
52  }
53  return (addr + 4 + imm12);
54 }
55 
56 typedef void (*XtensaOpFn)(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf);
57 
58 static void xtensa_null_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
60 }
61 
62 static void xtensa_unk_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
64 }
65 
66 static void xtensa_mov_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
68 }
69 
70 static void xtensa_load_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
72 }
73 
74 static void xtensa_store_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
76 }
77 
78 static void xtensa_add_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
80 }
81 
82 static void xtensa_sub_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
84 }
85 
86 static void xtensa_mul_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
88 }
89 
90 static void xtensa_div_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
92 }
93 
94 static void xtensa_mod_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
96 }
97 
98 static void xtensa_and_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
100 }
101 
102 static void xtensa_or_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
103  op->type = RZ_ANALYSIS_OP_TYPE_OR;
104 }
105 
106 static void xtensa_xor_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
107  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
108 }
109 
110 static void xtensa_shl_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
111  op->type = RZ_ANALYSIS_OP_TYPE_SHL;
112 }
113 
114 static void xtensa_shr_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
115  op->type = RZ_ANALYSIS_OP_TYPE_SHR;
116 }
117 
118 static void xtensa_l32r_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
120  op->ptr = ((addr + 3) & ~3) + ((buf[2] << 8 | buf[1]) << 2) - 0x40000;
121 }
122 
123 static void xtensa_snm0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
124  switch ((buf[0] >> 4) & 0xf) {
125  case 0x0:
126  case 0x1:
127  case 0x2:
128  case 0x3:
129  op->type = RZ_ANALYSIS_OP_TYPE_ILL;
130  break;
131  case 0x8:
132  case 0x9:
133  op->type = RZ_ANALYSIS_OP_TYPE_RET;
134  break;
135  case 0xa:
137  break;
138  case 0xc:
139  case 0xd:
140  case 0xe:
141  case 0xf:
143  break;
144  default:
145  xtensa_unk_op(analysis, op, addr, buf);
146  break;
147  }
148 }
149 
150 static void xtensa_sync_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
151  switch ((buf[0] >> 4) & 0xf) {
152  case 0x0:
153  case 0x1:
154  case 0x2:
155  case 0x3:
156  case 0x8:
157  case 0xc:
158  case 0xd:
159  /* Wait/sync instructions? */
161  break;
162  default:
163  xtensa_unk_op(analysis, op, addr, buf);
164  break;
165  }
166 }
167 
168 static void xtensa_rfei_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
169  switch ((buf[0] >> 4) & 0xf) {
170  case 0x0:
171  switch (buf[1] & 0xf) {
172  case 0x0:
173  case 0x1:
174  case 0x2:
175  case 0x4:
176  case 0x5:
177  op->type = RZ_ANALYSIS_OP_TYPE_RET;
178  break;
179  default:
180  xtensa_unk_op(analysis, op, addr, buf);
181  break;
182  }
183  break;
184  case 0x1:
185  case 0x2:
186  op->type = RZ_ANALYSIS_OP_TYPE_RET;
187  break;
188  default:
189  xtensa_unk_op(analysis, op, addr, buf);
190  break;
191  }
192 }
193 
194 static void xtensa_st0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
195  switch ((buf[1] >> 4) & 0xf) {
196  case 0x0:
197  xtensa_snm0_op(analysis, op, addr, buf);
198  break;
199  case 0x1:
201  break;
202  case 0x2:
203  xtensa_sync_op(analysis, op, addr, buf);
204  break;
205  case 0x3:
206  xtensa_rfei_op(analysis, op, addr, buf);
207  break;
208  case 0x4:
210  break;
211  case 0x5:
212  case 0x6:
213  case 0x7:
214  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
215  break;
216  case 0x8:
217  case 0x9:
218  case 0xa:
219  case 0xb:
220  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
221  break;
222  default:
223  xtensa_unk_op(analysis, op, addr, buf);
224  break;
225  }
226 }
227 
228 static void xtensa_st1_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
229  switch ((buf[1] >> 4) & 0xf) {
230  case 0x0:
231  case 0x1:
232  case 0x2:
233  case 0x3:
234  case 0x4:
235  /* Set shift-amount-register */
237  /*op->type = RZ_ANALYSIS_OP_TYPE_MOV;*/
238  break;
239  case 0x6:
240  case 0x7:
241  op->type = RZ_ANALYSIS_OP_TYPE_IO;
242  /*op->type = RZ_ANALYSIS_OP_TYPE_MOV;*/
243  break;
244  case 0x8:
245  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
246  break;
247  case 0xe:
248  case 0xf:
250  break;
251  default:
252  xtensa_unk_op(analysis, op, addr, buf);
253  break;
254  }
255 }
256 
257 static void xtensa_rt0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
258  switch (buf[1] & 0xf) {
259  case 0:
260  op->type = RZ_ANALYSIS_OP_TYPE_NOT;
261  break;
262  case 1:
263  /*op->type = RZ_ANALYSIS_OP_TYPE_ABS;*/
264  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
265  break;
266  default:
267  xtensa_unk_op(analysis, op, addr, buf);
268  break;
269  }
270 }
271 
272 static void xtensa_tlb_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
273  switch ((buf[2] >> 4) & 0xf) {
274  case 0x3:
275  case 0x4:
276  case 0x5:
277  case 0x6:
278  case 0x7:
279  case 0xb:
280  case 0xc:
281  case 0xd:
282  case 0xe:
283  case 0xf:
284  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
285  break;
286  default:
287  xtensa_unk_op(analysis, op, addr, buf);
288  break;
289  }
290 }
291 
292 static void xtensa_accer_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
293  switch ((buf[2] >> 4) & 0xf) {
294  case 0x0:
295  case 0x8:
296  op->type = RZ_ANALYSIS_OP_TYPE_IO;
297  /*op->type = RZ_ANALYSIS_OP_TYPE_MOV;*/
298  break;
299  default:
300  xtensa_unk_op(analysis, op, addr, buf);
301  break;
302  }
303 }
304 
305 static void xtensa_imp_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
306  switch ((buf[1] >> 4) & 0xf) {
307  case 0x0:
308  case 0x1:
309  case 0x2:
310  case 0x3:
311  case 0x8:
312  case 0x9:
314  break;
315  case 0xe:
316  if (((buf[0] >> 4) & 0xf) <= 1) {
317  op->type = RZ_ANALYSIS_OP_TYPE_RET;
318  } else {
319  xtensa_unk_op(analysis, op, addr, buf);
320  }
321  break;
322  default:
323  xtensa_unk_op(analysis, op, addr, buf);
324  break;
325  }
326 }
327 
331  xtensa_or_op,
345 };
346 
364 };
365 
369  xtensa_or_op,
370  xtensa_or_op,
383 };
384 
385 static void xtensa_rst0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
386  xtensa_rst0_fns[(buf[2] >> 4) & 0xf](analysis, op, addr, buf);
387 }
388 static void xtensa_rst1_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
389  xtensa_rst1_fns[(buf[2] >> 4) & 0xf](analysis, op, addr, buf);
390 }
391 
392 static void xtensa_rst2_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
393  xtensa_rst2_fns[(buf[2] >> 4) & 0xf](analysis, op, addr, buf);
394 }
395 
396 static void xtensa_lsc4_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
397  switch ((buf[2] >> 4) & 0xf) {
398  case 0x0:
399  xtensa_load_op(analysis, op, addr, buf);
400  break;
401  case 0x4:
402  xtensa_store_op(analysis, op, addr, buf);
403  break;
404  default:
405  xtensa_unk_op(analysis, op, addr, buf);
406  break;
407  }
408 }
409 
410 static void xtensa_lscx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
411  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
412  switch ((buf[2] >> 4) & 0xf) {
413  case 0x0:
414  case 0x1:
415  xtensa_load_op(analysis, op, addr, buf);
416  break;
417  case 0x4:
418  case 0x5:
419  xtensa_store_op(analysis, op, addr, buf);
420  break;
421  default:
422  xtensa_unk_op(analysis, op, addr, buf);
423  break;
424  }
425 }
426 
427 static void xtensa_fp0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
428  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
429  switch ((buf[2] >> 4) & 0xf) {
430  case 0x0:
431  case 0x4:
432  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
433  break;
434  case 0x1:
435  case 0x5:
436  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
437  break;
438  case 0x2:
439  op->type = RZ_ANALYSIS_OP_TYPE_MUL;
440  break;
441  case 0x8:
442  case 0x9:
443  case 0xa:
444  case 0xb:
445  case 0xc:
446  case 0xd:
447  case 0xe:
448  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
449  break;
450  case 0xf:
451  switch ((buf[0] >> 4) & 0xf) {
452  case 0x0:
453  case 0x4:
454  case 0x5:
455  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
456  break;
457  case 0x1:
458  op->type = RZ_ANALYSIS_OP_TYPE_ABS;
459  break;
460  case 0x6:
461  op->type = RZ_ANALYSIS_OP_TYPE_NOT;
462  break;
463  default:
464  xtensa_unk_op(analysis, op, addr, buf);
465  break;
466  }
467  break;
468  default:
469  xtensa_unk_op(analysis, op, addr, buf);
470  break;
471  }
472 }
473 
474 static void xtensa_fp1_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
475  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
476  switch ((buf[2] >> 4) & 0xf) {
477  case 0x1:
478  case 0x2:
479  case 0x3:
480  case 0x4:
481  case 0x5:
482  case 0x6:
483  case 0x7:
484  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
485  break;
486  case 0x8:
487  case 0x9:
488  case 0xa:
489  case 0xb:
490  case 0xc:
491  case 0xd:
492  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
493  break;
494  default:
495  xtensa_unk_op(analysis, op, addr, buf);
496  break;
497  }
498 }
499 
504  xtensa_mov_op, /*xtensa_rst3_op,*/
505  xtensa_null_op, /*xtensa_extui_op,*/
506  xtensa_null_op, /*xtensa_extui_op,*/
507  xtensa_unk_op, /*xtensa_cust0_op,*/
508  xtensa_unk_op, /*xtensa_cust1_op,*/
517 };
518 
519 static void xtensa_qrst_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
520  xtensa_qrst_fns[buf[2] & 0xf](analysis, op, addr, buf);
521 }
522 
531  xtensa_null_op, /*xtensa_cache_op,probably not interesting for analysis?*/
540 };
541 
542 static void xtensa_lsai_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
543  xtensa_lsai_fns[(buf[1] >> 4) & 0xf](analysis, op, addr, buf);
544 }
545 
546 static void xtensa_lsci_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
547  ut8 r = buf[1] >> 4;
548  op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
549  if ((r & 3) == 0) {
550  if (r & 4) {
551  xtensa_store_op(analysis, op, addr, buf);
552  } else {
553  xtensa_load_op(analysis, op, addr, buf);
554  }
555  } else {
556  xtensa_unk_op(analysis, op, addr, buf);
557  }
558 }
559 
560 static void xtensa_calln_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
562  op->fail = addr + op->size;
563  op->jump = xtensa_offset(addr, buf);
564 }
565 
566 static void xtensa_b_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
568  op->fail = addr + op->size;
569  op->jump = xtensa_imm8s(addr, buf[2]);
570 }
571 
572 static void xtensa_si_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
573  ut8 n = (buf[0] >> 4) & 3;
574  ut8 m = (buf[0] >> 6);
575  switch (n) {
576  case 0:
577  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
578  op->jump = xtensa_imm18s(addr, buf);
579  break;
580  case 1:
582  op->fail = addr + op->size;
583  op->jump = xtensa_imm12s(addr, buf);
584  break;
585  case 2:
586  xtensa_b_op(analysis, op, addr, buf);
587  break;
588  case 3:
589  switch (m) {
590  case 0:
592  break;
593  case 1:
594  switch (buf[1] >> 4) {
595  case 0:
596  case 1:
597  xtensa_b_op(analysis, op, addr, buf);
598  break;
599  case 0x8:
600  case 0x9:
601  case 0xa:
603  op->fail = addr + op->size;
604  op->jump = addr + 4 + buf[2];
605  break;
606  default:
607  xtensa_unk_op(analysis, op, addr, buf);
608  break;
609  }
610  break;
611  case 2:
612  case 3:
613  xtensa_b_op(analysis, op, addr, buf);
614  break;
615  default:
616  xtensa_unk_op(analysis, op, addr, buf);
617  break;
618  }
619  break;
620  default:
621  xtensa_unk_op(analysis, op, addr, buf);
622  break;
623  }
624 }
625 
626 static void xtensa_st2n_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
627  if (buf[0] & 0x80) {
629  op->fail = addr + op->size;
630  op->jump = xtensa_imm6s(addr, buf);
631  } else {
632  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
633  }
634 }
635 
636 static void xtensa_st3n_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
637  switch ((buf[1] >> 4) & 0xf) {
638  case 0x0:
639  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
640  break;
641  case 0xf:
642  switch ((buf[0] >> 4) & 0xf) {
643  case 0:
644  case 1:
645  op->type = RZ_ANALYSIS_OP_TYPE_RET;
646  break;
647  case 2:
649  break;
650  case 3:
651  op->type = RZ_ANALYSIS_OP_TYPE_NOP;
652  break;
653  case 6:
654  op->type = RZ_ANALYSIS_OP_TYPE_ILL;
655  break;
656  default:
657  xtensa_unk_op(analysis, op, addr, buf);
658  break;
659  }
660  break;
661  default:
662  xtensa_unk_op(analysis, op, addr, buf);
663  break;
664  }
665 }
666 
672  xtensa_null_op, /*xtensa_mac16_op,*/
674  xtensa_si_op,
675  xtensa_b_op,
676 
683  xtensa_null_op, /*xtensa_xt_format1_op,*/ /*TODO*/
684  xtensa_null_op /*xtensa_xt_format2_op*/ /*TODO*/
685 };
686 
687 static inline void sign_extend(st32 *value, ut8 bit) {
688  if (*value & (1 << bit)) {
689  *value |= 0xFFFFFFFF << bit;
690  }
691 }
692 
693 static inline void sign_extend2(st32 *value, ut8 bit1, ut8 bit2, ut8 shift) {
694  if (((*value >> bit1) & 1) && ((*value >> bit2) & 1)) {
695  *value |= UT32_MAX << (32 - shift);
696  }
697 }
698 
700  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
701  st32 imm;
702  ut32 dst;
703  ut32 src;
704 
705  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &dst);
706  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &src);
707  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, (ut32 *)&imm);
708 
709  // wide form of addi requires sign extension
710  if (opcode == 39) {
711  sign_extend(&imm, 7);
712  }
713 
714  // a1 = stack
715  if (dst == 1 && src == 1) {
716  op->val = imm;
717  op->stackptr = -imm;
718  op->stackop = RZ_ANALYSIS_STACK_INC;
719  }
720 }
721 
722 static void esil_push_signed_imm(RzStrBuf *esil, st32 imm) {
723  if (imm >= 0) {
724  rz_strbuf_appendf(esil, "0x%x" CM, imm);
725  } else {
727  esil,
728  "0x%x" CM
729  "0x0" CM
730  "-" CM,
731  -imm);
732  }
733 }
734 
735 static void esil_sign_extend(RzStrBuf *esil, ut8 bit) {
736  // check sign bit, and, if needed, apply or mask
737 
738  ut32 bit_mask = 1 << bit;
739  ut32 extend_mask = 0xFFFFFFFF << bit;
740 
742  esil,
743  "DUP" CM
744  "0x%x" CM
745  "&" CM
746  "0" CM
747  "==,$z,!" CM
748  "?{" CM
749  "0x%x" CM
750  "|" CM
751  "}" CM,
752  bit_mask,
753  extend_mask);
754 }
755 
756 static void esil_load_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
757  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
758  ut32 offset;
759  ut32 reg_d;
760  ut32 reg_a;
761  ut8 sign_extend_bit;
762 
763  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &reg_d);
764  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &reg_a);
765  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, &offset);
766 
767  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
768  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
769 
770  // example: l32i a2, a1, 0x10
771  // 0x10,a1,+, // address on stack
772  // [x], // read data
773  // a2, // push data reg
774  // = // assign to data reg
775 
776  ut8 data_size = opcode == 82 ? 2 // l16ui
777  : opcode == 83 ? 2 // l16si
778  : opcode == 84 ? 4 // l32i
779  : opcode == 31 ? 4 // l32i.n
780  : 1; // opcode == 86 ? 1 : 1; // l8ui
781 
782  sign_extend_bit = 0;
783 
784  switch (opcode) {
785  case 84: // l32i
786  case 31: // l32i.n
787  offset <<= 2;
788  break;
789  case 83: // l16si
790  sign_extend_bit = 15;
791  // fallthrough
792  case 82:
793  // l16ui
794  offset <<= 1;
795  break;
796  }
797 
799  &op->esil,
800  "0x%x" CM
801  "%s%d" CM
802  "+" CM
803  "[%d]" CM,
804  // offset
805  offset,
806  // address
807  xtensa_regfile_shortname(isa, src_rf),
808  reg_a,
809  // size
810  data_size);
811 
812  if (sign_extend_bit != 0) {
813  esil_sign_extend(&op->esil, sign_extend_bit);
814  }
815 
817  &op->esil,
818  "%s%d" CM
819  "=",
820  // data
821  xtensa_regfile_shortname(isa, dst_rf),
822  reg_d);
823 }
824 
826  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
827  ut32 offset;
828  st32 dst;
829 
830  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, (ut32 *)&dst);
831  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &offset);
832 
833  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
834 
835  // example: l32r a2, 0x10
836  // 0x10,$$,3,+ // l32r address + 3 on stack
837  // 0xFFFFFFFC,&, // clear 2 lsb
838  // -, // subtract offset
839  // [4], // read data
840  // a2, // push data reg
841  // = // assign to data reg
842 
843  offset = -((offset | 0xFFFF0000) << 2);
844 
846  &op->esil,
847  "0x%x" CM
848  "$$" CM
849  "3" CM
850  "+" CM
851  "0xFFFFFFFC" CM
852  "&" CM
853  "-" CM
854  "[4]" CM
855  "%s%d" CM
856  "=",
857  // offset
858  offset,
859  // data
860  xtensa_regfile_shortname(isa, dst_rf),
861  dst);
862 }
863 
864 static void esil_add_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
865  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
866  st32 imm;
867  ut32 dst;
868  ut32 src;
869 
870  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &dst);
871  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &src);
872  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, (ut32 *)&imm);
873 
874  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
875  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
876 
877  // example: addi a3, a4, 0x01
878  // a4,0x01,+,a3,=
879 
880  // wide form of addi requires sign extension
881  if (opcode == 39) {
882  sign_extend(&imm, 7);
883  }
884 
885  rz_strbuf_appendf(&op->esil, "%s%d" CM, xtensa_regfile_shortname(isa, src_rf), src);
886  esil_push_signed_imm(&op->esil, imm);
888  &op->esil,
889  "+" CM
890  "%s%d" CM
891  "=",
892  xtensa_regfile_shortname(isa, dst_rf),
893  dst);
894 }
895 
896 static void esil_store_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
897  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
898 
899  ut32 offset;
900  ut32 reg_d;
901  ut32 reg_a;
902 
903  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &reg_d);
904  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &reg_a);
905  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, &offset);
906 
907  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
908  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
909 
910  // example: s32i a2, a1, 0x10
911  // a2, // push data
912  // 0x10,a1,+, // address on stack
913  // =[x] // write data
914 
915  ut8 data_size =
916  opcode == 453 ? 4 // s32cli
917  : opcode == 36 ? 4 // s32i.n
918  : opcode == 100 ? 4 // s32i
919  : opcode == 99 ? 2 // s16i
920  : 1; // opcode == 101 ? 1 : 1; // s8i
921 
922  switch (opcode) {
923  case 100: // s32i
924  case 453: // s32cli
925  case 36: // s32i.n
926  offset <<= 2;
927  break;
928  case 99: // s16i
929  offset <<= 1;
930  break;
931  }
932 
934  &op->esil,
935  "%s%d" CM
936  "0x%x" CM
937  "%s%d" CM
938  "+" CM
939  "=[%d]",
940  // data
941  xtensa_regfile_shortname(isa, dst_rf),
942  reg_d,
943  // offset
944  offset,
945  // address
946  xtensa_regfile_shortname(isa, src_rf),
947  reg_a,
948  // size
949  data_size);
950 }
951 
952 static void esil_move_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
953  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
954  st32 imm;
955  ut32 reg;
956 
957  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &reg);
958  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, (ut32 *)&imm);
959 
960  xtensa_regfile rf = xtensa_operand_regfile(isa, opcode, 0);
961 
962  // sign extension
963  // 90: movi
964  if (opcode == 90) {
965  sign_extend(&imm, 11);
966  }
967 
968  // 33: movi.n
969  if (opcode == 33) {
970  sign_extend2(&imm, 6, 5, 25);
971  }
972 
973  esil_push_signed_imm(&op->esil, imm);
974 
976  &op->esil,
977  "%s%d" CM
978  "=",
979  xtensa_regfile_shortname(isa, rf),
980  reg);
981 }
982 
983 static void esil_move(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
984  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
985  ut32 dst;
986  ut32 src;
987 
988  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &dst);
989  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &src);
990 
991  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
992  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
993 
995  &op->esil,
996  "%s%d" CM
997  "%s%d" CM
998  "=",
999  xtensa_regfile_shortname(isa, src_rf),
1000  src,
1001  xtensa_regfile_shortname(isa, dst_rf),
1002  dst);
1003 }
1004 
1006  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1007  ut32 dst;
1008  ut32 src;
1009  ut32 cond;
1010 
1011  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &dst);
1012  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &src);
1013  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, &cond);
1014 
1015  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
1016  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
1017  xtensa_regfile cond_rf = xtensa_operand_regfile(isa, opcode, 2);
1018 
1019  const char *compare_op = "";
1020 
1021  switch (opcode) {
1022  case 91: /* moveqz */
1023  compare_op = "==,$z";
1024  break;
1025  case 92: /* movnez */
1026  compare_op = "==,$z,!";
1027  break;
1028  case 93: /* movltz */
1029  compare_op = "<";
1030  break;
1031  case 94: /* movgez */
1032  compare_op = ">=";
1033  break;
1034  }
1035 
1036  // example: moveqz a3, a4, a5
1037  // 0,
1038  // a5,
1039  // ==,
1040  // ?{,
1041  // a4,
1042  // a3,
1043  // =,
1044  // }
1045 
1047  &op->esil,
1048  "0" CM
1049  "%s%d" CM
1050  "%s" CM
1051  "?{" CM
1052  "%s%d" CM
1053  "%s%d" CM
1054  "=" CM
1055  "}",
1056  xtensa_regfile_shortname(isa, cond_rf),
1057  cond,
1058  compare_op,
1059  xtensa_regfile_shortname(isa, src_rf),
1060  src,
1061  xtensa_regfile_shortname(isa, dst_rf),
1062  dst);
1063 }
1064 
1065 static void esil_add_sub(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
1066  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1067  ut32 dst;
1068  ut32 op1;
1069  ut32 op2;
1070  bool is_add;
1071  ut8 shift;
1072 
1073  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &dst);
1074  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &op1);
1075  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, &op2);
1076 
1077  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
1078  xtensa_regfile op1_rf = xtensa_operand_regfile(isa, opcode, 1);
1079  xtensa_regfile op2_rf = xtensa_operand_regfile(isa, opcode, 2);
1080 
1081  is_add =
1082  (opcode == 26) ||
1083  (opcode == 41) ||
1084  (opcode == 43) ||
1085  (opcode == 44) ||
1086  (opcode == 45);
1087 
1088  switch (opcode) {
1089  case 43:
1090  case 46:
1091  shift = 1;
1092  break;
1093  case 44:
1094  case 47:
1095  shift = 2;
1096  break;
1097  case 45:
1098  case 48:
1099  shift = 3;
1100  break;
1101  default:
1102  shift = 0;
1103  break;
1104  }
1105 
1107  &op->esil,
1108  "%s%d" CM
1109  "%d" CM
1110  "%s%d" CM
1111  "<<" CM
1112  "%s" CM
1113  "%s%d" CM
1114  "=",
1115  xtensa_regfile_shortname(isa, op2_rf),
1116  op2,
1117  shift,
1118  xtensa_regfile_shortname(isa, op1_rf),
1119  op1,
1120  (is_add ? "+" : "-"),
1121  xtensa_regfile_shortname(isa, dst_rf),
1122  dst);
1123 }
1124 
1126  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1127  ut32 cmp_reg;
1128  // Unsigned immediate operands still fit in st32
1129  st32 cmp_imm;
1130  st32 branch_imm;
1131 
1132  const char *compare_op = "";
1133 
1134  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &cmp_reg);
1135  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, (ut32 *)&cmp_imm);
1136  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, (ut32 *)&branch_imm);
1137 
1138  xtensa_regfile cmp_rf = xtensa_operand_regfile(isa, opcode, 0);
1139 
1140  // TODO: unsigned comparisons
1141  switch (opcode) {
1142  case 52: /* beqi */
1143  compare_op = "==,$z";
1144  break;
1145  case 53: /* bnei */
1146  compare_op = "==,$z,!";
1147  break;
1148  case 58: /* bgeui */
1149  case 54: /* bgei */
1150  compare_op = ">=";
1151  break;
1152  case 59: /* bltui */
1153  case 55: /* blti */
1154  compare_op = "<";
1155  break;
1156  }
1157 
1158  // example: beqi a4, 4, offset
1159  // a4, // push data reg
1160  // 0x4, // push imm operand
1161  // ==,
1162  // ?{,
1163  // offset,
1164  // pc,
1165  // +=,
1166  // }
1167 
1169  &op->esil,
1170  "%s%d" CM,
1171  // data reg
1172  xtensa_regfile_shortname(isa, cmp_rf),
1173  cmp_reg);
1174 
1175  esil_push_signed_imm(&op->esil, cmp_imm);
1176 
1177  rz_strbuf_appendf(&op->esil, "%s" CM, compare_op);
1178  rz_strbuf_appendf(&op->esil, "?{" CM);
1179 
1180  // ISA defines branch target as offset + 4,
1181  // but at the time of ESIL evaluation
1182  // PC will be already incremented by 3
1183  esil_push_signed_imm(&op->esil, branch_imm + 4 - 3);
1184 
1185  rz_strbuf_appendf(&op->esil, "pc" CM "+=" CM "}");
1186 }
1187 
1189  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1190  ut32 op1_reg;
1191  ut32 op2_reg;
1192  st32 branch_imm;
1193 
1194  const char *compare_op = "";
1195 
1196  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &op1_reg);
1197  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &op2_reg);
1198  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, (ut32 *)&branch_imm);
1199 
1200  xtensa_regfile op1_rf = xtensa_operand_regfile(isa, opcode, 0);
1201  xtensa_regfile op2_rf = xtensa_operand_regfile(isa, opcode, 1);
1202 
1203  switch (opcode) {
1204  case 60: /* beq */
1205  compare_op = "==,$z";
1206  break;
1207  case 61: /* bne */
1208  compare_op = "==,$z,!";
1209  break;
1210  case 62: /* bge */
1211  case 64: /* bgeu */
1212  compare_op = ">=";
1213  break;
1214  case 63: /* blt */
1215  case 65: /* bltu */
1216  compare_op = "<";
1217  break;
1218  }
1219 
1220  sign_extend(&branch_imm, 7);
1221  branch_imm += 4 - 3;
1222 
1223  // example: beq a4, a3, offset
1224  // a3, // push op1
1225  // a4, // push op2
1226  // ==,
1227  // ?{,
1228  // offset,
1229  // pc,
1230  // +=,
1231  // }
1232 
1234  &op->esil,
1235  "%s%d" CM
1236  "%s%d" CM
1237  "%s" CM
1238  "?{" CM,
1239  xtensa_regfile_shortname(isa, op2_rf),
1240  op2_reg,
1241  xtensa_regfile_shortname(isa, op1_rf),
1242  op1_reg,
1243  compare_op);
1244 
1246 
1247  rz_strbuf_append(&op->esil, "pc" CM "+=" CM "}");
1248 }
1249 
1251  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1252  ut32 op_reg;
1253  st32 branch_imm;
1254 
1255  const char *compare_op = "";
1256 
1257  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &op_reg);
1258  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, (ut32 *)&branch_imm);
1259 
1260  xtensa_regfile op_rf = xtensa_operand_regfile(isa, opcode, 0);
1261 
1262  switch (opcode) {
1263  case 72: /* beqz */
1264  case 28: /* beqz.n */
1265  compare_op = "==,$z";
1266  break;
1267  case 73: /* bnez */
1268  case 29: /* bnez.n */
1269  compare_op = "==,$z,!";
1270  break;
1271  case 74: /* bgez */
1272  compare_op = ">=";
1273  break;
1274  case 75: /* bltz */
1275  compare_op = "<";
1276  break;
1277  }
1278 
1279  sign_extend(&branch_imm, 12);
1280  branch_imm += 4 - 3;
1281 
1282  // example: beqz a4, 0, offset
1283  // 0, // push 0
1284  // a4, // push op
1285  // ==,
1286  // ?{,
1287  // offset,
1288  // pc,
1289  // +=,
1290  // }
1291 
1293  &op->esil,
1294  "0" CM
1295  "%s%d" CM
1296  "%s" CM
1297  "?{" CM,
1298  xtensa_regfile_shortname(isa, op_rf),
1299  op_reg,
1300  compare_op);
1301 
1303 
1304  rz_strbuf_append(&op->esil, "pc" CM "+=" CM "}");
1305 }
1306 
1308  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1309  ut32 op1_reg;
1310  ut32 op2_reg;
1311  st32 branch_imm;
1312 
1313  const char *compare_op = "";
1314  char compare_val[4] = "0";
1315 
1316  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &op1_reg);
1317  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &op2_reg);
1318  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, (ut32 *)&branch_imm);
1319 
1320  xtensa_regfile op1_rf = xtensa_operand_regfile(isa, opcode, 0);
1321  xtensa_regfile op2_rf = xtensa_operand_regfile(isa, opcode, 1);
1322 
1323  switch (opcode) {
1324  case 69: /* bnall */
1325  case 66: /* bany */
1326  compare_op = "==,$z,!";
1327  break;
1328  case 68: /* ball */
1329  case 67: /* bnone */
1330  compare_op = "==,$z";
1331  break;
1332  }
1333 
1334  switch (opcode) {
1335  case 69: /* bnall */
1336  case 68: /* ball */
1337  snprintf(
1338  compare_val,
1339  sizeof(compare_val),
1340  "%s%d",
1341  xtensa_regfile_shortname(isa, op2_rf),
1342  op2_reg);
1343  break;
1344  }
1345 
1346  sign_extend(&branch_imm, 7);
1347  branch_imm += 4 - 3;
1348 
1349  // example: bnall a4, a3, offset
1350  // a4, // push op1
1351  // a3, // push op2
1352  // &,
1353  // a3,
1354  // ==,!,
1355  // ?{,
1356  // offset,
1357  // pc,
1358  // +=,
1359  // }
1360 
1362  &op->esil,
1363  "%s%d" CM
1364  "%s%d" CM
1365  "&" CM
1366  "%s%d" CM
1367  "%s" CM
1368  "?{" CM,
1369  xtensa_regfile_shortname(isa, op1_rf),
1370  op1_reg,
1371  xtensa_regfile_shortname(isa, op2_rf),
1372  op2_reg,
1373  xtensa_regfile_shortname(isa, op2_rf),
1374  op2_reg,
1375  compare_op);
1376 
1378 
1379  rz_strbuf_append(&op->esil, "pc" CM "+=" CM "}");
1380 }
1381 
1382 static void esil_bitwise_op(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
1383  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1384  ut32 dst;
1385  ut32 op1;
1386  ut32 op2;
1387  char bop;
1388 
1389  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &dst);
1390  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &op1);
1391  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, &op2);
1392 
1393  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
1394  xtensa_regfile op1_rf = xtensa_operand_regfile(isa, opcode, 1);
1395  xtensa_regfile op2_rf = xtensa_operand_regfile(isa, opcode, 2);
1396 
1397  switch (opcode) {
1398  case 49: /* and */
1399  bop = '&';
1400  break;
1401  case 50: /* or */
1402  bop = '|';
1403  break;
1404  case 51: /* xor */
1405  bop = '^';
1406  break;
1407  default:
1408  bop = '=';
1409  break;
1410  }
1411 
1413  &op->esil,
1414  "%s%d" CM
1415  "%s%d" CM
1416  "%c" CM
1417  "%s%d" CM
1418  "=",
1419  xtensa_regfile_shortname(isa, op1_rf),
1420  op1,
1421  xtensa_regfile_shortname(isa, op2_rf),
1422  op2,
1423  bop,
1424  xtensa_regfile_shortname(isa, dst_rf),
1425  dst);
1426 }
1427 
1429  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1430  ut32 src_reg;
1431  ut32 imm_bit;
1432  st32 imm_offset;
1433  ut8 bit_clear;
1434  ut32 mask;
1435  const char *cmp_op;
1436 
1437  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &src_reg);
1438  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &imm_bit);
1439  xtensa_operand_decode(isa, opcode, 1, &imm_bit);
1440  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, (ut32 *)&imm_offset);
1441 
1442  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 0);
1443 
1444  bit_clear = opcode == 56;
1445  cmp_op = bit_clear ? "==,$z" : "==,$z,!";
1446  mask = 1 << imm_bit;
1447 
1448  sign_extend(&imm_offset, 7);
1449  imm_offset += 4 - 3;
1450 
1451  // example: bbsi a4, 2, offset
1452  // a4,
1453  // mask,
1454  // &,
1455  // 0,
1456  // ==,
1457  // ?{,
1458  // offset,
1459  // pc,
1460  // +=,
1461  // }
1462 
1464  &op->esil,
1465  "%s%d" CM
1466  "0x%x" CM
1467  "&" CM
1468  "0" CM
1469  "%s" CM
1470  "?{" CM,
1471  xtensa_regfile_shortname(isa, src_rf),
1472  src_reg,
1473  mask,
1474  cmp_op);
1475 
1476  esil_push_signed_imm(&op->esil, imm_offset);
1477 
1479  &op->esil,
1480  "pc" CM
1481  "+=" CM
1482  "}");
1483 }
1484 
1486  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1487  ut32 src_reg;
1488  ut32 bit_reg;
1489  st32 imm_offset;
1490 
1491  ut8 bit_clear;
1492  const char *cmp_op;
1493 
1494  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &src_reg);
1495  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &bit_reg);
1496  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, (ut32 *)&imm_offset);
1497 
1498  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 0);
1499  xtensa_regfile bit_rf = xtensa_operand_regfile(isa, opcode, 1);
1500 
1501  // bbc
1502  bit_clear = opcode == 70;
1503  cmp_op = bit_clear ? "==,$z" : "==,$z,!";
1504 
1505  sign_extend(&imm_offset, 7);
1506  imm_offset += 4 - 3;
1507 
1508  // example: bbc a4, a2, offset
1509  // a2,
1510  // 1,
1511  // <<,
1512  // a4,
1513  // &
1514  // 0
1515  // ==,
1516  // ?{,
1517  // offset,
1518  // pc,
1519  // +=,
1520  // }
1521 
1523  &op->esil,
1524  "%s%d" CM
1525  "1" CM
1526  "<<" CM
1527  "%s%d" CM
1528  "&" CM
1529  "0" CM
1530  "%s" CM
1531  "?{" CM,
1532  xtensa_regfile_shortname(isa, bit_rf),
1533  bit_reg,
1534  xtensa_regfile_shortname(isa, src_rf),
1535  src_reg,
1536  cmp_op);
1537 
1538  esil_push_signed_imm(&op->esil, imm_offset);
1539 
1541  &op->esil,
1542  "pc" CM
1543  "+=" CM
1544  "}");
1545 }
1546 
1547 static void esil_abs_neg(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
1548  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1549  ut32 src_reg;
1550  ut32 dst_reg;
1551 
1552  ut8 neg;
1553 
1554  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &dst_reg);
1555  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &src_reg);
1556 
1557  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 1);
1558  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 0);
1559 
1560  neg = opcode == 95;
1561 
1562  if (!neg) {
1564  &op->esil,
1565  "0" CM
1566  "%s%d" CM
1567  "<" CM
1568  "?{" CM
1569  "0" CM
1570  "%s%d" CM
1571  "-" CM
1572  "}" CM
1573  "0" CM
1574  "%s%d" CM
1575  ">=" CM
1576  "?{" CM
1577  "%s%d" CM
1578  "}" CM,
1579  xtensa_regfile_shortname(isa, src_rf),
1580  src_reg,
1581  xtensa_regfile_shortname(isa, src_rf),
1582  src_reg,
1583  xtensa_regfile_shortname(isa, src_rf),
1584  src_reg,
1585  xtensa_regfile_shortname(isa, src_rf),
1586  src_reg);
1587  } else {
1589  &op->esil,
1590  "0" CM
1591  "%s%d" CM
1592  "-" CM,
1593  xtensa_regfile_shortname(isa, src_rf),
1594  src_reg);
1595  }
1596 
1598  &op->esil,
1599  "%s%d" CM
1600  "=" CM,
1601  xtensa_regfile_shortname(isa, dst_rf),
1602  dst_reg);
1603 }
1604 
1605 static void esil_call(xtensa_isa isa, xtensa_opcode opcode,
1606  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1607  bool call = opcode == 76;
1608  st32 imm_offset;
1609 
1610  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer,
1611  (ut32 *)&imm_offset);
1612 
1613  if (call) {
1615  &op->esil,
1616  "pc" CM
1617  "a0" CM
1618  "=" CM);
1619  }
1620 
1621  sign_extend(&imm_offset, 17);
1622 
1623  if (call) {
1624  imm_offset <<= 2;
1625  }
1626 
1627  imm_offset += 4 - 3;
1628 
1629  esil_push_signed_imm(&op->esil, imm_offset);
1630 
1631  rz_strbuf_append(&op->esil, "pc" CM "+=");
1632 }
1633 
1634 static void esil_callx(xtensa_isa isa, xtensa_opcode opcode,
1635  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1636  bool callx = opcode == 77;
1637  ut32 dst_reg;
1638 
1639  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &dst_reg);
1640  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
1641 
1643  &op->esil,
1644  "%s%d" CM "0" CM "+" CM,
1645  xtensa_regfile_shortname(isa, dst_rf),
1646  dst_reg);
1647 
1648  if (callx) {
1650  &op->esil,
1651  "pc" CM
1652  "a0" CM
1653  "=" CM);
1654  }
1655 
1656  rz_strbuf_append(&op->esil, "pc" CM "=");
1657 }
1658 
1660  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1661  ut32 src_reg;
1662 
1663  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &src_reg);
1664  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 0);
1665 
1667  &op->esil,
1668  "%s%d" CM
1669  "sar" CM
1670  "=",
1671  xtensa_regfile_shortname(isa, src_rf),
1672  src_reg);
1673 }
1674 
1676  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1677  ut32 sa_imm;
1678 
1679  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &sa_imm);
1680  xtensa_operand_decode(isa, opcode, 0, &sa_imm);
1681 
1683  &op->esil,
1684  "0x%x" CM
1685  "sar" CM
1686  "=",
1687  sa_imm);
1688 }
1689 
1691  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1692  ut32 reg_dst;
1693  ut32 reg_src;
1694  ut32 imm_amount;
1695 
1696  const char *shift_op = "";
1697 
1698  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &reg_dst);
1699  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &reg_src);
1700  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, &imm_amount);
1701  xtensa_operand_decode(isa, opcode, 2, &imm_amount);
1702 
1703  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
1704  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
1705 
1706  // srli
1707  if (opcode == 113) {
1708  shift_op = ">>";
1709  } else {
1710  shift_op = "<<";
1711  }
1712 
1714  &op->esil,
1715  "0x%x" CM
1716  "%s%d" CM
1717  "%s" CM
1718  "%s%d" CM
1719  "=",
1720  imm_amount,
1721  xtensa_regfile_shortname(isa, src_rf),
1722  reg_src,
1723  shift_op,
1724  xtensa_regfile_shortname(isa, dst_rf),
1725  reg_dst);
1726 }
1727 
1729  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1730  ut32 reg_dst;
1731  ut32 reg_src;
1732 
1733  const char *shift_op = "";
1734 
1735  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &reg_dst);
1736  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &reg_src);
1737 
1738  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
1739  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
1740 
1741  // srl
1742  if (opcode == 109) {
1743  shift_op = ">>";
1744  } else {
1745  shift_op = "<<";
1746  }
1747 
1749  &op->esil,
1750  "sar" CM
1751  "%s%d" CM
1752  "%s" CM
1753  "%s%d" CM
1754  "=",
1755  xtensa_regfile_shortname(isa, src_rf),
1756  reg_src,
1757  shift_op,
1758  xtensa_regfile_shortname(isa, dst_rf),
1759  reg_dst);
1760 }
1761 
1763  xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1764  ut32 reg_dst;
1765  ut32 reg_src;
1766  ut32 imm_shift;
1767  ut32 imm_mask;
1768 
1769  xtensa_operand_get_field(isa, opcode, 0, format, i, slot_buffer, &reg_dst);
1770  xtensa_operand_get_field(isa, opcode, 1, format, i, slot_buffer, &reg_src);
1771  xtensa_operand_get_field(isa, opcode, 2, format, i, slot_buffer, &imm_shift);
1772  xtensa_operand_get_field(isa, opcode, 3, format, i, slot_buffer, &imm_mask);
1773 
1774  xtensa_regfile dst_rf = xtensa_operand_regfile(isa, opcode, 0);
1775  xtensa_regfile src_rf = xtensa_operand_regfile(isa, opcode, 1);
1776 
1777  ut32 and_mask = (1 << (imm_mask + 1)) - 1;
1778 
1780  &op->esil,
1781  "0x%x" CM
1782  "%s%d" CM
1783  ">>" CM
1784  "0x%x" CM
1785  "&" CM
1786  "%s%d" CM
1787  "=",
1788  imm_shift,
1789  xtensa_regfile_shortname(isa, src_rf),
1790  reg_src,
1791  and_mask,
1792  xtensa_regfile_shortname(isa, dst_rf),
1793  reg_dst);
1794 }
1795 
1796 static void analop_esil(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format,
1797  size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op) {
1798  switch (opcode) {
1799  case 26: /* add.n */
1800  case 41: /* add */
1801  case 43: /* addx2 */
1802  case 44: /* addx4 */
1803  case 45: /* addx8 */
1804  case 42: /* sub */
1805  case 46: /* subx2 */
1806  case 47: /* subx4 */
1807  case 48: /* subx8 */
1808  esil_add_sub(isa, opcode, format, i, slot_buffer, op);
1809  break;
1810  case 32: /* mov.n */
1811  esil_move(isa, opcode, format, i, slot_buffer, op);
1812  break;
1813  case 90: /* movi */
1814  case 33: /* movi.n */
1815  esil_move_imm(isa, opcode, format, i, slot_buffer, op);
1816  break;
1817  case 0: /* excw */
1818  case 34: /* nop.n */
1819  rz_strbuf_setf(&op->esil, "%s", "");
1820  break;
1821  // TODO: s32cli (s32c1i) is conditional (CAS)
1822  // should it be handled here?
1823  case 453: /* s32c1i */
1824  case 36: /* s32i.n */
1825  case 100: /* s32i */
1826  case 99: /* s16i */
1827  case 101: /* s8i */
1828  esil_store_imm(isa, opcode, format, i, slot_buffer, op);
1829  break;
1830  case 27: /* addi.n */
1831  case 39: /* addi */
1832  xtensa_check_stack_op(isa, opcode, format, i, slot_buffer, op);
1833  esil_add_imm(isa, opcode, format, i, slot_buffer, op);
1834  break;
1835  case 98: /* ret */
1836  case 35: /* ret.n */
1837  rz_strbuf_setf(&op->esil, "a0,pc,=");
1838  break;
1839  case 82: /* l16ui */
1840  case 83: /* l16si */
1841  case 84: /* l32i */
1842  case 31: /* l32i.n */
1843  case 86: /* l8ui */
1844  esil_load_imm(isa, opcode, format, i, slot_buffer, op);
1845  break;
1846  // TODO: s32r
1847  // l32r is different because it is relative to LITBASE
1848  // which also may or may not be present
1849  case 85: /* l32r */
1850  esil_load_relative(isa, opcode, format, i, slot_buffer, op);
1851  break;
1852  case 40: /* addmi */
1853  break;
1854  case 49: /* and */
1855  case 50: /* or */
1856  case 51: /* xor */
1857  esil_bitwise_op(isa, opcode, format, i, slot_buffer, op);
1858  break;
1859  case 52: /* beqi */
1860  case 53: /* bnei */
1861  case 54: /* bgei */
1862  case 55: /* blti */
1863  case 58: /* bgeui */
1864  case 59: /* bltui */
1865  esil_branch_compare_imm(isa, opcode, format, i, slot_buffer, op);
1866  break;
1867  case 56: /* bbci */
1868  case 57: /* bbsi */
1869  esil_branch_check_bit_imm(isa, opcode, format, i, slot_buffer, op);
1870  break;
1871  case 60: /* beq */
1872  case 61: /* bne */
1873  case 62: /* bge */
1874  case 63: /* blt */
1875  case 64: /* bgeu */
1876  case 65: /* bltu */
1877  esil_branch_compare(isa, opcode, format, i, slot_buffer, op);
1878  break;
1879  case 66: /* bany */
1880  case 67: /* bnone */
1881  case 68: /* ball */
1882  case 69: /* bnall */
1883  esil_branch_check_mask(isa, opcode, format, i, slot_buffer, op);
1884  break;
1885  case 70: /* bbc */
1886  case 71: /* bbs */
1887  esil_branch_check_bit(isa, opcode, format, i, slot_buffer, op);
1888  break;
1889  case 72: /* beqz */
1890  case 73: /* bnez */
1891  case 28: /* beqz.n */
1892  case 29: /* bnez.n */
1893  case 74: /* bgez */
1894  case 75: /* bltz */
1895  esil_branch_compare_single(isa, opcode, format, i, slot_buffer, op);
1896  break;
1897  case 78: /* extui */
1898  esil_extract_unsigned(isa, opcode, format, i, slot_buffer, op);
1899  break;
1900  case 79: /* ill */
1901  rz_strbuf_setf(&op->esil, "%s", "");
1902  break;
1903  // TODO: windowed calls?
1904  case 7: /* call4 */
1905  break;
1906  case 76: /* call0 */
1907  case 80: /* j */
1908  esil_call(isa, opcode, format, i, slot_buffer, op);
1909  break;
1910  case 81: /* jx */
1911  case 77: /* callx0 */
1912  esil_callx(isa, opcode, format, i, slot_buffer, op);
1913  break;
1914  case 91: /* moveqz */
1915  case 92: /* movnez */
1916  case 93: /* movltz */
1917  case 94: /* movgez */
1918  esil_move_conditional(isa, opcode, format, i, slot_buffer, op);
1919  break;
1920  case 96: /* abs */
1921  case 95: /* neg */
1922  esil_abs_neg(isa, opcode, format, i, slot_buffer, op);
1923  break;
1924  case 102: /* ssr */
1925  case 103: /* ssl */
1926  esil_set_shift_amount(isa, opcode, format, i, slot_buffer, op);
1927  break;
1928  case 111: /* slli */
1929  case 113: /* srli */
1930  esil_shift_logic_imm(isa, opcode, format, i, slot_buffer, op);
1931  break;
1932  case 106: /* ssai */
1933  esil_set_shift_amount_imm(isa, opcode, format, i, slot_buffer, op);
1934  break;
1935  case 107: /* sll */
1936  case 109: /* srl */
1937  esil_shift_logic_sar(isa, opcode, format, i, slot_buffer, op);
1938  break;
1939  }
1940 }
1941 
1942 static int xtensa_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf_original, int len_original, RzAnalysisOpMask mask) {
1943  if (!op) {
1944  return 1;
1945  }
1946 
1947  op->size = xtensa_length(buf_original);
1948  if (op->size > len_original) {
1949  return 1;
1950  }
1951 
1952  xtensa_op0_fns[(buf_original[0] & 0xf)](analysis, op, addr, buf_original);
1953 
1954  ut8 buffer[XTENSA_MAX_LENGTH] = { 0 };
1955  int len = RZ_MIN(op->size, XTENSA_MAX_LENGTH);
1956  memcpy(buffer, buf_original, len);
1957 
1958  unsigned int i;
1959  if (!xtensa_default_isa) {
1961  }
1962 
1963  xtensa_opcode opcode;
1965  xtensa_format format;
1966  int nslots;
1967 
1968  static xtensa_insnbuf insn_buffer = NULL;
1969  static xtensa_insnbuf slot_buffer = NULL;
1970 
1971  if (!insn_buffer) {
1972  insn_buffer = xtensa_insnbuf_alloc(isa);
1973  slot_buffer = xtensa_insnbuf_alloc(isa);
1974  }
1975 
1976  memset(insn_buffer, 0, xtensa_insnbuf_size(isa) * sizeof(xtensa_insnbuf_word));
1977 
1978  xtensa_insnbuf_from_chars(isa, insn_buffer, buffer, len);
1979  format = xtensa_format_decode(isa, insn_buffer);
1980 
1981  if (format == XTENSA_UNDEFINED) {
1982  return op->size;
1983  }
1984 
1985  nslots = xtensa_format_num_slots(isa, format);
1986  if (nslots < 1) {
1987  return op->size;
1988  }
1989 
1990  for (i = 0; i < nslots; i++) {
1991  xtensa_format_get_slot(isa, format, i, insn_buffer, slot_buffer);
1992  opcode = xtensa_opcode_decode(isa, format, i, slot_buffer);
1993 
1994  if (opcode == 39) { /* addi */
1995  xtensa_check_stack_op(isa, opcode, format, i, slot_buffer, op);
1996  }
1997 
1999  analop_esil(isa, opcode, format, i, slot_buffer, op);
2000  }
2001  }
2002 
2003  return op->size;
2004 }
2005 
2006 static char *get_reg_profile(RzAnalysis *analysis) {
2007  return strdup(
2008  // Assuming call0 ABI
2009  "# a0 return address\n"
2010  "# a1 stack pointer\n"
2011  "# a2-a7 arguments\n"
2012  "# a2-a5 return value (call0 ABI)\n"
2013  "# a12-a15 callee-saved (call0 ABI)\n"
2014  "=PC pc\n"
2015  "=BP a14\n"
2016  "=SP a1\n"
2017  "=A0 a2\n"
2018  "=A1 a3\n"
2019  "=A2 a4\n"
2020  "=A3 a5\n"
2021  "=A4 a6\n"
2022  "=A5 a7\n"
2023  "gpr a0 .32 0 0\n"
2024  "gpr a1 .32 4 0\n"
2025  "gpr a2 .32 8 0\n"
2026  "gpr a3 .32 16 0\n"
2027  "gpr a4 .32 20 0\n"
2028  "gpr a5 .32 24 0\n"
2029  "gpr a6 .32 28 0\n"
2030  "gpr a7 .32 32 0\n"
2031  "gpr a8 .32 36 0\n"
2032  "gpr a9 .32 40 0\n"
2033  "gpr a10 .32 44 0\n"
2034  "gpr a11 .32 48 0\n"
2035  "gpr a12 .32 52 0\n"
2036  "gpr a13 .32 56 0\n"
2037  "gpr a14 .32 60 0\n"
2038  "gpr a15 .32 64 0\n"
2039 
2040  // pc
2041  "gpr pc .32 68 0\n"
2042 
2043  // sr
2044  "gpr sar .32 72 0\n");
2045 }
2046 
2048  .name = "xtensa",
2049  .desc = "Xtensa disassembler",
2050  .license = "LGPL3",
2051  .arch = "xtensa",
2052  .bits = 8,
2053  .esil = true,
2054  .op = &xtensa_op,
2055  .get_reg_profile = get_reg_profile,
2056 };
2057 
2058 #ifndef RZ_PLUGIN_INCORE
2061  .data = &rz_analysis_plugin_xtensa,
2062  .version = RZ_VERSION
2063 };
2064 #endif
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
@ branch_imm
Definition: aarch64.h:482
#define bit_mask
#define mask()
#define imm
static void esil_branch_compare_single(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_mul_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_si_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_unk_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_null_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_bitwise_op(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void esil_move(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static char * get_reg_profile(RzAnalysis *analysis)
static void xtensa_div_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_rt0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_shr_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void sign_extend2(st32 *value, ut8 bit1, ut8 bit2, ut8 shift)
static XtensaOpFn xtensa_op0_fns[]
static void xtensa_shl_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_call(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_lscx_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_fp0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_add_sub(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
RzAnalysisPlugin rz_analysis_plugin_xtensa
static void esil_move_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void esil_set_shift_amount(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void analop_esil(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_store_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_rst1_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_fp1_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_branch_compare_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_l32r_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_rst2_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_load_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static int xtensa_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf_original, int len_original, RzAnalysisOpMask mask)
static void sign_extend(st32 *value, ut8 bit)
#define XTENSA_MAX_LENGTH
static ut64 xtensa_imm8s(ut64 addr, ut8 imm8)
static void xtensa_and_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_st3n_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_store_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_rfei_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_branch_check_bit_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static XtensaOpFn xtensa_lsai_fns[]
static void xtensa_mov_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_check_stack_op(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_b_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
RZ_API RzLibStruct rizin_plugin
static void esil_sign_extend(RzStrBuf *esil, ut8 bit)
static void esil_shift_logic_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_rst0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static XtensaOpFn xtensa_rst1_fns[]
static void esil_abs_neg(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
#define CM
static void xtensa_qrst_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_branch_check_bit(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_lsai_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static XtensaOpFn xtensa_qrst_fns[]
static ut64 xtensa_offset(ut64 addr, const ut8 *buf)
static void esil_callx(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_calln_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static XtensaOpFn xtensa_rst0_fns[]
static void esil_extract_unsigned(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void esil_load_relative(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void esil_branch_compare(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void esil_set_shift_amount_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_tlb_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_shift_logic_sar(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_sub_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
void(* XtensaOpFn)(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_load_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_or_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_sync_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_xor_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static XtensaOpFn xtensa_rst2_fns[]
static void esil_branch_check_mask(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static ut64 xtensa_imm12s(ut64 addr, const ut8 *buf)
static void xtensa_st2n_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_st1_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static int xtensa_length(const ut8 *insn)
static void esil_push_signed_imm(RzStrBuf *esil, st32 imm)
static void xtensa_mod_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_st0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static ut64 xtensa_imm18s(ut64 addr, const ut8 *buf)
static void xtensa_accer_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_lsci_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_snm0_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void xtensa_add_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_add_imm(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static void xtensa_imp_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static void esil_move_conditional(xtensa_isa isa, xtensa_opcode opcode, xtensa_format format, size_t i, xtensa_insnbuf slot_buffer, RzAnalysisOp *op)
static ut64 xtensa_imm6s(ut64 addr, const ut8 *buf)
static void xtensa_lsc4_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
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 ut32 neg(ArmOp *op)
Definition: armass64.c:981
int call(int a, int b)
Definition: bcj_test.c:25
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RzCryptoSelector bit
Definition: crypto.c:16
#define r
Definition: crypto_rc6.c:12
uint16_t ut16
uint32_t ut32
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
char * dst
Definition: lz4.h:724
int n
Definition: mipsasm.c:19
#define compare_op(...)
Definition: opcode.h:158
static const char * cmp_op[]
Definition: pyc_dis.c:7
@ RZ_ANALYSIS_STACK_INC
Definition: rz_analysis.h:457
@ RZ_ANALYSIS_OP_FAMILY_FPU
Definition: rz_analysis.h:313
RzAnalysisOpMask
Definition: rz_analysis.h:439
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
@ RZ_ANALYSIS_OP_TYPE_CMP
Definition: rz_analysis.h:399
@ RZ_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_LOAD
Definition: rz_analysis.h:416
@ RZ_ANALYSIS_OP_TYPE_UNK
Definition: rz_analysis.h:388
@ RZ_ANALYSIS_OP_TYPE_MUL
Definition: rz_analysis.h:404
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_AND
Definition: rz_analysis.h:411
@ RZ_ANALYSIS_OP_TYPE_MOD
Definition: rz_analysis.h:422
@ RZ_ANALYSIS_OP_TYPE_UPUSH
Definition: rz_analysis.h:395
@ RZ_ANALYSIS_OP_TYPE_UJMP
Definition: rz_analysis.h:369
@ RZ_ANALYSIS_OP_TYPE_IO
Definition: rz_analysis.h:403
@ RZ_ANALYSIS_OP_TYPE_SWI
Definition: rz_analysis.h:393
@ RZ_ANALYSIS_OP_TYPE_ABS
Definition: rz_analysis.h:428
@ RZ_ANALYSIS_OP_TYPE_NULL
Definition: rz_analysis.h:367
@ RZ_ANALYSIS_OP_TYPE_CMOV
Definition: rz_analysis.h:391
@ RZ_ANALYSIS_OP_TYPE_TRAP
Definition: rz_analysis.h:392
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_OR
Definition: rz_analysis.h:410
@ RZ_ANALYSIS_OP_TYPE_STORE
Definition: rz_analysis.h:415
@ RZ_ANALYSIS_OP_TYPE_SHR
Definition: rz_analysis.h:406
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_DIV
Definition: rz_analysis.h:405
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_SHL
Definition: rz_analysis.h:407
@ RZ_ANALYSIS_OP_TYPE_ILL
Definition: rz_analysis.h:387
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
@ RZ_ANALYSIS_OP_TYPE_NOT
Definition: rz_analysis.h:414
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_NOP
Definition: rz_analysis.h:389
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
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
#define RZ_MIN(x, y)
#define UT32_MAX
Definition: rz_types_base.h:99
#define st32
Definition: rz_types_base.h:12
#define RZ_VERSION
Definition: rz_version.h:8
#define cond(bop, top, mask, flags)
Definition: buffer.h:15
const char * version
Definition: rz_analysis.h:1239
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
const char * xtensa_regfile_shortname(xtensa_isa isa, xtensa_regfile rf)
Definition: xtensa-isa.c:1474
int xtensa_format_get_slot(xtensa_isa isa, xtensa_format fmt, int slot, const xtensa_insnbuf insn, xtensa_insnbuf slotbuf)
Definition: xtensa-isa.c:629
int xtensa_opcode
Definition: xtensa-isa.h:83
int xtensa_format
Definition: xtensa-isa.h:84
int xtensa_format_num_slots(xtensa_isa isa, xtensa_format fmt)
Definition: xtensa-isa.c:606
uint32 xtensa_insnbuf_word
Definition: xtensa-isa.h:178
int xtensa_regfile
Definition: xtensa-isa.h:85
xtensa_opcode xtensa_opcode_decode(xtensa_isa isa, xtensa_format fmt, int slot, const xtensa_insnbuf slotbuf)
Definition: xtensa-isa.c:708
xtensa_insnbuf_word * xtensa_insnbuf
Definition: xtensa-isa.h:179
int xtensa_insnbuf_size(xtensa_isa isa)
Definition: xtensa-isa.c:80
xtensa_regfile xtensa_operand_regfile(xtensa_isa isa, xtensa_opcode opc, int opnd)
Definition: xtensa-isa.c:1173
int xtensa_operand_get_field(xtensa_isa isa, xtensa_opcode opc, int opnd, xtensa_format fmt, int slot, const xtensa_insnbuf slotbuf, uint32 *valp)
Definition: xtensa-isa.c:975
int xtensa_operand_decode(xtensa_isa isa, xtensa_opcode opc, int opnd, uint32 *valp)
Definition: xtensa-isa.c:1128
#define XTENSA_UNDEFINED
Definition: xtensa-isa.h:93
xtensa_format xtensa_format_decode(xtensa_isa isa, const xtensa_insnbuf insn)
Definition: xtensa-isa.c:570
void xtensa_insnbuf_from_chars(xtensa_isa isa, xtensa_insnbuf insn, const unsigned char *cp, int num_chars)
Definition: xtensa-isa.c:196
xtensa_isa xtensa_isa_init(xtensa_isa_status *errno_p, char **error_msg_p)
Definition: xtensa-isa.c:248
xtensa_isa xtensa_default_isa
Definition: elf32-xtensa.c:147
xtensa_insnbuf xtensa_insnbuf_alloc(xtensa_isa isa)
Definition: xtensa-isa.c:88
static int length_table[16]
static int addr
Definition: z80asm.c:58