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