Rizin
unix-like reverse engineering framework and cli tools
8051_disas.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2015-2019 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2015-2019 condret <condr3t@protonmail.com>
3 // SPDX-FileCopyrightText: 2015-2019 riq <ricardoquesada@gmail.com>
4 // SPDX-FileCopyrightText: 2015-2019 qnix <qnix@0x80.org>
5 // SPDX-FileCopyrightText: 2015-2019 astuder <github@adrianstuder.com>
6 // SPDX-License-Identifier: LGPL-3.0-only
7 
8 #include <rz_asm.h>
9 #include <rz_lib.h>
10 #include <string.h>
11 
12 #include "8051_ops.h"
13 
14 static const char *_8051_regs[] = {
15  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // 0x00
16  0, 0, 0, 0, 0, 0, 0, 0, // 0x08
17  0, 0, 0, 0, 0, 0, 0, 0, // 0x10
18  0, 0, 0, 0, 0, 0, 0, 0, // 0x18
19  0, 0, 0, 0, 0, 0, 0, 0, // 0x20
20  0, 0, 0, 0, 0, 0, 0, 0, // 0x28
21  0, 0, 0, 0, 0, 0, 0, 0, // 0x30
22  0, 0, 0, 0, 0, 0, 0, 0, // 0x38
23  0, 0, 0, 0, 0, 0, 0, 0, // 0x40
24  0, 0, 0, 0, 0, 0, 0, 0, // 0x48
25  0, 0, 0, 0, 0, 0, 0, 0, // 0x50
26  0, 0, 0, 0, 0, 0, 0, 0, // 0x58
27  0, 0, 0, 0, 0, 0, 0, 0, // 0x60
28  0, 0, 0, 0, 0, 0, 0, 0, // 0x68
29  0, 0, 0, 0, 0, 0, 0, 0, // 0x70
30  0, 0, 0, 0, 0, 0, 0, 0, // 0x78
31  "p0", "sp", "dpl", "dph", 0, 0, 0, "pcon", // 0x80
32  "tcon", "tmod", "tl0", "tl1", "th0", "th1", 0, 0, // 0x88
33  "p1", 0, 0, 0, 0, 0, 0, 0, // 0x90
34  "scon", "sbuf", 0, 0, 0, 0, 0, 0, // 0x98
35  "p2", 0, 0, 0, 0, 0, 0, 0, // 0xa0
36  "ie", 0, 0, 0, 0, 0, 0, 0, // 0xa8
37  "p3", 0, 0, 0, 0, 0, 0, 0, // 0xb0
38  "ip", 0, 0, 0, 0, 0, 0, 0, // 0xb8
39  0, 0, 0, 0, 0, 0, 0, 0, // 0xc0
40  0, 0, 0, 0, 0, 0, 0, 0, // 0xc8
41  "psw", 0, 0, 0, 0, 0, 0, 0, // 0xd0
42  0, 0, 0, 0, 0, 0, 0, 0, // 0xd8
43  "acc", 0, 0, 0, 0, 0, 0, 0, // 0xe0
44  0, 0, 0, 0, 0, 0, 0, 0, // 0xe8
45  "b", 0, 0, 0, 0, 0, 0, 0, // 0xf0
46  0, 0, 0, 0, 0, 0, 0, 0 // 0xf8
47 };
48 
49 static char *_replace_register(char *disasm, ut8 arg, ut8 val) {
50  char key[10];
51  char subst[10];
52  if (arg == A_DIRECT) {
53  if (_8051_regs[val]) {
54  sprintf(key, " 0x%02x", val);
55  sprintf(subst, " %s", _8051_regs[val]);
56  disasm = rz_str_replace(disasm, key, subst, 0);
57  }
58  } else if (arg == A_BIT) {
59  val = arg_bit(val);
60  if (_8051_regs[val]) {
61  sprintf(key, "0x%02x.", val);
62  sprintf(subst, "%s.", _8051_regs[val]);
63  disasm = rz_str_replace(disasm, key, subst, 0);
64  }
65  }
66  return disasm;
67 }
68 
69 static char *rz_8051_disas(ut64 pc, const ut8 *buf, int len, int *olen) {
70  int i = 0;
71  while (_8051_ops[i].string && _8051_ops[i].op != (buf[0] & ~_8051_ops[i].mask)) {
72  i++;
73  }
74 
75  if (_8051_ops[i].string) {
76  // valid opcodes
77  const char *name = _8051_ops[i].string;
78  ut8 mask = _8051_ops[i].mask;
79  ut8 arg1 = _8051_ops[i].arg1;
80  ut8 arg2 = _8051_ops[i].arg2;
81  ut8 arg3 = _8051_ops[i].arg3;
82  ut8 oplen = _8051_ops[i].len;
83  ut8 val1 = 0, val2 = 0;
84  char *disasm = 0;
85 
86  switch (oplen) {
87  case 1:
88  if ((arg1 == A_RI) || (arg1 == A_RN)) {
89  // op @Ri; op Rn
90  disasm = rz_str_newf(name, buf[0] & mask);
91  } else {
92  disasm = rz_str_new(name);
93  }
94  break;
95  case 2:
96  if (len > 1) {
97  if (arg1 == A_OFFSET) {
98  disasm = rz_str_newf(name, (unsigned int)arg_offset(pc, pc + 2, buf[1]));
99  } else if (arg1 == A_ADDR11) {
100  disasm = rz_str_newf(name, (unsigned int)arg_addr11(pc, pc + 2, buf));
101  } else if ((arg1 == A_RI) || (arg1 == A_RN)) {
102  // op @Ri, arg; op Rn, arg
103  if (arg2 == A_OFFSET) {
104  disasm = rz_str_newf(name, buf[0] & mask, (unsigned int)arg_offset(pc, pc + 2, buf[1]));
105  } else {
106  disasm = rz_str_newf(name, buf[0] & mask, buf[1]);
107  }
108  val2 = buf[1];
109  } else if ((arg2 == A_RI) || (arg2 == A_RN)) {
110  // op arg, @Ri; op arg, Rn
111  disasm = rz_str_newf(name, buf[1], buf[0] & mask);
112  val1 = buf[1];
113  } else if (arg1 == A_BIT) {
114  // bit addressing mode
115  disasm = rz_str_newf(name, arg_bit(buf[1]), buf[1] & 0x07);
116  val1 = buf[1];
117  } else {
118  // direct, immediate, bit
119  disasm = rz_str_newf(name, buf[1]);
120  val1 = buf[1];
121  }
122  } else {
123  *olen = -1;
124  return strdup("truncated");
125  }
126  break;
127  case 3:
128  if (len > 2) {
129  if (arg1 == A_ADDR16) {
130  disasm = rz_str_newf(name, (unsigned int)apply_bank(pc, 0x100 * buf[1] + buf[2]));
131  } else if (arg1 == A_IMM16) {
132  disasm = rz_str_newf(name, 0x100 * buf[1] + buf[2]);
133  } else if (arg2 == A_OFFSET) {
134  if (mask != A_NONE) {
135  // @Ri, immediate, offset; Rn, immediate, offset
136  disasm = rz_str_newf(name, buf[0] & mask, buf[1], (unsigned int)arg_offset(pc, pc + 3, buf[1]));
137  } else if (arg1 == A_BIT) {
138  // bit, offset
139  disasm = rz_str_newf(name, arg_bit(buf[1]), buf[1] & 0x07, (unsigned int)arg_offset(pc, pc + 3, buf[2]));
140  val1 = buf[1];
141  } else {
142  // direct, offset; a, immediate, offset
143  disasm = rz_str_newf(name, buf[1], (unsigned int)arg_offset(pc, pc + 3, buf[2]));
144  val1 = buf[1];
145  }
146  } else if (arg3 == A_OFFSET) {
147  // @Ri/Rn, direct, offset
148  disasm = rz_str_newf(name, buf[0] & mask, buf[1], (unsigned int)arg_offset(pc, pc + 3, buf[2]));
149  val2 = buf[1];
150  } else if (arg1 == A_DIRECT && arg2 == A_DIRECT) {
151  // op direct, direct has src and dest swapped
152  disasm = rz_str_newf(name, buf[2], buf[1]);
153  val1 = buf[2];
154  val2 = buf[1];
155  } else {
156  // direct, immediate
157  disasm = rz_str_newf(name, buf[1], buf[2]);
158  val1 = buf[1];
159  }
160  } else {
161  *olen = -1;
162  return strdup("truncated");
163  }
164  break;
165  default:
166  // if we get here something is wrong
167  return 0;
168  }
169 
170  // substitute direct addresses with register name
171  *olen = oplen;
172  if (disasm) {
173  disasm = _replace_register(disasm, arg1, val1);
174  disasm = _replace_register(disasm, arg2, val2);
175  return disasm;
176  }
177  return NULL;
178  }
179 
180  // invalid op-code
181  return 0;
182 }
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
static char * _replace_register(char *disasm, ut8 arg, ut8 val)
Definition: 8051_disas.c:49
static const char * _8051_regs[]
Definition: 8051_disas.c:14
@ A_ADDR11
Definition: 8051_ops.h:84
@ A_NONE
Definition: 8051_ops.h:81
@ 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
static _8051_op_t _8051_ops[]
Definition: 8051_ops.h:113
static ut8 arg_bit(ut8 bit_addr)
Definition: 8051_ops.h:31
#define mask()
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
voidpf void * buf
Definition: ioapi.h:138
sprintf
Definition: kernel.h:365
uint8_t ut8
Definition: lh5801.h:11
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")
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API char * rz_str_new(const char *str)
Definition: str.c:865
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
argtype8051 arg2
Definition: 8051_ops.h:109
argtype8051 arg1
Definition: 8051_ops.h:108
argtype8051 arg3
Definition: 8051_ops.h:110
size_t len
Definition: 8051_ops.h:106
argmask8051 mask
Definition: 8051_ops.h:107
char * string
Definition: 8051_ops.h:105
Definition: z80asm.h:102
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()