Rizin
unix-like reverse engineering framework and cli tools
analysis_8051.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2013-2019 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2013-2019 dkreuter <dkreuter@gmail.com>
3 // SPDX-FileCopyrightText: 2013-2019 astuder <github@adrianstuder.com>
4 // SPDX-License-Identifier: LGPL-3.0-only
5 
6 #include <string.h>
7 #include <rz_types.h>
8 #include <rz_lib.h>
9 #include <rz_asm.h>
10 #include <rz_analysis.h>
11 
12 #include <8051_ops.h>
13 #include "../asm/arch/8051/8051_disas.c"
14 
15 typedef struct {
16  const char *name;
23 
24 static const i8051_cpu_model cpu_models[] = {
25  { .name = "8051-generic",
26  .map_code = 0,
27  .map_idata = 0x10000000,
28  .map_sfr = 0x10000180,
29  .map_xdata = 0x20000000,
30  .map_pdata = 0x00000000 },
31  { .name = "8051-shared-code-xdata",
32  .map_code = 0,
33  .map_idata = 0x10000000,
34  .map_sfr = 0x10000180,
35  .map_xdata = 0x00000000,
36  .map_pdata = 0x00000000 },
37  {
38  .name = NULL // last entry
39  }
40 };
41 
42 static bool i8051_reg_write(RzReg *reg, const char *regname, ut32 num) {
43  if (reg) {
45  if (item) {
46  rz_reg_set_value(reg, item, num);
47  return true;
48  }
49  }
50  return false;
51 }
52 
53 static ut32 i8051_reg_read(RzReg *reg, const char *regname) {
54  if (reg) {
56  if (item) {
57  return rz_reg_get_value(reg, item);
58  }
59  }
60  return 0;
61 }
62 
63 typedef struct {
66  const char *name;
68 
69 static const int I8051_IDATA = 0;
70 static const int I8051_SFR = 1;
71 static const int I8051_XDATA = 2;
72 
73 static const i8051_map_entry init_mem_map[3] = {
74  { NULL, UT32_MAX, "idata" },
75  { NULL, UT32_MAX, "sfr" },
76  { NULL, UT32_MAX, "xdata" }
77 };
78 
79 typedef struct {
81  i8051_map_entry mem_map[3];
83 
84 static void map_cpu_memory(RzAnalysis *analysis, int entry, ut32 addr, ut32 size, bool force) {
86  RzIODesc *desc = ctx->mem_map[entry].desc;
87  if (desc && analysis->iob.fd_get_name(analysis->iob.io, desc->fd)) {
88  if (force || addr != ctx->mem_map[entry].addr) {
89  // reallocate mapped memory if address changed
90  analysis->iob.fd_remap(analysis->iob.io, desc->fd, addr);
91  }
92  } else {
93  // allocate memory for address space
94  char *mstr = rz_str_newf("malloc://%d", size);
95  desc = analysis->iob.open_at(analysis->iob.io, mstr, RZ_PERM_RW, 0, addr, NULL);
96  free(mstr);
97  // set 8051 address space as name of mapped memory
98  if (desc && analysis->iob.fd_get_name(analysis->iob.io, desc->fd)) {
99  RzList *maps = analysis->iob.fd_get_map(analysis->iob.io, desc->fd);
100  RzIOMap *current_map;
101  RzListIter *iter;
102  rz_list_foreach (maps, iter, current_map) {
103  char *cmdstr = rz_str_newf("omni %d %s", current_map->id, ctx->mem_map[entry].name);
104  analysis->coreb.cmd(analysis->coreb.core, cmdstr);
105  free(cmdstr);
106  }
108  }
109  }
110  ctx->mem_map[entry].desc = desc;
111  ctx->mem_map[entry].addr = addr;
112 }
113 
114 static void set_cpu_model(RzAnalysis *analysis, bool force) {
115  ut32 addr_idata, addr_sfr, addr_xdata;
116 
117  if (!analysis->reg) {
118  return;
119  }
120 
121  const char *cpu = analysis->cpu;
122  if (!cpu || !cpu[0]) {
123  cpu = cpu_models[0].name;
124  }
125  i8051_plugin_context *ctx = analysis->plugin_data;
126  // if cpu model changed, reinitialize emulation
127  if (force || !ctx->cpu_curr_model || rz_str_casecmp(cpu, ctx->cpu_curr_model->name)) {
128  // find model by name
129  int i = 0;
131  i++;
132  }
133  if (!cpu_models[i].name) {
134  i = 0; // if not found, default to generic 8051
135  }
136  ctx->cpu_curr_model = &cpu_models[i];
137 
138  // TODO: Add flags as needed - seek using pseudo registers works w/o flags
139 
140  // set memory map registers
141  addr_idata = cpu_models[i].map_idata;
142  addr_sfr = cpu_models[i].map_sfr;
143  addr_xdata = cpu_models[i].map_xdata;
144  i8051_reg_write(analysis->reg, "_code", cpu_models[i].map_code);
145  i8051_reg_write(analysis->reg, "_idata", addr_idata);
146  i8051_reg_write(analysis->reg, "_sfr", addr_sfr - 0x80);
147  i8051_reg_write(analysis->reg, "_xdata", addr_xdata);
148  i8051_reg_write(analysis->reg, "_pdata", cpu_models[i].map_pdata);
149  } else {
150  addr_idata = i8051_reg_read(analysis->reg, "_idata");
151  addr_sfr = i8051_reg_read(analysis->reg, "_sfr") + 0x80;
152  addr_xdata = i8051_reg_read(analysis->reg, "_xdata");
153  }
154 
155  // (Re)allocate memory as needed.
156  // We assume that code is allocated with firmware image
157  if (analysis->iob.fd_get_name && analysis->coreb.cmd) {
158  map_cpu_memory(analysis, I8051_IDATA, addr_idata, 0x100, force);
159  map_cpu_memory(analysis, I8051_SFR, addr_sfr, 0x80, force);
160  map_cpu_memory(analysis, I8051_XDATA, addr_xdata, 0x10000, force);
161  }
162 }
163 
164 static const ut8 bitindex[] = {
165  // bit 'i' can be found in (ram[bitindex[i>>3]] >> (i&7)) & 1
166  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, // 0x00
167  0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // 0x40
168  0x80, 0x88, 0x90, 0x98, 0xA0, 0xA8, 0xB0, 0xB8, // 0x80
169  0xC0, 0xC8, 0xD0, 0xD8, 0xE0, 0xE8, 0xF0, 0xF8 // 0xC0
170 };
171 
172 #if 0
173 typedef struct {
174  const char *name;
175  ut8 offset; // offset into memory, where the value is held
176  ut8 resetvalue; // value the register takes in case of a reset
177  ut8 num_bytes; // no more than sizeof(ut64)
178  ut8 banked : 1;
179  ut8 isdptr : 1;
180 } RI8051Reg;
181 
182 // custom reg read/write temporarily disabled - see r2 issue #9242
183 static RI8051Reg registers[] = {
184  // keep these sorted
185  {"a", 0xE0, 0x00, 1, 0},
186  {"b", 0xF0, 0x00, 1, 0},
187  {"dph", 0x83, 0x00, 1, 0},
188  {"dpl", 0x82, 0x00, 1, 0},
189  {"dptr", 0x82, 0x00, 2, 0, 1},
190  {"ie", 0xA8, 0x00, 1, 0},
191  {"ip", 0xB8, 0x00, 1, 0},
192  {"p0", 0x80, 0xFF, 1, 0},
193  {"p1", 0x90, 0xFF, 1, 0},
194  {"p2", 0xA0, 0xFF, 1, 0},
195  {"p3", 0xB0, 0xFF, 1, 0},
196  {"pcon", 0x87, 0x00, 1, 0},
197  {"psw", 0xD0, 0x00, 1, 0},
198  {"r0", 0x00, 0x00, 1, 1},
199  {"r1", 0x01, 0x00, 1, 1},
200  {"r2", 0x02, 0x00, 1, 1},
201  {"r3", 0x03, 0x00, 1, 1},
202  {"r4", 0x04, 0x00, 1, 1},
203  {"r5", 0x05, 0x00, 1, 1},
204  {"r6", 0x06, 0x00, 1, 1},
205  {"r7", 0x07, 0x00, 1, 1},
206  {"sbuf", 0x99, 0x00, 1, 0},
207  {"scon", 0x98, 0x00, 1, 0},
208  {"sp", 0x81, 0x07, 1, 0},
209  {"tcon", 0x88, 0x00, 1, 0},
210  {"th0", 0x8C, 0x00, 1, 0},
211  {"th1", 0x8D, 0x00, 1, 0},
212  {"tl0", 0x8A, 0x00, 1, 0},
213  {"tl1", 0x8B, 0x00, 1, 0},
214  {"tmod", 0x89, 0x00, 1, 0}
215 };
216 #endif
217 
218 #define e(frag) rz_strbuf_append(&op->esil, frag)
219 #define ef(frag, ...) rz_strbuf_appendf(&op->esil, frag, __VA_ARGS__)
220 
221 #define flag_c "7,$c,c,:=,"
222 #define flag_b "8,$b,c,:=,"
223 #define flag_ac "3,$c,ac,:=,"
224 #define flag_ab "3,$b,ac,:=,"
225 #define flag_ov "6,$c,ov,:=,"
226 #define flag_ob "7,$b,6,$b,^,ov,:=,"
227 #define flag_p "0xff,a,&=,$p,!,p,:=,"
228 
229 #define ev_a 0
230 #define ev_bit bitindex[buf[1] >> 3]
231 #define ev_c 0
232 #define ev_dir1 buf[1]
233 #define ev_dir2 buf[2]
234 #define ev_dp 0
235 #define ev_dpx 0
236 #define ev_imm1 buf[1]
237 #define ev_imm2 buf[2]
238 #define ev_imm16 op->val
239 #define ev_ri (1 & buf[0])
240 #define ev_rix (1 & buf[0])
241 #define ev_rn (7 & buf[0])
242 #define ev_sp2 0
243 #define ev_sp1 0
244 
245 static void exr_a(RzAnalysisOp *op, ut8 dummy) {
246  e("a,");
247 }
248 
249 static void exr_dir1(RzAnalysisOp *op, ut8 addr) {
250  if (addr < 0x80) {
251  ef("_idata,%d,+,[1],", addr);
252  } else {
253  ef("_sfr,%d,+,[1],", addr);
254  }
255 }
256 
257 static void exr_bit(RzAnalysisOp *op, ut8 addr) {
258  exr_dir1(op, addr);
259 }
260 
261 static void exr_dpx(RzAnalysisOp *op, ut8 dummy) {
262  e("_xdata,dptr,+,[1],");
263 }
264 
265 static void exr_imm1(RzAnalysisOp *op, ut8 val) {
266  ef("%d,", val);
267 }
268 
269 static void exr_imm2(RzAnalysisOp *op, ut8 val) {
270  ef("%d,", val);
271 }
272 
273 static void exr_imm16(RzAnalysisOp *op, ut16 val) {
274  ef("%d,", val);
275 }
276 
277 static void exr_ri(RzAnalysisOp *op, ut8 reg) {
278  ef("_idata,r%d,+,[1],", reg);
279 }
280 
281 static void exr_rix(RzAnalysisOp *op, ut8 reg) {
282  ef("8,0xff,_pdata,&,<<,_xdata,+,r%d,+,[1],", reg);
283 }
284 
285 static void exr_rn(RzAnalysisOp *op, ut8 reg) {
286  ef("r%d,", reg);
287 }
288 
289 static void exr_sp1(RzAnalysisOp *op, ut8 dummy) {
290  e("_idata,sp,+,[1],");
291  e("1,sp,-=,");
292 }
293 
294 static void exr_sp2(RzAnalysisOp *op, ut8 dummy) {
295  e("1,sp,-=,");
296  e("_idata,sp,+,[2],");
297  e("1,sp,-=,");
298 }
299 
300 static void exw_a(RzAnalysisOp *op, ut8 dummy) {
301  e("a,=,");
302 }
303 
304 static void exw_c(RzAnalysisOp *op, ut8 dummy) {
305  e("c,=,");
306 }
307 
308 static void exw_dir1(RzAnalysisOp *op, ut8 addr) {
309  if (addr < 0x80) {
310  ef("_idata,%d,+,=[1],", addr);
311  } else {
312  ef("_sfr,%d,+,=[1],", addr);
313  }
314 }
315 
316 static void exw_dir2(RzAnalysisOp *op, ut8 addr) {
317  exw_dir1(op, addr);
318 }
319 
320 static void exw_bit(RzAnalysisOp *op, ut8 addr) {
321  exw_dir1(op, addr);
322 }
323 
324 static void exw_dp(RzAnalysisOp *op, ut8 dummy) {
325  e("dptr,=,");
326 }
327 
328 static void exw_dpx(RzAnalysisOp *op, ut8 dummy) {
329  e("_xdata,dptr,+,=[1],");
330 }
331 
332 static void exw_ri(RzAnalysisOp *op, ut8 reg) {
333  ef("_idata,r%d,+,=[1],", reg);
334 }
335 
336 static void exw_rix(RzAnalysisOp *op, ut8 reg) {
337  ef("8,0xff,_pdata,&,<<,_xdata,+,r%d,+,=[1],", reg);
338 }
339 
340 static void exw_rn(RzAnalysisOp *op, ut8 reg) {
341  ef("r%d,=,", reg);
342 }
343 
344 static void exw_sp1(RzAnalysisOp *op, ut8 dummy) {
345  e("1,sp,+=,");
346  e("_idata,sp,+,=[1],");
347 }
348 
349 static void exw_sp2(RzAnalysisOp *op, ut8 dummy) {
350  e("1,sp,+=,");
351  e("_idata,sp,+,=[2],");
352  e("1,sp,+=,");
353 }
354 
355 static void exi_a(RzAnalysisOp *op, ut8 dummy, const char *operation) {
356  ef("a,%s=,", operation);
357 }
358 
359 static void exi_c(RzAnalysisOp *op, ut8 dummy, const char *operation) {
360  ef("c,%s=,", operation);
361 }
362 
363 static void exi_dp(RzAnalysisOp *op, ut8 dummy, const char *operation) {
364  ef("dptr,%s=,", operation);
365 }
366 
367 static void exi_dir1(RzAnalysisOp *op, ut8 addr, const char *operation) {
368  if (addr < 0x80) {
369  ef("_idata,%d,+,%s=[1],", addr, operation);
370  } else {
371  ef("_sfr,%d,+,%s=[1],", addr, operation);
372  }
373 }
374 
375 static void exi_bit(RzAnalysisOp *op, ut8 addr, const char *operation) {
376  exi_dir1(op, addr, operation);
377 }
378 
379 static void exi_ri(RzAnalysisOp *op, ut8 reg, const char *operation) {
380  ef("_idata,r%d,+,%s=[1],", reg, operation);
381 }
382 
383 static void exi_rn(RzAnalysisOp *op, ut8 reg, const char *operation) {
384  ef("r%d,%s=,", reg, operation);
385 }
386 
387 #define xr(subject) exr_##subject(op, ev_##subject)
388 #define xw(subject) exw_##subject(op, ev_##subject)
389 #define xi(subject, operation) exi_##subject(op, ev_##subject, operation)
390 
391 #define bit_set ef("%d,1,<<,", buf[1] & 7)
392 #define bit_mask \
393  bit_set; \
394  e("255,^,")
395 #define bit_r \
396  ef("%d,", buf[1] & 7); \
397  xr(bit); \
398  e(">>,1,&,")
399 #define bit_c ef("%d,c,<<,", buf[1] & 7);
400 
401 #define jmp ef("%" PFMT64d ",pc,=", op->jump)
402 #define cjmp \
403  e("?{,"); \
404  jmp; \
405  e(",}")
406 #define call \
407  ef("%" PFMT64d ",", op->fail); \
408  xw(sp2); \
409  jmp
410 
411 #define alu_op(val, aluop, flags) \
412  xr(val); \
413  e("a," aluop "=," flags)
414 #define alu_op_c(val, aluop, flags) \
415  e("c,"); \
416  xr(val); \
417  e("+,a," aluop "=," flags)
418 #define alu_op_d(val, aluop) \
419  xr(val); \
420  xi(dir1, aluop)
421 
422 #define template_alu4_c(base, aluop, flags) \
423  case base + 0x4: \
424  alu_op_c(imm1, aluop, flags); \
425  break; \
426  case base + 0x5: \
427  alu_op_c(dir1, aluop, flags); \
428  break; \
429  case base + 0x6: \
430  case base + 0x7: \
431  alu_op_c(ri, aluop, flags); \
432  break; \
433  case base + 0x8: \
434  case base + 0x9: \
435  case base + 0xA: \
436  case base + 0xB: \
437  case base + 0xC: \
438  case base + 0xD: \
439  case base + 0xE: \
440  case base + 0xF: \
441  alu_op_c(rn, aluop, flags); \
442  break;
443 
444 #define template_alu2(base, aluop) \
445  case base + 0x2: \
446  alu_op_d(a, aluop); \
447  break; \
448  case base + 0x3: \
449  alu_op_d(imm2, aluop); \
450  break;
451 
452 #define template_alu4(base, aluop, flags) \
453  case base + 0x4: \
454  alu_op(imm1, aluop, flags); \
455  break; \
456  case base + 0x5: \
457  alu_op(dir1, aluop, flags); \
458  break; \
459  case base + 0x6: \
460  case base + 0x7: \
461  alu_op(ri, aluop, flags); \
462  break; \
463  case base + 0x8: \
464  case base + 0x9: \
465  case base + 0xA: \
466  case base + 0xB: \
467  case base + 0xC: \
468  case base + 0xD: \
469  case base + 0xE: \
470  case base + 0xF: \
471  alu_op(rn, aluop, flags); \
472  break;
473 
474 static void analop_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf) {
475  rz_strbuf_init(&op->esil);
476  rz_strbuf_set(&op->esil, "");
477 
478  switch (buf[0]) {
479  // Irregulars sorted by lower nibble
480  case 0x00: /* nop */
481  e(",");
482  break;
483 
484  case 0x10: /* jbc bit, offset */
485  bit_r;
486  e("?{,");
487  bit_mask;
488  xi(bit, "&");
489  jmp;
490  e(",}");
491  break;
492  case 0x20: /* jb bit, offset */
493  bit_r;
494  cjmp;
495  break;
496  case 0x30: /* jnb bit, offset */
497  bit_r;
498  e("!,");
499  cjmp;
500  break;
501  case 0x40: /* jc offset */
502  e("c,1,&,");
503  cjmp;
504  break;
505  case 0x50: /* jnc offset */
506  e("c,1,&,!,");
507  cjmp;
508  break;
509  case 0x60: /* jz offset */
510  e("a,0,==,$z,");
511  cjmp;
512  break;
513  case 0x70: /* jnz offset */
514  e("a,0,==,$z,!,");
515  cjmp;
516  break;
517 
518  case 0x11:
519  case 0x31:
520  case 0x51:
521  case 0x71:
522  case 0x91:
523  case 0xB1:
524  case 0xD1:
525  case 0xF1: /* acall addr11 */
526  case 0x12: /* lcall addr16 */
527  call;
528  break;
529  case 0x01:
530  case 0x21:
531  case 0x41:
532  case 0x61:
533  case 0x81:
534  case 0xA1:
535  case 0xC1:
536  case 0xE1: /* ajmp addr11 */
537  case 0x02: /* ljmp addr16 */
538  case 0x80: /* sjmp offset */
539  jmp;
540  break;
541 
542  case 0x22: /* ret */
543  case 0x32: /* reti */
544  xr(sp2);
545  e("pc,=");
546  break;
547 
548  case 0x03: /* rr a */
549  e("1,a,0x101,*,>>,a,=," flag_p);
550  break;
551  case 0x04: /* inc a */
552  xi(a, "++");
553  e(flag_p);
554  break;
555  case 0x05: /* inc direct */
556  xi(dir1, "++");
557  break;
558  case 0x06:
559  case 0x07: /* inc @Ri */
560  xi(ri, "++");
561  break;
562  case 0x08:
563  case 0x09:
564  case 0x0A:
565  case 0x0B:
566  case 0x0C:
567  case 0x0D:
568  case 0x0E:
569  case 0x0F: /* inc @Rn */
570  xi(rn, "++");
571  break;
572  case 0x13: /* rrc a */
573  e("7,c,<<,1,a,&,c,=,0x7f,1,a,>>,&,+,a,=," flag_p);
574  break;
575  case 0x14: /* dec a */
576  xi(a, "--");
577  e(flag_p);
578  break;
579  case 0x15: /* dec direct */
580  xi(dir1, "--");
581  e(flag_p);
582  break;
583  case 0x16:
584  case 0x17: /* dec @Ri */
585  xi(ri, "--");
586  break;
587  case 0x18:
588  case 0x19:
589  case 0x1A:
590  case 0x1B:
591  case 0x1C:
592  case 0x1D:
593  case 0x1E:
594  case 0x1F: /* dec @Rn */
595  xi(rn, "--");
596  break;
597  case 0x23: /* rl a */
598  e("7,a,0x101,*,>>,a,=," flag_p);
599  break;
600  template_alu4(0x20, "+", flag_c flag_ac flag_ov flag_p) /* 0x24..0x2f add a,.. */
601  case 0x33 : /* rlc a */
602  e("c,1,&,a,a,+=,7,$c,c,:=,a,+=," flag_p);
603  break;
604  template_alu4_c(0x30, "+", flag_c flag_ac flag_ov flag_p) /* 0x34..0x3f addc a,.. */
605  template_alu2(0x40, "|") /* 0x42..0x43 orl direct,.. */
606  template_alu4(0x40, "|", flag_p) /* 0x44..0x4f orl a,.. */
607  template_alu2(0x50, "&") /* 0x52..0x53 anl direct,.. */
608  template_alu4(0x50, "&", flag_p) /* 0x54..0x5f anl a,.. */
609  template_alu2(0x60, "^") /* 0x62..0x63 xrl direct,.. */
610  template_alu4(0x60, "^", flag_p) /* 0x64..0x6f xrl a,.. */
611  case 0x72 : /* orl C, bit */
612  bit_r;
613  xi(c, "|");
614  break;
615  case 0x73: /* jmp @a+dptr */
616  e("dptr,a,+,pc,=");
617  break;
618  case 0x74: /* mov a, imm */
619  xr(imm1);
620  xw(a);
621  e(flag_p);
622  break;
623  case 0x75: /* mov direct, imm */
624  xr(imm2);
625  xw(dir1);
626  break;
627  case 0x76:
628  case 0x77: /* mov @Ri, imm */
629  xr(imm1);
630  xw(ri);
631  break;
632  case 0x78:
633  case 0x79:
634  case 0x7A:
635  case 0x7B:
636  case 0x7C:
637  case 0x7D:
638  case 0x7E:
639  case 0x7F: /* mov Rn, imm */
640  xr(imm1);
641  xw(rn);
642  break;
643  case 0x82: /* anl C, bit */
644  bit_r;
645  xi(c, "&");
646  break;
647  case 0x83: /* movc a, @a+pc */
648  e("a,pc,--,+,[1],a,=," flag_p);
649  break;
650  case 0x84: /* div ab */
651  // note: escape % if this becomes a format string
652  e("b,0,==,$z,ov,:=,b,a,%,b,a,/=,b,=,0,c,=," flag_p);
653  break;
654  case 0x85: /* mov direct, direct */
655  xr(dir1);
656  xw(dir2);
657  break;
658  case 0x86:
659  case 0x87: /* mov direct, @Ri */
660  xr(ri);
661  xw(dir1);
662  break;
663  case 0x88:
664  case 0x89:
665  case 0x8A:
666  case 0x8B:
667  case 0x8C:
668  case 0x8D:
669  case 0x8E:
670  case 0x8F: /* mov direct, Rn */
671  xr(rn);
672  xw(dir1);
673  break;
674  case 0x90: /* mov dptr, imm */
675  xr(imm16);
676  xw(dp);
677  break;
678  case 0x92: /* mov bit, C */
679  bit_c;
680  bit_mask;
681  xr(bit);
682  e("&,|,");
683  xw(bit);
684  break;
685  case 0x93: /* movc a, @a+dptr */
686  e("a,dptr,+,[1],a,=," flag_p);
687  break;
688  template_alu4_c(0x90, "-", flag_b flag_ab flag_ob flag_p) /* 0x94..0x9f subb a,.. */
689  case 0xA0 : /* orl C, /bit */
690  bit_r;
691  e("!,");
692  xi(c, "|");
693  break;
694  case 0xA2: /* mov C, bit */
695  bit_r;
696  xw(c);
697  break;
698  case 0xA3: /* inc dptr */
699  xi(dp, "++");
700  break;
701  case 0xA4: /* mul ab */
702  e("8,a,b,*,DUP,a,=,>>,DUP,b,=,0,==,$z,!,ov,:=,0,c,=," flag_p);
703  break;
704  case 0xA5: /* "reserved" */
705  e("0,trap");
706  break;
707  case 0xA6:
708  case 0xA7: /* mov @Ri, direct */
709  xr(dir1);
710  xw(ri);
711  break;
712  case 0xA8:
713  case 0xA9:
714  case 0xAA:
715  case 0xAB:
716  case 0xAC:
717  case 0xAD:
718  case 0xAE:
719  case 0xAF: /* mov Rn, direct */
720  xr(dir1);
721  xw(rn);
722  break;
723  case 0xB0: /* anl C, /bit */
724  bit_r;
725  e("!,");
726  xi(c, "&");
727  break;
728  case 0xB2: /* cpl bit */
729  bit_set;
730  xi(bit, "^");
731  break;
732  case 0xB3: /* cpl C */
733  e("1,");
734  xi(c, "^");
735  break;
736  case 0xB4: /* cjne a, imm, offset */
737  xr(imm1);
738  xr(a);
739  e("==,$z,!," flag_b);
740  cjmp;
741  break;
742  case 0xB5: /* cjne a, direct, offset */
743  xr(dir1);
744  xr(a);
745  e("==,$z,!," flag_b);
746  cjmp;
747  break;
748  case 0xB6:
749  case 0xB7: /* cjne @ri, imm, offset */
750  xr(imm1);
751  xr(ri);
752  e("==,$z,!," flag_b);
753  cjmp;
754  break;
755  case 0xB8:
756  case 0xB9:
757  case 0xBA:
758  case 0xBB:
759  case 0xBC:
760  case 0xBD:
761  case 0xBE:
762  case 0xBF: /* cjne Rn, imm, offset */
763  xr(imm1);
764  xr(rn);
765  e("==,$z,!," flag_b);
766  cjmp;
767  break;
768  case 0xC0: /* push direct */
769  xr(dir1);
770  xw(sp1);
771  break;
772  case 0xC2: /* clr bit */
773  bit_mask;
774  xi(bit, "&");
775  break;
776  case 0xC3: /* clr C */
777  e("0,");
778  xw(c);
779  break;
780  case 0xC4: /* swap a */
781  e("0xff,4,a,0x101,*,>>,&,a,=," flag_p);
782  break;
783  case 0xC5: /* xch a, direct */
784  xr(a);
785  e("0,+,");
786  xr(dir1);
787  xw(a);
788  xw(dir1);
789  e(flag_p);
790  break;
791  case 0xC6:
792  case 0xC7: /* xch a, @Ri */
793  xr(a);
794  e("0,+,");
795  xr(ri);
796  xw(a);
797  xw(ri);
798  e(flag_p);
799  break;
800  case 0xC8:
801  case 0xC9:
802  case 0xCA:
803  case 0xCB:
804  case 0xCC:
805  case 0xCD:
806  case 0xCE:
807  case 0xCF: /* xch a, Rn */
808  xr(a);
809  e("0,+,");
810  xr(rn);
811  xw(a);
812  xw(rn);
813  e(flag_p);
814  break;
815  case 0xD0: /* pop direct */
816  xr(sp1);
817  xw(dir1);
818  break;
819  case 0xD2: /* setb bit */
820  bit_set;
821  xi(bit, "|");
822  break;
823  case 0xD3: /* setb C */
824  e("1,");
825  xw(c);
826  break;
827  case 0xD4: /* da a */
828  // BCD adjust after add:
829  // if (lower nibble > 9) or (AC == 1) add 6
830  // if (higher nibble > 9) or (C == 1) add 0x60
831  // carry |= carry caused by this operation
832  e("a,0x0f,&,9,==,4,$b,ac,|,?{,6,a,+=,7,$c,c,|,c,:=,},a,0xf0,&,0x90,==,8,$b,c,|,?{,0x60,a,+=,7,$c,c,|,c,:=,}," flag_p);
833  break;
834  case 0xD5: /* djnz direct, offset */
835  xi(dir1, "--");
836  xr(dir1);
837  e("0,==,$z,!,");
838  cjmp;
839  break;
840  case 0xD6:
841  case 0xD7: /* xchd a, @Ri*/
842  xr(a);
843  e("0xf0,&,");
844  xr(ri);
845  e("0x0f,&,|,");
846  xr(ri);
847  e("0xf0,&,");
848  xr(a);
849  e("0x0f,&,|,");
850  xw(ri);
851  xw(a);
852  e(flag_p);
853  break;
854  case 0xD8:
855  case 0xD9:
856  case 0xDA:
857  case 0xDB:
858  case 0xDC:
859  case 0xDD:
860  case 0xDE:
861  case 0xDF: /* djnz Rn, offset */
862  xi(rn, "--");
863  xr(rn);
864  e("0,==,$z,!,");
865  cjmp;
866  break;
867  case 0xE0: /* movx a, @dptr */
868  xr(dpx);
869  xw(a);
870  e(flag_p);
871  break;
872  case 0xE2:
873  case 0xE3: /* movx a, @Ri */
874  xr(rix);
875  xw(a);
876  e(flag_p);
877  break;
878  case 0xE4: /* clr a */
879  e("0,");
880  xw(a);
881  e(flag_p);
882  break;
883  case 0xE5: /* mov a, direct */
884  xr(dir1);
885  xw(a);
886  e(flag_p);
887  break;
888  case 0xE6:
889  case 0xE7: /* mov a, @Ri */
890  xr(ri);
891  xw(a);
892  e(flag_p);
893  break;
894  case 0xE8:
895  case 0xE9:
896  case 0xEA:
897  case 0xEB:
898  case 0xEC:
899  case 0xED:
900  case 0xEE:
901  case 0xEF: /* mov a, Rn */
902  xr(rn);
903  xw(a);
904  e(flag_p);
905  break;
906  case 0xF0: /* movx @dptr, a */
907  xr(a);
908  xw(dpx);
909  break;
910  case 0xF2:
911  case 0xF3: /* movx @Ri, a */
912  xr(a);
913  xw(rix);
914  break;
915  case 0xF4: /* cpl a */
916  e("255,");
917  xi(a, "^");
918  e(flag_p);
919  break;
920  case 0xF5: /* mov direct, a */
921  xr(a);
922  xw(dir1);
923  break;
924  case 0xF6:
925  case 0xF7: /* mov @Ri, a */
926  xr(a);
927  xw(ri);
928  break;
929  case 0xF8:
930  case 0xF9:
931  case 0xFA:
932  case 0xFB:
933  case 0xFC:
934  case 0xFD:
935  case 0xFE:
936  case 0xFF: /* mov Rn, a */
937  xr(a);
938  xw(rn);
939  break;
940  default:
941  break;
942  }
943 }
944 
945 #if 0
946 // custom reg read/write temporarily disabled - see r2 issue #9242
947 static int i8051_hook_reg_read(RzAnalysisEsil *, const char *, ut64 *, int *);
948 
949 static int i8051_reg_compare(const void *name, const void *reg) {
950  return strcmp ((const char*)name, ((RI8051Reg*)reg)->name);
951 }
952 
953 static RI8051Reg *i8051_reg_find(const char *name) {
954  return (RI8051Reg *) bsearch (
955  name, registers,
956  sizeof (registers) / sizeof (registers[0]),
957  sizeof (registers[0]),
958  i8051_reg_compare);
959 }
960 
961 static int i8051_reg_get_offset(RzAnalysisEsil *esil, RI8051Reg *ri) {
962  ut8 offset = ri->offset;
963  if (ri->banked) {
964  ut64 psw = 0LL;
965  i8051_hook_reg_read (esil, "psw", &psw, NULL);
966  offset += psw & 0x18;
967  }
968  return offset;
969 }
970 
971 // dkreuter: It would be nice if we could attach hooks to RzRegItems directly.
972 // That way we could avoid doing a string lookup on register names
973 // as rz_reg_get already does this. Also, the analysis esil callbacks
974 // approach interferes with rz_reg_arena_swap.
975 
976 static int i8051_hook_reg_read(RzAnalysisEsil *esil, const char *name, ut64 *res, int *size) {
977  int ret = 0;
978  ut64 val = 0LL;
979  RI8051Reg *ri;
980  RzAnalysisEsilCallbacks cbs = esil->cb;
981 
982  if ((ri = i8051_reg_find (name))) {
983  ut8 offset = i8051_reg_get_offset(esil, ri);
984  ret = rz_analysis_esil_mem_read (esil, IRAM_BASE + offset, (ut8*)res, ri->num_bytes);
985  }
986  esil->cb = ocbs;
987  if (!ret && ocbs.hook_reg_read) {
988  ret = ocbs.hook_reg_read (esil, name, res, NULL);
989  }
990  if (!ret && ocbs.reg_read) {
991  ret = ocbs.reg_read (esil, name, &val, NULL);
992  }
993  esil->cb = cbs;
994 
995  return ret;
996 }
997 
998 static int i8051_hook_reg_write(RzAnalysisEsil *esil, const char *name, ut64 *val) {
999  int ret = 0;
1000  RI8051Reg *ri;
1001  RzAnalysisEsilCallbacks cbs = esil->cb;
1002  if ((ri = i8051_reg_find (name))) {
1003  ut8 offset = i8051_reg_get_offset(esil, ri);
1004  ret = rz_analysis_esil_mem_write (esil, IRAM_BASE + offset, (ut8*)val, ri->num_bytes);
1005  }
1006  esil->cb = ocbs;
1007  if (!ret && ocbs.hook_reg_write) {
1008  ret = ocbs.hook_reg_write (esil, name, val);
1009  }
1010  esil->cb = cbs;
1011  return ret;
1012 }
1013 #endif
1014 
1015 static int esil_i8051_init(RzAnalysisEsil *esil) {
1016  // reset emulation control registers based on cpu
1017  set_cpu_model(esil->analysis, true);
1018 
1019  if (esil->cb.user) {
1020  return true;
1021  }
1023  if (!ocbs) {
1024  return 0;
1025  }
1026  *ocbs = esil->cb;
1027  esil->cb.user = ocbs;
1028  /* these hooks break esil emulation */
1029  /* pc is not read properly, mem mapped registers are not shown in ar, ... */
1030  /* all 8051 regs are mem mapped, and reg access via mem is very common */
1031  // disabled to make esil work, before digging deeper
1032  // esil->cb.hook_reg_read = i8051_hook_reg_read;
1033  // esil->cb.hook_reg_write = i8051_hook_reg_write;
1034  return true;
1035 }
1036 
1037 static int esil_i8051_fini(RzAnalysisEsil *esil) {
1038  RZ_FREE(esil->cb.user);
1039  return true;
1040 }
1041 
1042 static char *get_reg_profile(RzAnalysis *analysis) {
1043  const char *p =
1044  "=PC pc\n"
1045  "=SP sp\n"
1046  "=A0 r0\n"
1047  "=A1 r1\n"
1048  "gpr r0 .8 0 0\n"
1049  "gpr r1 .8 1 0\n"
1050  "gpr r2 .8 2 0\n"
1051  "gpr r3 .8 3 0\n"
1052  "gpr r4 .8 4 0\n"
1053  "gpr r5 .8 5 0\n"
1054  "gpr r6 .8 6 0\n"
1055  "gpr r7 .8 7 0\n"
1056  "gpr a .8 8 0\n"
1057  "gpr b .8 9 0\n"
1058  "gpr dptr .16 10 0\n"
1059  "gpr dpl .8 10 0\n"
1060  "gpr dph .8 11 0\n"
1061  "gpr psw .8 12 0\n"
1062  "gpr p .1 .96 0\n"
1063  "gpr ov .1 .98 0\n"
1064  "gpr ac .1 .102 0\n"
1065  "gpr c .1 .103 0\n"
1066  "gpr sp .8 13 0\n"
1067  "gpr pc .16 15 0\n"
1068  // ---------------------------------------------------
1069  // 8051 memory emulation control registers
1070  // These registers map 8051 memory classes to r2's
1071  // linear address space. Registers contain base addr
1072  // in r2 memory space representing the memory class.
1073  // Offsets are initialized based on asm.cpu, but can
1074  // be updated with ar command.
1075  //
1076  // _code
1077  // program memory (CODE)
1078  // _idata
1079  // internal data memory (IDATA, IRAM)
1080  // _sfr
1081  // special function registers (SFR)
1082  // _xdata
1083  // external data memory (XDATA, XRAM)
1084  // _pdata
1085  // page accessed by movx @ri op (PDATA, XREG)
1086  // r2 addr = (_pdata & 0xff) << 8 + x_data
1087  // if 0xffffffnn, addr = ([SFRnn] << 8) + _xdata (TODO)
1088  "gpr _code .32 20 0\n"
1089  "gpr _idata .32 24 0\n"
1090  "gpr _sfr .32 28 0\n"
1091  "gpr _xdata .32 32 0\n"
1092  "gpr _pdata .32 36 0\n";
1093  return strdup(p);
1094 }
1095 
1097  if (addr < 0x80) {
1098  return addr + i8051_reg_read(analysis->reg, "_idata");
1099  } else {
1100  return addr + i8051_reg_read(analysis->reg, "_sfr");
1101  }
1102 }
1103 
1104 static int i8051_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
1105  set_cpu_model(analysis, false);
1106 
1107  int i = 0;
1108  while (_8051_ops[i].string && _8051_ops[i].op != (buf[0] & ~_8051_ops[i].mask)) {
1109  i++;
1110  }
1111 
1112  ut8 arg1 = _8051_ops[i].arg1;
1113  ut8 arg2 = _8051_ops[i].arg2;
1114 
1115  op->cycles = _8051_ops[i].cycles;
1116  op->failcycles = _8051_ops[i].cycles;
1117  op->nopcode = 1;
1118  op->size = _8051_ops[i].len;
1119  op->type = _8051_ops[i].type;
1120  op->family = RZ_ANALYSIS_OP_FAMILY_CPU; // maybe also FAMILY_IO...
1121  op->id = i;
1122 
1123  switch (_8051_ops[i].instr) {
1124  default:
1125  op->cond = RZ_TYPE_COND_AL;
1126  break;
1127  case OP_CJNE:
1128  case OP_DJNZ:
1129  case OP_JB:
1130  case OP_JBC:
1131  case OP_JNZ:
1132  op->cond = RZ_TYPE_COND_NE;
1133  break;
1134  case OP_JNB:
1135  case OP_JZ:
1136  op->cond = RZ_TYPE_COND_EQ;
1137  break;
1138  case OP_JC:
1139  op->cond = RZ_TYPE_COND_HS;
1140  break;
1141  case OP_JNC:
1142  op->cond = RZ_TYPE_COND_LO;
1143  }
1144 
1145  switch (_8051_ops[i].instr) {
1146  default:
1147  op->eob = false;
1148  break;
1149  case OP_CJNE:
1150  case OP_DJNZ:
1151  case OP_JB:
1152  case OP_JBC:
1153  case OP_JC:
1154  case OP_JMP:
1155  case OP_JNB:
1156  case OP_JNC:
1157  case OP_JNZ:
1158  case OP_JZ:
1159  op->eob = true;
1160  }
1161 
1162  // TODO: op->datatype
1163 
1164  switch (arg1) {
1165  default:
1166  break;
1167  case A_DIRECT:
1168  op->ptr = map_direct_addr(analysis, buf[1]);
1169  break;
1170  case A_BIT:
1171  op->ptr = map_direct_addr(analysis, arg_bit(buf[1]));
1172  break;
1173  case A_IMMEDIATE:
1174  op->val = buf[1];
1175  break;
1176  case A_IMM16:
1177  op->val = buf[1] * 256 + buf[2];
1178  op->ptr = op->val + i8051_reg_read(analysis->reg, "_xdata"); // best guess, it's a XRAM pointer
1179  }
1180 
1181  switch (arg2) {
1182  default:
1183  break;
1184  case A_DIRECT:
1185  if (arg1 == A_RI || arg1 == A_RN) {
1186  op->ptr = map_direct_addr(analysis, buf[1]);
1187  } else if (arg1 != A_DIRECT) {
1188  op->ptr = map_direct_addr(analysis, buf[2]);
1189  }
1190  break;
1191  case A_BIT:
1192  op->ptr = arg_bit((arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2]);
1193  op->ptr = map_direct_addr(analysis, op->ptr);
1194  break;
1195  case A_IMMEDIATE:
1196  op->val = (arg1 == A_RI || arg1 == A_RN) ? buf[1] : buf[2];
1197  }
1198 
1199  switch (_8051_ops[i].instr) {
1200  default:
1201  break;
1202  case OP_PUSH:
1203  op->stackop = RZ_ANALYSIS_STACK_INC;
1204  op->stackptr = 1;
1205  break;
1206  case OP_POP:
1207  op->stackop = RZ_ANALYSIS_STACK_INC;
1208  op->stackptr = -1;
1209  break;
1210  case OP_RET:
1211  op->stackop = RZ_ANALYSIS_STACK_INC;
1212  op->stackptr = -2;
1213  break;
1214  case OP_CALL:
1215  op->stackop = RZ_ANALYSIS_STACK_INC;
1216  op->stackptr = 2;
1217  if (arg1 == A_ADDR11) {
1218  op->jump = arg_addr11(addr, addr + op->size, buf);
1219  op->fail = addr + op->size;
1220  } else if (arg1 == A_ADDR16) {
1221  op->jump = apply_bank(addr, 0x100 * buf[1] + buf[2]);
1222  op->fail = addr + op->size;
1223  }
1224  break;
1225  case OP_JMP:
1226  if (arg1 == A_ADDR11) {
1227  op->jump = arg_addr11(addr, addr + op->size, buf);
1228  op->fail = addr + op->size;
1229  } else if (arg1 == A_ADDR16) {
1230  op->jump = apply_bank(addr, 0x100 * buf[1] + buf[2]);
1231  op->fail = addr + op->size;
1232  } else if (arg1 == A_OFFSET) {
1233  op->jump = arg_offset(addr, addr + op->size, buf[1]);
1234  op->fail = addr + op->size;
1235  }
1236  break;
1237  case OP_CJNE:
1238  case OP_DJNZ:
1239  case OP_JC:
1240  case OP_JNC:
1241  case OP_JZ:
1242  case OP_JNZ:
1243  case OP_JB:
1244  case OP_JBC:
1245  case OP_JNB:
1246  op->jump = arg_offset(addr, addr + op->size, buf[op->size - 1]);
1247  op->fail = addr + op->size;
1248  }
1249 
1250  if (op->ptr != -1 && op->refptr == 0) {
1251  op->refptr = 1;
1252  }
1253 
1255  ut8 copy[3] = { 0, 0, 0 };
1256  memcpy(copy, buf, len >= 3 ? 3 : len);
1257  analop_esil(analysis, op, addr, copy);
1258  }
1259 
1260  int olen = 0;
1261  op->mnemonic = rz_8051_disas(addr, buf, len, &olen);
1262  op->size = olen;
1263 
1265  // TODO: op->hint
1266  }
1267 
1268  return op->size;
1269 }
1270 
1271 static bool i8051_init(void **user) {
1273  if (!ctx) {
1274  return false;
1275  }
1276  ctx->mem_map[I8051_IDATA] = init_mem_map[I8051_IDATA];
1277  ctx->mem_map[I8051_SFR] = init_mem_map[I8051_SFR];
1278  ctx->mem_map[I8051_XDATA] = init_mem_map[I8051_XDATA];
1279  *user = ctx;
1280  return true;
1281 }
1282 
1283 static bool i8051_fini(void *user) {
1284  free(user);
1285  return true;
1286 }
1287 
1289  .name = "8051",
1290  .arch = "8051",
1291  .esil = true,
1292  .bits = 8 | 16,
1293  .desc = "8051 CPU code analysis plugin",
1294  .license = "LGPL3",
1295  .op = &i8051_op,
1296  .get_reg_profile = &get_reg_profile,
1297  .esil_init = esil_i8051_init,
1298  .esil_fini = esil_i8051_fini,
1299  .init = &i8051_init,
1300  .fini = &i8051_fini,
1301 };
1302 
1303 #ifndef RZ_PLUGIN_INCORE
1306  .data = &rz_analysis_plugin_8051,
1307  .version = RZ_VERSION
1308 };
1309 #endif
size_t len
Definition: 6502dis.c:15
static char * rz_8051_disas(ut64 pc, const ut8 *buf, int len, int *olen)
Definition: 8051_disas.c:69
@ A_ADDR11
Definition: 8051_ops.h:84
@ A_IMMEDIATE
Definition: 8051_ops.h:88
@ A_DIRECT
Definition: 8051_ops.h:86
@ A_RN
Definition: 8051_ops.h:83
@ A_BIT
Definition: 8051_ops.h:87
@ A_OFFSET
Definition: 8051_ops.h:90
@ A_RI
Definition: 8051_ops.h:82
@ A_ADDR16
Definition: 8051_ops.h:85
@ A_IMM16
Definition: 8051_ops.h:89
static ut64 arg_offset(ut64 bank, ut16 pc, ut8 offset)
Definition: 8051_ops.h:18
static ut64 arg_addr11(ut64 bank, ut16 pc, const ut8 *buf)
Definition: 8051_ops.h:26
static ut64 apply_bank(ut64 ref, ut16 addr)
Construct an address with the higher bits from ref (determining the bank) and the lower from addr (of...
Definition: 8051_ops.h:14
@ OP_JZ
Definition: 8051_ops.h:61
@ OP_JNC
Definition: 8051_ops.h:59
@ OP_CJNE
Definition: 8051_ops.h:46
@ OP_JBC
Definition: 8051_ops.h:55
@ OP_JC
Definition: 8051_ops.h:56
@ OP_RET
Definition: 8051_ops.h:68
@ OP_PUSH
Definition: 8051_ops.h:67
@ OP_JB
Definition: 8051_ops.h:54
@ OP_JNZ
Definition: 8051_ops.h:60
@ OP_JNB
Definition: 8051_ops.h:58
@ OP_POP
Definition: 8051_ops.h:66
@ OP_JMP
Definition: 8051_ops.h:57
@ OP_DJNZ
Definition: 8051_ops.h:52
static _8051_op_t _8051_ops[]
Definition: 8051_ops.h:113
static ut8 arg_bit(ut8 bit_addr)
Definition: 8051_ops.h:31
static void exw_sp2(RzAnalysisOp *op, ut8 dummy)
static bool i8051_reg_write(RzReg *reg, const char *regname, ut32 num)
Definition: analysis_8051.c:42
static void exi_a(RzAnalysisOp *op, ut8 dummy, const char *operation)
static void exr_rn(RzAnalysisOp *op, ut8 reg)
#define ef(frag,...)
static void exi_dir1(RzAnalysisOp *op, ut8 addr, const char *operation)
#define flag_ov
static char * get_reg_profile(RzAnalysis *analysis)
static void exr_ri(RzAnalysisOp *op, ut8 reg)
static void exi_rn(RzAnalysisOp *op, ut8 reg, const char *operation)
#define e(frag)
static const int I8051_SFR
Definition: analysis_8051.c:70
#define bit_r
static void set_cpu_model(RzAnalysis *analysis, bool force)
static int esil_i8051_fini(RzAnalysisEsil *esil)
static void exw_bit(RzAnalysisOp *op, ut8 addr)
#define jmp
#define bit_set
static void exw_a(RzAnalysisOp *op, ut8 dummy)
#define flag_ac
#define xi(subject, operation)
#define xr(subject)
static void exi_c(RzAnalysisOp *op, ut8 dummy, const char *operation)
RzAnalysisPlugin rz_analysis_plugin_8051
static void exr_dir1(RzAnalysisOp *op, ut8 addr)
static ut32 map_direct_addr(RzAnalysis *analysis, ut8 addr)
#define flag_b
static void exi_ri(RzAnalysisOp *op, ut8 reg, const char *operation)
static void exr_imm2(RzAnalysisOp *op, ut8 val)
static void exr_rix(RzAnalysisOp *op, ut8 reg)
RZ_API RzLibStruct rizin_plugin
static int i8051_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask)
#define template_alu4_c(base, aluop, flags)
static const ut8 bitindex[]
static const i8051_map_entry init_mem_map[3]
Definition: analysis_8051.c:73
#define xw(subject)
static void exw_dpx(RzAnalysisOp *op, ut8 dummy)
#define bit_c
static const int I8051_IDATA
Definition: analysis_8051.c:69
static const int I8051_XDATA
Definition: analysis_8051.c:71
static void exr_sp1(RzAnalysisOp *op, ut8 dummy)
static void exw_ri(RzAnalysisOp *op, ut8 reg)
static void map_cpu_memory(RzAnalysis *analysis, int entry, ut32 addr, ut32 size, bool force)
Definition: analysis_8051.c:84
static void exi_bit(RzAnalysisOp *op, ut8 addr, const char *operation)
#define template_alu2(base, aluop)
static void analop_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf)
static const i8051_cpu_model cpu_models[]
Definition: analysis_8051.c:24
#define template_alu4(base, aluop, flags)
static void exw_rix(RzAnalysisOp *op, ut8 reg)
static void exw_rn(RzAnalysisOp *op, ut8 reg)
static void exw_dp(RzAnalysisOp *op, ut8 dummy)
static void exr_imm16(RzAnalysisOp *op, ut16 val)
static void exw_dir1(RzAnalysisOp *op, ut8 addr)
#define flag_ab
static bool i8051_init(void **user)
#define flag_p
static int esil_i8051_init(RzAnalysisEsil *esil)
#define cjmp
static void exr_a(RzAnalysisOp *op, ut8 dummy)
#define flag_ob
static void exr_sp2(RzAnalysisOp *op, ut8 dummy)
static ut32 i8051_reg_read(RzReg *reg, const char *regname)
Definition: analysis_8051.c:53
static void exr_dpx(RzAnalysisOp *op, ut8 dummy)
static void exw_c(RzAnalysisOp *op, ut8 dummy)
static void exi_dp(RzAnalysisOp *op, ut8 dummy, const char *operation)
#define bit_mask
static void exw_sp1(RzAnalysisOp *op, ut8 dummy)
static void exw_dir2(RzAnalysisOp *op, ut8 addr)
static bool i8051_fini(void *user)
static void exr_bit(RzAnalysisOp *op, ut8 addr)
static void exr_imm1(RzAnalysisOp *op, ut8 val)
#define flag_c
#define call
#define mask()
static ut32 cpu[32]
Definition: analysis_or1k.c:21
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
static RzList * maps(RzBinFile *bf)
Definition: bin_bf.c:116
const char * desc
Definition: bin_vsf.c:19
#define cmdstr(x)
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RzCryptoSelector bit
Definition: crypto.c:16
uint16_t ut16
uint32_t ut32
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_mem_read(RzAnalysisEsil *esil, ut64 addr, ut8 *buf, int len)
Definition: esil.c:259
static RzAnalysisEsilCallbacks ocbs
Definition: esil_trace.c:11
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
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")
#define OP_CALL
Definition: nios2.h:263
const char * name
Definition: op.c:541
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API bool rz_reg_set_value(RzReg *reg, RzRegItem *item, ut64 value)
Definition: rvalue.c:186
RZ_API ut64 rz_reg_get_value(RzReg *reg, RzRegItem *item)
Definition: rvalue.c:114
@ RZ_ANALYSIS_STACK_INC
Definition: rz_analysis.h:457
@ RZ_ANALYSIS_OP_FAMILY_CPU
Definition: rz_analysis.h:312
RzAnalysisOpMask
Definition: rz_analysis.h:439
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
@ RZ_ANALYSIS_OP_MASK_HINT
Definition: rz_analysis.h:443
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
RZ_API int rz_str_casecmp(const char *dst, const char *orig)
Definition: str.c:121
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
@ RZ_TYPE_COND_LO
Carry clear Less than.
Definition: rz_type.h:192
@ RZ_TYPE_COND_EQ
Equal.
Definition: rz_type.h:184
@ RZ_TYPE_COND_HS
Carry set >, ==, or unordered.
Definition: rz_type.h:191
@ RZ_TYPE_COND_NE
Not equal.
Definition: rz_type.h:185
@ RZ_TYPE_COND_AL
Always executed (no condition)
Definition: rz_type.h:183
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_PERM_RW
Definition: rz_types.h:96
#define RZ_FREE(x)
Definition: rz_types.h:369
#define UT32_MAX
Definition: rz_types_base.h:99
#define RZ_VERSION
Definition: rz_version.h:8
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
argtype8051 arg2
Definition: 8051_ops.h:109
argtype8051 arg1
Definition: 8051_ops.h:108
_RzAnalysisOpType type
Definition: 8051_ops.h:104
size_t len
Definition: 8051_ops.h:106
int cycles
Definition: 8051_ops.h:102
Definition: zipcmp.c:77
const char * name
Definition: analysis_8051.c:16
Definition: analysis_8051.c:63
RzIODesc * desc
Definition: analysis_8051.c:64
const char * name
Definition: analysis_8051.c:66
ut32 addr
Definition: analysis_8051.c:65
const i8051_cpu_model * cpu_curr_model
Definition: analysis_8051.c:80
Definition: z80asm.h:102
int(* reg_read)(ANALYSIS_ESIL *esil, const char *name, ut64 *res, int *size)
Definition: rz_analysis.h:1037
int(* hook_reg_read)(ANALYSIS_ESIL *esil, const char *name, ut64 *res, int *size)
Definition: rz_analysis.h:1036
RzAnalysisEsilHookRegWriteCB hook_reg_write
Definition: rz_analysis.h:1038
RzAnalysis * analysis
Definition: rz_analysis.h:1043
RzAnalysisEsilCallbacks cb
Definition: rz_analysis.h:1078
const char * version
Definition: rz_analysis.h:1239
void * plugin_data
Definition: rz_analysis.h:561
RzIOBind iob
Definition: rz_analysis.h:574
RzCoreBind coreb
Definition: rz_analysis.h:580
RzCoreCmd cmd
Definition: rz_bind.h:32
void * core
Definition: rz_bind.h:31
RzIOOpenAt open_at
Definition: rz_io.h:238
RzIO * io
Definition: rz_io.h:232
RzIOFdGetMap fd_get_map
Definition: rz_io.h:254
RzIOFdGetName fd_get_name
Definition: rz_io.h:253
RzIOFdRemap fd_remap
Definition: rz_io.h:255
ut32 id
Definition: rz_io.h:148
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static char * regname(int reg)
Definition: dis.c:71
static int addr
Definition: z80asm.c:58