1 /* radare2 - LGPL - Copyright 2015-2019 - pancake */
2
3 #include <r_asm.h>
4 #include <r_lib.h>
5 #include <capstone.h>
6
7 #if CS_API_MAJOR >= 4 && CS_API_MINOR >= 0
8 #define CAPSTONE_HAS_M680X 1
9 #else
10 #define CAPSTONE_HAS_M680X 0
11 #endif
12
13 #if !CAPSTONE_HAS_M680X
14 #ifdef _MSC_VER
15 #pragma message ("Cannot find support for m680x in capstone")
16 #else
17 #warning Cannot find capstone-m680x support
18 #endif
19 #endif
20
21 #if CAPSTONE_HAS_M680X
22 #include <m680x.h>
23
m680xmode(const char * str)24 static int m680xmode(const char *str) {
25 if (!str) {
26 return CS_MODE_M680X_6800;
27 }
28 // replace this with the asm.features?
29 if (str && strstr (str, "6800")) {
30 return CS_MODE_M680X_6800;
31 }
32 if (str && strstr (str, "6801")) {
33 return CS_MODE_M680X_6801;
34 } else if (str && strstr (str, "6805")) {
35 return CS_MODE_M680X_6805;
36 } else if (str && strstr (str, "6808")) {
37 return CS_MODE_M680X_6808;
38 } else if (str && strstr (str, "6809")) {
39 return CS_MODE_M680X_6809;
40 } else if (str && strstr (str, "6811")) {
41 return CS_MODE_M680X_6811;
42 }
43 //
44 if (str && strstr (str, "cpu12")) {
45 return CS_MODE_M680X_CPU12;
46 }
47 if (str && strstr (str, "6301")) {
48 return CS_MODE_M680X_6301;
49 }
50 if (str && strstr (str, "6309")) {
51 return CS_MODE_M680X_6309;
52 }
53 if (str && strstr (str, "hcs08")) {
54 return CS_MODE_M680X_HCS08;
55 }
56 return CS_MODE_M680X_6800;
57 }
58
59 #define IMM(x) insn->detail->m680x.operands[x].imm
60 #define REL(x) insn->detail->m680x.operands[x].rel
61
analop(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,RAnalOpMask mask)62 static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
63 int n, ret, opsize = -1;
64 static csh handle = 0;
65 static int omode = -1;
66 static int obits = 32;
67 cs_insn* insn;
68
69 int mode = m680xmode (a->cpu);
70
71 if (mode != omode || a->bits != obits) {
72 cs_close (&handle);
73 handle = 0;
74 omode = mode;
75 obits = a->bits;
76 }
77 op->size = 4;
78 if (handle == 0) {
79 ret = cs_open (CS_ARCH_M680X, mode, &handle);
80 if (ret != CS_ERR_OK) {
81 goto fin;
82 }
83 cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON);
84 }
85 n = cs_disasm (handle, (ut8*)buf, len, addr, 1, &insn);
86 if (n < 1 || insn->size < 1) {
87 op->type = R_ANAL_OP_TYPE_ILL;
88 op->size = 2;
89 opsize = -1;
90 goto beach;
91 }
92 if (!memcmp (buf, "\xff\xff", R_MIN (len, 2))) {
93 op->type = R_ANAL_OP_TYPE_ILL;
94 op->size = 2;
95 opsize = -1;
96 goto beach;
97 }
98 op->id = insn->id;
99 opsize = op->size = insn->size;
100 switch (insn->id) {
101 case M680X_INS_INVLD:
102 op->type = R_ANAL_OP_TYPE_ILL;
103 break;
104 case M680X_INS_ABA: ///< M6800/1/2/3
105 case M680X_INS_ABX:
106 case M680X_INS_ABY:
107 break;
108 case M680X_INS_ADC:
109 case M680X_INS_ADCA:
110 case M680X_INS_ADCB:
111 case M680X_INS_ADCD:
112 case M680X_INS_ADCR:
113 case M680X_INS_ADD:
114 case M680X_INS_ADDA:
115 case M680X_INS_ADDB:
116 case M680X_INS_ADDD:
117 case M680X_INS_ADDE:
118 case M680X_INS_ADDF:
119 case M680X_INS_ADDR:
120 case M680X_INS_ADDW:
121 op->type = R_ANAL_OP_TYPE_ADD;
122 break;
123 case M680X_INS_AIM:
124 case M680X_INS_AIS:
125 case M680X_INS_AIX:
126 case M680X_INS_AND:
127 case M680X_INS_ANDA:
128 case M680X_INS_ANDB:
129 case M680X_INS_ANDCC:
130 case M680X_INS_ANDD:
131 case M680X_INS_ANDR:
132 case M680X_INS_ASL:
133 case M680X_INS_ASLA:
134 case M680X_INS_ASLB:
135 case M680X_INS_ASLD: ///< or LSLD
136 case M680X_INS_ASR:
137 case M680X_INS_ASRA:
138 case M680X_INS_ASRB:
139 case M680X_INS_ASRD:
140 case M680X_INS_ASRX:
141 case M680X_INS_BAND:
142 case M680X_INS_BCC: ///< or BHS
143 case M680X_INS_BCLR:
144 case M680X_INS_BCS: ///< or BLO
145 case M680X_INS_BEOR:
146 break;
147 case M680X_INS_BIAND:
148 case M680X_INS_BIEOR:
149 case M680X_INS_BIH:
150 case M680X_INS_BIL:
151 case M680X_INS_BIOR:
152 case M680X_INS_BIT:
153 case M680X_INS_BITA:
154 case M680X_INS_BITB:
155 case M680X_INS_BITD:
156 case M680X_INS_BITMD:
157 break;
158 case M680X_INS_BRA:
159 op->type = R_ANAL_OP_TYPE_JMP;
160 op->jump = addr + op->size + REL(0).offset;
161 op->fail = UT64_MAX;
162 break;
163 case M680X_INS_BEQ:
164 case M680X_INS_BGE:
165 case M680X_INS_BGND:
166 case M680X_INS_BGT:
167 case M680X_INS_BHCC:
168 case M680X_INS_BHCS:
169 case M680X_INS_BHI:
170 case M680X_INS_BLE:
171 case M680X_INS_BLS:
172 case M680X_INS_BLT:
173 case M680X_INS_BMC:
174 case M680X_INS_BMI:
175 case M680X_INS_BMS:
176 case M680X_INS_BNE:
177 case M680X_INS_BOR:
178 case M680X_INS_BPL:
179 case M680X_INS_BRCLR:
180 case M680X_INS_BRSET:
181 case M680X_INS_BRN:
182 case M680X_INS_BSET:
183 case M680X_INS_BSR:
184 case M680X_INS_BVC:
185 case M680X_INS_BVS:
186 op->type = R_ANAL_OP_TYPE_CJMP;
187 op->jump = addr + op->size + REL(0).offset;
188 op->fail = addr + op->size;
189 break;
190 case M680X_INS_CALL:
191 case M680X_INS_CBA: ///< M6800/1/2/3
192 case M680X_INS_CBEQ:
193 case M680X_INS_CBEQA:
194 case M680X_INS_CBEQX:
195 case M680X_INS_CLC: ///< M6800/1/2/3
196 case M680X_INS_CLI: ///< M6800/1/2/3
197 case M680X_INS_CLR:
198 case M680X_INS_CLRA:
199 case M680X_INS_CLRB:
200 case M680X_INS_CLRD:
201 case M680X_INS_CLRE:
202 case M680X_INS_CLRF:
203 case M680X_INS_CLRH:
204 case M680X_INS_CLRW:
205 case M680X_INS_CLRX:
206 case M680X_INS_CLV: ///< M6800/1/2/3
207 break;
208 case M680X_INS_CMP:
209 case M680X_INS_CMPA:
210 case M680X_INS_CMPB:
211 case M680X_INS_CMPD:
212 case M680X_INS_CMPE:
213 case M680X_INS_CMPF:
214 case M680X_INS_CMPR:
215 case M680X_INS_CMPS:
216 case M680X_INS_CMPU:
217 case M680X_INS_CMPW:
218 case M680X_INS_CMPX:
219 case M680X_INS_CMPY:
220 op->type = R_ANAL_OP_TYPE_CMP;
221 break;
222 case M680X_INS_COM:
223 case M680X_INS_COMA:
224 case M680X_INS_COMB:
225 case M680X_INS_COMD:
226 case M680X_INS_COME:
227 case M680X_INS_COMF:
228 case M680X_INS_COMW:
229 case M680X_INS_COMX:
230 case M680X_INS_CPD:
231 case M680X_INS_CPHX:
232 case M680X_INS_CPS:
233 case M680X_INS_CPX: ///< M6800/1/2/3
234 case M680X_INS_CPY:
235 case M680X_INS_CWAI:
236 case M680X_INS_DAA:
237 case M680X_INS_DBEQ:
238 case M680X_INS_DBNE:
239 case M680X_INS_DBNZ:
240 case M680X_INS_DBNZA:
241 case M680X_INS_DBNZX:
242 case M680X_INS_DEC:
243 case M680X_INS_DECA:
244 case M680X_INS_DECB:
245 case M680X_INS_DECD:
246 case M680X_INS_DECE:
247 case M680X_INS_DECF:
248 case M680X_INS_DECW:
249 case M680X_INS_DECX:
250 case M680X_INS_DES: ///< M6800/1/2/3
251 case M680X_INS_DEX: ///< M6800/1/2/3
252 case M680X_INS_DEY:
253 case M680X_INS_DIV:
254 case M680X_INS_DIVD:
255 case M680X_INS_DIVQ:
256 case M680X_INS_EDIV:
257 case M680X_INS_EDIVS:
258 case M680X_INS_EIM:
259 case M680X_INS_EMACS:
260 case M680X_INS_EMAXD:
261 case M680X_INS_EMAXM:
262 case M680X_INS_EMIND:
263 case M680X_INS_EMINM:
264 break;
265 case M680X_INS_EMUL:
266 case M680X_INS_EMULS:
267 op->type = R_ANAL_OP_TYPE_MUL;
268 break;
269 case M680X_INS_EOR:
270 case M680X_INS_EORA:
271 case M680X_INS_EORB:
272 case M680X_INS_EORD:
273 case M680X_INS_EORR:
274 op->type = R_ANAL_OP_TYPE_XOR;
275 break;
276 case M680X_INS_ETBL:
277 case M680X_INS_EXG:
278 case M680X_INS_FDIV:
279 case M680X_INS_IBEQ:
280 case M680X_INS_IBNE:
281 break;
282 case M680X_INS_IDIV:
283 case M680X_INS_IDIVS:
284 op->type = R_ANAL_OP_TYPE_DIV;
285 break;
286 case M680X_INS_ILLGL:
287 break;
288 case M680X_INS_INC:
289 case M680X_INS_INCA:
290 case M680X_INS_INCB:
291 case M680X_INS_INCD:
292 case M680X_INS_INCE:
293 case M680X_INS_INCF:
294 case M680X_INS_INCW:
295 case M680X_INS_INCX:
296 op->type = R_ANAL_OP_TYPE_ADD;
297 break;
298 case M680X_INS_INS: ///< M6800/1/2/3
299 case M680X_INS_INX: ///< M6800/1/2/3
300 case M680X_INS_INY:
301 break;
302 case M680X_INS_JMP:
303 op->type = R_ANAL_OP_TYPE_JMP;
304 break;
305 case M680X_INS_JSR:
306 op->type = R_ANAL_OP_TYPE_RJMP;
307 break;
308 case M680X_INS_LBCC: ///< or LBHS
309 case M680X_INS_LBCS: ///< or LBLO
310 case M680X_INS_LBEQ:
311 case M680X_INS_LBGE:
312 case M680X_INS_LBGT:
313 case M680X_INS_LBHI:
314 case M680X_INS_LBLE:
315 case M680X_INS_LBLS:
316 case M680X_INS_LBLT:
317 case M680X_INS_LBMI:
318 case M680X_INS_LBNE:
319 case M680X_INS_LBPL:
320 case M680X_INS_LBRA:
321 case M680X_INS_LBRN:
322 case M680X_INS_LBSR:
323 case M680X_INS_LBVC:
324 case M680X_INS_LBVS:
325 case M680X_INS_LDA:
326 case M680X_INS_LDAA: ///< M6800/1/2/3
327 case M680X_INS_LDAB: ///< M6800/1/2/3
328 case M680X_INS_LDB:
329 case M680X_INS_LDBT:
330 case M680X_INS_LDD:
331 case M680X_INS_LDE:
332 case M680X_INS_LDF:
333 case M680X_INS_LDHX:
334 case M680X_INS_LDMD:
335 case M680X_INS_LDQ:
336 case M680X_INS_LDS:
337 case M680X_INS_LDU:
338 case M680X_INS_LDW:
339 case M680X_INS_LDX:
340 case M680X_INS_LDY:
341 case M680X_INS_LEAS:
342 case M680X_INS_LEAU:
343 case M680X_INS_LEAX:
344 case M680X_INS_LEAY:
345 case M680X_INS_LSL:
346 case M680X_INS_LSLA:
347 case M680X_INS_LSLB:
348 case M680X_INS_LSLD:
349 case M680X_INS_LSLX:
350 case M680X_INS_LSR:
351 case M680X_INS_LSRA:
352 case M680X_INS_LSRB:
353 case M680X_INS_LSRD: ///< or ASRD
354 case M680X_INS_LSRW:
355 case M680X_INS_LSRX:
356 case M680X_INS_MAXA:
357 case M680X_INS_MAXM:
358 case M680X_INS_MEM:
359 case M680X_INS_MINA:
360 case M680X_INS_MINM:
361 break;
362 case M680X_INS_MOV:
363 case M680X_INS_MOVB:
364 case M680X_INS_MOVW:
365 op->type = R_ANAL_OP_TYPE_MOV;
366 break;
367 case M680X_INS_MUL:
368 case M680X_INS_MULD:
369 op->type = R_ANAL_OP_TYPE_MUL;
370 break;
371 case M680X_INS_NEG:
372 case M680X_INS_NEGA:
373 case M680X_INS_NEGB:
374 case M680X_INS_NEGD:
375 case M680X_INS_NEGX:
376 op->type = R_ANAL_OP_TYPE_NOT;
377 break;
378 case M680X_INS_NOP:
379 op->type = R_ANAL_OP_TYPE_NOP;
380 break;
381 case M680X_INS_NSA:
382 case M680X_INS_OIM:
383 case M680X_INS_ORA:
384 case M680X_INS_ORAA: ///< M6800/1/2/3
385 case M680X_INS_ORAB: ///< M6800/1/2/3
386 case M680X_INS_ORB:
387 case M680X_INS_ORCC:
388 case M680X_INS_ORD:
389 case M680X_INS_ORR:
390 case M680X_INS_PSHA: ///< M6800/1/2/3
391 case M680X_INS_PSHB: ///< M6800/1/2/3
392 case M680X_INS_PSHC:
393 case M680X_INS_PSHD:
394 case M680X_INS_PSHH:
395 case M680X_INS_PSHS:
396 case M680X_INS_PSHSW:
397 case M680X_INS_PSHU:
398 case M680X_INS_PSHUW:
399 case M680X_INS_PSHX: ///< M6800/1/2/3
400 case M680X_INS_PSHY:
401 case M680X_INS_PULA: ///< M6800/1/2/3
402 case M680X_INS_PULB: ///< M6800/1/2/3
403 case M680X_INS_PULC:
404 case M680X_INS_PULD:
405 case M680X_INS_PULH:
406 case M680X_INS_PULS:
407 case M680X_INS_PULSW:
408 case M680X_INS_PULU:
409 case M680X_INS_PULUW:
410 case M680X_INS_PULX: ///< M6800/1/2/3
411 case M680X_INS_PULY:
412 case M680X_INS_REV:
413 case M680X_INS_REVW:
414 case M680X_INS_ROL:
415 case M680X_INS_ROLA:
416 case M680X_INS_ROLB:
417 case M680X_INS_ROLD:
418 case M680X_INS_ROLW:
419 case M680X_INS_ROLX:
420 case M680X_INS_ROR:
421 case M680X_INS_RORA:
422 case M680X_INS_RORB:
423 case M680X_INS_RORD:
424 case M680X_INS_RORW:
425 case M680X_INS_RORX:
426 case M680X_INS_RSP:
427 case M680X_INS_RTC:
428 case M680X_INS_RTI:
429 case M680X_INS_RTS:
430 case M680X_INS_SBA: ///< M6800/1/2/3
431 case M680X_INS_SBC:
432 case M680X_INS_SBCA:
433 case M680X_INS_SBCB:
434 case M680X_INS_SBCD:
435 case M680X_INS_SBCR:
436 case M680X_INS_SEC:
437 case M680X_INS_SEI:
438 case M680X_INS_SEV:
439 case M680X_INS_SEX:
440 case M680X_INS_SEXW:
441 case M680X_INS_SLP:
442 case M680X_INS_STA:
443 case M680X_INS_STAA: ///< M6800/1/2/3
444 case M680X_INS_STAB: ///< M6800/1/2/3
445 case M680X_INS_STB:
446 case M680X_INS_STBT:
447 case M680X_INS_STD:
448 case M680X_INS_STE:
449 case M680X_INS_STF:
450 case M680X_INS_STOP:
451 case M680X_INS_STHX:
452 case M680X_INS_STQ:
453 case M680X_INS_STS:
454 case M680X_INS_STU:
455 case M680X_INS_STW:
456 case M680X_INS_STX:
457 case M680X_INS_STY:
458 case M680X_INS_SUB:
459 case M680X_INS_SUBA:
460 case M680X_INS_SUBB:
461 case M680X_INS_SUBD:
462 case M680X_INS_SUBE:
463 case M680X_INS_SUBF:
464 case M680X_INS_SUBR:
465 case M680X_INS_SUBW:
466 op->type = R_ANAL_OP_TYPE_SUB;
467 break;
468 case M680X_INS_SWI:
469 case M680X_INS_SWI2:
470 case M680X_INS_SWI3:
471 op->type = R_ANAL_OP_TYPE_SWI;
472 break;
473 case M680X_INS_SYNC:
474 case M680X_INS_TAB: ///< M6800/1/2/3
475 case M680X_INS_TAP: ///< M6800/1/2/3
476 case M680X_INS_TAX:
477 break;
478 case M680X_INS_TBA: ///< M6800/1/2/3
479 case M680X_INS_TBEQ:
480 case M680X_INS_TBL:
481 case M680X_INS_TBNE:
482 case M680X_INS_TEST:
483 case M680X_INS_TFM:
484 case M680X_INS_TFR:
485 case M680X_INS_TIM:
486 case M680X_INS_TPA: ///< M6800/1/2/3
487 case M680X_INS_TST:
488 case M680X_INS_TSTA:
489 case M680X_INS_TSTB:
490 case M680X_INS_TSTD:
491 case M680X_INS_TSTE:
492 case M680X_INS_TSTF:
493 case M680X_INS_TSTW:
494 case M680X_INS_TSTX:
495 op->type = R_ANAL_OP_TYPE_CMP;
496 break;
497 case M680X_INS_TSX: ///< M6800/1/2/3
498 case M680X_INS_TSY:
499 case M680X_INS_TXA:
500 case M680X_INS_TXS: ///< M6800/1/2/3
501 case M680X_INS_TYS:
502 case M680X_INS_WAI: ///< M6800/1/2/3
503 case M680X_INS_WAIT:
504 case M680X_INS_WAV:
505 case M680X_INS_WAVR:
506 case M680X_INS_XGDX: ///< HD6301
507 case M680X_INS_XGDY:
508 break;
509 }
510 beach:
511 cs_free (insn, n);
512 //cs_close (&handle);
513 fin:
514 return opsize;
515 }
516
517 // XXX
set_reg_profile(RAnal * anal)518 static bool set_reg_profile(RAnal *anal) {
519 const char *p = \
520 "=PC pc\n"
521 "=SP sp\n"
522 "=A0 a0\n"
523 "=A1 a1\n"
524 "gpr pc .16 48 0\n"
525 "gpr sp .16 48 0\n"
526 "gpr a0 .16 48 0\n"
527 "gpr a1 .16 48 0\n";
528 return r_reg_set_profile_string (anal->reg, p);
529 }
530
531 RAnalPlugin r_anal_plugin_m680x_cs = {
532 .name = "m680x",
533 .desc = "Capstone M680X analysis plugin",
534 .license = "BSD",
535 .esil = false,
536 .arch = "m680x",
537 .set_reg_profile = &set_reg_profile,
538 .bits = 16 | 32,
539 .op = &analop,
540 };
541 #else
542 RAnalPlugin r_anal_plugin_m680x_cs = {
543 .name = "m680x (unsupported)",
544 .desc = "Capstone M680X analyzer (unsupported)",
545 .license = "BSD",
546 .arch = "m680x",
547 .bits = 32,
548 };
549 #endif
550
551 #ifndef R2_PLUGIN_INCORE
552 R_API RLibStruct radare_plugin = {
553 .type = R_LIB_TYPE_ANAL,
554 .data = &r_anal_plugin_m680x_cs,
555 .version = R2_VERSION
556 };
557 #endif
558