Rizin
unix-like reverse engineering framework and cli tools
analysis_gb.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2012 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2019 condret
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 // this file was based on analysis_i8080.c
6 
7 #include <string.h>
8 #include <rz_types.h>
9 #include <rz_util.h>
10 #include <rz_asm.h>
11 #include <rz_analysis.h>
12 #include <rz_reg.h>
13 #define GB_DIS_LEN_ONLY
14 #include "../../asm/arch/gb/gbdis.c"
15 #include "../arch/gb/gb_makros.h"
16 #include "../arch/gb/meta_gb_cmt.c"
17 #include <gb_makros.h>
18 #include <gb.h>
19 
20 static const char *regs_1[] = { "Z", "N", "H", "C" };
21 static const char *regs_8[] = { "b", "c", "d", "e", "h", "l", "a", "a" }; // deprecate this and rename regs_x
22 static const char *regs_x[] = { "b", "c", "d", "e", "h", "l", "hl", "a" };
23 static const char *regs_16[] = { "bc", "de", "hl", "sp" };
24 static const char *regs_16_alt[] = { "bc", "de", "hl", "af" };
25 
27  if (GB_IS_RAM_DST(data[1], data[2])) {
28  op->jump = GB_SOFTCAST(data[1], data[2]);
29  rz_meta_set_string(a, RZ_META_TYPE_COMMENT, addr, "--> unpredictable");
30  return false;
31  }
32  if (!GB_IS_VBANK_DST(data[1], data[2])) {
33  op->jump = GB_SOFTCAST(data[1], data[2]);
34  } else {
35  op->jump = GB_IB_DST(data[1], data[2], addr);
36  }
37  return true;
38 }
39 
41  rz_strbuf_setf(&op->esil, "2,sp,-=,pc,sp,=[2],%" PFMT64d ",pc,:=", (op->jump & 0xffff));
42 }
43 
44 static inline void gb_analysis_esil_ccall(RzAnalysisOp *op, const ut8 data) {
45  char cond;
46  switch (data) {
47  case 0xc4:
48  case 0xcc:
49  cond = 'Z';
50  break;
51  default:
52  cond = 'C';
53  }
54  if (op->cond == RZ_TYPE_COND_EQ) {
55  rz_strbuf_setf(&op->esil, "%c,?{,2,sp,-=,pc,sp,=[2],%" PFMT64d ",pc,:=,}", cond, (op->jump & 0xffff));
56  } else {
57  rz_strbuf_setf(&op->esil, "%c,!,?{,2,sp,-=,pc,sp,=[2],%" PFMT64d ",pc,:=,}", cond, (op->jump & 0xffff));
58  }
59 }
60 
61 static inline void gb_analysis_esil_ret(RzAnalysisOp *op) {
62  rz_strbuf_append(&op->esil, "sp,[2],pc,:=,2,sp,+=");
63 }
64 
65 static inline void gb_analysis_esil_cret(RzAnalysisOp *op, const ut8 data) {
66  char cond;
67  if ((data & 0xd0) == 0xd0) {
68  cond = 'C';
69  } else {
70  cond = 'Z';
71  }
72  if (op->cond == RZ_TYPE_COND_EQ) {
73  rz_strbuf_setf(&op->esil, "%c,?{,sp,[2],pc,:=,2,sp,+=,}", cond);
74  } else {
75  rz_strbuf_setf(&op->esil, "%c,!,?{,sp,[2],pc,:=,2,sp,+=,}", cond);
76  }
77 }
78 
79 static inline void gb_analysis_esil_cjmp(RzAnalysisOp *op, const ut8 data) {
80  char cond;
81  switch (data) {
82  case 0x20:
83  case 0x28:
84  case 0xc2:
85  case 0xca:
86  cond = 'Z';
87  break;
88  default:
89  cond = 'C';
90  }
91  if (op->cond == RZ_TYPE_COND_EQ) {
92  rz_strbuf_setf(&op->esil, "%c,?{,0x%" PFMT64x ",pc,:=,}", cond, (op->jump & 0xffff));
93  } else {
94  rz_strbuf_setf(&op->esil, "%c,!,?{,0x%" PFMT64x ",pc,:=,}", cond, (op->jump & 0xffff));
95  }
96 }
97 
98 static inline void gb_analysis_esil_jmp(RzAnalysisOp *op) {
99  rz_strbuf_setf(&op->esil, "0x%" PFMT64x ",pc,:=", (op->jump & 0xffff));
100 }
101 
102 static inline void gb_analysis_jmp_hl(RzReg *reg, RzAnalysisOp *op) {
103  op->dst = rz_analysis_value_new();
104  op->src[0] = rz_analysis_value_new();
105  op->dst->reg = rz_reg_get(reg, "pc", RZ_REG_TYPE_GPR);
106  op->src[0]->reg = rz_reg_get(reg, "hl", RZ_REG_TYPE_GPR);
107  rz_strbuf_set(&op->esil, "hl,pc,:=");
108 }
109 
110 static inline void gb_analysis_id(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 data) {
111  op->dst = rz_analysis_value_new();
112  op->src[0] = rz_analysis_value_new();
113  op->src[0]->imm = 1;
114  op->src[0]->absolute = true;
115  if (data == 0x34 || data == 0x35) {
116  op->dst->memref = 1;
117  op->dst->reg = rz_reg_get(analysis->reg, "hl", RZ_REG_TYPE_GPR);
118  if (op->type == RZ_ANALYSIS_OP_TYPE_ADD) {
119  rz_strbuf_set(&op->esil, "1,hl,[1],+,hl,=[1],3,$c,H,:=,$z,Z,:=,0,N,:=");
120  } else {
121  rz_strbuf_set(&op->esil, "1,hl,[1],-,hl,=[1],4,$b,H,:=,$z,Z,:=,1,N,:=");
122  }
123  } else {
124  if (!(data & (1 << 2))) {
125  op->dst->reg = rz_reg_get(analysis->reg, regs_16[data >> 4], RZ_REG_TYPE_GPR);
126  if (op->type == RZ_ANALYSIS_OP_TYPE_ADD) {
127  rz_strbuf_setf(&op->esil, "1,%s,+=", regs_16[data >> 4]);
128  } else {
129  rz_strbuf_setf(&op->esil, "1,%s,-=", regs_16[data >> 4]);
130  }
131  } else {
132  op->dst->reg = rz_reg_get(analysis->reg, regs_8[data >> 3], RZ_REG_TYPE_GPR);
133  if (op->type == RZ_ANALYSIS_OP_TYPE_ADD) {
134  rz_strbuf_setf(&op->esil, "1,%s,+=,3,$c,H,:=,$z,Z,:=,0,N,:=", regs_8[data >> 3]);
135  } else {
136  rz_strbuf_setf(&op->esil, "1,%s,-=,4,$b,H,:=,$z,Z,:=,1,N,:=", regs_8[data >> 3]);
137  }
138  }
139  }
140 }
141 
142 static inline void gb_analysis_add_hl(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
143  op->dst = rz_analysis_value_new();
144  op->src[0] = rz_analysis_value_new();
145  op->dst->reg = rz_reg_get(reg, "hl", RZ_REG_TYPE_GPR);
146  op->src[0]->reg = rz_reg_get(reg, regs_16[((data & 0xf0) >> 4)], RZ_REG_TYPE_GPR);
147  rz_strbuf_setf(&op->esil, "%s,hl,+=,0,N,:=", regs_16[((data & 0xf0) >> 4)]); // hl+=<reg>,N=0
148 }
149 
150 static inline void gb_analysis_add_sp(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
151  op->dst = rz_analysis_value_new();
152  op->src[0] = rz_analysis_value_new();
153  op->dst->reg = rz_reg_get(reg, "sp", RZ_REG_TYPE_GPR);
154  op->src[0]->imm = (st8)data;
155  if (data < 128) {
156  rz_strbuf_setf(&op->esil, "0x%02x,sp,+=", data);
157  } else {
158  rz_strbuf_setf(&op->esil, "0x%02x,sp,-=", 0 - (st8)data);
159  }
160  rz_strbuf_append(&op->esil, ",0,Z,=,0,N,:=");
161 }
162 
163 static void gb_analysis_mov_imm(RzReg *reg, RzAnalysisOp *op, const ut8 *data) {
164  op->dst = rz_analysis_value_new();
165  op->src[0] = rz_analysis_value_new();
166  if (data[0] & 1) {
167  op->dst->reg = rz_reg_get(reg, regs_16[data[0] >> 4], RZ_REG_TYPE_GPR);
168  op->src[0]->imm = GB_SOFTCAST(data[1], data[2]);
169  rz_strbuf_setf(&op->esil, "0x%04" PFMT64x ",%s,=", op->src[0]->imm, regs_16[data[0] >> 4]);
170  } else {
171  op->dst->reg = rz_reg_get(reg, regs_8[data[0] >> 3], RZ_REG_TYPE_GPR);
172  op->src[0]->imm = data[1];
173  rz_strbuf_setf(&op->esil, "0x%02" PFMT64x ",%s,=", op->src[0]->imm, regs_8[data[0] >> 3]);
174  }
175  op->src[0]->absolute = true;
176  op->val = op->src[0]->imm;
177 }
178 
180  op->dst = rz_analysis_value_new();
181  op->src[0] = rz_analysis_value_new();
182  op->dst->reg = rz_reg_get(reg, "sp", RZ_REG_TYPE_GPR);
183  op->src[0]->reg = rz_reg_get(reg, "hl", RZ_REG_TYPE_GPR);
184  rz_strbuf_set(&op->esil, "hl,sp,=");
185 }
186 
187 static inline void gb_analysis_mov_hl_sp(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
188  op->dst = rz_analysis_value_new();
189  op->src[0] = rz_analysis_value_new();
190  op->src[1] = rz_analysis_value_new();
191  op->dst->reg = rz_reg_get(reg, regs_16[2], RZ_REG_TYPE_GPR);
192  op->src[0]->reg = rz_reg_get(reg, regs_16[3], RZ_REG_TYPE_GPR);
193  op->src[1]->imm = (st8)data;
194  if (data < 128) {
195  rz_strbuf_setf(&op->esil, "0x%02x,sp,+,hl,=", data);
196  } else {
197  rz_strbuf_setf(&op->esil, "0x%02x,sp,-,hl,=", 0 - (st8)data);
198  }
199  rz_strbuf_append(&op->esil, ",0,Z,=,0,N,:=");
200 }
201 
202 static void gb_analysis_mov_reg(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
203  op->dst = rz_analysis_value_new();
204  op->src[0] = rz_analysis_value_new();
205  op->dst->reg = rz_reg_get(reg, regs_8[(data / 8) - 8], RZ_REG_TYPE_GPR);
206  op->src[0]->reg = rz_reg_get(reg, regs_8[data & 7], RZ_REG_TYPE_GPR);
207  rz_strbuf_setf(&op->esil, "%s,%s,=", regs_8[data & 7], regs_8[(data / 8) - 8]);
208 }
209 
210 static inline void gb_analysis_mov_ime(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
211  op->dst = rz_analysis_value_new();
212  op->src[0] = rz_analysis_value_new();
213  op->dst->reg = rz_reg_get(reg, "ime", RZ_REG_TYPE_GPR);
214  op->src[0]->absolute = true;
215  op->src[0]->imm = (data != 0xf3);
216  rz_strbuf_setf(&op->esil, "%d,ime,=", (int)op->src[0]->imm);
217  if (data == 0xd9) {
218  rz_strbuf_append(&op->esil, ",");
219  }
220 }
221 
222 static inline void gb_analysis_mov_scf(RzReg *reg, RzAnalysisOp *op) {
223  op->dst = rz_analysis_value_new();
224  op->src[0] = rz_analysis_value_new();
225  op->dst->reg = rz_reg_get(reg, regs_1[3], RZ_REG_TYPE_GPR);
226  op->src[0]->imm = 1;
227  rz_strbuf_set(&op->esil, "1,C,:=");
228 }
229 
230 static inline void gb_analysis_xor_cpl(RzReg *reg, RzAnalysisOp *op) {
231  op->dst = rz_analysis_value_new();
232  op->src[0] = rz_analysis_value_new();
233  op->dst->reg = rz_reg_get(reg, regs_8[7], RZ_REG_TYPE_GPR);
234  op->src[0]->imm = 0xff;
235  rz_strbuf_set(&op->esil, "0xff,a,^=,1,N,:=,1,H,:=");
236 }
237 
238 static inline void gb_analysis_xor_ccf(RzReg *reg, RzAnalysisOp *op) {
239  op->dst = rz_analysis_value_new();
240  op->src[0] = rz_analysis_value_new();
241  op->dst->reg = rz_reg_get(reg, regs_1[3], RZ_REG_TYPE_GPR);
242  op->src[0]->imm = 1;
243  rz_strbuf_set(&op->esil, "C,!=");
244 }
245 
246 static inline void gb_analysis_cond(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
247  op->dst = rz_analysis_value_new();
248  op->src[0] = rz_analysis_value_new();
249  op->src[0]->imm = 1;
250  if (data & 0x8) {
251  op->cond = RZ_TYPE_COND_EQ;
252  } else {
253  op->cond = RZ_TYPE_COND_NE;
254  }
255  switch (data) {
256  case 0x20:
257  case 0x28:
258  case 0xc0:
259  case 0xc2:
260  case 0xc4:
261  case 0xc8:
262  case 0xca:
263  case 0xcc:
264  op->dst->reg = rz_reg_get(reg, regs_1[0], RZ_REG_TYPE_GPR);
265  break;
266  default:
267  op->dst->reg = rz_reg_get(reg, regs_1[3], RZ_REG_TYPE_GPR);
268  }
269 }
270 
271 static inline void gb_analysis_pp(RzReg *reg, RzAnalysisOp *op, const ut8 data) // push , pop
272 {
274  val->reg = rz_reg_get(reg, regs_16_alt[(data >> 4) - 12], RZ_REG_TYPE_GPR);
275  if ((data & 0xf) == 1) {
276  op->dst = val;
277  rz_strbuf_setf(&op->esil, "sp,[2],%s,=,2,sp,+=", regs_16_alt[(data >> 4) - 12]); // pop
278  } else {
279  op->src[0] = val;
280  rz_strbuf_setf(&op->esil, "2,sp,-=,%s,sp,=[2]", regs_16_alt[(data >> 4) - 12]); // push
281  }
282 }
283 
284 static inline void gb_analysis_and_res(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 data) {
285  op->dst = rz_analysis_value_new();
286  op->src[0] = rz_analysis_value_new();
287  op->src[0]->imm = ((~(0x1 << ((data >> 3) & 7))) & 0xff);
288  op->dst->memref = ((data & 7) == 6);
289  op->dst->reg = rz_reg_get(analysis->reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
290  if (op->dst->memref) {
291  rz_strbuf_setf(&op->esil, "0x%02" PFMT64x ",%s,[1],&,%s,=[1]", op->src[0]->imm, regs_x[data & 7], regs_x[data & 7]);
292  } else {
293  rz_strbuf_setf(&op->esil, "0x%02" PFMT64x ",%s,&=", op->src[0]->imm, regs_x[data & 7]);
294  }
295 }
296 
297 static inline void gb_analysis_and_bit(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
298  op->dst = rz_analysis_value_new();
299  op->src[0] = rz_analysis_value_new();
300  op->src[0]->imm = 1 << ((data >> 3) & 7);
301  op->dst->memref = ((data & 7) == 6);
302  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
303  if (op->dst->memref) {
304  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,[1],&,0,==,$z,Z,:=,0,N,:=,1,H,:=", op->src[0]->imm, regs_x[data & 7]);
305  } else {
306  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%s,&,0,==,$z,Z,:=,0,N,:=,1,H,:=", op->src[0]->imm, regs_x[data & 7]);
307  }
308 }
309 
310 static inline void gb_analysis_or_set(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 data) {
311  op->dst = rz_analysis_value_new();
312  op->src[0] = rz_analysis_value_new();
313  op->src[0]->imm = (data >> 3) & 7;
314  op->dst->memref = ((data & 7) == 6);
315  op->dst->reg = rz_reg_get(analysis->reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
316  if (op->dst->memref) {
317  rz_strbuf_setf(&op->esil, "0x%02" PFMT64x ",%s,[1],|,%s,=[1]", op->src[0]->imm, regs_x[data & 7], regs_x[data & 7]);
318  } else {
319  rz_strbuf_setf(&op->esil, "0x%02" PFMT64x ",%s,|=", op->src[0]->imm, regs_x[data & 7]);
320  }
321 }
322 
323 static void gb_analysis_xoaasc(RzReg *reg, RzAnalysisOp *op, const ut8 *data) {
324  op->dst = rz_analysis_value_new();
325  op->src[0] = rz_analysis_value_new();
326  op->dst->reg = rz_reg_get(reg, "a", RZ_REG_TYPE_GPR);
327  op->src[0]->reg = rz_reg_get(reg, regs_x[data[0] & 7], RZ_REG_TYPE_GPR);
328  op->src[0]->memref = ((data[0] & 7) == 6);
329  switch (op->type) {
331  if (op->src[0]->memref) {
332  rz_strbuf_setf(&op->esil, "%s,[1],a,^=,$z,Z,:=,0,N,:=,0,H,:=,0,C,:=", regs_x[data[0] & 7]);
333  } else {
334  rz_strbuf_setf(&op->esil, "%s,a,^=,$z,Z,:=,0,N,:=,0,H,:=,0,C,:=", regs_x[data[0] & 7]);
335  }
336  break;
338  if (op->src[0]->memref) {
339  rz_strbuf_setf(&op->esil, "%s,[1],a,|=,$z,Z,:=,0,N,:=,0,H,:=,0,C,:=", regs_x[data[0] & 7]);
340  } else {
341  rz_strbuf_setf(&op->esil, "%s,a,|=,$z,Z,:=,0,N,:=,0,H,:=,0,C,:=", regs_x[data[0] & 7]);
342  }
343  break;
345  if (op->src[0]->memref) {
346  rz_strbuf_setf(&op->esil, "%s,[1],a,&=,$z,Z,:=,0,N,:=,1,H,:=,0,C,:=", regs_x[data[0] & 7]);
347  } else {
348  rz_strbuf_setf(&op->esil, "%s,a,&=,$z,Z,:=,0,N,:=,1,H,:=,0,C,:=", regs_x[data[0] & 7]);
349  }
350  break;
352  if (op->src[0]->memref) {
353  if (data[0] > 0x87) {
354  op->src[1] = rz_analysis_value_new();
355  op->src[1]->reg = rz_reg_get(reg, "C", RZ_REG_TYPE_GPR);
356  rz_strbuf_setf(&op->esil, "C,%s,[1],+,a,+=,$z,Z,:=,3,$c,H,:=,7,$c,C,:=,0,N,:=", regs_x[data[0] & 7]);
357  } else {
358  rz_strbuf_setf(&op->esil, "%s,[1],a,+=,$z,Z,:=,3,$c,H,:=,7,$c,C,:=,0,N,:=", regs_x[data[0] & 7]);
359  }
360  } else {
361  if (data[0] > 0x87) {
362  op->src[1] = rz_analysis_value_new();
363  op->src[1]->reg = rz_reg_get(reg, "C", RZ_REG_TYPE_GPR);
364  rz_strbuf_setf(&op->esil, "C,%s,+,a,+=,$z,Z,:=,3,$c,H,:=,7,$c,C,:=,0,N,:=", regs_x[data[0] & 7]);
365  } else {
366  rz_strbuf_setf(&op->esil, "%s,a,+=,$z,Z,:=,3,$c,H,:=,7,$c,C,:=,0,N,:=", regs_x[data[0] & 7]);
367  }
368  }
369  break;
371  if (op->src[0]->memref) {
372  if (data[0] > 0x97) {
373  op->src[1] = rz_analysis_value_new();
374  op->src[1]->reg = rz_reg_get(reg, "C", RZ_REG_TYPE_GPR);
375  rz_strbuf_setf(&op->esil, "C,%s,[1],+,a,-=,$z,Z,:=,4,$b,H,:=,8,$b,C,:=,1,N,:=", regs_x[data[0] & 7]);
376  } else {
377  rz_strbuf_setf(&op->esil, "%s,[1],a,-=,$z,Z,:=,4,$b,H,:=,8,$b,C,:=,1,N,:=", regs_x[data[0] & 7]);
378  }
379  } else {
380  if (data[0] > 0x97) {
381  op->src[1] = rz_analysis_value_new();
382  op->src[1]->reg = rz_reg_get(reg, "C", RZ_REG_TYPE_GPR);
383  rz_strbuf_setf(&op->esil, "C,%s,+,a,-=,$z,Z,:=,4,$b,H,:=,8,$b,C,:=,1,N,:=", regs_x[data[0] & 7]);
384  } else {
385  rz_strbuf_setf(&op->esil, "%s,a,-=,$z,Z,:=,4,$b,H,:=,8,$b,C,:=,1,N,:=", regs_x[data[0] & 7]);
386  }
387  }
388  break;
390  if (op->src[0]->memref) {
391  rz_strbuf_setf(&op->esil, "%s,[1],a,==,$z,Z,:=,4,$b,H,:=,8,$b,C,:=,1,N,:=", regs_x[data[0] & 7]);
392  } else {
393  rz_strbuf_setf(&op->esil, "%s,a,==,$z,Z,:=,4,$b,H,:=,8,$b,C,:=,1,N,:=", regs_x[data[0] & 7]);
394  }
395  break;
396  default:
397  // not handled yet
398  break;
399  }
400 }
401 
402 static void gb_analysis_xoaasc_imm(RzReg *reg, RzAnalysisOp *op, const ut8 *data) // xor , or, and, add, adc, sub, sbc, cp
403 {
404  op->dst = rz_analysis_value_new();
405  op->src[0] = rz_analysis_value_new();
406  op->dst->reg = rz_reg_get(reg, "a", RZ_REG_TYPE_GPR);
407  op->src[0]->absolute = true;
408  op->src[0]->imm = data[1];
409  switch (op->type) {
411  rz_strbuf_setf(&op->esil, "0x%02x,a,^=,$z,Z,:=,0,N,:=,0,H,:=,0,C,:=", data[1]);
412  break;
414  rz_strbuf_setf(&op->esil, "0x%02x,a,|=,$z,Z,:=,0,N,:=,0,H,:=,0,C,:=", data[1]);
415  break;
417  rz_strbuf_setf(&op->esil, "0x%02x,a,&=,$z,Z,:=,0,N,:=,1,H,:=,0,C,:=", data[1]);
418  break;
420  rz_strbuf_setf(&op->esil, "0x%02x,", data[1]);
421  if (data[0] == 0xce) { // adc
422  op->src[1] = rz_analysis_value_new();
423  op->src[1]->reg = rz_reg_get(reg, "C", RZ_REG_TYPE_GPR);
424  rz_strbuf_append(&op->esil, "a,+=,C,NUM,7,$c,C,:=,3,$c,H,:=,a,+=,7,$c,C,|,C,:=,3,$c,H,|=,a,a,=,$z,Z,:=,0,N,:=");
425  } else {
426  rz_strbuf_append(&op->esil, "a,+=,3,$c,H,:=,7,$c,C,:=,0,N,:=,a,a,=,$z,Z,:=");
427  }
428  break;
430  rz_strbuf_setf(&op->esil, "0x%02x,", data[1]);
431  if (data[0] == 0xde) { // sbc
432  op->src[1] = rz_analysis_value_new();
433  op->src[1]->reg = rz_reg_get(reg, "C", RZ_REG_TYPE_GPR);
434  rz_strbuf_append(&op->esil, "a,-=,C,NUM,8,$b,C,:=,4,$b,H,:=,a,-=,8,$b,C,|,C,=,4,$b,H,|,H,=,a,a,=,$z,Z,:=,1,N,:=");
435  } else {
436  rz_strbuf_append(&op->esil, "a,-=,4,$b,H,:=,8,$b,C,:=,1,N,:=,a,a,=,$z,Z,:=");
437  }
438  break;
440  rz_strbuf_setf(&op->esil, "%d,a,==,$z,Z,:=,4,$b,H,:=,8,$b,C,:=,1,N,:=", data[1]);
441  break;
442  }
443 }
444 
445 static inline void gb_analysis_load_hl(RzReg *reg, RzAnalysisOp *op, const ut8 data) // load with [hl] as memref
446 {
447  op->dst = rz_analysis_value_new();
448  op->src[0] = rz_analysis_value_new();
449  op->src[0]->reg = rz_reg_get(reg, "hl", RZ_REG_TYPE_GPR);
450  op->src[0]->memref = 1;
451  op->src[0]->absolute = true;
452  op->dst->reg = rz_reg_get(reg, regs_8[((data & 0x38) >> 3)], RZ_REG_TYPE_GPR);
453  rz_strbuf_setf(&op->esil, "hl,[1],%s,=", regs_8[((data & 0x38) >> 3)]);
454  if (data == 0x3a) {
455  rz_strbuf_append(&op->esil, ",1,hl,-=");
456  }
457  if (data == 0x2a) {
458  rz_strbuf_set(&op->esil, "hl,[1],a,=,1,hl,+="); // hack in concept
459  }
460 }
461 
462 static inline void gb_analysis_load(RzReg *reg, RzAnalysisOp *op, const ut8 *data) {
463  op->dst = rz_analysis_value_new();
464  op->src[0] = rz_analysis_value_new();
465  op->dst->reg = rz_reg_get(reg, "a", RZ_REG_TYPE_GPR);
466  op->src[0]->memref = 1;
467  switch (data[0]) {
468  case 0xf0:
469  op->src[0]->base = 0xff00 + data[1];
470  rz_strbuf_setf(&op->esil, "0x%04" PFMT64x ",[1],a,=", op->src[0]->base);
471  break;
472  case 0xf2:
473  op->src[0]->base = 0xff00;
474  op->src[0]->regdelta = rz_reg_get(reg, "c", RZ_REG_TYPE_GPR);
475  rz_strbuf_set(&op->esil, "0xff00,c,+,[1],a,=");
476  break;
477  case 0xfa:
478  op->src[0]->base = GB_SOFTCAST(data[1], data[2]);
479  if (op->src[0]->base < 0x4000) {
480  op->ptr = op->src[0]->base;
481  } else {
482  if (op->addr > 0x3fff && op->src[0]->base < 0x8000) { /* hack */
483  op->ptr = op->src[0]->base + (op->addr & 0xffffffffffff0000LL);
484  }
485  }
486  rz_strbuf_setf(&op->esil, "0x%04" PFMT64x ",[1],a,=", op->src[0]->base);
487  break;
488  default:
489  op->src[0]->reg = rz_reg_get(reg, regs_16[(data[0] & 0xf0) >> 4], RZ_REG_TYPE_GPR);
490  rz_strbuf_setf(&op->esil, "%s,[1],a,=", regs_16[(data[0] & 0xf0) >> 4]);
491  break;
492  }
493 }
494 
495 static inline void gb_analysis_store_hl(RzReg *reg, RzAnalysisOp *op, const ut8 *data) {
496  op->dst = rz_analysis_value_new();
497  op->src[0] = rz_analysis_value_new();
498  op->dst->reg = rz_reg_get(reg, "hl", RZ_REG_TYPE_GPR);
499  op->dst->memref = 1;
500  op->src[0]->absolute = true;
501  if (data[0] == 0x36) {
502  op->src[0]->imm = data[1];
503  rz_strbuf_setf(&op->esil, "0x%02x,hl,=[1]", data[1]);
504  } else {
505  op->src[0]->reg = rz_reg_get(reg, regs_8[data[0] & 0x07], RZ_REG_TYPE_GPR);
506  rz_strbuf_setf(&op->esil, "%s,hl,=[1]", regs_8[data[0] & 0x07]);
507  }
508  if (data[0] == 0x32) {
509  rz_strbuf_set(&op->esil, "a,hl,=[1],1,hl,-=");
510  }
511  if (data[0] == 0x22) {
512  rz_strbuf_set(&op->esil, "a,hl,=[1],1,hl,+=");
513  }
514 }
515 
516 static void gb_analysis_store(RzReg *reg, RzAnalysisOp *op, const ut8 *data) {
517  op->dst = rz_analysis_value_new();
518  op->src[0] = rz_analysis_value_new();
519  op->dst->memref = 1;
520  op->src[0]->reg = rz_reg_get(reg, "a", RZ_REG_TYPE_GPR);
521  switch (data[0]) {
522  case 0x08:
523  op->dst->memref = 2;
524  op->dst->base = GB_SOFTCAST(data[1], data[2]);
525  op->src[0]->reg = rz_reg_get(reg, "sp", RZ_REG_TYPE_GPR);
526  rz_strbuf_setf(&op->esil, "sp,0x%04" PFMT64x ",=[2]", op->dst->base);
527  break;
528  case 0xe0:
529  op->dst->base = 0xff00 + data[1];
530  rz_strbuf_setf(&op->esil, "a,0x%04" PFMT64x ",=[1]", op->dst->base);
531  break;
532  case 0xe2:
533  op->dst->base = 0xff00;
534  op->dst->regdelta = rz_reg_get(reg, "c", RZ_REG_TYPE_GPR);
535  rz_strbuf_set(&op->esil, "a,0xff00,c,+,=[1]");
536  break;
537  case 0xea:
538  op->dst->base = GB_SOFTCAST(data[1], data[2]);
539  rz_strbuf_setf(&op->esil, "a,0x%04" PFMT64x ",=[1]", op->dst->base);
540  break;
541  default:
542  op->dst->reg = rz_reg_get(reg, regs_16[(data[0] & 0xf0) >> 4], RZ_REG_TYPE_GPR);
543  rz_strbuf_setf(&op->esil, "a,%s,=[1]", regs_16[(data[0] & 0xf0) >> 4]);
544  }
545 }
546 
547 static inline void gb_analysis_cb_swap(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
548  op->dst = rz_analysis_value_new();
549  op->src[0] = rz_analysis_value_new();
550  op->src[0]->imm = 4;
551  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
552  if ((data & 7) == 6) {
553  op->dst->memref = 1;
554  rz_strbuf_setf(&op->esil, "4,%s,[1],>>,4,%s,[1],<<,|,%s,=[1],$z,Z,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
555  } else {
556  rz_strbuf_setf(&op->esil, "4,%s,>>,4,%s,<<,|,%s,=,$z,Z,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
557  }
558 }
559 
560 static inline void gb_analysis_cb_rlc(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
561  op->dst = rz_analysis_value_new();
562  op->src[0] = rz_analysis_value_new();
563  op->src[0]->imm = 1;
564  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
565  if ((data & 7) == 6) {
566  op->dst->memref = 1;
567  rz_strbuf_setf(&op->esil, "7,%s,[1],>>,1,&,C,:=,1,%s,[1],<<,C,|,%s,=[1],$z,Z,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
568  } else {
569  rz_strbuf_setf(&op->esil, "1,%s,<<=,7,$c,C,:=,C,%s,|=,$z,Z,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7]);
570  }
571 }
572 
573 static inline void gb_analysis_cb_rl(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
574  op->dst = rz_analysis_value_new();
575  op->src[0] = rz_analysis_value_new();
576  op->src[0]->imm = 1;
577  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
578  if ((data & 7) == 6) {
579  op->dst->memref = 1;
580  rz_strbuf_setf(&op->esil, "1,%s,<<,C,|,%s,=[1],7,$c,C,:=,$z,Z,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7]);
581  } else {
582  rz_strbuf_setf(&op->esil, "1,%s,<<,C,|,%s,=,7,$c,C,:=,$z,Z,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7]);
583  }
584 }
585 
586 static inline void gb_analysis_cb_rrc(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
587  op->dst = rz_analysis_value_new();
588  op->src[0] = rz_analysis_value_new();
589  op->src[0]->imm = 1;
590  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
591  if ((data & 7) == 6) {
592  op->dst->memref = 1;
593  rz_strbuf_setf(&op->esil, "1,%s,[1],&,C,:=,1,%s,[1],>>,7,C,<<,|,%s,=[1],$z,Z,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
594  } else {
595  rz_strbuf_setf(&op->esil, "1,%s,&,C,:=,1,%s,>>,7,C,<<,|,%s,=,$z,Z,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
596  }
597 }
598 
599 static inline void gb_analysis_cb_rr(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
600  op->dst = rz_analysis_value_new();
601  op->src[0] = rz_analysis_value_new();
602  op->src[0]->imm = 1;
603  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
604  if ((data & 7) == 6) {
605  op->dst->memref = 1;
606  rz_strbuf_setf(&op->esil, "1,%s,[1],&,H,:=,1,%s,[1],>>,7,C,<<,|,%s,=[1],H,C,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
607  } else {
608  rz_strbuf_setf(&op->esil, "1,%s,&,H,:=,1,%s,>>,7,C,<<,|,%s,=,H,C,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]); // HACK
609  }
610 }
611 
612 static inline void gb_analysis_cb_sla(RzReg *reg, RzAnalysisOp *op, const ut8 data) // sra+sla+srl in one function, like xoaasc
613 {
614  op->dst = rz_analysis_value_new();
615  op->src[0] = rz_analysis_value_new();
616  op->src[0]->imm = 1;
617  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
618  op->dst->memref = ((data & 7) == 6);
619  if (op->dst->memref) {
620  rz_strbuf_setf(&op->esil, "1,%s,[1],<<,%s,=[1],7,$c,C,:=,%s,[1],%s,=[1],$z,Z,:=,0,H,:=,0,N,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
621  } else {
622  rz_strbuf_setf(&op->esil, "1,%s,<<=,7,$c,C,:=,%s,%s,=,$z,Z,:=,0,H,:=0,N,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]); // %s,%s,= is a HACK for $z
623  }
624 }
625 
626 static inline void gb_analysis_cb_sra(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
627  op->dst = rz_analysis_value_new();
628  op->src[0] = rz_analysis_value_new();
629  op->src[0]->imm = 1;
630  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
631  op->dst->memref = ((data & 7) == 6);
632  if (op->dst->memref) {
633  rz_strbuf_setf(&op->esil, "1,%s,[1],&,C,:=,0x80,%s,[1],&,1,%s,[1],>>,|,%s,=[1],$z,Z,:=,0,N,:=,0,H,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]); // spaguesil
634  } else {
635  rz_strbuf_setf(&op->esil, "1,%s,&,C,:=,0x80,%s,&,1,%s,>>,|,%s,=,$z,Z,:=,0,N,:=,0,H,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
636  }
637 }
638 
639 static inline void gb_analysis_cb_srl(RzReg *reg, RzAnalysisOp *op, const ut8 data) {
640  op->dst = rz_analysis_value_new();
641  op->src[0] = rz_analysis_value_new();
642  op->src[0]->imm = 1;
643  op->dst->reg = rz_reg_get(reg, regs_x[data & 7], RZ_REG_TYPE_GPR);
644  op->dst->memref = ((data & 7) == 6);
645  if (op->dst->memref) {
646  rz_strbuf_setf(&op->esil, "1,%s,[1],&,C,:=,1,%s,[1],>>,%s,=[1],$z,Z,:=,0,N,:=,0,H,:=", regs_x[data & 7], regs_x[data & 7], regs_x[data & 7]);
647  } else {
648  rz_strbuf_setf(&op->esil, "1,%s,&,C,:=,1,%s,>>=,$z,Z,:=,0,N,:=,0,H,:=", regs_x[data & 7], regs_x[data & 7]);
649  }
650 }
651 
652 static bool gb_custom_daa(RzAnalysisEsil *esil) {
653  if (!esil || !esil->analysis || !esil->analysis->reg) {
654  return false;
655  }
656  char *v = rz_analysis_esil_pop(esil);
657  ut64 n;
658  if (!v || !rz_analysis_esil_get_parm(esil, v, &n)) {
659  return false;
660  }
661  RZ_FREE(v);
662  ut8 val = (ut8)n;
663  rz_analysis_esil_reg_read(esil, "H", &n, NULL);
664  const ut8 H = (ut8)n;
665  rz_analysis_esil_reg_read(esil, "C", &n, NULL);
666  const ut8 C = (ut8)n;
667  rz_analysis_esil_reg_read(esil, "N", &n, NULL);
668  if (n) {
669  if (C) {
670  val = (val - 0x60) & 0xff;
671  }
672  if (H) {
673  val = (val - 0x06) & 0xff;
674  }
675  } else {
676  if (C || (val > 0x99)) {
677  val = (val + 0x60) & 0xff;
678  }
679  if (H || ((val & 0x0f) > 0x09)) {
680  val += 0x06;
681  };
682  }
683  return rz_analysis_esil_pushnum(esil, val);
684 }
685 
686 static int gb_anop(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
687  int ilen = gbOpLength(gb_op[data[0]].type);
688  if (ilen > len) {
689  op->type = RZ_ANALYSIS_OP_TYPE_ILL;
690  op->size = 0;
691  return 0;
692  }
694  char mn[32];
695  memset(mn, '\0', sizeof(char) * sizeof(mn));
696  char reg[32];
697  memset(reg, '\0', sizeof(char) * sizeof(reg));
698  switch (gb_op[data[0]].type) {
699  case GB_8BIT:
700  sprintf(mn, "%s", gb_op[data[0]].name);
701  break;
702  case GB_16BIT:
703  sprintf(mn, "%s %s", cb_ops[data[1] >> 3], cb_regs[data[1] & 7]);
704  break;
705  case GB_8BIT + ARG_8:
706  sprintf(mn, gb_op[data[0]].name, data[1]);
707  break;
708  case GB_8BIT + ARG_16:
709  sprintf(mn, gb_op[data[0]].name, data[1] | (data[2] << 8));
710  break;
711  case GB_8BIT + ARG_8 + GB_IO:
712  gb_hardware_register_name(reg, data[1]);
713  sprintf(mn, gb_op[data[0]].name, reg);
714  break;
715  }
716  op->mnemonic = strdup(mn);
717  }
718  op->addr = addr;
719  op->type = RZ_ANALYSIS_OP_TYPE_UNK;
720  op->size = ilen;
721  op->nopcode = 1;
722  switch (data[0]) {
723  case 0x00:
724  case 0x40:
725  case 0x49:
726  case 0x52:
727  case 0x5b:
728  case 0x64:
729  case 0x6d:
730  case 0x7f:
731  op->cycles = 4;
732  op->type = RZ_ANALYSIS_OP_TYPE_NOP;
733  break;
734  case 0x01:
735  case 0x11:
736  case 0x21:
737  case 0x31:
738  gb_analysis_mov_imm(analysis->reg, op, data);
739  op->cycles = 12;
740  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
741  break;
742  case 0xf8:
743  gb_analysis_mov_hl_sp(analysis->reg, op, data[1]);
744  op->cycles = 12;
745  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
746  op->type2 = RZ_ANALYSIS_OP_TYPE_ADD;
747  break;
748  case 0x06:
749  case 0x0e:
750  case 0x16:
751  case 0x1e:
752  case 0x26:
753  case 0x2e:
754  case 0x3e:
755  gb_analysis_mov_imm(analysis->reg, op, data);
756  op->cycles = 8;
757  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
758  break;
759  case 0xf9:
760  gb_analysis_mov_sp_hl(analysis->reg, op);
761  op->cycles = 8;
762  op->type = RZ_ANALYSIS_OP_TYPE_MOV; // LD
763  break;
764  case 0x03:
765  case 0x13:
766  case 0x23:
767  case 0x33:
768  op->cycles = 8;
769  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
770  gb_analysis_id(analysis, op, data[0]);
771  break;
772  case 0x04:
773  case 0x0c:
774  case 0x14:
775  case 0x1c:
776  case 0x24:
777  case 0x2c:
778  case 0x3c:
779  op->cycles = 4;
780  op->type = RZ_ANALYSIS_OP_TYPE_ADD; // INC
781  gb_analysis_id(analysis, op, data[0]);
782  break;
783  case 0x34:
784  op->cycles = 12;
785  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
786  gb_analysis_id(analysis, op, data[0]);
787  break;
788  case 0xea:
789  meta_gb_bankswitch_cmt(analysis, addr, GB_SOFTCAST(data[1], data[2]));
790  gb_analysis_store(analysis->reg, op, data);
791  op->cycles = 16;
793  break;
794  case 0x08:
795  meta_gb_bankswitch_cmt(analysis, addr, GB_SOFTCAST(data[1], data[2]));
796  gb_analysis_store(analysis->reg, op, data);
797  op->cycles = 20;
799  break;
800  case 0x02:
801  case 0x12:
802  case 0xe2:
803  gb_analysis_store(analysis->reg, op, data);
804  op->cycles = 8;
806  break;
807  case 0x36:
808  case 0x22:
809  case 0x32:
810  case 0x70:
811  case 0x71:
812  case 0x72:
813  case 0x73:
814  case 0x74:
815  case 0x75:
816  case 0x77:
817  gb_analysis_store_hl(analysis->reg, op, data);
818  op->cycles = 8;
819  op->type = RZ_ANALYSIS_OP_TYPE_STORE; // LD
820  break;
821  case 0xe0:
822  gb_analysis_store(analysis->reg, op, data);
823  op->cycles = 12;
825  break;
826  case 0x41:
827  case 0x42:
828  case 0x43:
829  case 0x44:
830  case 0x45:
831  case 0x47:
832  case 0x48:
833  case 0x4a:
834  case 0x4b:
835  case 0x4c:
836  case 0x4d:
837  case 0x4f:
838  case 0x50:
839  case 0x51:
840  case 0x53:
841  case 0x54:
842  case 0x55:
843  case 0x57:
844  case 0x58:
845  case 0x59:
846  case 0x5a:
847  case 0x5c:
848  case 0x5d:
849  case 0x5f:
850  case 0x60:
851  case 0x61:
852  case 0x62:
853  case 0x63:
854  case 0x65:
855  case 0x67:
856  case 0x68:
857  case 0x69:
858  case 0x6a:
859  case 0x6b:
860  case 0x6c:
861  case 0x6f:
862  case 0x78:
863  case 0x79:
864  case 0x7a:
865  case 0x7b:
866  case 0x7c:
867  case 0x7d:
868  gb_analysis_mov_reg(analysis->reg, op, data[0]);
869  op->cycles = 4;
870  op->type = RZ_ANALYSIS_OP_TYPE_MOV; // LD
871  break;
872  case 0x0a:
873  case 0x1a:
874  case 0xf2:
875  gb_analysis_load(analysis->reg, op, data);
876  op->cycles = 8;
878  break;
879  case 0x2a:
880  case 0x3a:
881  case 0x46:
882  case 0x4e:
883  case 0x56:
884  case 0x5e:
885  case 0x66:
886  case 0x6e:
887  case 0x7e:
888  gb_analysis_load_hl(analysis->reg, op, data[0]);
889  op->cycles = 8;
891  break;
892  case 0xf0:
893  gb_analysis_load(analysis->reg, op, data);
894  op->cycles = 12;
896  break;
897  case 0xfa:
898  gb_analysis_load(analysis->reg, op, data);
899  op->cycles = 16;
901  break;
902  case 0x80:
903  case 0x81:
904  case 0x82:
905  case 0x83:
906  case 0x84:
907  case 0x85:
908  case 0x87:
909  case 0x88:
910  case 0x89:
911  case 0x8a:
912  case 0x8b:
913  case 0x8c:
914  case 0x8d:
915  case 0x8f:
916  op->cycles = 4;
917  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
918  gb_analysis_xoaasc(analysis->reg, op, data);
919  break;
920  case 0x09:
921  case 0x19:
922  case 0x29:
923  case 0x39:
924  gb_analysis_add_hl(analysis->reg, op, data[0]);
925  op->cycles = 8;
926  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
927  break;
928  case 0x86:
929  case 0x8e:
930  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
931  gb_analysis_xoaasc(analysis->reg, op, data);
932  op->cycles = 8;
933  break;
934  case 0xc6:
935  case 0xce:
936  op->cycles = 8;
937  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
938  gb_analysis_xoaasc_imm(analysis->reg, op, data);
939  break;
940  case 0xe8:
941  gb_analysis_add_sp(analysis->reg, op, data[1]);
942  op->cycles = 16;
943  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
944  break;
945  case 0x90:
946  case 0x91:
947  case 0x92:
948  case 0x93:
949  case 0x94:
950  case 0x95:
951  case 0x97:
952  case 0x98:
953  case 0x99:
954  case 0x9a:
955  case 0x9b:
956  case 0x9c:
957  case 0x9d:
958  case 0x9f:
959  op->cycles = 4;
960  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
961  gb_analysis_xoaasc(analysis->reg, op, data);
962  break;
963  case 0x96:
964  case 0x9e:
965  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
966  gb_analysis_xoaasc(analysis->reg, op, data);
967  op->cycles = 8;
968  break;
969  case 0xd6:
970  case 0xde:
971  op->cycles = 8;
972  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
973  gb_analysis_xoaasc_imm(analysis->reg, op, data);
974  break;
975  case 0xa0:
976  case 0xa1:
977  case 0xa2:
978  case 0xa3:
979  case 0xa4:
980  case 0xa5:
981  case 0xa7:
982  op->cycles = 4;
983  op->type = RZ_ANALYSIS_OP_TYPE_AND;
984  gb_analysis_xoaasc(analysis->reg, op, data);
985  break;
986  case 0xe6:
987  op->cycles = 8;
988  op->type = RZ_ANALYSIS_OP_TYPE_AND;
989  gb_analysis_xoaasc_imm(analysis->reg, op, data);
990  break;
991  case 0xa6:
992  op->type = RZ_ANALYSIS_OP_TYPE_AND;
993  gb_analysis_xoaasc(analysis->reg, op, data);
994  op->cycles = 8;
995  break;
996  case 0x07: // rlca
997  op->cycles = 4;
998  op->type = RZ_ANALYSIS_OP_TYPE_ROL;
999  gb_analysis_cb_rlc(analysis->reg, op, 7);
1000  break;
1001  case 0x17: // rla
1002  op->cycles = 4;
1003  op->type = RZ_ANALYSIS_OP_TYPE_ROL;
1004  gb_analysis_cb_rl(analysis->reg, op, 7);
1005  break;
1006  case 0x0f: // rrca
1007  op->cycles = 4;
1008  op->type = RZ_ANALYSIS_OP_TYPE_ROR;
1009  gb_analysis_cb_rrc(analysis->reg, op, 7);
1010  break;
1011  case 0x1f: // rra
1012  op->cycles = 4;
1013  op->type = RZ_ANALYSIS_OP_TYPE_ROR;
1014  gb_analysis_cb_rr(analysis->reg, op, 7);
1015  break;
1016  case 0x2f:
1017  gb_analysis_xor_cpl(analysis->reg, op); // cpl
1018  op->cycles = 4;
1019  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
1020  break;
1021  case 0x3f: // ccf
1022  gb_analysis_xor_ccf(analysis->reg, op);
1023  op->cycles = 4;
1024  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
1025  break;
1026  case 0xa8:
1027  case 0xa9:
1028  case 0xaa:
1029  case 0xab:
1030  case 0xac:
1031  case 0xad:
1032  case 0xaf:
1033  op->cycles = 4;
1034  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
1035  gb_analysis_xoaasc(analysis->reg, op, data);
1036  break;
1037  case 0xee:
1038  op->cycles = 8;
1039  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
1040  gb_analysis_xoaasc_imm(analysis->reg, op, data);
1041  break;
1042  case 0xae:
1043  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
1044  gb_analysis_xoaasc(analysis->reg, op, data);
1045  op->cycles = 8;
1046  break;
1047  case 0xb0:
1048  case 0xb1:
1049  case 0xb2:
1050  case 0xb3:
1051  case 0xb4:
1052  case 0xb5:
1053  case 0xb7:
1054  op->cycles = 4;
1055  op->type = RZ_ANALYSIS_OP_TYPE_OR;
1056  gb_analysis_xoaasc(analysis->reg, op, data);
1057  break;
1058  case 0xf6:
1059  op->cycles = 8;
1060  op->type = RZ_ANALYSIS_OP_TYPE_OR;
1061  gb_analysis_xoaasc_imm(analysis->reg, op, data);
1062  break;
1063  case 0xb6:
1064  op->type = RZ_ANALYSIS_OP_TYPE_OR;
1065  gb_analysis_xoaasc(analysis->reg, op, data);
1066  op->cycles = 8;
1067  break;
1068  case 0xb8:
1069  case 0xb9:
1070  case 0xba:
1071  case 0xbb:
1072  case 0xbc:
1073  case 0xbd:
1074  case 0xbf:
1075  op->cycles = 4;
1076  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
1077  gb_analysis_xoaasc(analysis->reg, op, data);
1078  break;
1079  case 0xfe:
1080  op->cycles = 8;
1081  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
1082  gb_analysis_xoaasc_imm(analysis->reg, op, data);
1083  break;
1084  case 0xbe:
1085  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
1086  gb_analysis_xoaasc(analysis->reg, op, data);
1087  op->cycles = 8;
1088  break;
1089  case 0xc0:
1090  case 0xc8:
1091  case 0xd0:
1092  case 0xd8:
1093  gb_analysis_cond(analysis->reg, op, data[0]);
1094  gb_analysis_esil_cret(op, data[0]);
1095  op->eob = true;
1096  op->cycles = 20;
1097  op->failcycles = 8;
1098  op->type = RZ_ANALYSIS_OP_TYPE_CRET;
1099  break;
1100  case 0xd9:
1101  gb_analysis_mov_ime(analysis->reg, op, data[0]);
1102  op->type2 = RZ_ANALYSIS_OP_TYPE_MOV;
1103  // fallthrough
1104  case 0xc9:
1105  op->eob = true;
1106  op->cycles = 16;
1108  op->stackop = RZ_ANALYSIS_STACK_INC;
1109  op->stackptr = -2;
1110  op->type = RZ_ANALYSIS_OP_TYPE_RET;
1111  break;
1112  case 0x0b:
1113  case 0x1b:
1114  case 0x2b:
1115  case 0x3b:
1116  op->cycles = 8;
1117  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
1118  gb_analysis_id(analysis, op, data[0]);
1119  break;
1120  case 0x05:
1121  case 0x0d:
1122  case 0x15:
1123  case 0x1d:
1124  case 0x25:
1125  case 0x2d:
1126  case 0x3d:
1127  op->cycles = 4;
1128  op->type = RZ_ANALYSIS_OP_TYPE_SUB; // DEC
1129  gb_analysis_id(analysis, op, data[0]);
1130  break;
1131  case 0x35:
1132  op->cycles = 12;
1133  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
1134  gb_analysis_id(analysis, op, data[0]);
1135  break;
1136  case 0xc5:
1137  case 0xd5:
1138  case 0xe5:
1139  case 0xf5:
1140  gb_analysis_pp(analysis->reg, op, data[0]);
1141  op->cycles = 16;
1142  op->stackop = RZ_ANALYSIS_STACK_INC;
1143  op->stackptr = 2;
1144  op->type = RZ_ANALYSIS_OP_TYPE_RPUSH;
1145  break;
1146  case 0xc1:
1147  case 0xd1:
1148  case 0xe1:
1149  case 0xf1:
1150  gb_analysis_pp(analysis->reg, op, data[0]);
1151  op->cycles = 12;
1152  op->stackop = RZ_ANALYSIS_STACK_INC;
1153  op->stackptr = -2;
1154  op->type = RZ_ANALYSIS_OP_TYPE_POP;
1155  break;
1156  case 0xc3:
1157  if (gb_op_calljump(analysis, op, data, addr)) {
1158  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
1160  } else {
1161  op->type = RZ_ANALYSIS_OP_TYPE_UJMP;
1162  }
1163  op->eob = true;
1164  op->cycles = 16;
1165  op->fail = addr + ilen;
1166  break;
1167  case 0x18: // JR
1168  op->jump = addr + ilen + (st8)data[1];
1169  op->fail = addr + ilen;
1171  op->cycles = 12;
1172  op->eob = true;
1173  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
1174  break;
1175  case 0x20:
1176  case 0x28:
1177  case 0x30:
1178  case 0x38: // JR cond
1179  gb_analysis_cond(analysis->reg, op, data[0]);
1180  op->jump = addr + ilen + (st8)data[1];
1181  op->fail = addr + ilen;
1182  gb_analysis_esil_cjmp(op, data[0]);
1183  op->cycles = 12;
1184  op->failcycles = 8;
1185  op->eob = true;
1186  op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
1187  break;
1188  case 0xc2:
1189  case 0xca:
1190  case 0xd2:
1191  case 0xda:
1192  if (gb_op_calljump(analysis, op, data, addr)) {
1193  op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
1194  } else {
1195  op->type = RZ_ANALYSIS_OP_TYPE_UCJMP;
1196  }
1197  op->eob = true;
1198  gb_analysis_cond(analysis->reg, op, data[0]);
1199  gb_analysis_esil_cjmp(op, data[0]);
1200  op->cycles = 16;
1201  op->failcycles = 12;
1202  op->fail = addr + ilen;
1203  break;
1204  case 0xe9:
1205  op->cycles = 4;
1206  op->eob = true;
1207  op->type = RZ_ANALYSIS_OP_TYPE_UJMP;
1208  gb_analysis_jmp_hl(analysis->reg, op);
1209  break;
1210  case 0x76:
1211  op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
1212  op->eob = true; // halt might wait for interrupts
1213  op->fail = addr + ilen;
1214  if (len > 1) {
1215  op->jump = addr + gbOpLength(gb_op[data[1]].type) + ilen;
1216  }
1217  break;
1218  case 0xcd:
1219  if (gb_op_calljump(analysis, op, data, addr)) {
1220  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1221  } else {
1222  op->type = RZ_ANALYSIS_OP_TYPE_UCALL;
1223  }
1224  op->fail = addr + ilen;
1225  op->eob = true;
1227  op->cycles = 24;
1228  break;
1229  case 0xc4:
1230  case 0xcc:
1231  case 0xd4:
1232  case 0xdc:
1233  gb_analysis_cond(analysis->reg, op, data[0]);
1234  if (gb_op_calljump(analysis, op, data, addr)) {
1235  op->type = RZ_ANALYSIS_OP_TYPE_CCALL;
1236  } else {
1238  }
1239  op->fail = addr + ilen;
1240  op->eob = true;
1241  gb_analysis_esil_ccall(op, data[0]);
1242  op->cycles = 24;
1243  op->failcycles = 12;
1244  break;
1245  case 0xc7: // rst 0
1246  op->jump = 0x00;
1247  op->fail = addr + ilen;
1248  op->eob = true;
1250  op->cycles = 16;
1251  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1252  break;
1253  case 0xcf: // rst 8
1254  op->jump = 0x08;
1255  op->fail = addr + ilen;
1256  op->eob = true;
1258  op->cycles = 16;
1259  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1260  break;
1261  case 0xd7: // rst 16
1262  op->jump = 0x10;
1263  op->fail = addr + ilen;
1264  op->eob = true;
1266  op->cycles = 16;
1267  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1268  break;
1269  case 0xdf: // rst 24
1270  op->jump = 0x18;
1271  op->fail = addr + ilen;
1272  op->eob = true;
1274  op->cycles = 16;
1275  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1276  break;
1277  case 0xe7: // rst 32
1278  op->jump = 0x20;
1279  op->fail = addr + ilen;
1280  op->eob = true;
1282  op->cycles = 16;
1283  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1284  break;
1285  case 0xef: // rst 40
1286  op->jump = 0x28;
1287  op->fail = addr + ilen;
1288  op->eob = true;
1290  op->cycles = 16;
1291  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1292  break;
1293  case 0xf7: // rst 48
1294  op->jump = 0x30;
1295  op->fail = addr + ilen;
1296  op->eob = true;
1298  op->cycles = 16;
1299  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1300  break;
1301  case 0xff: // rst 56
1302  op->jump = 0x38;
1303  op->fail = addr + ilen;
1304  op->eob = true;
1306  op->cycles = 16;
1307  op->type = RZ_ANALYSIS_OP_TYPE_CALL;
1308  break;
1309  case 0xf3: // di
1310  case 0xfb: // ei
1311  gb_analysis_mov_ime(analysis->reg, op, data[0]);
1312  op->cycles = 4;
1313  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
1314  break;
1315  case 0x37:
1316  gb_analysis_mov_scf(analysis->reg, op);
1317  op->cycles = 4;
1318  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
1319  break;
1320  case 0x27: // daa
1321  op->cycles = 4;
1322  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
1323  rz_strbuf_set(&op->esil, "a,daa,a,=,$z,Z,:=,3,$c,H,:=,7,$c,C,:=");
1324  break;
1325  case 0x10: // stop
1326  op->type = RZ_ANALYSIS_OP_TYPE_NULL;
1327  rz_strbuf_set(&op->esil, "TODO,stop");
1328  break;
1329  case 0xcb:
1330  op->nopcode = 2;
1331  switch (data[1] >> 3) {
1332  case 0:
1333  if ((data[1] & 7) == 6) {
1334  op->cycles = 16;
1335  } else {
1336  op->cycles = 8;
1337  }
1338  op->type = RZ_ANALYSIS_OP_TYPE_ROL;
1339  gb_analysis_cb_rlc(analysis->reg, op, data[1]);
1340  break;
1341  case 1:
1342  if ((data[1] & 7) == 6) {
1343  op->cycles = 16;
1344  } else {
1345  op->cycles = 8;
1346  }
1347  op->type = RZ_ANALYSIS_OP_TYPE_ROR;
1348  gb_analysis_cb_rrc(analysis->reg, op, data[1]);
1349  break;
1350  case 2:
1351  if ((data[1] & 7) == 6) {
1352  op->cycles = 16;
1353  } else {
1354  op->cycles = 8;
1355  }
1356  op->type = RZ_ANALYSIS_OP_TYPE_ROL;
1357  gb_analysis_cb_rl(analysis->reg, op, data[1]);
1358  break;
1359  case 3:
1360  if ((data[1] & 7) == 6) {
1361  op->cycles = 16;
1362  } else {
1363  op->cycles = 8;
1364  }
1365  op->type = RZ_ANALYSIS_OP_TYPE_ROR;
1366  gb_analysis_cb_rr(analysis->reg, op, data[1]);
1367  break;
1368  case 4:
1369  if ((data[1] & 7) == 6) {
1370  op->cycles = 16;
1371  } else {
1372  op->cycles = 8;
1373  }
1374  op->type = RZ_ANALYSIS_OP_TYPE_SAL;
1375  gb_analysis_cb_sla(analysis->reg, op, data[1]);
1376  break;
1377  case 6:
1378  if ((data[1] & 7) == 6) {
1379  op->cycles = 16;
1380  } else {
1381  op->cycles = 8;
1382  }
1383  op->type = RZ_ANALYSIS_OP_TYPE_ROL;
1384  gb_analysis_cb_swap(analysis->reg, op, data[1]);
1385  break;
1386  case 5:
1387  if ((data[1] & 7) == 6) {
1388  op->cycles = 16;
1389  } else {
1390  op->cycles = 8;
1391  }
1392  op->type = RZ_ANALYSIS_OP_TYPE_SAR;
1393  gb_analysis_cb_sra(analysis->reg, op, data[1]);
1394  break;
1395  case 7:
1396  if ((data[1] & 7) == 6) {
1397  op->cycles = 16;
1398  } else {
1399  op->cycles = 8;
1400  }
1401  op->type = RZ_ANALYSIS_OP_TYPE_SHR;
1402  gb_analysis_cb_srl(analysis->reg, op, data[1]);
1403  break;
1404  case 8:
1405  case 9:
1406  case 10:
1407  case 11:
1408  case 12:
1409  case 13:
1410  case 14:
1411  case 15:
1412  if ((data[1] & 7) == 6) {
1413  op->cycles = 12;
1414  } else {
1415  op->cycles = 8;
1416  }
1417  op->type = RZ_ANALYSIS_OP_TYPE_ACMP;
1418  gb_analysis_and_bit(analysis->reg, op, data[1]);
1419  break; // bit
1420  case 16:
1421  case 17:
1422  case 18:
1423  case 19:
1424  case 20:
1425  case 21:
1426  case 22:
1427  case 23:
1428  if ((data[1] & 7) == 6) {
1429  op->cycles = 16;
1430  } else {
1431  op->cycles = 8;
1432  }
1433  gb_analysis_and_res(analysis, op, data[1]);
1434  op->type = RZ_ANALYSIS_OP_TYPE_AND;
1435  break; // res
1436  case 24:
1437  case 25:
1438  case 26:
1439  case 27:
1440  case 28:
1441  case 29:
1442  case 30:
1443  case 31:
1444  if ((data[1] & 7) == 6) {
1445  op->cycles = 16;
1446  } else {
1447  op->cycles = 8;
1448  }
1449  gb_analysis_or_set(analysis, op, data[1]);
1450  op->type = RZ_ANALYSIS_OP_TYPE_OR;
1451  break; // set
1452  }
1453  }
1454  if (op->type == RZ_ANALYSIS_OP_TYPE_CALL) {
1455  op->stackop = RZ_ANALYSIS_STACK_INC;
1456  op->stackptr = 2;
1457  }
1458  return op->size;
1459 }
1460 
1461 /*
1462  The reg-profile below does not represent the real gameboy registers.
1463  ->There is no such thing like m, mpc or mbc. there is only pc.
1464  m and mbc should make it easier to inspect the current mbc-state, because
1465  the mbc can be seen as a register but it isn't. For the Gameboy the mbc is invisble.
1466 */
1467 
1468 static char *get_reg_profile(RzAnalysis *analysis) {
1469  const char *p =
1470  "=PC mpc\n"
1471  "=SP sp\n"
1472  "=A0 af\n"
1473  "=A1 bc\n"
1474  "=A2 de\n"
1475  "=A3 hl\n"
1476 
1477  "gpr mpc .32 0 0\n"
1478  "gpr pc .16 0 0\n"
1479  "gpr m .16 2 0\n"
1480 
1481  "gpr sp .16 4 0\n"
1482 
1483  "gpr af .16 6 0\n"
1484  "gpr f .8 6 0\n"
1485  "gpr a .8 7 0\n"
1486  "gpr Z .1 .55 0\n"
1487  "gpr N .1 .54 0\n"
1488  "gpr H .1 .53 0\n"
1489  "gpr C .1 .52 0\n"
1490 
1491  "gpr bc .16 8 0\n"
1492  "gpr c .8 8 0\n"
1493  "gpr b .8 9 0\n"
1494 
1495  "gpr de .16 10 0\n"
1496  "gpr e .8 10 0\n"
1497  "gpr d .8 11 0\n"
1498 
1499  "gpr hl .16 12 0\n"
1500  "gpr l .8 12 0\n"
1501  "gpr h .8 13 0\n"
1502 
1503  "gpr mbcrom .16 14 0\n"
1504  "gpr mbcram .16 16 0\n"
1505 
1506  "gpr ime .1 18 0\n";
1507  return strdup(p);
1508 }
1509 
1510 static int esil_gb_init(RzAnalysisEsil *esil) {
1511  GBUser *user = RZ_NEW0(GBUser);
1513  if (user) {
1514  if (esil->analysis) {
1515  esil->analysis->iob.read_at(esil->analysis->iob.io, 0x147, &user->mbc_id, 1);
1516  esil->analysis->iob.read_at(esil->analysis->iob.io, 0x148, &user->romsz_id, 1);
1517  esil->analysis->iob.read_at(esil->analysis->iob.io, 0x149, &user->ramsz_id, 1);
1518  if (esil->analysis->reg) { // initial values
1519  rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "mpc", -1), 0x100);
1520  rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "sp", -1), 0xfffe);
1521  rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "af", -1), 0x01b0);
1522  rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "bc", -1), 0x0013);
1523  rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "de", -1), 0x00d8);
1524  rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "hl", -1), 0x014d);
1525  rz_reg_set_value(esil->analysis->reg, rz_reg_get(esil->analysis->reg, "ime", -1), true);
1526  }
1527  }
1528  esil->cb.user = user;
1529  }
1530  return true;
1531 }
1532 
1533 static int esil_gb_fini(RzAnalysisEsil *esil) {
1534  RZ_FREE(esil->cb.user);
1535  return true;
1536 }
1537 
1539  .name = "gb",
1540  .desc = "Gameboy CPU code analysis plugin",
1541  .license = "LGPL3",
1542  .arch = "z80",
1543  .esil = true,
1544  .bits = 16,
1545  .op = &gb_anop,
1546  .get_reg_profile = &get_reg_profile,
1547  .esil_init = esil_gb_init,
1548  .esil_fini = esil_gb_fini,
1549 };
1550 
1551 #ifndef RZ_PLUGIN_INCORE
1554  .data = &rz_analysis_plugin_gb,
1555  .version = RZ_VERSION
1556 };
1557 #endif
size_t len
Definition: 6502dis.c:15
RZ_API RzAnalysisValue * rz_analysis_value_new(void)
Definition: value.c:6
static void gb_analysis_cb_swap(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:547
static void gb_analysis_esil_call(RzAnalysisOp *op)
Definition: analysis_gb.c:40
static void gb_analysis_cb_srl(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:639
static void gb_analysis_id(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:110
static void gb_analysis_mov_hl_sp(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:187
static void gb_analysis_esil_cjmp(RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:79
static char * get_reg_profile(RzAnalysis *analysis)
Definition: analysis_gb.c:1468
static bool gb_custom_daa(RzAnalysisEsil *esil)
Definition: analysis_gb.c:652
static int gb_anop(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask)
Definition: analysis_gb.c:686
static void gb_analysis_cb_rrc(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:586
static void gb_analysis_esil_ccall(RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:44
static void gb_analysis_load(RzReg *reg, RzAnalysisOp *op, const ut8 *data)
Definition: analysis_gb.c:462
static const char * regs_8[]
Definition: analysis_gb.c:21
static int esil_gb_init(RzAnalysisEsil *esil)
Definition: analysis_gb.c:1510
static void gb_analysis_xor_ccf(RzReg *reg, RzAnalysisOp *op)
Definition: analysis_gb.c:238
static void gb_analysis_store(RzReg *reg, RzAnalysisOp *op, const ut8 *data)
Definition: analysis_gb.c:516
static void gb_analysis_mov_scf(RzReg *reg, RzAnalysisOp *op)
Definition: analysis_gb.c:222
static void gb_analysis_esil_ret(RzAnalysisOp *op)
Definition: analysis_gb.c:61
static const char * regs_16[]
Definition: analysis_gb.c:23
static const char * regs_x[]
Definition: analysis_gb.c:22
static void gb_analysis_xoaasc_imm(RzReg *reg, RzAnalysisOp *op, const ut8 *data)
Definition: analysis_gb.c:402
static void gb_analysis_and_res(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:284
static void gb_analysis_xor_cpl(RzReg *reg, RzAnalysisOp *op)
Definition: analysis_gb.c:230
static void gb_analysis_cb_sla(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:612
static void gb_analysis_pp(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:271
RZ_API RzLibStruct rizin_plugin
Definition: analysis_gb.c:1552
RzAnalysisPlugin rz_analysis_plugin_gb
Definition: analysis_gb.c:1538
static const char * regs_16_alt[]
Definition: analysis_gb.c:24
static void gb_analysis_cb_rl(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:573
static void gb_analysis_cb_sra(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:626
static void gb_analysis_or_set(RzAnalysis *analysis, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:310
static void gb_analysis_esil_cret(RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:65
static ut8 gb_op_calljump(RzAnalysis *a, RzAnalysisOp *op, const ut8 *data, ut64 addr)
Definition: analysis_gb.c:26
static void gb_analysis_mov_reg(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:202
static void gb_analysis_cb_rlc(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:560
static void gb_analysis_cond(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:246
static void gb_analysis_mov_sp_hl(RzReg *reg, RzAnalysisOp *op)
Definition: analysis_gb.c:179
static void gb_analysis_load_hl(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:445
static void gb_analysis_mov_imm(RzReg *reg, RzAnalysisOp *op, const ut8 *data)
Definition: analysis_gb.c:163
static void gb_analysis_store_hl(RzReg *reg, RzAnalysisOp *op, const ut8 *data)
Definition: analysis_gb.c:495
static const char * regs_1[]
Definition: analysis_gb.c:20
static void gb_analysis_xoaasc(RzReg *reg, RzAnalysisOp *op, const ut8 *data)
Definition: analysis_gb.c:323
static int esil_gb_fini(RzAnalysisEsil *esil)
Definition: analysis_gb.c:1533
static void gb_analysis_cb_rr(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:599
static void gb_analysis_add_hl(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:142
static void gb_analysis_add_sp(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:150
static void gb_analysis_esil_jmp(RzAnalysisOp *op)
Definition: analysis_gb.c:98
static void gb_analysis_and_bit(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:297
static void gb_analysis_jmp_hl(RzReg *reg, RzAnalysisOp *op)
Definition: analysis_gb.c:102
static void gb_analysis_mov_ime(RzReg *reg, RzAnalysisOp *op, const ut8 data)
Definition: analysis_gb.c:210
#define mask()
#define C(x)
Definition: arc.h:167
ut16 val
Definition: armass64_const.h:6
#define H(x)
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define ut8
Definition: dcpu16.h:8
const char * v
Definition: dsignal.c:12
RZ_API int rz_analysis_esil_get_parm(RzAnalysisEsil *esil, const char *str, ut64 *num)
Definition: esil.c:483
RZ_API bool rz_analysis_esil_pushnum(RzAnalysisEsil *esil, ut64 num)
Definition: esil.c:408
RZ_API int rz_analysis_esil_reg_read(RzAnalysisEsil *esil, const char *regname, ut64 *num, int *size)
Definition: esil.c:507
RZ_API bool rz_analysis_esil_set_op(RzAnalysisEsil *esil, const char *op, RzAnalysisEsilOpCb code, ut32 push, ut32 pop, ut32 type)
Definition: esil.c:110
RZ_API char * rz_analysis_esil_pop(RzAnalysisEsil *esil)
Definition: esil.c:422
#define GB_IB_DST(x, y, z)
Definition: gb_makros.h:11
#define GB_IS_VBANK_DST(x, y)
Definition: gb_makros.h:13
#define GB_IS_RAM_DST(x, y)
Definition: gb_makros.h:9
#define GB_SOFTCAST(x, y)
Definition: gb_makros.h:8
#define GB_IO
Definition: gb_op_table.h:8
static const char * cb_ops[]
Definition: gb_op_table.h:15
#define GB_16BIT
Definition: gb_op_table.h:5
#define ARG_16
Definition: gb_op_table.h:7
#define ARG_8
Definition: gb_op_table.h:6
static const char * cb_regs[]
Definition: gb_op_table.h:20
static gb_opcode gb_op[]
Definition: gb_op_table.h:22
#define GB_8BIT
Definition: gb_op_table.h:4
static void gb_hardware_register_name(char *reg, ut8 offset)
Definition: gbdis.c:28
static int gbOpLength(int gboptype)
Definition: gbdis.c:13
sprintf
Definition: kernel.h:365
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
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")
RZ_API bool rz_meta_set_string(RzAnalysis *a, RzAnalysisMetaType type, ut64 addr, const char *s)
Definition: meta.c:141
void meta_gb_bankswitch_cmt(RzAnalysis *a, ut64 addr, ut16 ldarg)
Definition: meta_gb_cmt.c:7
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
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_ANALYSIS_STACK_INC
Definition: rz_analysis.h:457
@ RZ_ANALYSIS_ESIL_OP_TYPE_MATH
Definition: rz_analysis.h:1183
@ RZ_ANALYSIS_ESIL_OP_TYPE_CUSTOM
Definition: rz_analysis.h:1184
@ RZ_META_TYPE_COMMENT
Definition: rz_analysis.h:295
RzAnalysisOpMask
Definition: rz_analysis.h:439
@ RZ_ANALYSIS_OP_MASK_DISASM
Definition: rz_analysis.h:445
@ RZ_ANALYSIS_OP_TYPE_CMP
Definition: rz_analysis.h:399
@ 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_SAL
Definition: rz_analysis.h:408
@ RZ_ANALYSIS_OP_TYPE_RPUSH
Definition: rz_analysis.h:396
@ RZ_ANALYSIS_OP_TYPE_UJMP
Definition: rz_analysis.h:369
@ RZ_ANALYSIS_OP_TYPE_UCCALL
Definition: rz_analysis.h:384
@ RZ_ANALYSIS_OP_TYPE_ROR
Definition: rz_analysis.h:419
@ RZ_ANALYSIS_OP_TYPE_SAR
Definition: rz_analysis.h:409
@ RZ_ANALYSIS_OP_TYPE_NULL
Definition: rz_analysis.h:367
@ 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_OR
Definition: rz_analysis.h:410
@ RZ_ANALYSIS_OP_TYPE_STORE
Definition: rz_analysis.h:415
@ RZ_ANALYSIS_OP_TYPE_CRET
Definition: rz_analysis.h:386
@ RZ_ANALYSIS_OP_TYPE_SHR
Definition: rz_analysis.h:406
@ RZ_ANALYSIS_OP_TYPE_POP
Definition: rz_analysis.h:398
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_UCJMP
Definition: rz_analysis.h:377
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_ILL
Definition: rz_analysis.h:387
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_NOP
Definition: rz_analysis.h:389
@ RZ_ANALYSIS_OP_TYPE_ACMP
Definition: rz_analysis.h:400
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API const char * rz_strbuf_setf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
@ RZ_TYPE_COND_EQ
Equal.
Definition: rz_type.h:184
@ RZ_TYPE_COND_NE
Not equal.
Definition: rz_type.h:185
#define PFMT64d
Definition: rz_types.h:394
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define st8
Definition: rz_types_base.h:16
#define RZ_VERSION
Definition: rz_version.h:8
#define a(i)
Definition: sha256.c:41
#define cond(bop, top, mask, flags)
Definition: gb.h:8
ut8 mbc_id
Definition: gb.h:9
ut8 romsz_id
Definition: gb.h:10
ut8 ramsz_id
Definition: gb.h:11
Definition: z80asm.h:102
RzAnalysis * analysis
Definition: rz_analysis.h:1043
RzAnalysisEsilCallbacks cb
Definition: rz_analysis.h:1078
const char * version
Definition: rz_analysis.h:1239
RzIOBind iob
Definition: rz_analysis.h:574
RzIOReadAt read_at
Definition: rz_io.h:240
RzIO * io
Definition: rz_io.h:232
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58