1 /* Capstone Disassembler Engine */
2 /* M680X Backend by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net> 2017 */
3 
4 #include <stdio.h>
5 #include <string.h>
6 
7 #include <capstone/platform.h>
8 #include <capstone/capstone.h>
9 
10 #define WITH_DETAILS
11 
12 struct platform {
13 	cs_arch arch;
14 	cs_mode mode;
15 	unsigned char *code;
16 	size_t size;
17 	const char *comment;
18 };
19 
print_string_hex(const char * comment,unsigned char * str,size_t len)20 static void print_string_hex(const char *comment, unsigned char *str, size_t len)
21 {
22 	unsigned char *c;
23 
24 	printf("%s", comment);
25 
26 	for (c = str; c < str + len; c++)
27 		printf("0x%02x ", *c & 0xff);
28 
29 	printf("\n");
30 }
31 
print_string_hex_short(unsigned char * str,size_t len)32 static void print_string_hex_short(unsigned char *str, size_t len)
33 {
34 	unsigned char *c;
35 
36 	for (c = str; c < str + len; c++)
37 		printf("%02x", *c & 0xff);
38 }
39 
40 static const char *s_access[] = {
41 	"UNCHANGED", "READ", "WRITE", "READ | WRITE",
42 };
43 
print_read_write_regs(csh handle,cs_detail * detail)44 static void print_read_write_regs(csh handle, cs_detail *detail)
45 {
46 	int i;
47 
48 	if (detail->regs_read_count > 0) {
49 		printf("\tRegisters read:");
50 
51 		for (i = 0; i < detail->regs_read_count; ++i)
52 			printf(" %s",
53 				cs_reg_name(handle, detail->regs_read[i]));
54 
55 		printf("\n");
56 	}
57 
58 	if (detail->regs_write_count > 0) {
59 		printf("\tRegisters modified:");
60 
61 		for (i = 0; i < detail->regs_write_count; ++i)
62 			printf(" %s",
63 				cs_reg_name(handle, detail->regs_write[i]));
64 
65 		printf("\n");
66 	}
67 }
68 
print_insn_detail(csh handle,cs_insn * insn)69 static void print_insn_detail(csh handle, cs_insn *insn)
70 {
71 	cs_detail *detail = insn->detail;
72 	cs_m680x *m680x = NULL;
73 	int i;
74 
75 	// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
76 	if (detail == NULL)
77 		return;
78 
79 	m680x = &detail->m680x;
80 
81 	if (m680x->op_count)
82 		printf("\top_count: %u\n", m680x->op_count);
83 
84 	for (i = 0; i < m680x->op_count; i++) {
85 		cs_m680x_op *op = &(m680x->operands[i]);
86 		const char *comment;
87 
88 		switch ((int)op->type) {
89 		default:
90 			break;
91 
92 		case M680X_OP_REGISTER:
93 			comment = "";
94 
95 			if ((i == 0 && (m680x->flags &
96 						M680X_FIRST_OP_IN_MNEM)) ||
97 				((i == 1 && (m680x->flags &
98 							M680X_SECOND_OP_IN_MNEM))))
99 				comment = " (in mnemonic)";
100 
101 			printf("\t\toperands[%u].type: REGISTER = %s%s\n", i,
102 				cs_reg_name(handle, op->reg), comment);
103 			break;
104 
105 		case M680X_OP_CONSTANT:
106 			printf("\t\toperands[%u].type: CONSTANT = %u\n", i,
107 				op->const_val);
108 			break;
109 
110 		case M680X_OP_IMMEDIATE:
111 			printf("\t\toperands[%u].type: IMMEDIATE = #%d\n", i,
112 				op->imm);
113 			break;
114 
115 		case M680X_OP_DIRECT:
116 			printf("\t\toperands[%u].type: DIRECT = 0x%02x\n", i,
117 				op->direct_addr);
118 			break;
119 
120 		case M680X_OP_EXTENDED:
121 			printf("\t\toperands[%u].type: EXTENDED %s = 0x%04x\n",
122 				i, op->ext.indirect ? "INDIRECT" : "",
123 				op->ext.address);
124 			break;
125 
126 		case M680X_OP_RELATIVE:
127 			printf("\t\toperands[%u].type: RELATIVE = 0x%04x\n", i,
128 				op->rel.address);
129 			break;
130 
131 		case M680X_OP_INDEXED:
132 			printf("\t\toperands[%u].type: INDEXED%s\n", i,
133 				(op->idx.flags & M680X_IDX_INDIRECT) ?
134 				" INDIRECT" : "");
135 
136 			if (op->idx.base_reg != M680X_REG_INVALID)
137 				printf("\t\t\tbase register: %s\n",
138 					cs_reg_name(handle, op->idx.base_reg));
139 
140 			if (op->idx.offset_reg != M680X_REG_INVALID)
141 				printf("\t\t\toffset register: %s\n",
142 					cs_reg_name(handle, op->idx.offset_reg));
143 
144 			if ((op->idx.offset_bits != 0) &&
145 				(op->idx.offset_reg == M680X_REG_INVALID) &&
146 				!op->idx.inc_dec) {
147 				printf("\t\t\toffset: %d\n", op->idx.offset);
148 
149 				if (op->idx.base_reg == M680X_REG_PC)
150 					printf("\t\t\toffset address: 0x%x\n",
151 						op->idx.offset_addr);
152 
153 				printf("\t\t\toffset bits: %u\n",
154 					op->idx.offset_bits);
155 			}
156 
157 			if (op->idx.inc_dec) {
158 				const char *post_pre = op->idx.flags &
159 					M680X_IDX_POST_INC_DEC ? "post" : "pre";
160 				const char *inc_dec = (op->idx.inc_dec > 0) ?
161 					"increment" : "decrement";
162 
163 				printf("\t\t\t%s %s: %d\n", post_pre, inc_dec,
164 					abs(op->idx.inc_dec));
165 			}
166 
167 			break;
168 		}
169 
170 		if (op->size != 0)
171 			printf("\t\t\tsize: %u\n", op->size);
172 
173 		if (op->access != CS_AC_INVALID)
174 			printf("\t\t\taccess: %s\n", s_access[op->access]);
175 
176 	}
177 
178 	print_read_write_regs(handle, detail);
179 
180 	if (detail->groups_count) {
181 		printf("\tgroups_count: %u\n", detail->groups_count);
182 	}
183 
184 	printf("\n");
185 }
186 
consistency_checks()187 static bool consistency_checks()
188 {
189 	return true;
190 }
191 
test()192 static void test()
193 {
194 #define M6800_CODE \
195   "\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39"
196 
197 #define M6801_CODE \
198   "\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39"
199 
200 #define M6805_CODE \
201   "\x04\x7f\x00\x17\x22\x28\x00\x2e\x00\x40\x42\x5a\x70\x8e\x97\x9c" \
202   "\xa0\x15\xad\x00\xc3\x10\x00\xda\x12\x34\xe5\x7f\xfe"
203 
204 #define M6808_CODE \
205   "\x31\x22\x00\x35\x22\x45\x10\x00\x4b\x00\x51\x10\x52\x5e\x22\x62" \
206   "\x65\x12\x34\x72\x84\x85\x86\x87\x8a\x8b\x8c\x94\x95\xa7\x10\xaf\x10" \
207   "\x9e\x60\x7f\x9e\x6b\x7f\x00\x9e\xd6\x10\x00\x9e\xe6\x7f"
208 
209 #define HCS08_CODE \
210   "\x32\x10\x00\x9e\xae\x9e\xce\x7f\x9e\xbe\x10\x00\x9e\xfe\x7f" \
211   "\x3e\x10\x00\x9e\xf3\x7f\x96\x10\x00\x9e\xff\x7f\x82"
212 
213 #define M6811_CODE \
214   "\x02\x03\x12\x7f\x10\x00\x13\x99\x08\x00\x14\x7f\x02\x15\x7f\x01" \
215   "\x1e\x7f\x20\x00\x8f\xcf" \
216   "\x18\x08\x18\x30\x18\x3c\x18\x67\x18\x8c\x10\x00\x18\x8f" \
217   "\x18\xce\x10\x00\x18\xff\x10\x00" \
218   "\x1a\xa3\x7f\x1a\xac\x1a\xee\x7f\x1a\xef\x7f\xcd\xac\x7f"
219 
220 #define CPU12_CODE \
221   "\x00\x04\x01\x00\x0c\x00\x80\x0e\x00\x80\x00\x11\x1e\x10\x00\x80\x00" \
222   "\x3b\x4a\x10\x00\x04\x4b\x01\x04\x4f\x7f\x80\x00\x8f\x10\x00\xb7\x52" \
223   "\xb7\xb1\xa6\x67\xa6\xfe\xa6\xf7\x18\x02\xe2\x30\x39\xe2\x10\x00" \
224   "\x18\x0c\x30\x39\x10\x00\x18\x11\x18\x12\x10\x00\x18\x19\x00\x18\x1e\x00" \
225   "\x18\x3e\x18\x3f\x00"
226 
227 #define HD6301_CODE \
228   "\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39"
229 
230 #define M6809_CODE \
231   "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81" \
232   "\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00" \
233   "\x11\xac\x99\x10\x00\x39" \
234   \
235   "\xA6\x07\xA6\x27\xA6\x47\xA6\x67\xA6\x0F\xA6\x10" \
236   "\xA6\x80\xA6\x81\xA6\x82\xA6\x83\xA6\x84\xA6\x85\xA6\x86" \
237   "\xA6\x88\x7F\xA6\x88\x80\xA6\x89\x7F\xFF\xA6\x89\x80\x00" \
238   "\xA6\x8B\xA6\x8C\x10\xA6\x8D\x10\x00" \
239   \
240   "\xA6\x91\xA6\x93\xA6\x94\xA6\x95\xA6\x96" \
241   "\xA6\x98\x7F\xA6\x98\x80\xA6\x99\x7F\xFF\xA6\x99\x80\x00" \
242   "\xA6\x9B\xA6\x9C\x10\xA6\x9D\x10\x00\xA6\x9F\x10\x00"
243 
244 #define HD6309_CODE \
245   "\x01\x10\x10\x62\x10\x10\x7b\x10\x10\x00\xcd\x49\x96\x02\xd2" \
246   "\x10\x30\x23\x10\x38\x10\x3b\x10\x53\x10\x5d" \
247   "\x11\x30\x43\x10\x11\x37\x25\x10\x11\x38\x12\x11\x39\x23\x11\x3b\x34" \
248   "\x11\x8e\x10\x00\x11\xaf\x10\x11\xab\x10\x11\xf6\x80\x00"
249 
250 	struct platform platforms[] = {
251 		{
252 			CS_ARCH_M680X,
253 			(cs_mode)(CS_MODE_M680X_6301),
254 			(unsigned char *)HD6301_CODE,
255 			sizeof(HD6301_CODE) - 1,
256 			"M680X_HD6301",
257 		},
258 		{
259 			CS_ARCH_M680X,
260 			(cs_mode)(CS_MODE_M680X_6309),
261 			(unsigned char *)HD6309_CODE,
262 			sizeof(HD6309_CODE) - 1,
263 			"M680X_HD6309",
264 		},
265 		{
266 			CS_ARCH_M680X,
267 			(cs_mode)(CS_MODE_M680X_6800),
268 			(unsigned char *)M6800_CODE,
269 			sizeof(M6800_CODE) - 1,
270 			"M680X_M6800",
271 		},
272 		{
273 			CS_ARCH_M680X,
274 			(cs_mode)(CS_MODE_M680X_6801),
275 			(unsigned char *)M6801_CODE,
276 			sizeof(M6801_CODE) - 1,
277 			"M680X_M6801",
278 		},
279 		{
280 			CS_ARCH_M680X,
281 			(cs_mode)(CS_MODE_M680X_6805),
282 			(unsigned char *)M6805_CODE,
283 			sizeof(M6805_CODE) - 1,
284 			"M680X_M68HC05",
285 		},
286 		{
287 			CS_ARCH_M680X,
288 			(cs_mode)(CS_MODE_M680X_6808),
289 			(unsigned char *)M6808_CODE,
290 			sizeof(M6808_CODE) - 1,
291 			"M680X_M68HC08",
292 		},
293 		{
294 			CS_ARCH_M680X,
295 			(cs_mode)(CS_MODE_M680X_6809),
296 			(unsigned char *)M6809_CODE,
297 			sizeof(M6809_CODE) - 1,
298 			"M680X_M6809",
299 		},
300 		{
301 			CS_ARCH_M680X,
302 			(cs_mode)(CS_MODE_M680X_6811),
303 			(unsigned char *)M6811_CODE,
304 			sizeof(M6811_CODE) - 1,
305 			"M680X_M68HC11",
306 		},
307 		{
308 			CS_ARCH_M680X,
309 			(cs_mode)(CS_MODE_M680X_CPU12),
310 			(unsigned char *)CPU12_CODE,
311 			sizeof(CPU12_CODE) - 1,
312 			"M680X_CPU12",
313 		},
314 		{
315 			CS_ARCH_M680X,
316 			(cs_mode)(CS_MODE_M680X_HCS08),
317 			(unsigned char *)HCS08_CODE,
318 			sizeof(HCS08_CODE) - 1,
319 			"M680X_HCS08",
320 		},
321 	};
322 
323 	uint64_t address = 0x1000;
324 	csh handle;
325 	cs_insn *insn;
326 	int i;
327 	size_t count;
328 	const char *nine_spaces = "         ";
329 
330 	if (!consistency_checks())
331 		abort();
332 
333 	for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
334 		cs_err err = cs_open(platforms[i].arch, platforms[i].mode,
335 				&handle);
336 
337 		if (err) {
338 			printf("Failed on cs_open() with error returned: %u\n",
339 				err);
340 			abort();
341 		}
342 
343 #ifdef WITH_DETAILS
344 		cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
345 #endif
346 
347 		count = cs_disasm(handle, platforms[i].code, platforms[i].size,
348 				address, 0, &insn);
349 
350 		if (count) {
351 			size_t j;
352 
353 			printf("********************\n");
354 			printf("Platform: %s\n", platforms[i].comment);
355 			print_string_hex("Code: ", platforms[i].code,
356 				platforms[i].size);
357 			printf("Disasm:\n");
358 
359 			for (j = 0; j < count; j++) {
360 				int slen;
361 				printf("0x%04x: ", (uint16_t)insn[j].address);
362 				print_string_hex_short(insn[j].bytes,
363 					insn[j].size);
364 				printf("%.*s", 1 + ((5 - insn[j].size) * 2),
365 					nine_spaces);
366 				printf("%s", insn[j].mnemonic);
367 				slen = (int)strlen(insn[j].mnemonic);
368 				printf("%.*s", 1 + (5 - slen), nine_spaces);
369 				printf("%s\n", insn[j].op_str);
370 #ifdef WITH_DETAILS
371 				print_insn_detail(handle, &insn[j]);
372 #endif
373 			}
374 
375 			// free memory allocated by cs_disasm()
376 			cs_free(insn, count);
377 		}
378 		else {
379 			printf("********************\n");
380 			printf("Platform: %s\n", platforms[i].comment);
381 			print_string_hex("Code:", platforms[i].code,
382 				platforms[i].size);
383 			printf("ERROR: Failed to disasm given code!\n");
384 			abort();
385 		}
386 
387 		cs_close(&handle);
388 	}
389 }
390 
main()391 int main()
392 {
393 	test();
394 
395 	return 0;
396 }
397