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