Rizin
unix-like reverse engineering framework and cli tools
avr_esil.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2019 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2011-2019 Roc Valles <vallesroc@gmail.com>
3 // SPDX-FileCopyrightText: 2011-2019 condret <condr3t@protonmail.com>
4 // SPDX-FileCopyrightText: 2011-2019 killabyte <killabytenow@gmail.com>
5 // SPDX-FileCopyrightText: 2022 deroad <wargio@libero.it>
6 // SPDX-License-Identifier: LGPL-3.0-only
7 
8 #include "avr_esil.h"
9 #include <rz_crypto.h>
10 
19 typedef struct _cpu_const_tag {
20  const char *const key;
25 
26 #define CPU_CONST_NONE 0
27 #define CPU_CONST_PARAM 1
28 #define CPU_CONST_REG 2
29 
30 typedef struct _cpu_model_tag {
31  const char *const model;
32  int pc;
33  char *inherit;
37 
38 typedef void (*inst_handler_t)(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 *buf, int len, int *fail, CPU_MODEL *cpu);
39 
40 typedef struct _opcodes_tag_ {
41  const char *const name;
42  int mask;
43  int selector;
45  int cycles;
46  int size;
49 
50 static OPCODE_DESC *avr_op_analyze(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, CPU_MODEL *cpu);
51 
52 #define CPU_MODEL_DECL(model, pc, consts) \
53  { \
54  model, \
55  pc, \
56  consts \
57  }
58 #define MASK(bits) ((bits) == 32 ? 0xffffffff : (~((~((ut32)0)) << (bits))))
59 #define CPU_PC_MASK(cpu) MASK((cpu)->pc)
60 #define CPU_PC_SIZE(cpu) ((((cpu)->pc) >> 3) + ((((cpu)->pc) & 0x07) ? 1 : 0))
61 
62 #define INST_HANDLER(OPCODE_NAME) static void _inst__##OPCODE_NAME(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 *buf, int len, int *fail, CPU_MODEL *cpu)
63 #define INST_DECL(OP, M, SL, C, SZ, T) \
64  { #OP, (M), (SL), _inst__##OP, (C), (SZ), RZ_ANALYSIS_OP_TYPE_##T }
65 #define INST_LAST \
66  { "unknown", 0, 0, (void *)0, 2, 1, RZ_ANALYSIS_OP_TYPE_UNK }
67 
68 #define INST_CALL(OPCODE_NAME) _inst__##OPCODE_NAME(analysis, op, buf, len, fail, cpu)
69 #define INST_INVALID \
70  { \
71  *fail = 1; \
72  return; \
73  }
74 #define INST_ASSERT(x) \
75  { \
76  if (!(x)) { \
77  INST_INVALID; \
78  } \
79  }
80 
81 #define ESIL_A(e, ...) rz_strbuf_appendf(&op->esil, e, ##__VA_ARGS__)
82 
83 #define STR_BEGINS(in, s) rz_str_ncasecmp(in, s, strlen(s))
84 
85 // Following IO definitions are valid for:
86 // ATmega8
87 // ATmega88
89  { "spl", CPU_CONST_REG, 0x3d, sizeof(ut8) },
90  { "sph", CPU_CONST_REG, 0x3e, sizeof(ut8) },
91  { "sreg", CPU_CONST_REG, 0x3f, sizeof(ut8) },
92  { "spmcsr", CPU_CONST_REG, 0x37, sizeof(ut8) },
93  { NULL, 0, 0, 0 },
94 };
95 
97  { "eeprom_size", CPU_CONST_PARAM, 512, sizeof(ut32) },
98  { "io_size", CPU_CONST_PARAM, 0x40, sizeof(ut32) },
99  { "sram_start", CPU_CONST_PARAM, 0x60, sizeof(ut32) },
100  { "sram_size", CPU_CONST_PARAM, 1024, sizeof(ut32) },
101  { NULL, 0, 0, 0 },
102 };
103 
105  { "eeprom_size", CPU_CONST_PARAM, 512, sizeof(ut32) },
106  { "io_size", CPU_CONST_PARAM, 0x1ff, sizeof(ut32) },
107  { "sram_start", CPU_CONST_PARAM, 0x200, sizeof(ut32) },
108  { "sram_size", CPU_CONST_PARAM, 0x2000, sizeof(ut32) },
109  { NULL, 0, 0, 0 },
110 };
111 
113  { "eeprom_size", CPU_CONST_PARAM, 0x800, sizeof(ut32) },
114  { "io_size", CPU_CONST_PARAM, 0x1000, sizeof(ut32) },
115  { "sram_start", CPU_CONST_PARAM, 0x800, sizeof(ut32) },
116  { "sram_size", CPU_CONST_PARAM, 0x2000, sizeof(ut32) },
117  { NULL, 0, 0, 0 },
118 };
119 
121  { "page_size", CPU_CONST_PARAM, 5, sizeof(ut8) },
122  { NULL, 0, 0, 0 },
123 };
124 
126  { "page_size", CPU_CONST_PARAM, 7, sizeof(ut8) },
127  { NULL, 0, 0, 0 },
128 };
129 
131  {
132  .model = "ATmega640",
133  .pc = 15,
134  .consts = {
138  NULL },
139  },
140  { .model = "ATxmega128a4u", .pc = 17, .consts = { cpu_reg_common, cpu_memsize_xmega128a4u, cpu_pagesize_7_bits, NULL } },
141  { .model = "ATmega1280", .pc = 16, .inherit = "ATmega640" },
142  { .model = "ATmega1281", .pc = 16, .inherit = "ATmega640" },
143  { .model = "ATmega2560", .pc = 17, .inherit = "ATmega640" },
144  { .model = "ATmega2561", .pc = 17, .inherit = "ATmega640" },
145  { .model = "ATmega88", .pc = 8, .inherit = "ATmega8" },
146  // CPU_MODEL_DECL ("ATmega168", 13, 512, 512),
147  // last model is the default AVR - ATmega8 forever!
148  { .model = "ATmega8", .pc = 13, .consts = { cpu_reg_common, cpu_memsize_common, cpu_pagesize_5_bits, NULL } },
149 };
150 
151 static CPU_MODEL *get_cpu_model(char *model);
152 
153 static CPU_MODEL *__get_cpu_model_recursive(char *model) {
154  if (!model) {
155  return &cpu_models[0];
156  }
157  CPU_MODEL *cpu = NULL;
158 
159  for (cpu = cpu_models; cpu < cpu_models + ((sizeof(cpu_models) / sizeof(CPU_MODEL))) - 1; cpu++) {
160  if (!rz_str_casecmp(model, cpu->model)) {
161  break;
162  }
163  }
164 
165  // fix inheritance tree
166  if (cpu->inherit && !cpu->inherit_cpu_p) {
167  cpu->inherit_cpu_p = get_cpu_model(cpu->inherit);
168  if (!cpu->inherit_cpu_p) {
169  RZ_LOG_ERROR("Cannot inherit from unknown CPU model '%s'.\n", cpu->inherit);
170  }
171  }
172 
173  return cpu;
174 }
175 
176 static CPU_MODEL *get_cpu_model(char *model) {
177  if (!model) {
178  return &cpu_models[0];
179  }
180  static CPU_MODEL *cpu = NULL;
181  // cached value?
182  if (cpu && !rz_str_casecmp(model, cpu->model)) {
183  return cpu;
184  }
185  // do the real search
187  return cpu;
188 }
189 
191  return c ? MASK(c->size * 8) & c->value : 0;
192 }
193 
194 static CPU_CONST *const_by_name(CPU_MODEL *cpu, int type, char *c) {
195  CPU_CONST **clist, *citem;
196 
197  for (clist = cpu->consts; *clist; clist++) {
198  for (citem = *clist; citem->key; citem++) {
199  if (!strcmp(c, citem->key) && (type == CPU_CONST_NONE || type == citem->type)) {
200  return citem;
201  }
202  }
203  }
204  if (cpu->inherit_cpu_p) {
205  return const_by_name(cpu->inherit_cpu_p, type, c);
206  }
207  RZ_LOG_ERROR("Cannot find const key[%s].\n", c);
208  return NULL;
209 }
210 
212  char *t = rz_analysis_esil_pop(esil);
213  if (!t || !rz_analysis_esil_get_parm(esil, t, v)) {
214  free(t);
215  return false;
216  }
217  free(t);
218  return true;
219 }
220 
222  CPU_CONST **clist, *citem;
223 
224  for (clist = cpu->consts; *clist; clist++) {
225  for (citem = *clist; citem && citem->key; citem++) {
226  if (citem->value == (MASK(citem->size * 8) & v) && (type == CPU_CONST_NONE || type == citem->type)) {
227  return citem;
228  }
229  }
230  }
231  if (cpu->inherit_cpu_p) {
232  return const_by_value(cpu->inherit_cpu_p, type, v);
233  }
234  return NULL;
235 }
236 
238  RzStrBuf *r = rz_strbuf_new("");
240  if (c != NULL) {
241  rz_strbuf_set(r, c->key);
242  if (write) {
243  rz_strbuf_append(r, ",=");
244  }
245  } else {
246  rz_strbuf_setf(r, "_io,%d,+,%s[1]", port, write ? "=" : "");
247  }
248 
249  return r;
250 }
251 
252 static void __generic_ld_st(RzAnalysisOp *op, char *mem, char ireg, int use_ramp, int prepostdec, int offset, int st) {
253  if (ireg) {
254  // preincrement index register
255  if (prepostdec < 0) {
256  ESIL_A("1,%c,-,%c,=,", ireg, ireg);
257  }
258  // set register index address
259  ESIL_A("%c,", ireg);
260  // add offset
261  if (offset != 0) {
262  ESIL_A("%d,+,", offset);
263  }
264  } else {
265  ESIL_A("%d,", offset);
266  }
267  if (use_ramp) {
268  ESIL_A("16,ramp%c,<<,+,", ireg ? ireg : 'd');
269  }
270  // set SRAM base address
271  ESIL_A("_%s,+,", mem);
272  // read/write from SRAM
273  ESIL_A("%s[1],", st ? "=" : "");
274  // postincrement index register
275  if (ireg && prepostdec > 0) {
276  ESIL_A("1,%c,+,%c,=,", ireg, ireg);
277  }
278 }
279 
280 static void __generic_pop(RzAnalysisOp *op, int sz) {
281  if (sz > 1) {
282  ESIL_A("1,sp,+,_ram,+,"); // calc SRAM(sp+1)
283  ESIL_A("[%d],", sz); // read value
284  ESIL_A("%d,sp,+=,", sz); // sp += item_size
285  } else {
286  ESIL_A("1,sp,+=," // increment stack pointer
287  "sp,_ram,+,[1],"); // load SRAM[sp]
288  }
289 }
290 
291 static void __generic_push(RzAnalysisOp *op, int sz) {
292  ESIL_A("sp,_ram,+,"); // calc pointer SRAM(sp)
293  if (sz > 1) {
294  ESIL_A("-%d,+,", sz - 1); // dec SP by 'sz'
295  }
296  ESIL_A("=[%d],", sz); // store value in stack
297  ESIL_A("-%d,sp,+=,", sz); // decrement stack pointer
298 }
299 
300 INST_HANDLER(adc) { // ADC Rd, Rr
301  // ROL Rd
302  if (len < 2) {
303  return;
304  }
305  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
306  const ut32 r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
307  ESIL_A("r%d,cf,+,r%d,+=,", r, d); // Rd + Rr + C
308  ESIL_A("$z,zf,:=,");
309  ESIL_A("3,$c,hf,:=,");
310  ESIL_A("7,$c,cf,:=,");
311  ESIL_A("7,$o,vf,:=,");
312  ESIL_A("0x80,r%d,&,!,!,nf,:=", d);
313 }
314 
315 INST_HANDLER(add) { // ADD Rd, Rr
316  // LSL Rd
317  if (len < 2) {
318  return;
319  }
320  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
321  const ut32 r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
322  ESIL_A("r%d,r%d,+=,", r, d); // Rd + Rr
323  ESIL_A("$z,zf,:=,");
324  ESIL_A("3,$c,hf,:=,");
325  ESIL_A("7,$c,cf,:=,");
326  ESIL_A("7,$o,vf,:=,");
327  ESIL_A("0x80,r%d,&,!,!,nf,:=,", d);
328 }
329 
330 INST_HANDLER(adiw) { // ADIW Rd+1:Rd, K
331  if (len < 1) {
332  return;
333  }
334  const ut32 d = ((buf[0] & 0x30) >> 3) + 24;
335  const ut32 k = (buf[0] & 0x0f) | ((buf[0] >> 2) & 0x30);
336  ESIL_A("7,r%d,>>,", d + 1); // remember previous highest bit
337  ESIL_A("8,%d,8,r%d,<<,r%d,|,+,DUP,r%d,=,>>,r%d,=,", k, d + 1, d, d, d + 1); // Rd+1_Rd + k
338  // FLAGS:
339  ESIL_A("DUP,!,7,r%d,>>,&,vf,:=,", d + 1); // V
340  ESIL_A("r%d,0x80,&,!,!,nf,:=,", d + 1); // N
341  ESIL_A("8,r%d,<<,r%d,|,!,zf,:=,", d + 1, d); // Z
342  ESIL_A("7,r%d,>>,!,&,cf,:=,", d + 1); // C
343  ESIL_A("vf,nf,^,sf,:="); // S
344 }
345 
346 INST_HANDLER(and) { // AND Rd, Rr
347  // TST Rd
348  if (len < 2) {
349  return;
350  }
351  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
352  const ut32 r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
353  ESIL_A("r%d,r%d,&=,$z,zf,:=,r%d,0x80,&,!,!,nf,:=,0,vf,:=,nf,sf,:=,", r, d, d);
354 }
355 
356 INST_HANDLER(andi) { // ANDI Rd, K
357  // CBR Rd, K (= ANDI Rd, 1-K)
358  if (len < 2) {
359  return;
360  }
361  const ut32 d = ((buf[0] >> 4) & 0xf) + 16;
362  const ut32 k = ((buf[1] & 0x0f) << 4) | (buf[0] & 0x0f);
363  ESIL_A("%d,r%d,&=,$z,zf,:=,r%d,0x80,&,!,!,nf,:=,0,vf,:=,nf,sf,:=,", k, d, d);
364 }
365 
366 INST_HANDLER(asr) { // ASR Rd
367  if (len < 2) {
368  return;
369  }
370  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
371  ESIL_A("r%d,0x1,&,cf,:=,0x1,r%d,>>,r%d,0x80,&,|,", d, d, d);
372  // 0: R=(Rd >> 1) | Rd7
373  ESIL_A("$z,zf,:=,"); // Z
374  ESIL_A("r%d,0x80,&,!,!,nf,:=,", d); // N
375  ESIL_A("nf,cf,^,vf,:=,"); // V
376  ESIL_A("nf,vf,^,sf,:=,"); // S
377 }
378 
379 INST_HANDLER(bclr) { // BCLR s
380  // CLC
381  // CLH
382  // CLI
383  // CLN
384  // CLR
385  // CLS
386  // CLT
387  // CLV
388  // CLZ
389  if (len < 1) {
390  return;
391  }
392  int s = (buf[0] >> 4) & 0x7;
393  ESIL_A("0xff,%d,1,<<,^,sreg,&=,", s);
394 }
395 
396 INST_HANDLER(bld) { // BLD Rd, b
397  if (len < 2) {
398  return;
399  }
400  int d = ((buf[1] & 0x01) << 4) | ((buf[0] >> 4) & 0xf);
401  int b = buf[0] & 0x7;
402  ESIL_A("r%d,%d,1,<<,0xff,^,&,", d, b); // Rd/b = 0
403  ESIL_A("%d,tf,<<,|,r%d,=,", b, d); // Rd/b |= T<<b
404 }
405 
406 INST_HANDLER(brbx) { // BRBC s, k
407  // BRBS s, k
408  // BRBC/S 0: BRCC BRCS
409  // BRSH BRLO
410  // BRBC/S 1: BREQ BRNE
411  // BRBC/S 2: BRPL BRMI
412  // BRBC/S 3: BRVC BRVS
413  // BRBC/S 4: BRGE BRLT
414  // BRBC/S 5: BRHC BRHS
415  // BRBC/S 6: BRTC BRTS
416  // BRBC/S 7: BRID BRIE
417  if (len < 2) {
418  return;
419  }
420  int s = buf[0] & 0x7;
421  ut64 jump = op->addr + ((((buf[1] & 0x03) << 6) | ((buf[0] & 0xf8) >> 2)) | (buf[1] & 0x2 ? ~((int)0x7f) : 0)) + 2;
422  ESIL_A("%d,1,<<,sreg,&,", s); // SREG(s)
423  ESIL_A(buf[1] & 0x4
424  ? "!," // BRBC => branch if cleared
425  : "!,!,"); // BRBS => branch if set
426  ESIL_A("?{,%" PFMT64d ",pc,=,},", jump); // ?true => jmp
427 }
428 
429 INST_HANDLER(break) { // BREAK
430  ESIL_A("BREAK");
431 }
432 
433 INST_HANDLER(bset) { // BSET s
434  // SEC
435  // SEH
436  // SEI
437  // SEN
438  // SER
439  // SES
440  // SET
441  // SEV
442  // SEZ
443  if (len < 1) {
444  return;
445  }
446  int s = (buf[0] >> 4) & 0x7;
447  ESIL_A("%d,1,<<,sreg,|=,", s);
448 }
449 
450 INST_HANDLER(bst) { // BST Rd, b
451  if (len < 2) {
452  return;
453  }
454  ESIL_A("r%d,%d,1,<<,&,!,!,tf,=,", // tf = Rd/b
455  ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf), // r
456  buf[0] & 0x7); // b
457 }
458 
459 INST_HANDLER(call) { // CALL k
460  if (len < 4) {
461  return;
462  }
463  ut64 jump = (buf[2] << 1) | (buf[3] << 9) | (buf[1] & 0x01) << 23 | (buf[0] & 0x01) << 17 | (buf[0] & 0xf0) << 14;
464  ESIL_A("pc,"); // esil is already pointing to
465  // next instruction (@ret)
466  __generic_push(op, CPU_PC_SIZE(cpu)); // push @ret in stack
467  ESIL_A("%" PFMT64d ",pc,=,", jump); // jump!
468 }
469 
470 INST_HANDLER(cbi) { // CBI A, b
471  if (len < 1) {
472  return;
473  }
474  int a = (buf[0] >> 3) & 0x1f;
475  int b = buf[0] & 0x07;
476  RzStrBuf *io_port;
477 
478  // read port a and clear bit b
479  io_port = __generic_io_dest(a, 0, cpu);
480  ESIL_A("0xff,%d,1,<<,^,%s,&,", b, rz_strbuf_get(io_port));
481  rz_strbuf_free(io_port);
482 
483  // write result to port a
484  io_port = __generic_io_dest(a, 1, cpu);
485  ESIL_A("%s,", rz_strbuf_get(io_port));
486  rz_strbuf_free(io_port);
487 }
488 
489 INST_HANDLER(com) { // COM Rd
490  if (len < 2) {
491  return;
492  }
493  int r = ((buf[0] >> 4) & 0x0f) | ((buf[1] & 1) << 4);
494 
495  ESIL_A("r%d,0xff,-,r%d,=,$z,zf,:=,0,cf,:=,0,vf,:=,r%d,0x80,&,!,!,nf,:=,vf,nf,^,sf,:=", r, r, r);
496  // Rd = 0xFF-Rd
497 }
498 
499 INST_HANDLER(cp) { // CP Rd, Rr
500  if (len < 2) {
501  return;
502  }
503  const ut32 r = (buf[0] & 0x0f) | ((buf[1] << 3) & 0x10);
504  const ut32 d = ((buf[0] >> 4) & 0x0f) | ((buf[1] << 4) & 0x10);
505  ESIL_A("r%d,r%d,-,0x80,&,!,!,nf,:=,", r, d);
506  ESIL_A("r%d,r%d,==,", r, d);
507  ESIL_A("$z,zf,:=,");
508  ESIL_A("3,$b,hf,:=,");
509  ESIL_A("8,$b,cf,:=,");
510  ESIL_A("7,$o,vf,:=,");
511  ESIL_A("vf,nf,^,sf,:=");
512 }
513 
514 INST_HANDLER(cpc) { // CPC Rd, Rr
515  if (len < 2) {
516  return;
517  }
518  const ut32 r = (buf[0] & 0x0f) | ((buf[1] << 3) & 0x10);
519  const ut32 d = ((buf[0] >> 4) & 0x0f) | ((buf[1] << 4) & 0x10);
520 
521  ESIL_A("cf,r%d,+,DUP,r%d,-,0x80,&,!,!,nf,:=,", r, d); // Rd - Rr - C
522  ESIL_A("r%d,==,", d);
523  ESIL_A("$z,zf,:=,");
524  ESIL_A("3,$b,hf,:=,");
525  ESIL_A("8,$b,cf,:=,");
526  ESIL_A("7,$o,vf,:=,");
527  ESIL_A("vf,nf,^,sf,:=");
528 }
529 
530 INST_HANDLER(cpi) { // CPI Rd, K
531  if (len < 2) {
532  return;
533  }
534  const ut32 d = ((buf[0] >> 4) & 0xf) + 16;
535  const ut32 k = (buf[0] & 0xf) | ((buf[1] & 0xf) << 4);
536  ESIL_A("%d,r%d,-,0x80,&,!,!,nf,:=,", k, d); // Rd - k
537  ESIL_A("%d,r%d,==,", k, d);
538  ESIL_A("$z,zf,:=,");
539  ESIL_A("3,$b,hf,:=,");
540  ESIL_A("8,$b,cf,:=,");
541  ESIL_A("7,$o,vf,:=,");
542  ESIL_A("vf,nf,^,sf,:=");
543 }
544 
545 INST_HANDLER(cpse) { // CPSE Rd, Rr
546  if (len < 2) {
547  return;
548  }
549  int r = (buf[0] & 0xf) | ((buf[1] & 0x2) << 3);
550  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
551  ESIL_A("r%d,r%d,^,!,", r, d); // Rr == Rd
552  ESIL_A("?{,%" PFMT64d ",pc,=,},", op->jump); // ?true => jmp
553 }
554 
555 INST_HANDLER(dec) { // DEC Rd
556  if (len < 2) {
557  return;
558  }
559  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
560  ESIL_A("0x1,r%d,-=,", d); // Rd--
561  // FLAGS:
562  ESIL_A("7,$o,vf,:=,"); // V
563  ESIL_A("r%d,0x80,&,!,!,nf,:=,", d); // N
564  ESIL_A("$z,zf,:=,"); // Z
565  ESIL_A("vf,nf,^,sf,:=,"); // S
566 }
567 
568 INST_HANDLER(des) { // DES k
569  int round = (buf[0] >> 4);
570  ESIL_A("%d,des", round);
571 }
572 
573 INST_HANDLER(eijmp) { // EIJMP
574  ESIL_A("1,z,16,eind,<<,+,<<,pc,=,");
575 }
576 
577 INST_HANDLER(eicall) { // EICALL
578  // push pc in stack
579  ESIL_A("pc,"); // esil is already pointing to
580  // next instruction (@ret)
581  __generic_push(op, CPU_PC_SIZE(cpu)); // push @ret in stack
582  // do a standard EIJMP
583  INST_CALL(eijmp);
584 }
585 
586 INST_HANDLER(elpm) { // ELPM
587  // ELPM Rd
588  // ELPM Rd, Z+
589  if (len < 2) {
590  return;
591  }
592  int d = ((buf[1] & 0xfe) == 0x90)
593  ? ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf) // Rd
594  : 0; // R0
595  ESIL_A("16,rampz,<<,z,+,_prog,+,[1],"); // read RAMPZ:Z
596  ESIL_A("r%d,=,", d); // Rd = [1]
597  if ((buf[1] & 0xfe) == 0x90 && (buf[0] & 0xf) == 0x7) {
598  ESIL_A("16,1,z,+,DUP,z,=,>>,1,&,rampz,+=,"); // ++(rampz:z)
599  }
600 }
601 
602 INST_HANDLER(eor) { // EOR Rd, Rr
603  // CLR Rd
604  if (len < 2) {
605  return;
606  }
607  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
608  const ut32 r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
609  ESIL_A("r%d,r%d,^=,$z,zf,:=,0,vf,:=,r%d,0x80,&,!,!,nf,:=,nf,sf,:=", r, d, d);
610  // 0: Rd ^= Rr
611 }
612 
613 INST_HANDLER(fmul) { // FMUL Rd, Rr
614  if (len < 1) {
615  return;
616  }
617  const ut32 d = ((buf[0] >> 4) & 0x7) + 16;
618  const ut32 r = (buf[0] & 0x7) + 16;
619 
620  ESIL_A("8,");
621  ESIL_A("0xffff,1,r%d,r%d,*,<<,&,DUP,r0,=,>>,r1,=,", r, d); // 0: r1_r0 = (rd * rr) << 1
622  ESIL_A("8,r1,<<,r0,|,DUP,0x8000,&,!,!,cf,:=,"); // C = R/15
623  ESIL_A("!,zf,:="); // Z = !R
624 }
625 
626 INST_HANDLER(fmuls) { // FMULS Rd, Rr
627  if (len < 1) {
628  return;
629  }
630  const ut32 d = ((buf[0] >> 4) & 0x7) + 16;
631  const ut32 r = (buf[0] & 0x7) + 16;
632 
633  ESIL_A("8,1,");
634  ESIL_A("r%d,DUP,0x80,&,?{,0xff00,|,},", d); // sign extension Rd
635  ESIL_A("r%d,DUP,0x80,&,?{,0xff00,|,},", r); // sign extension Rr
636  ESIL_A("*,<<,DUP,r0,=,>>,r1,=,"); // 0: (Rd*Rr)<<1
637 
638  ESIL_A("8,r1,<<,r0,|,DUP,0x8000,&,!,!,cf,:=,"); // C = R/16
639  ESIL_A("!,zf,:="); // Z = !R
640 }
641 
642 INST_HANDLER(fmulsu) { // FMULSU Rd, Rr
643  if (len < 1) {
644  return;
645  }
646  const ut32 d = ((buf[0] >> 4) & 0x7) + 16;
647  const ut32 r = (buf[0] & 0x7) + 16;
648 
649  ESIL_A("8,1,");
650  ESIL_A("r%d,DUP,0x80,&,?{,0xff00,|,},", d); // sign extension Rd
651  ESIL_A("r%d,*,<<,DUP,r0,=,>>,r1,=,", r); // 0: (Rd*Rr)<<1
652 
653  ESIL_A("8,r1,<<,r0,|,DUP,0x8000,&,!,!,cf,:=,"); // C = R/16
654  ESIL_A("!,zf,:="); // Z = !R
655 }
656 
657 INST_HANDLER(ijmp) { // IJMP k
658  // read z for calculating jump address on runtime
659  ESIL_A("1,z,<<,pc,=,"); // jump!
660 }
661 
662 INST_HANDLER(icall) { // ICALL k
663  // push pc in stack
664  ESIL_A("pc,"); // esil is already pointing to
665  // next instruction (@ret)
666  __generic_push(op, CPU_PC_SIZE(cpu)); // push @ret in stack
667  // do a standard IJMP
668  INST_CALL(ijmp);
669 }
670 
671 INST_HANDLER(in) { // IN Rd, A
672  if (len < 2) {
673  return;
674  }
675  int r = ((buf[0] >> 4) & 0x0f) | ((buf[1] & 0x01) << 4);
676  int a = (buf[0] & 0x0f) | ((buf[1] & 0x6) << 3);
677  RzStrBuf *io_src = __generic_io_dest(a, 0, cpu);
678  ESIL_A("%s,r%d,=,", rz_strbuf_get(io_src), r);
679  rz_strbuf_free(io_src);
680 }
681 
682 INST_HANDLER(inc) { // INC Rd
683  if (len < 2) {
684  return;
685  }
686  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
687  ESIL_A("1,r%d,+=,", d); // Rd++
688  // FLAGS:
689  ESIL_A("7,$o,vf,:=,"); // V
690  ESIL_A("r%d,0x80,&,!,!,nf,:=,", d); // N
691  ESIL_A("$z,zf,:=,"); // Z
692  ESIL_A("vf,nf,^,sf,:=,"); // S
693 }
694 
695 INST_HANDLER(jmp) { // JMP k
696  if (len < 4) {
697  return;
698  }
699  ut64 jump = (buf[2] << 1) | (buf[3] << 9) | (buf[1] & 0x01) << 23 | (buf[0] & 0x01) << 17 | (buf[0] & 0xf0) << 14;
700  ESIL_A("%" PFMT64d ",pc,=,", jump); // jump!
701 }
702 
703 INST_HANDLER(lac) { // LAC Z, Rd
704  if (len < 2) {
705  return;
706  }
707  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
708 
709  // read memory from RAMPZ:Z
710  __generic_ld_st(op, "ram", 'z', 1, 0, 0, 0); // 0: Read (RAMPZ:Z)
711  ESIL_A("r%d,0xff,^,&,", d); // 0: (Z) & ~Rd
712  ESIL_A("DUP,r%d,=,", d); // Rd = [0]
713  __generic_ld_st(op, "ram", 'z', 1, 0, 0, 1); // Store in RAM
714 }
715 
716 INST_HANDLER(las) { // LAS Z, Rd
717  if (len < 2) {
718  return;
719  }
720  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
721 
722  // read memory from RAMPZ:Z
723  __generic_ld_st(op, "ram", 'z', 1, 0, 0, 0); // 0: Read (RAMPZ:Z)
724  ESIL_A("r%d,|,", d); // 0: (Z) | Rd
725  ESIL_A("DUP,r%d,=,", d); // Rd = [0]
726  __generic_ld_st(op, "ram", 'z', 1, 0, 0, 1); // Store in RAM
727 }
728 
729 INST_HANDLER(lat) { // LAT Z, Rd
730  if (len < 2) {
731  return;
732  }
733  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
734 
735  // read memory from RAMPZ:Z
736  __generic_ld_st(op, "ram", 'z', 1, 0, 0, 0); // 0: Read (RAMPZ:Z)
737  ESIL_A("r%d,^,", d); // 0: (Z) ^ Rd
738  ESIL_A("DUP,r%d,=,", d); // Rd = [0]
739  __generic_ld_st(op, "ram", 'z', 1, 0, 0, 1); // Store in RAM
740 }
741 
742 INST_HANDLER(ld) { // LD Rd, X
743  // LD Rd, X+
744  // LD Rd, -X
745  if (len < 2) {
746  return;
747  }
748  // read memory
750  op, "ram",
751  'x', // use index register X
752  0, // no use RAMP* registers
753  (buf[0] & 0xf) == 0xe
754  ? -1 // pre decremented
755  : (buf[0] & 0xf) == 0xd
756  ? 1 // post incremented
757  : 0, // no increment
758  0, // offset always 0
759  0); // load operation (!st)
760  // load register
761  ESIL_A("r%d,=,", ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf));
762 }
763 
764 INST_HANDLER(ldd) { // LD Rd, Y LD Rd, Z
765  // LD Rd, Y+ LD Rd, Z+
766  // LD Rd, -Y LD Rd, -Z
767  // LD Rd, Y+q LD Rd, Z+q
768  if (len < 2) {
769  return;
770  }
771  // calculate offset (this value only has sense in some opcodes,
772  // but we are optimistic and we calculate it always)
773  int offset = (buf[1] & 0x20) | ((buf[1] & 0xc) << 1) | (buf[0] & 0x7);
774  // read memory
776  op, "ram",
777  buf[0] & 0x8 ? 'y' : 'z', // index register Y/Z
778  0, // no use RAMP* registers
779  !(buf[1] & 0x10)
780  ? 0 // no increment
781  : buf[0] & 0x1
782  ? 1 // post incremented
783  : -1, // pre decremented
784  !(buf[1] & 0x10) ? offset : 0, // offset or not offset
785  0); // load operation (!st)
786  // load register
787  ESIL_A("r%d,=,", ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf));
788 }
789 
790 INST_HANDLER(ldi) { // LDI Rd, K
791  if (len < 2) {
792  return;
793  }
794  int k = (buf[0] & 0xf) + ((buf[1] & 0xf) << 4);
795  int d = ((buf[0] >> 4) & 0xf) + 16;
796  ESIL_A("0x%x,r%d,=,", k, d);
797 }
798 
799 INST_HANDLER(lds) { // LDS Rd, k
800  if (len < 4) {
801  return;
802  }
803  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
804  int k = (buf[3] << 8) | buf[2];
805 
806  // load value from RAMPD:k
807  __generic_ld_st(op, "ram", 0, 1, 0, k, 0);
808  ESIL_A("r%d,=,", d);
809 }
810 
811 INST_HANDLER(sts) { // STS k, Rr
812  if (len < 4) {
813  return;
814  }
815  int r = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
816  int k = (buf[3] << 8) | buf[2];
817 
818  ESIL_A("r%d,", r);
819  __generic_ld_st(op, "ram", 0, 1, 0, k, 1);
820 }
821 
822 INST_HANDLER(lpm) { // LPM
823  // LPM Rd, Z
824  // LPM Rd, Z+
825  if (len < 2) {
826  return;
827  }
828  ut16 ins = (((ut16)buf[1]) << 8) | ((ut16)buf[0]);
829  // read program memory
831  op, "prog",
832  'z', // index register Y/Z
833  1, // use RAMP* registers
834  (ins & 0xfe0f) == 0x9005
835  ? 1 // post incremented
836  : 0, // no increment
837  0, // not offset
838  0); // load operation (!st)
839  // load register
840  ESIL_A("r%d,=,",
841  (ins == 0x95c8)
842  ? 0 // LPM (r0)
843  : ((buf[0] >> 4) & 0xf) // LPM Rd
844  | ((buf[1] & 0x1) << 4));
845 }
846 
847 INST_HANDLER(lsr) { // LSR Rd
848  if (len < 2) {
849  return;
850  }
851  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
852  ESIL_A("r%d,0x1,&,cf,:=,", d); // C = Rd0
853  ESIL_A("1,r%d,>>=,", d); // 0: R=(Rd >> 1)
854  ESIL_A("$z,zf,:=,"); // Z
855  ESIL_A("0,nf,:=,"); // N
856  ESIL_A("cf,vf,:=,"); // V
857  ESIL_A("cf,sf,:=,"); // S
858 }
859 
860 INST_HANDLER(mov) { // MOV Rd, Rr
861  if (len < 2) {
862  return;
863  }
864  const ut32 d = ((buf[1] << 4) & 0x10) | ((buf[0] >> 4) & 0x0f);
865  const ut32 r = ((buf[1] << 3) & 0x10) | (buf[0] & 0x0f);
866  ESIL_A("r%d,r%d,=,", r, d);
867 }
868 
869 INST_HANDLER(movw) { // MOVW Rd+1:Rd, Rr+1:Rr
870  if (len < 1) {
871  return;
872  }
873  const ut32 d = (buf[0] & 0xf0) >> 3;
874  const ut32 r = (buf[0] & 0x0f) << 1;
875  ESIL_A("r%d,r%d,=,r%d,r%d,=,", r, d, r + 1, d + 1);
876 }
877 
878 INST_HANDLER(mul) { // MUL Rd, Rr
879  if (len < 2) {
880  return;
881  }
882  const ut32 d = ((buf[1] << 4) & 0x10) | ((buf[0] >> 4) & 0x0f);
883  const ut32 r = ((buf[1] << 3) & 0x10) | (buf[0] & 0x0f);
884 
885  ESIL_A("8,r%d,r%d,*,DUP,r0,=,>>,r1,=,", r, d); // 0: r1_r0 = rd * rr
886  ESIL_A("8,r1,<<,r0,|,DUP,0x8000,&,!,!,cf,:=,"); // C = R/15
887  ESIL_A("!,zf,:="); // Z = !R
888 }
889 
890 INST_HANDLER(muls) { // MULS Rd, Rr
891  if (len < 1) {
892  return;
893  }
894  const ut32 d = (buf[0] >> 4 & 0x0f) + 16;
895  const ut32 r = (buf[0] & 0x0f) + 16;
896 
897  ESIL_A("8,");
898  ESIL_A("r%d,DUP,0x80,&,?{,0xff00,|,},", d); // sign extension Rd
899  ESIL_A("r%d,DUP,0x80,&,?{,0xff00,|,},", r); // sign extension Rr
900  ESIL_A("*,DUP,r0,=,>>,r1,=,"); // 0: (Rd*Rr)
901 
902  ESIL_A("8,r1,<<,r0,|,DUP,0x8000,&,!,!,cf,:=,"); // C = R/16
903  ESIL_A("!,zf,:="); // Z = !R
904 }
905 
906 INST_HANDLER(mulsu) { // MULSU Rd, Rr
907  if (len < 1) {
908  return;
909  }
910  const ut32 d = (buf[0] >> 4 & 0x07) + 16;
911  const ut32 r = (buf[0] & 0x07) + 16;
912 
913  ESIL_A("8,");
914  ESIL_A("r%d,DUP,0x80,&,?{,0xff00,|,},", d); // sign extension Rd
915  ESIL_A("r%d,*,DUP,r0,=,>>,r1,=,", r); // 0: (Rd*Rr)
916 
917  ESIL_A("8,r1,<<,r0,|,DUP,0x8000,&,!,!,cf,:=,"); // C = R/16
918  ESIL_A("!,zf,:="); // Z = !R
919 }
920 
921 INST_HANDLER(neg) { // NEG Rd
922  if (len < 2) {
923  return;
924  }
925  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
926  ESIL_A("r%d,0x00,-,0xff,&,", d); // 0: (0-Rd)
927  ESIL_A("DUP,r%d,0xff,^,|,0x08,&,!,!,hf,=,", d); // H
928  ESIL_A("DUP,0x80,-,!,vf,=,"); // V
929  ESIL_A("DUP,0x80,&,!,!,nf,=,"); // N
930  ESIL_A("DUP,!,zf,=,"); // Z
931  ESIL_A("DUP,!,!,cf,=,"); // C
932  ESIL_A("vf,nf,^,sf,=,"); // S
933  ESIL_A("r%d,=,", d); // Rd = result
934 }
935 
936 INST_HANDLER(nop) { // NOP
937  ESIL_A(",,");
938 }
939 
940 INST_HANDLER(or) { // OR Rd, Rr
941  if (len < 2) {
942  return;
943  }
944  int d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
945  int r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
946  ESIL_A("r%d,r%d,|=,", r, d); // 0: (Rd | Rr)
947  ESIL_A("$z,zf,:=,"); // Z
948  ESIL_A("r%d,&,!,!,nf,:=,", d); // N
949  ESIL_A("0,vf,:=,"); // V
950  ESIL_A("nf,sf,:="); // S
951 }
952 
953 INST_HANDLER(ori) { // ORI Rd, K
954  // SBR Rd, K
955  if (len < 2) {
956  return;
957  }
958  const ut32 d = ((buf[0] >> 4) & 0xf) + 16;
959  const ut32 k = (buf[0] & 0xf) | ((buf[1] & 0xf) << 4);
960  ESIL_A("%d,r%d,|=,", k, d); // 0: (Rd | k)
961  ESIL_A("$z,zf,:=,"); // Z
962  ESIL_A("r%d,0x80,&,!,!,nf,:=,", d); // N
963  ESIL_A("0,vf,:=,"); // V
964  ESIL_A("nf,sf,:="); // S
965 }
966 
967 INST_HANDLER(out) { // OUT A, Rr
968  if (len < 2) {
969  return;
970  }
971  int r = ((buf[0] >> 4) & 0x0f) | ((buf[1] & 0x01) << 4);
972  int a = (buf[0] & 0x0f) | ((buf[1] & 0x6) << 3);
973  RzStrBuf *io_dst = __generic_io_dest(a, 1, cpu);
974  ESIL_A("r%d,%s,", r, rz_strbuf_get(io_dst));
975  rz_strbuf_free(io_dst);
976 }
977 
978 INST_HANDLER(pop) { // POP Rd
979  if (len < 2) {
980  return;
981  }
982  int d = ((buf[1] & 0x1) << 4) | ((buf[0] >> 4) & 0xf);
983  __generic_pop(op, 1);
984  ESIL_A("r%d,=,", d); // store in Rd
985 }
986 
987 INST_HANDLER(push) { // PUSH Rr
988  if (len < 2) {
989  return;
990  }
991  int r = ((buf[1] & 0x1) << 4) | ((buf[0] >> 4) & 0xf);
992  ESIL_A("r%d,", r); // load Rr
993  __generic_push(op, 1); // push it into stack
994 }
995 
996 INST_HANDLER(rcall) { // RCALL k
997  if (len < 2) {
998  return;
999  }
1000  // target address
1001  ut64 jump = op->addr + ((((((buf[1] & 0xf) << 8) | buf[0]) << 1) | (((buf[1] & 0x8) ? ~((int)0x1fff) : 0))) + 2);
1002  // esil
1003  ESIL_A("pc,"); // esil already points to next
1004  // instruction (@ret)
1005  __generic_push(op, CPU_PC_SIZE(cpu)); // push @ret addr
1006  ESIL_A("%" PFMT64d ",pc,=,", jump); // jump!
1007 }
1008 
1009 INST_HANDLER(ret) { // RET
1010  // esil
1012  ESIL_A("pc,=,"); // jump!
1013 }
1014 
1015 INST_HANDLER(reti) { // RETI
1016  // first perform a standard 'ret'
1017  INST_CALL(ret);
1018 
1019  // RETI: The I-bit is cleared by hardware after an interrupt
1020  // has occurred, and is set by the RETI instruction to enable
1021  // subsequent interrupts
1022  ESIL_A("1,if,=,");
1023 }
1024 
1025 INST_HANDLER(rjmp) { // RJMP k
1026  st32 loc = (((((buf[1] & 0xf) << 9) | (buf[0] << 1))) | (buf[1] & 0x8 ? ~(0x1fff) : 0)) + 2;
1027  ut64 jump = op->addr + loc;
1028  ESIL_A("%" PFMT64d ",pc,=,", jump);
1029 }
1030 
1031 INST_HANDLER(ror) { // ROR Rd
1032  const ut32 d = ((buf[0] >> 4) & 0x0f) | ((buf[1] << 4) & 0x10);
1033  ESIL_A("cf,nf,:=,"); // N
1034  ESIL_A("r%d,0x1,&,", d); // C
1035  ESIL_A("1,r%d,>>,7,cf,<<,|,r%d,=,cf,:=,", d, d); // 0: (Rd>>1) | (cf<<7)
1036  ESIL_A("$z,zf,:=,"); // Z
1037  ESIL_A("nf,cf,^,vf,:=,"); // V
1038  ESIL_A("vf,nf,^,sf,:="); // S
1039 }
1040 
1041 INST_HANDLER(sbc) { // SBC Rd, Rr
1042  if (len < 2) {
1043  return;
1044  }
1045  const ut32 r = (buf[0] & 0x0f) | ((buf[1] & 0x2) << 3);
1046  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x1) << 4);
1047 
1048  ESIL_A("cf,r%d,+,r%d,-=,", r, d); // 0: (Rd-Rr-C)
1049  ESIL_A("$z,zf,:=,");
1050  ESIL_A("3,$b,hf,:=,");
1051  ESIL_A("8,$b,cf,:=,");
1052  ESIL_A("7,$o,vf,:=,");
1053  ESIL_A("0x80,r%d,&,!,!,nf,:=,", d);
1054  ESIL_A("vf,nf,^,sf,:=");
1055 }
1056 
1057 INST_HANDLER(sbci) { // SBCI Rd, k
1058  if (len < 2) {
1059  return;
1060  }
1061  const ut32 d = ((buf[0] >> 4) & 0xf) + 16;
1062  const ut32 k = ((buf[1] & 0xf) << 4) | (buf[0] & 0xf);
1063 
1064  ESIL_A("cf,%d,+,r%d,-=,", k, d); // 0: (Rd-k-C)
1065  ESIL_A("$z,zf,:=,");
1066  ESIL_A("3,$b,hf,:=,");
1067  ESIL_A("8,$b,cf,:=,");
1068  ESIL_A("7,$o,vf,:=,");
1069  ESIL_A("0x80,r%d,&,!,!,nf,:=,", d);
1070  ESIL_A("vf,nf,^,sf,:=");
1071 }
1072 
1073 INST_HANDLER(sub) { // SUB Rd, Rr
1074  if (len < 2) {
1075  return;
1076  }
1077  const ut32 d = ((buf[0] >> 4) & 0xf) | ((buf[1] & 1) << 4);
1078  const ut32 r = (buf[0] & 0xf) | ((buf[1] & 2) << 3);
1079 
1080  ESIL_A("r%d,r%d,-=,", r, d); // 0: (Rd-k)
1081  ESIL_A("$z,zf,:=,");
1082  ESIL_A("3,$b,hf,:=,");
1083  ESIL_A("8,$b,cf,:=,");
1084  ESIL_A("7,$o,vf,:=,");
1085  ESIL_A("0x80,r%d,&,!,!,nf,:=,", d);
1086  ESIL_A("vf,nf,^,sf,:=");
1087 }
1088 
1089 INST_HANDLER(subi) { // SUBI Rd, k
1090  if (len < 2) {
1091  return;
1092  }
1093  const ut32 d = ((buf[0] >> 4) & 0xf) + 16;
1094  const ut32 k = ((buf[1] & 0xf) << 4) | (buf[0] & 0xf);
1095 
1096  ESIL_A("%d,r%d,-=,", k, d); // 0: (Rd-k)
1097  ESIL_A("$z,zf,:=,");
1098  ESIL_A("3,$b,hf,:=,");
1099  ESIL_A("8,$b,cf,:=,");
1100  ESIL_A("7,$o,vf,:=,");
1101  ESIL_A("0x80,r%d,&,!,!,nf,:=,", d);
1102  ESIL_A("vf,nf,^,sf,:=");
1103 }
1104 
1105 INST_HANDLER(sbi) { // SBI A, b
1106  if (len < 1) {
1107  return;
1108  }
1109  int a = (buf[0] >> 3) & 0x1f;
1110  int b = buf[0] & 0x07;
1111  RzStrBuf *io_port;
1112 
1113  // read port a and clear bit b
1114  io_port = __generic_io_dest(a, 0, cpu);
1115  ESIL_A("0xff,%d,1,<<,|,%s,&,", b, rz_strbuf_get(io_port));
1116  rz_strbuf_free(io_port);
1117 
1118  // write result to port a
1119  io_port = __generic_io_dest(a, 1, cpu);
1120  ESIL_A("%s,", rz_strbuf_get(io_port));
1121  rz_strbuf_free(io_port);
1122 }
1123 
1124 INST_HANDLER(sbix) { // SBIC A, b
1125  // SBIS A, b
1126  if (len < 2) {
1127  return;
1128  }
1129  int a = (buf[0] >> 3) & 0x1f;
1130  int b = buf[0] & 0x07;
1131  RzStrBuf *io_port;
1132 
1133  // read port a and clear bit b
1134  io_port = __generic_io_dest(a, 0, cpu);
1135  ESIL_A("%d,1,<<,%s,&,", b, rz_strbuf_get(io_port)); // IO(A,b)
1136  ESIL_A((buf[1] & 0xe) == 0xc
1137  ? "!," // SBIC => branch if 0
1138  : "!,!,"); // SBIS => branch if 1
1139  ESIL_A("?{,%" PFMT64d ",pc,=,},", op->jump); // ?true => jmp
1140  rz_strbuf_free(io_port);
1141 }
1142 
1143 INST_HANDLER(sbiw) { // SBIW Rd+1:Rd, K
1144  if (len < 1) {
1145  return;
1146  }
1147  int d = ((buf[0] & 0x30) >> 3) + 24;
1148  int k = (buf[0] & 0xf) | ((buf[0] >> 2) & 0x30);
1149  ESIL_A("7,r%d,>>,", d + 1); // remember previous highest bit
1150  ESIL_A("8,%d,8,r%d,<<,r%d,|,-,DUP,r%d,=,>>,r%d,=,", k, d + 1, d, d, d + 1); // 0(Rd+1_Rd - k)
1151  ESIL_A("$z,zf,:=,");
1152  ESIL_A("DUP,!,7,r%d,>>,&,cf,:=,", d + 1); // C
1153  ESIL_A("r%d,0x80,&,!,!,nf,:=,", d + 1); // N
1154  ESIL_A("7,r%d,>>,!,&,vf,:=,", d + 1); // V
1155  ESIL_A("vf,nf,^,sf,:="); // S
1156 }
1157 
1158 INST_HANDLER(sbrx) { // SBRC Rr, b
1159  // SBRS Rr, b
1160  if (len < 2) {
1161  return;
1162  }
1163  int b = buf[0] & 0x7;
1164  int r = ((buf[0] >> 4) & 0xf) | ((buf[1] & 0x01) << 4);
1165  ESIL_A("%d,1,<<,r%d,&,", b, r); // Rr(b)
1166  ESIL_A((buf[1] & 0xe) == 0xc
1167  ? "!," // SBRC => branch if cleared
1168  : "!,!,"); // SBRS => branch if set
1169  ESIL_A("?{,%" PFMT64d ",pc,=,},", op->jump); // ?true => jmp
1170 }
1171 
1172 INST_HANDLER(sleep) { // SLEEP
1173  ESIL_A("BREAK");
1174 }
1175 
1176 INST_HANDLER(spm) { // SPM Z+
1177  ut64 spmcsr;
1178 
1179  // read SPM Control Register (SPMCR)
1180  rz_analysis_esil_reg_read(analysis->esil, "spmcsr", &spmcsr, NULL);
1181 
1182  // clear SPMCSR
1183  ESIL_A("0x7c,spmcsr,&=,");
1184 
1185  // decide action depending on the old value of SPMCSR
1186  switch (spmcsr & 0x7f) {
1187  case 0x03: // PAGE ERASE
1188  // invoke SPM_CLEAR_PAGE (erases target page writing
1189  // the 0xff value
1190  ESIL_A("16,rampz,<<,z,+,"); // push target address
1191  ESIL_A("SPM_PAGE_ERASE,"); // do magic
1192  break;
1193 
1194  case 0x01: // FILL TEMPORARY BUFFER
1195  ESIL_A("r1,r0,"); // push data
1196  ESIL_A("z,"); // push target address
1197  ESIL_A("SPM_PAGE_FILL,"); // do magic
1198  break;
1199 
1200  case 0x05: // WRITE PAGE
1201  ESIL_A("16,rampz,<<,z,+,"); // push target address
1202  ESIL_A("SPM_PAGE_WRITE,"); // do magic
1203  break;
1204 
1205  default:
1206  RZ_LOG_DEBUG("SPM: I dont know what to do with SPMCSR %02" PFMT64x ".\n", spmcsr);
1207  break;
1208  }
1209 }
1210 
1211 INST_HANDLER(st) { // ST X, Rr
1212  // ST X+, Rr
1213  // ST -X, Rr
1214  if (len < 2) {
1215  return;
1216  }
1217  // load register
1218  ESIL_A("r%d,", ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf));
1219  // write in memory
1221  op, "ram",
1222  'x', // use index register X
1223  0, // no use RAMP* registers
1224  (buf[0] & 0xf) == 0xe
1225  ? -1 // pre decremented
1226  : (buf[0] & 0xf) == 0xd
1227  ? 1 // post increment
1228  : 0, // no increment
1229  0, // offset always 0
1230  1); // store operation (st)
1231 }
1232 
1233 INST_HANDLER(std) { // ST Y, Rr ST Z, Rr
1234  // ST Y+, Rr ST Z+, Rr
1235  // ST -Y, Rr ST -Z, Rr
1236  // ST Y+q, Rr ST Z+q, Rr
1237  if (len < 2) {
1238  return;
1239  }
1240  // load register
1241  ESIL_A("r%d,", ((buf[1] & 1) << 4) | ((buf[0] >> 4) & 0xf));
1242  // write in memory
1244  op, "ram",
1245  buf[0] & 0x8 ? 'y' : 'z', // index register Y/Z
1246  0, // no use RAMP* registers
1247  !(buf[1] & 0x10)
1248  ? 0 // no increment
1249  : buf[0] & 0x1
1250  ? 1 // post incremented
1251  : -1, // pre decremented
1252  !(buf[1] & 0x10)
1253  ? (buf[1] & 0x20) // offset
1254  | ((buf[1] & 0xc) << 1) | (buf[0] & 0x7)
1255  : 0, // no offset
1256  1); // load operation (!st)
1257 }
1258 
1259 INST_HANDLER(swap) { // SWAP Rd
1260  if (len < 2) {
1261  return;
1262  }
1263  int d = ((buf[1] & 0x1) << 4) | ((buf[0] >> 4) & 0xf);
1264  ESIL_A("4,r%d,>>,0x0f,&,", d); // (Rd >> 4) & 0xf
1265  ESIL_A("4,r%d,<<,0xf0,&,", d); // (Rd >> 4) & 0xf
1266  ESIL_A("|,"); // S[0] | S[1]
1267  ESIL_A("r%d,=,", d); // Rd = result
1268 }
1269 
1271  // op mask select cycles size type
1272  INST_DECL(break, 0xffff, 0x9698, 1, 2, TRAP), // BREAK
1273  INST_DECL(eicall, 0xffff, 0x9519, 0, 2, UCALL), // EICALL
1274  INST_DECL(eijmp, 0xffff, 0x9419, 0, 2, UJMP), // EIJMP
1275  INST_DECL(icall, 0xffff, 0x9509, 0, 2, UCALL), // ICALL
1276  INST_DECL(ijmp, 0xffff, 0x9409, 0, 2, UJMP), // IJMP
1277  INST_DECL(lpm, 0xffff, 0x95c8, 3, 2, LOAD), // LPM
1278  INST_DECL(nop, 0xffff, 0x0000, 1, 2, NOP), // NOP
1279  INST_DECL(ret, 0xffff, 0x9508, 4, 2, RET), // RET
1280  INST_DECL(reti, 0xffff, 0x9518, 4, 2, RET), // RETI
1281  INST_DECL(sleep, 0xffff, 0x9588, 1, 2, NOP), // SLEEP
1282  INST_DECL(spm, 0xffff, 0x95e8, 1, 2, TRAP), // SPM ...
1283  INST_DECL(bclr, 0xff8f, 0x9488, 1, 2, MOV), // BCLR s
1284  INST_DECL(bset, 0xff8f, 0x9408, 1, 2, MOV), // BSET s
1285  INST_DECL(fmul, 0xff88, 0x0308, 2, 2, MUL), // FMUL Rd, Rr
1286  INST_DECL(fmuls, 0xff88, 0x0380, 2, 2, MUL), // FMULS Rd, Rr
1287  INST_DECL(fmulsu, 0xff88, 0x0388, 2, 2, MUL), // FMULSU Rd, Rr
1288  INST_DECL(mulsu, 0xff88, 0x0300, 2, 2, AND), // MUL Rd, Rr
1289  INST_DECL(des, 0xff0f, 0x940b, 0, 2, CRYPTO), // DES k
1290  INST_DECL(adiw, 0xff00, 0x9600, 2, 2, ADD), // ADIW Rd+1:Rd, K
1291  INST_DECL(sbiw, 0xff00, 0x9700, 2, 2, SUB), // SBIW Rd+1:Rd, K
1292  INST_DECL(cbi, 0xff00, 0x9800, 1, 2, IO), // CBI A, K
1293  INST_DECL(sbi, 0xff00, 0x9a00, 1, 2, IO), // SBI A, K
1294  INST_DECL(movw, 0xff00, 0x0100, 1, 2, MOV), // MOVW Rd+1:Rd, Rr+1:Rr
1295  INST_DECL(muls, 0xff00, 0x0200, 2, 2, AND), // MUL Rd, Rr
1296  INST_DECL(asr, 0xfe0f, 0x9405, 1, 2, SAR), // ASR Rd
1297  INST_DECL(com, 0xfe0f, 0x9400, 1, 2, NOT), // COM Rd
1298  INST_DECL(dec, 0xfe0f, 0x940a, 1, 2, SUB), // DEC Rd
1299  INST_DECL(elpm, 0xfe0f, 0x9006, 0, 2, LOAD), // ELPM Rd, Z
1300  INST_DECL(elpm, 0xfe0f, 0x9007, 0, 2, LOAD), // ELPM Rd, Z+
1301  INST_DECL(inc, 0xfe0f, 0x9403, 1, 2, ADD), // INC Rd
1302  INST_DECL(lac, 0xfe0f, 0x9206, 2, 2, LOAD), // LAC Z, Rd
1303  INST_DECL(las, 0xfe0f, 0x9205, 2, 2, LOAD), // LAS Z, Rd
1304  INST_DECL(lat, 0xfe0f, 0x9207, 2, 2, LOAD), // LAT Z, Rd
1305  INST_DECL(ld, 0xfe0f, 0x900c, 0, 2, LOAD), // LD Rd, X
1306  INST_DECL(ld, 0xfe0f, 0x900d, 0, 2, LOAD), // LD Rd, X+
1307  INST_DECL(ld, 0xfe0f, 0x900e, 0, 2, LOAD), // LD Rd, -X
1308  INST_DECL(lds, 0xfe0f, 0x9000, 0, 4, LOAD), // LDS Rd, k
1309  INST_DECL(sts, 0xfe0f, 0x9200, 2, 4, STORE), // STS k, Rr
1310  INST_DECL(lpm, 0xfe0f, 0x9004, 3, 2, LOAD), // LPM Rd, Z
1311  INST_DECL(lpm, 0xfe0f, 0x9005, 3, 2, LOAD), // LPM Rd, Z+
1312  INST_DECL(lsr, 0xfe0f, 0x9406, 1, 2, SHR), // LSR Rd
1313  INST_DECL(neg, 0xfe0f, 0x9401, 2, 2, SUB), // NEG Rd
1314  INST_DECL(pop, 0xfe0f, 0x900f, 2, 2, POP), // POP Rd
1315  INST_DECL(push, 0xfe0f, 0x920f, 0, 2, PUSH), // PUSH Rr
1316  INST_DECL(ror, 0xfe0f, 0x9407, 1, 2, SAR), // ROR Rd
1317  INST_DECL(st, 0xfe0f, 0x920c, 2, 2, STORE), // ST X, Rr
1318  INST_DECL(st, 0xfe0f, 0x920d, 0, 2, STORE), // ST X+, Rr
1319  INST_DECL(st, 0xfe0f, 0x920e, 0, 2, STORE), // ST -X, Rr
1320  INST_DECL(swap, 0xfe0f, 0x9402, 1, 2, SAR), // SWAP Rd
1321  INST_DECL(call, 0xfe0e, 0x940e, 0, 4, CALL), // CALL k
1322  INST_DECL(jmp, 0xfe0e, 0x940c, 2, 4, JMP), // JMP k
1323  INST_DECL(bld, 0xfe08, 0xf800, 1, 2, MOV), // BLD Rd, b
1324  INST_DECL(bst, 0xfe08, 0xfa00, 1, 2, MOV), // BST Rd, b
1325  INST_DECL(sbix, 0xff00, 0x9900, 2, 2, CJMP), // SBIC A, b
1326  INST_DECL(sbix, 0xff00, 0x9b00, 2, 2, CJMP), // SBIS A, b
1327  INST_DECL(sbrx, 0xfe08, 0xfc00, 2, 2, CJMP), // SBRC Rr, b
1328  INST_DECL(sbrx, 0xfe08, 0xfe00, 2, 2, CJMP), // SBRS Rr, b
1329  INST_DECL(ldd, 0xfe07, 0x9001, 0, 2, LOAD), // LD Rd, Y/Z+
1330  INST_DECL(ldd, 0xfe07, 0x9002, 0, 2, LOAD), // LD Rd, -Y/Z
1331  INST_DECL(std, 0xfe07, 0x9201, 0, 2, STORE), // ST Y/Z+, Rr
1332  INST_DECL(std, 0xfe07, 0x9202, 0, 2, STORE), // ST -Y/Z, Rr
1333  INST_DECL(adc, 0xfc00, 0x1c00, 1, 2, ADD), // ADC Rd, Rr
1334  INST_DECL(add, 0xfc00, 0x0c00, 1, 2, ADD), // ADD Rd, Rr
1335  INST_DECL(and, 0xfc00, 0x2000, 1, 2, AND), // AND Rd, Rr
1336  INST_DECL(brbx, 0xfc00, 0xf000, 0, 2, CJMP), // BRBS s, k
1337  INST_DECL(brbx, 0xfc00, 0xf400, 0, 2, CJMP), // BRBC s, k
1338  INST_DECL(cp, 0xfc00, 0x1400, 1, 2, CMP), // CP Rd, Rr
1339  INST_DECL(cpc, 0xfc00, 0x0400, 1, 2, CMP), // CPC Rd, Rr
1340  INST_DECL(cpse, 0xfc00, 0x1000, 0, 2, CJMP), // CPSE Rd, Rr
1341  INST_DECL(eor, 0xfc00, 0x2400, 1, 2, XOR), // EOR Rd, Rr
1342  INST_DECL(mov, 0xfc00, 0x2c00, 1, 2, MOV), // MOV Rd, Rr
1343  INST_DECL(mul, 0xfc00, 0x9c00, 2, 2, AND), // MUL Rd, Rr
1344  INST_DECL(or, 0xfc00, 0x2800, 1, 2, OR), // OR Rd, Rr
1345  INST_DECL(sbc, 0xfc00, 0x0800, 1, 2, SUB), // SBC Rd, Rr
1346  INST_DECL(sub, 0xfc00, 0x1800, 1, 2, SUB), // SUB Rd, Rr
1347  INST_DECL(in, 0xf800, 0xb000, 1, 2, IO), // IN Rd, A
1348  INST_DECL(out, 0xf800, 0xb800, 1, 2, IO), // OUT A, Rr
1349  INST_DECL(andi, 0xf000, 0x7000, 1, 2, AND), // ANDI Rd, K
1350  INST_DECL(cpi, 0xf000, 0x3000, 1, 2, CMP), // CPI Rd, K
1351  INST_DECL(ldi, 0xf000, 0xe000, 1, 2, LOAD), // LDI Rd, K
1352  INST_DECL(ori, 0xf000, 0x6000, 1, 2, OR), // ORI Rd, K
1353  INST_DECL(rcall, 0xf000, 0xd000, 0, 2, CALL), // RCALL k
1354  INST_DECL(rjmp, 0xf000, 0xc000, 2, 2, JMP), // RJMP k
1355  INST_DECL(sbci, 0xf000, 0x4000, 1, 2, SUB), // SBC Rd, Rr
1356  INST_DECL(subi, 0xf000, 0x5000, 1, 2, SUB), // SUBI Rd, Rr
1357  INST_DECL(ldd, 0xd200, 0x8000, 0, 2, LOAD), // LD Rd, Y/Z+q
1358  INST_DECL(std, 0xd200, 0x8200, 0, 2, STORE), // ST Y/Z+q, Rr
1359  // INST_DECL(lds16, 0xf800, 0xa000, 1, 2, LOAD), // LDS Rd, k
1360 
1361  INST_LAST
1362 };
1363 
1365  OPCODE_DESC *opcode_desc;
1366  if (len < 2) {
1367  return NULL;
1368  }
1369  ut16 ins = (buf[1] << 8) | buf[0];
1370  int fail;
1371  char *t;
1372 
1373  // process opcode
1374  for (opcode_desc = opcodes; opcode_desc->handler; opcode_desc++) {
1375  if ((ins & opcode_desc->mask) == opcode_desc->selector) {
1376  fail = 0;
1377 
1378  // start void esil expression
1379  rz_strbuf_set(&op->esil, "");
1380 
1381  // handle opcode
1382  opcode_desc->handler(analysis, op, buf, len, &fail, cpu);
1383  if (fail) {
1384  break;
1385  } else if (opcode_desc->cycles <= 0) {
1386  opcode_desc->cycles = 2;
1387  }
1388 
1389  // remove trailing coma (COMETE LA COMA)
1390  t = rz_strbuf_get(&op->esil);
1391  if (t && strlen(t) > 1) {
1392  t += strlen(t) - 1;
1393  if (*t == ',') {
1394  *t = '\0';
1395  }
1396  }
1397 
1398  return opcode_desc;
1399  }
1400  }
1401 
1402  return NULL;
1403 }
1404 
1405 static bool avr_custom_des(RzAnalysisEsil *esil) {
1406  if (!esil || !esil->analysis || !esil->analysis->reg) {
1407  return false;
1408  }
1409  ut64 arg;
1410  if (!__esil_pop_argument(esil, &arg)) {
1411  return false;
1412  }
1413  int round = arg;
1414  if (round < 0 || round > 15) {
1415  return false;
1416  }
1417  ut64 decrypt;
1418  rz_analysis_esil_reg_read(esil, "hf", &decrypt, NULL);
1419  if (decrypt) {
1420  round = 15 - round;
1421  }
1422  ut8 regs[0x10];
1423  static const char *reg_names[] = {
1424  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1425  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
1426  };
1427  for (size_t i = 0; i < sizeof(regs); i++) {
1428  ut64 v = 0;
1430  regs[i] = v;
1431  }
1432 
1433  // Atmel's "AVR Instruction Set Manual" unfortunately is very ambiguous
1434  // regarding the details of this instruction and leaves the most interesting
1435  // questions open, especially what intermediate results are stored and how.
1436  // The below implementation has been developed based on observing the exact
1437  // results in the Simulator in Atmel/Microchip Studio emulating ATxmega128A1.
1438  // Things may seem very strange (especially hi/lo swapping), but it is all
1439  // intended to get the right behavior!
1440  ut32 buf_hi = rz_read_at_le32(regs, 0);
1441  ut32 buf_lo = rz_read_at_le32(regs, 4);
1442  ut32 key_orig_hi = rz_read_at_le32(regs, 8);
1443  ut32 key_orig_lo = rz_read_at_le32(regs, 0xc);
1444  ut32 key_lo = key_orig_lo;
1445  ut32 key_hi = key_orig_hi;
1446  rz_des_permute_key(&key_lo, &key_hi);
1447  int i = round;
1448  if (!decrypt) {
1449  rz_des_shift_key(i, false, &key_lo, &key_hi);
1450  }
1451  ut32 round_key_lo, round_key_hi;
1452  rz_des_pc2(&round_key_lo, &round_key_hi, key_lo, key_hi);
1453  if (decrypt) {
1454  rz_des_shift_key(i, true, &key_lo, &key_hi);
1455  }
1456  rz_des_permute_block0(&buf_lo, &buf_hi);
1457  rz_des_round(&buf_lo, &buf_hi, &round_key_lo, &round_key_hi);
1458  if (arg < 15) {
1459  rz_des_permute_block1(&buf_lo, &buf_hi);
1460  } else {
1461  rz_des_permute_block1(&buf_hi, &buf_lo);
1462  buf_lo ^= buf_hi;
1463  buf_hi ^= buf_lo;
1464  buf_lo ^= buf_hi;
1465  }
1466  rz_des_permute_key_inv(&key_lo, &key_hi); // un-permute so the rz_des_permute_key() in the next round will restore it
1467  key_lo |= key_orig_hi & 0x01010101; // restore the parity bits that got lost in PC-1
1468  key_hi |= key_orig_lo & 0x01010101;
1469 
1470  rz_write_at_le32(regs, buf_hi, 0);
1471  rz_write_at_le32(regs, buf_lo, 4);
1472  rz_write_at_le32(regs, key_lo, 8);
1473  rz_write_at_le32(regs, key_hi, 0xc);
1474  for (size_t i = 0; i < sizeof(regs); i++) {
1475  ut64 v = regs[i];
1477  }
1478  return true;
1479 }
1480 
1481 // ESIL operation SPM_PAGE_ERASE
1483  CPU_MODEL *cpu;
1484  ut8 c;
1485  ut64 addr, page_size_bits, i;
1486 
1487  // sanity check
1488  if (!esil || !esil->analysis || !esil->analysis->reg) {
1489  return false;
1490  }
1491 
1492  // get target address
1493  if (!__esil_pop_argument(esil, &addr)) {
1494  return false;
1495  }
1496 
1497  // get details about current MCU and fix input address
1498  cpu = get_cpu_model(esil->analysis->cpu);
1499  page_size_bits = const_get_value(const_by_name(cpu, CPU_CONST_PARAM, "page_size"));
1500 
1501  // align base address to page_size_bits
1502  addr &= ~(MASK(page_size_bits));
1503 
1504  // perform erase
1505  // RZ_LOG_DEBUG("SPM_PAGE_ERASE %ld bytes @ 0x%08" PFMT64x ".\n", page_size, addr);
1506  c = 0xff;
1507  for (i = 0; i < (1ULL << page_size_bits); i++) {
1509  esil, (addr + i) & CPU_PC_MASK(cpu), &c, 1);
1510  }
1511 
1512  return true;
1513 }
1514 
1515 // ESIL operation SPM_PAGE_FILL
1517  CPU_MODEL *cpu;
1518  ut64 addr, page_size_bits, i;
1519  ut8 r0, r1;
1520 
1521  // sanity check
1522  if (!esil || !esil->analysis || !esil->analysis->reg) {
1523  return false;
1524  }
1525 
1526  // get target address, r0, r1
1527  if (!__esil_pop_argument(esil, &addr)) {
1528  return false;
1529  }
1530 
1531  if (!__esil_pop_argument(esil, &i)) {
1532  return false;
1533  }
1534  r0 = i;
1535 
1536  if (!__esil_pop_argument(esil, &i)) {
1537  return false;
1538  }
1539  r1 = i;
1540 
1541  // get details about current MCU and fix input address
1542  cpu = get_cpu_model(esil->analysis->cpu);
1543  page_size_bits = const_get_value(const_by_name(cpu, CPU_CONST_PARAM, "page_size"));
1544 
1545  // align and crop base address
1546  addr &= (MASK(page_size_bits) ^ 1);
1547 
1548  // perform write to temporary page
1549  // RZ_LOG_DEBUG("SPM_PAGE_FILL bytes (%02x, %02x) @ 0x%08" PFMT64x ".\n", r1, r0, addr);
1550  rz_analysis_esil_mem_write(esil, addr++, &r0, 1);
1551  rz_analysis_esil_mem_write(esil, addr++, &r1, 1);
1552 
1553  return true;
1554 }
1555 
1556 // ESIL operation SPM_PAGE_WRITE
1558  CPU_MODEL *cpu;
1559  char *t = NULL;
1560  ut64 addr, page_size_bits, tmp_page;
1561 
1562  // sanity check
1563  if (!esil || !esil->analysis || !esil->analysis->reg) {
1564  return false;
1565  }
1566 
1567  // get target address
1568  if (!__esil_pop_argument(esil, &addr)) {
1569  return false;
1570  }
1571 
1572  // get details about current MCU and fix input address and base address
1573  // of the internal temporary page
1574  cpu = get_cpu_model(esil->analysis->cpu);
1575  page_size_bits = const_get_value(const_by_name(cpu, CPU_CONST_PARAM, "page_size"));
1576  rz_analysis_esil_reg_read(esil, "_page", &tmp_page, NULL);
1577 
1578  // align base address to page_size_bits
1579  addr &= (~(MASK(page_size_bits)) & CPU_PC_MASK(cpu));
1580 
1581  // perform writing
1582  // RZ_LOG_DEBUG("SPM_PAGE_WRITE %ld bytes @ 0x%08" PFMT64x ".\n", page_size, addr);
1583  if (!(t = malloc(1 << page_size_bits))) {
1584  RZ_LOG_ERROR("Cannot alloc a buffer for copying the temporary page.\n");
1585  return false;
1586  }
1587  rz_analysis_esil_mem_read(esil, tmp_page, (ut8 *)t, 1 << page_size_bits);
1588  rz_analysis_esil_mem_write(esil, addr, (ut8 *)t, 1 << page_size_bits);
1589 
1590  return true;
1591 }
1592 
1593 static int esil_avr_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *val) {
1594  CPU_MODEL *cpu;
1595 
1596  if (!esil || !esil->analysis) {
1597  return 0;
1598  }
1599 
1600  // select cpu info
1601  cpu = get_cpu_model(esil->analysis->cpu);
1602 
1603  // crop registers and force certain values
1604  if (!strcmp(name, "pc")) {
1605  *val &= CPU_PC_MASK(cpu);
1606  } else if (!strcmp(name, "pcl")) {
1607  if (cpu->pc < 8) {
1608  *val &= MASK(8);
1609  }
1610  } else if (!strcmp(name, "pch")) {
1611  *val = cpu->pc > 8
1612  ? *val & MASK(cpu->pc - 8)
1613  : 0;
1614  }
1615 
1616  return 0;
1617 }
1618 
1620  if (!esil) {
1621  return false;
1622  }
1623  rz_analysis_esil_set_op(esil, "des", avr_custom_des, 0, 0, RZ_ANALYSIS_ESIL_OP_TYPE_CUSTOM); // better meta info plz
1628 
1629  return true;
1630 }
1631 
1633  return true;
1634 }
1635 
1637  // select cpu info
1638  CPU_MODEL *cpu = get_cpu_model(analysis->cpu);
1639  avr_op_analyze(analysis, op, addr, buf, len, cpu);
1640 }
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
#define CRYPTO
Definition: aarch64-tbl.h:2169
#define jmp
static ut32 cpu[32]
Definition: analysis_or1k.c:21
static char * regs[]
Definition: analysis_sh.c:203
#define RZ_IPI
Definition: analysis_wasm.c:11
lzma_index ** i
Definition: index.h:629
#define RET
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
static RzILOpEffect * mov(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:351
static RzILOpEffect * mul(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:539
static ut32 neg(ArmOp *op)
Definition: armass64.c:981
ut16 val
Definition: armass64_const.h:6
#define CPU_CONST_PARAM
Definition: avr_esil.c:27
static void __generic_push(RzAnalysisOp *op, int sz)
Definition: avr_esil.c:291
#define INST_CALL(OPCODE_NAME)
Definition: avr_esil.c:68
#define MASK(bits)
Definition: avr_esil.c:58
RZ_IPI int rz_avr_esil_fini(RzAnalysisEsil *esil)
Definition: avr_esil.c:1632
#define ESIL_A(e,...)
Definition: avr_esil.c:81
static RzStrBuf * __generic_io_dest(ut8 port, int write, CPU_MODEL *cpu)
Definition: avr_esil.c:237
static int esil_avr_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *val)
Definition: avr_esil.c:1593
static int __esil_pop_argument(RzAnalysisEsil *esil, ut64 *v)
Definition: avr_esil.c:211
static bool avr_custom_des(RzAnalysisEsil *esil)
Definition: avr_esil.c:1405
#define CPU_PC_SIZE(cpu)
Definition: avr_esil.c:60
CPU_CONST cpu_memsize_m640_m1280m_m1281_m2560_m2561[]
Definition: avr_esil.c:104
CPU_CONST cpu_memsize_common[]
Definition: avr_esil.c:96
static bool avr_custom_spm_page_write(RzAnalysisEsil *esil)
Definition: avr_esil.c:1557
CPU_CONST cpu_reg_common[]
Definition: avr_esil.c:88
#define CPU_PC_MASK(cpu)
Definition: avr_esil.c:59
static CPU_MODEL * get_cpu_model(char *model)
Definition: avr_esil.c:176
static CPU_MODEL * __get_cpu_model_recursive(char *model)
Definition: avr_esil.c:153
#define INST_LAST
Definition: avr_esil.c:65
static bool avr_custom_spm_page_erase(RzAnalysisEsil *esil)
Definition: avr_esil.c:1482
RZ_IPI void rz_avr_esil_opcode(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len)
Definition: avr_esil.c:1636
static CPU_CONST * const_by_value(CPU_MODEL *cpu, int type, ut32 v)
Definition: avr_esil.c:221
CPU_CONST cpu_pagesize_7_bits[]
Definition: avr_esil.c:125
CPU_CONST cpu_pagesize_5_bits[]
Definition: avr_esil.c:120
static ut32 const_get_value(CPU_CONST *c)
Definition: avr_esil.c:190
RZ_IPI int rz_avr_esil_init(RzAnalysisEsil *esil)
Definition: avr_esil.c:1619
static void __generic_ld_st(RzAnalysisOp *op, char *mem, char ireg, int use_ramp, int prepostdec, int offset, int st)
Definition: avr_esil.c:252
CPU_MODEL cpu_models[]
Definition: avr_esil.c:130
void(* inst_handler_t)(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 *buf, int len, int *fail, CPU_MODEL *cpu)
Definition: avr_esil.c:38
#define INST_HANDLER(OPCODE_NAME)
Definition: avr_esil.c:62
static OPCODE_DESC * avr_op_analyze(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, CPU_MODEL *cpu)
Definition: avr_esil.c:1364
CPU_CONST cpu_memsize_xmega128a4u[]
Definition: avr_esil.c:112
#define CPU_CONST_REG
Definition: avr_esil.c:28
static void __generic_pop(RzAnalysisOp *op, int sz)
Definition: avr_esil.c:280
struct _cpu_model_tag CPU_MODEL
static CPU_CONST * const_by_name(CPU_MODEL *cpu, int type, char *c)
Definition: avr_esil.c:194
#define INST_DECL(OP, M, SL, C, SZ, T)
Definition: avr_esil.c:63
#define CPU_CONST_NONE
Definition: avr_esil.c:26
OPCODE_DESC opcodes[]
Definition: avr_esil.c:1270
static bool avr_custom_spm_page_fill(RzAnalysisEsil *esil)
Definition: avr_esil.c:1516
struct _opcodes_tag_ OPCODE_DESC
struct _cpu_const_tag CPU_CONST
int jump(int a, int b)
Definition: bcj_test.c:35
int call(int a, int b)
Definition: bcj_test.c:25
static bool rjmp(RzBuffer *b, ut64 addr)
Definition: bin_avr.c:24
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
static static fork write
Definition: sflib.h:33
#define CMP(x, y)
#define ut8
Definition: dcpu16.h:8
uint16_t ut16
uint32_t ut32
RZ_API void rz_des_permute_key(ut32 *keylo, ut32 *keyhi)
Apply PC-1.
Definition: des.c:115
RZ_API void rz_des_pc2(RZ_OUT ut32 *keylo, RZ_OUT ut32 *keyhi, RZ_IN ut32 deslo, RZ_IN ut32 deshi)
PC-2 permutation of a key.
Definition: des.c:247
RZ_API void rz_des_permute_block1(ut32 *blocklo, ut32 *blockhi)
last permutation of the block
Definition: des.c:195
RZ_API void rz_des_shift_key(int i, bool decrypt, RZ_INOUT ut32 *deskeylo, RZ_INOUT ut32 *deskeyhi)
Apply the respective shift to the key for a given round.
Definition: des.c:225
RZ_API void rz_des_round(RZ_OUT ut32 *buflo, RZ_OUT ut32 *bufhi, RZ_IN ut32 *roundkeylo, RZ_IN ut32 *roundkeyhi)
Apply the cipher function (f)
Definition: des.c:292
RZ_API void rz_des_permute_key_inv(ut32 *keylo, ut32 *keyhi)
Inverse of rz_des_permute_key (PC-1)
Definition: des.c:153
RZ_API void rz_des_permute_block0(ut32 *blocklo, ut32 *blockhi)
first permutation of the input block
Definition: des.c:171
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
RZ_API int rz_analysis_esil_get_parm(RzAnalysisEsil *esil, const char *str, ut64 *num)
Definition: esil.c:483
RZ_API int rz_analysis_esil_mem_write(RzAnalysisEsil *esil, ut64 addr, const ut8 *buf, int len)
Definition: esil.c:341
RZ_API int rz_analysis_esil_reg_read(RzAnalysisEsil *esil, const char *regname, ut64 *num, int *size)
Definition: esil.c:507
RZ_API bool rz_analysis_esil_set_op(RzAnalysisEsil *esil, const char *op, RzAnalysisEsilOpCb code, ut32 push, ut32 pop, ut32 type)
Definition: esil.c:110
RZ_API int rz_analysis_esil_reg_write(RzAnalysisEsil *esil, const char *dst, ut64 num)
Definition: esil.c:487
RZ_API char * rz_analysis_esil_pop(RzAnalysisEsil *esil)
Definition: esil.c:422
RZ_API int rz_analysis_esil_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len)
Definition: esil.c:259
static const char *const reg_names[]
Definition: hppa-dis.c:33
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * mem
Definition: libc.cpp:91
#define AND
Definition: ansidecl.h:254
void * malloc(size_t size)
Definition: malloc.c:123
#define TRAP
Definition: mips-opc.c:40
int type
Definition: mipsasm.c:17
#define swap(a, b)
Definition: qsort.h:111
#define OR
Definition: rsp_idec.c:210
#define XOR
Definition: rsp_idec.c:212
#define NOP
Definition: rsp_idec.c:182
#define ADD
Definition: rsp_idec.c:200
static RzSocket * s
Definition: rtr.c:28
@ RZ_ANALYSIS_ESIL_OP_TYPE_CUSTOM
Definition: rz_analysis.h:1184
static ut32 rz_read_at_le32(const void *src, size_t offset)
Definition: rz_endian.h:248
static void rz_write_at_le32(void *dest, ut32 val, size_t offset)
Definition: rz_endian.h:261
#define LOAD(addr)
#define MUL(x, y)
#define STORE(addr, val)
#define JMP(tgt)
#define RZ_LOG_DEBUG(fmtstr,...)
Definition: rz_log.h:49
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API char * rz_strbuf_get(RzStrBuf *sb)
Definition: strbuf.c:321
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 RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
#define PFMT64d
Definition: rz_types.h:394
#define PFMT64x
Definition: rz_types.h:393
#define st32
Definition: rz_types_base.h:12
#define SUB(ns, call)
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
const char *const key
Definition: avr_esil.c:20
char * inherit
Definition: avr_esil.c:33
struct _cpu_model_tag * inherit_cpu_p
Definition: avr_esil.c:34
CPU_CONST * consts[10]
Definition: avr_esil.c:35
const char *const model
Definition: avr_esil.c:31
inst_handler_t handler
Definition: avr_esil.c:44
const char *const name
Definition: avr_esil.c:41
int selector
Definition: avr_esil.c:43
Definition: z80asm.h:102
RzAnalysisEsilHookRegWriteCB hook_reg_write
Definition: rz_analysis.h:1038
RzAnalysis * analysis
Definition: rz_analysis.h:1043
RzAnalysisEsilCallbacks cb
Definition: rz_analysis.h:1078
#define fail(test)
Definition: tests.h:29
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58
static int add(char *argv[])
Definition: ziptool.c:84