Rizin
unix-like reverse engineering framework and cli tools
analysis_z80.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2012 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2013 condret
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <string.h>
6 #include <rz_types.h>
7 #include <rz_lib.h>
8 #include <rz_asm.h>
9 #include <rz_analysis.h>
10 #include "../../asm/arch/z80/z80_tab.h"
11 
12 static void z80_op_size(const ut8 *data, int len, int *size, int *size_prefix) {
13  int type = 0;
14  if (len < 1) {
15  return;
16  }
17  switch (data[0]) {
18  case 0xed:
19  if (len > 1) {
20  int idx = z80_ed_branch_index_res(data[1]);
21  type = ed[idx].type;
22  }
23  break;
24  case 0xcb:
25  type = Z80_OP16;
26  break;
27  case 0xdd:
28  if (len > 1) {
30  }
31  break;
32  case 0xfd:
33  if (len > 1) {
35  }
36  break;
37  default:
38  type = z80_op[data[0]].type;
39  break;
40  }
41 
42  if (type & Z80_OP8) {
43  *size_prefix = 1;
44  } else if (type & Z80_OP16) {
45  *size_prefix = 2;
46  } else if (type & Z80_OP24) {
47  *size_prefix = 3;
48  }
49 
50  if (type & Z80_ARG16) {
51  *size = *size_prefix + 2;
52  } else if (type & Z80_ARG8) {
53  *size = *size_prefix + 1;
54  } else {
55  *size = *size_prefix;
56  }
57 }
58 
59 static int z80_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
60  int ilen = 0;
61  z80_op_size(data, len, &ilen, &op->nopcode);
62 
63  op->addr = addr;
64  op->size = ilen;
66 
67  switch (data[0]) {
68  case 0x00:
70  break;
71  case 0x03:
72  case 0x04:
73  case 0x0c:
74  case 0x13:
75  case 0x14:
76  case 0x1c:
77  case 0x23:
78  case 0x24:
79  case 0x2c:
80  case 0x33:
81  case 0x34:
82  case 0x3c:
83  op->type = RZ_ANALYSIS_OP_TYPE_ADD; // INC
84  break;
85  case 0x09:
86  case 0x19:
87  case 0x29:
88  case 0x39:
89  case 0x80:
90  case 0x81:
91  case 0x82:
92  case 0x83:
93  case 0x84:
94  case 0x85:
95  case 0x86:
96  case 0x87:
97  case 0xc6:
99  break;
100  case 0x90:
101  case 0x91:
102  case 0x92:
103  case 0x93:
104  case 0x94:
105  case 0x95:
106  case 0x96:
107  case 0x97:
108  case 0xd6:
109  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
110  break;
111  case 0x22: // ld (**), hl
113  op->refptr = 2;
114  op->ptr = data[1] | data[2] << 8;
115  break;
116  case 0x32: // ld (**), a
118  op->refptr = 1;
119  op->ptr = data[1] | data[2] << 8;
120  break;
121  case 0x2a: // ld hl, (**)
123  op->refptr = 2;
124  op->ptr = data[1] | data[2] << 8;
125  break;
126  case 0x3a: // ld a, (**)
128  op->refptr = 1;
129  op->ptr = data[1] | data[2] << 8;
130  break;
131  case 0xc0:
132  case 0xc8:
133  case 0xd0:
134  case 0xd8:
135  case 0xe0:
136  case 0xe8:
137  case 0xf0:
138  case 0xf8:
140  break;
141  case 0xc9:
142  op->type = RZ_ANALYSIS_OP_TYPE_RET;
143  op->eob = true;
144  op->stackop = RZ_ANALYSIS_STACK_INC;
145  op->stackptr = -2;
146  break;
147  case 0xed:
148  switch (data[1]) {
149  case 0x43:
150  case 0x53:
151  case 0x63:
152  case 0x73:
154  op->refptr = 2;
155  op->ptr = data[2] | data[3] << 8;
156  break;
157  case 0x4b:
158  case 0x5b:
159  case 0x6b:
160  case 0x7b:
162  op->refptr = 2;
163  op->ptr = data[2] | data[3] << 8;
164  break;
165  case 0x45: // retn
166  case 0x4d: // reti
167  op->type = RZ_ANALYSIS_OP_TYPE_RET;
168  op->eob = true;
169  break;
170  }
171  break;
172  case 0xdd: // IX ops prefix
173  case 0xfd: // IY ops prefix
174  switch (data[1]) {
175  case 0x22: // ld (**), ix; ld (**), iy
177  op->refptr = 2;
178  op->ptr = data[2] | data[3] << 8;
179  break;
180  case 0x2a: // ld ix, (**); ld ix, (**)
182  op->refptr = 2;
183  op->ptr = data[2] | data[3] << 8;
184  break;
185  }
186  break;
187  case 0x05:
188  case 0x0b:
189  case 0x0d:
190  case 0x15:
191  case 0x1b:
192  case 0x1d:
193  case 0x25:
194  case 0x2b:
195  case 0x2d:
196  case 0x35:
197  case 0x3b:
198  case 0x3d:
199  // XXXX: DEC
200  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
201  break;
202  case 0xc5:
203  case 0xd5:
204  case 0xe5:
205  case 0xf5:
207  break;
208  case 0xc1:
209  case 0xd1:
210  case 0xe1:
211  case 0xf1:
212  op->type = RZ_ANALYSIS_OP_TYPE_POP;
213  break;
214  // ld from register to register
215  case 0x40:
216  case 0x49:
217  case 0x52:
218  case 0x5b:
219  case 0x64:
220  case 0x6d:
221  case 0x7f:
222  break;
223  case 0x76:
224  op->type = RZ_ANALYSIS_OP_TYPE_TRAP; // HALT
225  break;
226 
227  case 0x10: // djnz
229  op->jump = addr + (st8)data[1] + ilen;
230  op->fail = addr + ilen;
231  break;
232  case 0x18: // jr xx
233  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
234  op->jump = addr + (st8)data[1] + ilen;
235  break;
236  // jr cond, xx
237  case 0x20:
238  case 0x28:
239  case 0x30:
240  case 0x38:
242  op->jump = addr + ((len > 1) ? (st8)data[1] : 0) + ilen;
243  op->fail = addr + ilen;
244  break;
245 
246  // conditional jumps
247  case 0xc2:
248  case 0xca:
249  case 0xd2:
250  case 0xda:
251  case 0xe2:
252  case 0xea:
253  case 0xf2:
254  case 0xfa:
256  op->jump = (len > 2) ? data[1] | data[2] << 8 : 0;
257  op->fail = addr + ilen;
258  break;
259  case 0xc3: // jp xx
260  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
261  op->jump = (len > 2) ? data[1] | data[2] << 8 : 0;
262  break;
263  case 0xe9: // jp (HL)
265  break;
266 
267  case 0xc7: // rst 0
268  op->jump = 0x00;
269  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
270  break;
271  case 0xcf: // rst 8
272  op->jump = 0x08;
273  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
274  break;
275  case 0xd7: // rst 16
276  op->jump = 0x10;
277  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
278  break;
279  case 0xdf: // rst 24
280  op->jump = 0x18;
281  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
282  break;
283  case 0xe7: // rst 32
284  op->jump = 0x20;
285  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
286  break;
287  case 0xef: // rst 40
288  op->jump = 0x28;
289  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
290  break;
291  case 0xf7: // rst 48
292  op->jump = 0x30;
293  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
294  break;
295  case 0xff: // rst 56
296  op->jump = 0x38;
297  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
298  break;
299 
300  // conditional call
301  case 0xc4: // nz
302  case 0xd4: // nc
303  case 0xe4: // po
304  case 0xf4: // p
305 
306  case 0xcc: // z
307  case 0xdc: // c
308  case 0xec: // pe
309  case 0xfc: // m
311  op->jump = (len > 2) ? data[1] | data[2] << 8 : 0;
312  op->fail = addr + ilen;
313  break;
314 
315  // call
316  case 0xcd:
318  op->stackop = RZ_ANALYSIS_STACK_INC;
319  op->stackptr = 2;
320  op->jump = data[1] | data[2] << 8;
321  break;
322  case 0xcb: // the same as for gameboy
323  switch (data[1] / 8) {
324  case 0:
325  case 2:
326  case 4:
327  case 6: // swap
328  op->type = RZ_ANALYSIS_OP_TYPE_ROL;
329  break;
330  case 1:
331  case 3:
332  case 5:
333  case 7:
334  op->type = RZ_ANALYSIS_OP_TYPE_ROR;
335  break;
336  case 8:
337  case 9:
338  case 10:
339  case 11:
340  case 12:
341  case 13:
342  case 14:
343  case 15:
344  op->type = RZ_ANALYSIS_OP_TYPE_AND;
345  break; // bit
346  case 16:
347  case 17:
348  case 18:
349  case 19:
350  case 20:
351  case 21:
352  case 22:
353  case 23:
354  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
355  break; // set
356  case 24:
357  case 25:
358  case 26:
359  case 27:
360  case 28:
361  case 29:
362  case 30:
363  case 31:
364  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
365  break; // res
366  }
367  break;
368  }
369  return ilen;
370 }
371 
372 static char *get_reg_profile(RzAnalysis *analysis) {
373  const char *p =
374  "=PC mpc\n"
375  "=SP sp\n"
376  "=A0 af\n"
377  "=A1 bc\n"
378  "=A2 de\n"
379  "=A3 hl\n"
380 
381  "gpr mpc .32 0 0\n"
382  "gpr pc .16 0 0\n"
383  "gpr m .16 2 0\n"
384 
385  "gpr sp .16 4 0\n"
386 
387  "gpr af .16 6 0\n"
388  "gpr f .8 6 0\n"
389  "gpr a .8 7 0\n"
390  "gpr Z .1 .55 0\n"
391  "gpr N .1 .54 0\n"
392  "gpr H .1 .53 0\n"
393  "gpr C .1 .52 0\n"
394 
395  "gpr bc .16 8 0\n"
396  "gpr c .8 8 0\n"
397  "gpr b .8 9 0\n"
398 
399  "gpr de .16 10 0\n"
400  "gpr e .8 10 0\n"
401  "gpr d .8 11 0\n"
402 
403  "gpr hl .16 12 0\n"
404  "gpr l .8 12 0\n"
405  "gpr h .8 13 0\n"
406 
407  "gpr mbcrom .16 14 0\n"
408  "gpr mbcram .16 16 0\n"
409 
410  "gpr ime .1 18 0\n";
411  return strdup(p);
412 }
413 
414 static int archinfo(RzAnalysis *analysis, int q) {
415  return 1;
416 }
417 
419  .name = "z80",
420  .arch = "z80",
421  .license = "LGPL3",
422  .bits = 16,
423  .get_reg_profile = &get_reg_profile,
424  .desc = "Z80 CPU code analysis plugin",
425  .archinfo = archinfo,
426  .op = &z80_analysis_op,
427 };
428 
429 #ifndef RZ_PLUGIN_INCORE
432  .data = &rz_analysis_plugin_z80,
434 };
435 #endif
size_t len
Definition: 6502dis.c:15
#define mask()
static char * get_reg_profile(RzAnalysis *analysis)
Definition: analysis_z80.c:372
RZ_API RzLibStruct rizin_plugin
Definition: analysis_z80.c:430
static int archinfo(RzAnalysis *analysis, int q)
Definition: analysis_z80.c:414
static void z80_op_size(const ut8 *data, int len, int *size, int *size_prefix)
Definition: analysis_z80.c:12
RzAnalysisPlugin rz_analysis_plugin_z80
Definition: analysis_z80.c:418
static int z80_analysis_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: analysis_z80.c:59
#define RZ_API
voidpf void uLong size
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
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")
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
@ RZ_ANALYSIS_STACK_INC
Definition: rz_analysis.h:457
RzAnalysisOpMask
Definition: rz_analysis.h:439
@ RZ_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_LOAD
Definition: rz_analysis.h:416
@ RZ_ANALYSIS_OP_TYPE_UNK
Definition: rz_analysis.h:388
@ RZ_ANALYSIS_OP_TYPE_ROL
Definition: rz_analysis.h:420
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_AND
Definition: rz_analysis.h:411
@ RZ_ANALYSIS_OP_TYPE_UJMP
Definition: rz_analysis.h:369
@ RZ_ANALYSIS_OP_TYPE_ROR
Definition: rz_analysis.h:419
@ RZ_ANALYSIS_OP_TYPE_SWI
Definition: rz_analysis.h:393
@ RZ_ANALYSIS_OP_TYPE_TRAP
Definition: rz_analysis.h:392
@ RZ_ANALYSIS_OP_TYPE_CCALL
Definition: rz_analysis.h:383
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_STORE
Definition: rz_analysis.h:415
@ RZ_ANALYSIS_OP_TYPE_CRET
Definition: rz_analysis.h:386
@ RZ_ANALYSIS_OP_TYPE_PUSH
Definition: rz_analysis.h:397
@ RZ_ANALYSIS_OP_TYPE_POP
Definition: rz_analysis.h:398
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_NOP
Definition: rz_analysis.h:389
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
#define st8
Definition: rz_types_base.h:16
#define RZ_VERSION
Definition: rz_version.h:8
const char * version
Definition: rz_analysis.h:1239
int type
Definition: z80_tab.h:25
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
@ Z80_OP24
Definition: z80_tab.h:16
@ Z80_ARG8
Definition: z80_tab.h:17
@ Z80_ARG16
Definition: z80_tab.h:18
@ Z80_OP8
Definition: z80_tab.h:14
@ Z80_OP16
Definition: z80_tab.h:15
static const z80_opcode fd[]
Definition: z80_tab.h:997
static const z80_opcode z80_op[]
Definition: z80_tab.h:1087
static const z80_opcode dd[]
Definition: z80_tab.h:844
static ut8 z80_ed_branch_index_res(ut8 hex)
Definition: z80_tab.h:148
static ut8 z80_fddd_branch_index_res(ut8 hex)
Definition: z80_tab.h:29
static const z80_opcode ed[]
Definition: z80_tab.h:934
static int addr
Definition: z80asm.c:58