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