Rizin
unix-like reverse engineering framework and cli tools
pic_pic18.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2015-2018 oddcoder <ahmedsoliman@oddcoder.com>
2 // SPDX-FileCopyrightText: 2015-2018 thestr4ng3r <info@florianmaerkl.de>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_types.h>
6 
7 #include "pic_pic18.h"
8 
9 // PIC18CXXX instruction set
10 
11 // instruction classification according to the argument types
12 #define NO_ARG 0
13 #define DAF_T 1
14 #define F32_T 2
15 #define BAF_T 3
16 #define K_T 4
17 #define N_T 5
18 #define CALL_T 6
19 #define NEX_T 7
20 #define AF_T 8
21 #define GOTO_T 9
22 #define SHK_T 10
23 #define S_T 11
24 #define LFSR_T 12
25 
26 static char *fsr[] = { "fsr0", "fsr1", "fsr2", "reserved" };
27 
28 static struct {
31  char *name;
33  // and some magical hocus pocus ;)
34 } ops[] = {
35  { 0xf000, 0xffff, "nop", NO_ARG },
36  { 0xef00, 0xefff, "goto", GOTO_T },
37  { 0xee00, 0xee3f, "lfsr", LFSR_T },
38  { 0xec00, 0xedff, "call", CALL_T },
39  { 0xe700, 0xe7ff, "bnn", N_T },
40  { 0xe600, 0xe6ff, "bn", N_T },
41  { 0xe500, 0xe5ff, "bnov", N_T },
42  { 0xe400, 0xe4ff, "bov", N_T },
43  { 0xe300, 0xe3ff, "bnc", N_T },
44  { 0xe200, 0xe2ff, "bc", N_T },
45  { 0xe100, 0xe1ff, "bnz", N_T },
46  { 0xe000, 0xe0ff, "bz", N_T },
47  { 0xd800, 0xdfff, "rcall", NEX_T },
48  { 0xd000, 0xd7ff, "bra", NEX_T },
49  { 0xc000, 0xcfff, "movff", F32_T },
50  { 0xb000, 0xbfff, "btfsc", BAF_T },
51  { 0xa000, 0xafff, "btfss", BAF_T },
52  { 0x9000, 0x9fff, "bcf", BAF_T },
53  { 0x8000, 0x8fff, "bsf", BAF_T },
54  { 0x7000, 0x7fff, "btg", BAF_T },
55  { 0x6e00, 0x6fff, "movwf", AF_T },
56  { 0x6c00, 0x6dff, "negf", AF_T },
57  { 0x6a00, 0x6bff, "clrf", AF_T },
58  { 0x6800, 0x69ff, "setf", AF_T },
59  { 0x6600, 0x67ff, "tstfsz", AF_T },
60  { 0x6400, 0x65ff, "cpfsgt", AF_T },
61  { 0x6200, 0x63ff, "cpfseq", AF_T },
62  { 0x6000, 0x61ff, "cpfslt", AF_T },
63  { 0x5c00, 0x5fff, "subwf", DAF_T },
64  { 0x5800, 0x5bff, "subwfb", DAF_T },
65  { 0x5400, 0x57ff, "subfwb", DAF_T },
66  { 0x5000, 0x53ff, "movf", DAF_T },
67  { 0x4c00, 0x4fff, "dcfsnz", DAF_T },
68  { 0x4800, 0x4bff, "infsnz", DAF_T },
69  { 0x4400, 0x47ff, "rlncf", DAF_T },
70  { 0x4000, 0x43ff, "rrncf", DAF_T },
71  { 0x3c00, 0x3fff, "incfsz", DAF_T },
72  { 0x3800, 0x3bff, "swapf", DAF_T },
73  { 0x3400, 0x37ff, "rlcf", DAF_T },
74  { 0x3000, 0x33ff, "rrcf", DAF_T },
75  { 0x2c00, 0x2fff, "decfsz", DAF_T },
76  { 0x2800, 0x2bff, "incf", DAF_T },
77  { 0x2400, 0x27ff, "addwf", DAF_T },
78  { 0x2000, 0x23ff, "addwfc", DAF_T },
79  { 0x1c00, 0x1fff, "comf", DAF_T },
80  { 0x1800, 0x1bff, "xorwf", DAF_T },
81  { 0x1400, 0x17ff, "andwf", DAF_T },
82  { 0x1000, 0x13ff, "iorwf", DAF_T },
83  { 0xf00, 0xfff, "addlw", K_T },
84  { 0xe00, 0xeff, "movlw", K_T },
85  { 0xd00, 0xdff, "mullw", K_T },
86  { 0xc00, 0xcff, "retlw", K_T },
87  { 0xb00, 0xbff, "andlw", K_T },
88  { 0xa00, 0xaff, "xorlw", K_T },
89  { 0x900, 0x9ff, "iorlw", K_T },
90  { 0x800, 0x8ff, "sublw", K_T },
91  { 0x400, 0x7ff, "decf", DAF_T },
92  { 0x200, 0x3ff, "mulwf", AF_T },
93  { 0x100, 0x10f, "movlb", SHK_T },
94  { 0xff, 0xff, "reset", NO_ARG },
95  { 0x12, 0x13, "return", S_T },
96  { 0x10, 0x11, "retfie", S_T },
97  { 0xf, 0xf, "tblwt+*", NO_ARG },
98  { 0xe, 0xe, "tblwt*-", NO_ARG },
99  { 0xd, 0xd, "tblwt*+", NO_ARG },
100  { 0xc, 0xc, "tblwt*", NO_ARG },
101  { 0xb, 0xb, "tblrd+*", NO_ARG },
102  { 0xa, 0xa, "tblrd*-", NO_ARG },
103  { 0x9, 0x9, "tblrd*+", NO_ARG },
104  { 0x8, 0x8, "tblrd*", NO_ARG },
105  { 0x7, 0x7, "daw", NO_ARG },
106  { 0x6, 0x6, "pop", NO_ARG },
107  { 0x5, 0x5, "push", NO_ARG },
108  { 0x4, 0x4, "clrwdt", NO_ARG },
109  { 0x3, 0x3, "sleep", NO_ARG },
110  { 0x0, 0x0, "nop", NO_ARG },
111  { 0x0, 0xffff, "invalid", NO_ARG },
112 };
113 
114 int pic_pic18_disassemble(RzAsmOp *op, char *opbuf, const ut8 *b, int blen) {
115  int i;
116  if (blen < 2) { // well noone loves reading bitstream of size zero or 1 !!
117  strcpy(opbuf, "invalid");
118  op->size = blen;
119  return -1;
120  }
121  ut16 instr = rz_read_le16(b); // instruction
122  // if still redundan code is reported think of this of instr=0x2
123  const char *buf_asm = "invalid";
124  strcpy(opbuf, buf_asm);
125 
126  for (i = 0; ops[i].opmin != (ops[i].opmin & instr) || ops[i].opmax != (ops[i].opmax | instr); i++) {
127  ;
128  }
129  if (ops[i].opmin == 0 && ops[i].opmax == 0xffff) {
130  strcpy(opbuf, ops[i].name);
131  op->size = 2;
132  return -1;
133  }
134  op->size = 2;
135  switch (ops[i].optype) {
136  case NO_ARG:
137  buf_asm = ops[i].name;
138  break;
139  case N_T:
140  case K_T:
141  buf_asm = sdb_fmt("%s 0x%x", ops[i].name, instr & 0xff);
142  break;
143  case DAF_T:
144  buf_asm = sdb_fmt("%s 0x%x, %d, %d", ops[i].name, instr & 0xff, (instr >> 9) & 1, (instr >> 8) & 1);
145  break;
146  case AF_T:
147  buf_asm = sdb_fmt("%s 0x%x, %d", ops[i].name, instr & 0xff, (instr >> 8) & 1);
148  break;
149  case BAF_T:
150  buf_asm = sdb_fmt("%s 0x%x, %d, %d", ops[i].name, instr & 0xff, (instr >> 9) & 0x7, (instr >> 8) & 0x1);
151  break;
152  case NEX_T:
153  buf_asm = sdb_fmt("%s 0x%x", ops[i].name, instr & 0x7ff);
154  break;
155  case CALL_T:
156  if (blen < 4) {
157  return -1;
158  }
159  op->size = 4;
160  {
161  ut32 dword_instr = rz_read_le32(b);
162  // I dont even know how the bits are arranged but it works !!!
163  //`the wierdness of little endianess`
164  if (dword_instr >> 28 != 0xf) {
165  return -1;
166  }
167  buf_asm = sdb_fmt("%s 0x%x, %d", ops[i].name,
168  (dword_instr & 0xff) | (dword_instr >> 8 & 0xfff00), (dword_instr >> 8) & 0x1);
169  }
170  break;
171  case GOTO_T:
172  if (blen < 4) {
173  return -1;
174  }
175  {
176  op->size = 4;
177  ut32 dword_instr = rz_read_le32(b);
178  if (dword_instr >> 28 != 0xf) {
179  return -1;
180  }
181  buf_asm = sdb_fmt("%s 0x%x", ops[i].name,
182  ((dword_instr & 0xff) | ((dword_instr & 0xfff0000) >> 8)) * 2);
183  }
184  break;
185  case F32_T:
186  if (blen < 4) {
187  return -1;
188  }
189  op->size = 4;
190  {
191  ut32 dword_instr = rz_read_le32(b);
192  if (dword_instr >> 28 != 0xf) {
193  return -1;
194  }
195  buf_asm = sdb_fmt("%s 0x%x, 0x%x", ops[i].name,
196  dword_instr & 0xfff, (dword_instr >> 16) & 0xfff);
197  }
198  break;
199  case SHK_T:
200  buf_asm = sdb_fmt("%s 0x%x", ops[i].name, instr & 0xf);
201  break;
202  case S_T:
203  buf_asm = sdb_fmt("%s %d", ops[i].name, instr & 0x1);
204  break;
205  case LFSR_T: {
206  if (blen < 4) {
207  return -1;
208  }
209  op->size = 4;
210  ut32 dword_instr = rz_read_le32(b);
211  if (dword_instr >> 28 != 0xf) {
212  return -1;
213  }
214  ut8 reg_n = (dword_instr >> 4) & 0x3;
215  buf_asm = sdb_fmt("%s %s, %d", ops[i].name, fsr[reg_n],
216  (dword_instr & 0xf) << 8 | ((dword_instr >> 16) & 0xff));
217  break;
218  }
219  default:
220  buf_asm = "unknown args";
221  };
222  strcpy(opbuf, buf_asm);
223  return op->size;
224 }
lzma_index ** i
Definition: index.h:629
uint16_t ut16
uint32_t ut32
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
uint8_t ut8
Definition: lh5801.h:11
#define BAF_T
Definition: pic_pic18.c:15
ut8 optype
Definition: pic_pic18.c:32
#define GOTO_T
Definition: pic_pic18.c:21
#define NO_ARG
Definition: pic_pic18.c:12
#define K_T
Definition: pic_pic18.c:16
ut16 opmin
Definition: pic_pic18.c:29
ut16 opmax
Definition: pic_pic18.c:30
#define SHK_T
Definition: pic_pic18.c:22
char * name
Definition: pic_pic18.c:31
#define S_T
Definition: pic_pic18.c:23
#define DAF_T
Definition: pic_pic18.c:13
static char * fsr[]
Definition: pic_pic18.c:26
int pic_pic18_disassemble(RzAsmOp *op, char *opbuf, const ut8 *b, int blen)
Definition: pic_pic18.c:114
#define CALL_T
Definition: pic_pic18.c:18
static struct @106 ops[]
#define N_T
Definition: pic_pic18.c:17
#define AF_T
Definition: pic_pic18.c:20
#define F32_T
Definition: pic_pic18.c:14
#define NEX_T
Definition: pic_pic18.c:19
#define LFSR_T
Definition: pic_pic18.c:24
static ut16 rz_read_le16(const void *src)
Definition: rz_endian.h:206
static ut32 rz_read_le32(const void *src)
Definition: rz_endian.h:239
#define b(i)
Definition: sha256.c:42
Definition: z80asm.h:102
Definition: op.c:222
Definition: dis.c:32