1 /* Capstone Disassembly Engine */
2 /* M680X Backend by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net> 2017 */
3 
4 /* ======================================================================== */
5 /* ================================ INCLUDES ============================== */
6 /* ======================================================================== */
7 
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 
12 #include "../../cs_priv.h"
13 #include "../../utils.h"
14 
15 #include "../../MCInst.h"
16 #include "../../MCInstrDesc.h"
17 #include "../../MCRegisterInfo.h"
18 #include "M680XInstPrinter.h"
19 #include "M680XDisassembler.h"
20 #include "M680XDisassemblerInternals.h"
21 
22 #ifdef CAPSTONE_HAS_M680X
23 
24 #ifndef DECL_SPEC
25 #ifdef _MSC_VER
26 #define DECL_SPEC __cdecl
27 #else
28 #define DECL_SPEC
29 #endif  // _MSC_VER
30 #endif  // DECL_SPEC
31 
32 /* ======================================================================== */
33 /* ============================ GENERAL DEFINES =========================== */
34 /* ======================================================================== */
35 
36 /* ======================================================================== */
37 /* =============================== PROTOTYPES ============================= */
38 /* ======================================================================== */
39 
40 typedef enum insn_hdlr_id {
41 	illgl_hid,
42 	rel8_hid,
43 	rel16_hid,
44 	imm8_hid,
45 	imm16_hid,
46 	imm32_hid,
47 	dir_hid,
48 	ext_hid,
49 	idxX_hid,
50 	idxY_hid,
51 	idx09_hid,
52 	inh_hid,
53 	rr09_hid,
54 	rbits_hid,
55 	bitmv_hid,
56 	tfm_hid,
57 	opidx_hid,
58 	opidxdr_hid,
59 	idxX0_hid,
60 	idxX16_hid,
61 	imm8rel_hid,
62 	idxS_hid,
63 	idxS16_hid,
64 	idxXp_hid,
65 	idxX0p_hid,
66 	idx12_hid,
67 	idx12s_hid,
68 	rr12_hid,
69 	loop_hid,
70 	index_hid,
71 	imm8i12x_hid,
72 	imm16i12x_hid,
73 	exti12x_hid,
74 	HANDLER_ID_ENDING,
75 } insn_hdlr_id;
76 
77 // Access modes for the first 4 operands. If there are more than
78 // four operands they use the same access mode as the 4th operand.
79 //
80 // u: unchanged
81 // r: (r)read access
82 // w: (w)write access
83 // m: (m)odify access (= read + write)
84 //
85 typedef enum e_access_mode {
86 
87 	uuuu,
88 	rrrr,
89 	wwww,
90 	rwww,
91 	rrrm,
92 	rmmm,
93 	wrrr,
94 	mrrr,
95 	mwww,
96 	mmmm,
97 	mwrr,
98 	mmrr,
99 	wmmm,
100 	rruu,
101 	muuu,
102 	ACCESS_MODE_ENDING,
103 } e_access_mode;
104 
105 // Access type values are compatible with enum cs_ac_type:
106 typedef enum e_access {
107 	UNCHANGED = CS_AC_INVALID,
108 	READ = CS_AC_READ,
109 	WRITE = CS_AC_WRITE,
110 	MODIFY = (CS_AC_READ | CS_AC_WRITE),
111 } e_access;
112 
113 /* Properties of one instruction in PAGE1 (without prefix) */
114 typedef struct inst_page1 {
115 	unsigned insn : 9;        // A value of type m680x_insn
116 	unsigned handler_id1 : 6; // Type insn_hdlr_id, first instr. handler id
117 	unsigned handler_id2 : 6; // Type insn_hdlr_id, second instr. handler id
118 } inst_page1;
119 
120 /* Properties of one instruction in any other PAGE X */
121 typedef struct inst_pageX {
122 	unsigned opcode : 8;      // The opcode byte
123 	unsigned insn : 9;        // A value of type m680x_insn
124 	unsigned handler_id1 : 6; // Type insn_hdlr_id, first instr. handler id
125 	unsigned handler_id2 : 6; // Type insn_hdlr_id, second instr. handler id
126 } inst_pageX;
127 
128 typedef struct insn_props {
129 	unsigned group : 4;
130 	unsigned access_mode : 5; // A value of type e_access_mode
131 	unsigned reg0 : 5;        // A value of type m680x_reg
132 	unsigned reg1 : 5;        // A value of type m680x_reg
133 	bool cc_modified : 1;
134 	bool update_reg_access : 1;
135 } insn_props;
136 
137 #include "m6800.inc"
138 #include "m6801.inc"
139 #include "hd6301.inc"
140 #include "m6811.inc"
141 #include "cpu12.inc"
142 #include "m6805.inc"
143 #include "m6808.inc"
144 #include "hcs08.inc"
145 #include "m6809.inc"
146 #include "hd6309.inc"
147 
148 #include "insn_props.inc"
149 
150 //////////////////////////////////////////////////////////////////////////////
151 
152 // M680X instuctions have 1 up to 8 bytes (CPU12: MOVW IDX2,IDX2).
153 // A reader is needed to read a byte or word from a given memory address.
154 // See also X86 reader(...)
read_byte(const m680x_info * info,uint8_t * byte,uint16_t address)155 static bool read_byte(const m680x_info *info, uint8_t *byte, uint16_t address)
156 {
157 	if (address < info->offset ||
158 		(uint32_t)(address - info->offset) >= info->size)
159 		// out of code buffer range
160 		return false;
161 
162 	*byte = info->code[address - info->offset];
163 
164 	return true;
165 }
166 
read_byte_sign_extended(const m680x_info * info,int16_t * word,uint16_t address)167 static bool read_byte_sign_extended(const m680x_info *info, int16_t *word,
168 	uint16_t address)
169 {
170 	if (address < info->offset ||
171 		(uint32_t)(address - info->offset) >= info->size)
172 		// out of code buffer range
173 		return false;
174 
175 	*word = (int16_t) info->code[address - info->offset];
176 
177 	if (*word & 0x80)
178 		*word |= 0xFF00;
179 
180 	return true;
181 }
182 
read_word(const m680x_info * info,uint16_t * word,uint16_t address)183 static bool read_word(const m680x_info *info, uint16_t *word, uint16_t address)
184 {
185 	if (address < info->offset ||
186 		(uint32_t)(address + 1 - info->offset) >= info->size)
187 		// out of code buffer range
188 		return false;
189 
190 	*word = (uint16_t)info->code[address - info->offset] << 8;
191 	*word |= (uint16_t)info->code[address + 1 - info->offset];
192 
193 	return true;
194 }
195 
read_sdword(const m680x_info * info,int32_t * sdword,uint16_t address)196 static bool read_sdword(const m680x_info *info, int32_t *sdword,
197 	uint16_t address)
198 {
199 	if (address < info->offset ||
200 		(uint32_t)(address + 3 - info->offset) >= info->size)
201 		// out of code buffer range
202 		return false;
203 
204 	*sdword = (uint32_t)info->code[address - info->offset] << 24;
205 	*sdword |= (uint32_t)info->code[address + 1 - info->offset] << 16;
206 	*sdword |= (uint32_t)info->code[address + 2 - info->offset] << 8;
207 	*sdword |= (uint32_t)info->code[address + 3 - info->offset];
208 
209 	return true;
210 }
211 
212 // For PAGE2 and PAGE3 opcodes when using an an array of inst_page1 most
213 // entries have M680X_INS_ILLGL. To avoid wasting memory an inst_pageX is
214 // used which contains the opcode. Using a binary search for the right opcode
215 // is much faster (= O(log n) ) in comparison to a linear search ( = O(n) ).
binary_search(const inst_pageX * const inst_pageX_table,size_t table_size,unsigned int opcode)216 static int binary_search(const inst_pageX *const inst_pageX_table,
217 	size_t table_size, unsigned int opcode)
218 {
219 	// As part of the algorithm last may get negative.
220 	// => signed integer has to be used.
221 	int first = 0;
222 	int last = (int)table_size - 1;
223 	int middle = (first + last) / 2;
224 
225 	while (first <= last) {
226 		if (inst_pageX_table[middle].opcode < opcode) {
227 			first = middle + 1;
228 		}
229 		else if (inst_pageX_table[middle].opcode == opcode) {
230 			return middle;  /* item found */
231 		}
232 		else
233 			last = middle - 1;
234 
235 		middle = (first + last) / 2;
236 	}
237 
238 	if (first > last)
239 		return -1;  /* item not found */
240 
241 	return -2;
242 }
243 
M680X_get_insn_id(cs_struct * handle,cs_insn * insn,unsigned int id)244 void M680X_get_insn_id(cs_struct *handle, cs_insn *insn, unsigned int id)
245 {
246 	const m680x_info *const info = (const m680x_info *)handle->printer_info;
247 	const cpu_tables *cpu = info->cpu;
248 	uint8_t insn_prefix = (id >> 8) & 0xff;
249 	// opcode is the first instruction byte without the prefix.
250 	uint8_t opcode = id & 0xff;
251 	int index;
252 	int i;
253 
254 	insn->id = M680X_INS_ILLGL;
255 
256 	for (i = 0; i < ARR_SIZE(cpu->pageX_prefix); ++i) {
257 		if (cpu->pageX_table_size[i] == 0 ||
258 			(cpu->inst_pageX_table[i] == NULL))
259 			break;
260 
261 		if (cpu->pageX_prefix[i] == insn_prefix) {
262 			index = binary_search(cpu->inst_pageX_table[i],
263 					cpu->pageX_table_size[i], opcode);
264 			insn->id = (index >= 0) ?
265 				cpu->inst_pageX_table[i][index].insn :
266 				M680X_INS_ILLGL;
267 			return;
268 		}
269 	}
270 
271 	if (insn_prefix != 0)
272 		return;
273 
274 	insn->id = cpu->inst_page1_table[id].insn;
275 
276 	if (insn->id != M680X_INS_ILLGL)
277 		return;
278 
279 	// Check if opcode byte is present in an overlay table
280 	for (i = 0; i < ARR_SIZE(cpu->overlay_table_size); ++i) {
281 		if (cpu->overlay_table_size[i] == 0 ||
282 			(cpu->inst_overlay_table[i] == NULL))
283 			break;
284 
285 		if ((index = binary_search(cpu->inst_overlay_table[i],
286 						cpu->overlay_table_size[i],
287 						opcode)) >= 0) {
288 			insn->id = cpu->inst_overlay_table[i][index].insn;
289 			return;
290 		}
291 	}
292 }
293 
add_insn_group(cs_detail * detail,m680x_group_type group)294 static void add_insn_group(cs_detail *detail, m680x_group_type group)
295 {
296 	if (detail != NULL &&
297 		(group != M680X_GRP_INVALID) && (group != M680X_GRP_ENDING))
298 		detail->groups[detail->groups_count++] = (uint8_t)group;
299 }
300 
exists_reg_list(uint16_t * regs,uint8_t count,m680x_reg reg)301 static bool exists_reg_list(uint16_t *regs, uint8_t count, m680x_reg reg)
302 {
303 	uint8_t i;
304 
305 	for (i = 0; i < count; ++i) {
306 		if (regs[i] == (uint16_t)reg)
307 			return true;
308 	}
309 
310 	return false;
311 }
312 
add_reg_to_rw_list(MCInst * MI,m680x_reg reg,e_access access)313 static void add_reg_to_rw_list(MCInst *MI, m680x_reg reg, e_access access)
314 {
315 	cs_detail *detail = MI->flat_insn->detail;
316 
317 	if (detail == NULL || (reg == M680X_REG_INVALID))
318 		return;
319 
320 	switch (access) {
321 	case MODIFY:
322 		if (!exists_reg_list(detail->regs_read,
323 				detail->regs_read_count, reg))
324 			detail->regs_read[detail->regs_read_count++] =
325 				(uint16_t)reg;
326 
327 	// intentionally fall through
328 
329 	case WRITE:
330 		if (!exists_reg_list(detail->regs_write,
331 				detail->regs_write_count, reg))
332 			detail->regs_write[detail->regs_write_count++] =
333 				(uint16_t)reg;
334 
335 		break;
336 
337 	case READ:
338 		if (!exists_reg_list(detail->regs_read,
339 				detail->regs_read_count, reg))
340 			detail->regs_read[detail->regs_read_count++] =
341 				(uint16_t)reg;
342 
343 		break;
344 
345 	case UNCHANGED:
346 	default:
347 		break;
348 	}
349 }
350 
update_am_reg_list(MCInst * MI,m680x_info * info,cs_m680x_op * op,e_access access)351 static void update_am_reg_list(MCInst *MI, m680x_info *info, cs_m680x_op *op,
352 	e_access access)
353 {
354 	if (MI->flat_insn->detail == NULL)
355 		return;
356 
357 	switch (op->type) {
358 	case M680X_OP_REGISTER:
359 		add_reg_to_rw_list(MI, op->reg, access);
360 		break;
361 
362 	case M680X_OP_INDEXED:
363 		add_reg_to_rw_list(MI, op->idx.base_reg, READ);
364 
365 		if (op->idx.base_reg == M680X_REG_X &&
366 			info->cpu->reg_byte_size[M680X_REG_H])
367 			add_reg_to_rw_list(MI, M680X_REG_H, READ);
368 
369 
370 		if (op->idx.offset_reg != M680X_REG_INVALID)
371 			add_reg_to_rw_list(MI, op->idx.offset_reg, READ);
372 
373 		if (op->idx.inc_dec) {
374 			add_reg_to_rw_list(MI, op->idx.base_reg, WRITE);
375 
376 			if (op->idx.base_reg == M680X_REG_X &&
377 				info->cpu->reg_byte_size[M680X_REG_H])
378 				add_reg_to_rw_list(MI, M680X_REG_H, WRITE);
379 		}
380 
381 		break;
382 
383 	default:
384 		break;
385 	}
386 }
387 
388 static const e_access g_access_mode_to_access[4][15] = {
389 	{
390 		UNCHANGED, READ, WRITE, READ,  READ, READ,   WRITE, MODIFY,
391 		MODIFY, MODIFY, MODIFY, MODIFY, WRITE, READ, MODIFY,
392 	},
393 	{
394 		UNCHANGED, READ, WRITE, WRITE, READ, MODIFY, READ,  READ,
395 		WRITE, MODIFY, WRITE, MODIFY, MODIFY, READ, UNCHANGED,
396 	},
397 	{
398 		UNCHANGED, READ, WRITE, WRITE, READ, MODIFY, READ,  READ,
399 		WRITE, MODIFY, READ, READ, MODIFY, UNCHANGED, UNCHANGED,
400 	},
401 	{
402 		UNCHANGED, READ, WRITE, WRITE, MODIFY, MODIFY, READ, READ,
403 		WRITE, MODIFY, READ, READ, MODIFY, UNCHANGED, UNCHANGED,
404 	},
405 };
406 
get_access(int operator_index,e_access_mode access_mode)407 static e_access get_access(int operator_index, e_access_mode access_mode)
408 {
409 	int idx = (operator_index > 3) ? 3 : operator_index;
410 
411 	return g_access_mode_to_access[idx][access_mode];
412 }
413 
build_regs_read_write_counts(MCInst * MI,m680x_info * info,e_access_mode access_mode)414 static void build_regs_read_write_counts(MCInst *MI, m680x_info *info,
415 	e_access_mode access_mode)
416 {
417 	cs_m680x *m680x = &info->m680x;
418 	int i;
419 
420 	if (MI->flat_insn->detail == NULL || (!m680x->op_count))
421 		return;
422 
423 	for (i = 0; i < m680x->op_count; ++i) {
424 
425 		e_access access = get_access(i, access_mode);
426 		update_am_reg_list(MI, info, &m680x->operands[i], access);
427 	}
428 }
429 
add_operators_access(MCInst * MI,m680x_info * info,e_access_mode access_mode)430 static void add_operators_access(MCInst *MI, m680x_info *info,
431 	e_access_mode access_mode)
432 {
433 	cs_m680x *m680x = &info->m680x;
434 	int offset = 0;
435 	int i;
436 
437 	if (MI->flat_insn->detail == NULL || (!m680x->op_count) ||
438 		(access_mode == uuuu))
439 		return;
440 
441 	for (i = 0; i < m680x->op_count; ++i) {
442 		e_access access;
443 
444 		// Ugly fix: MULD has a register operand, an immediate operand
445 		// AND an implicitly changed register W
446 		if (info->insn == M680X_INS_MULD && (i == 1))
447 			offset = 1;
448 
449 		access = get_access(i + offset, access_mode);
450 		m680x->operands[i].access = access;
451 	}
452 }
453 
454 typedef struct insn_to_changed_regs {
455 	m680x_insn insn;
456 	e_access_mode access_mode;
457 	m680x_reg regs[10];
458 } insn_to_changed_regs;
459 
set_changed_regs_read_write_counts(MCInst * MI,m680x_info * info)460 static void set_changed_regs_read_write_counts(MCInst *MI, m680x_info *info)
461 {
462 	//TABLE
463 #define EOL M680X_REG_INVALID
464 	static const insn_to_changed_regs changed_regs[] = {
465 		{ M680X_INS_BSR, mmmm, { M680X_REG_S, EOL } },
466 		{ M680X_INS_CALL, mmmm, { M680X_REG_S, EOL } },
467 		{
468 			M680X_INS_CWAI, mrrr, {
469 				M680X_REG_S, M680X_REG_PC, M680X_REG_U,
470 				M680X_REG_Y, M680X_REG_X, M680X_REG_DP,
471 				M680X_REG_D, M680X_REG_CC, EOL
472 			},
473 		},
474 		{ M680X_INS_DAA, mrrr, { M680X_REG_A, EOL } },
475 		{
476 			M680X_INS_DIV, mmrr, {
477 				M680X_REG_A, M680X_REG_H, M680X_REG_X, EOL
478 			}
479 		},
480 		{
481 			M680X_INS_EDIV, mmrr, {
482 				M680X_REG_D, M680X_REG_Y, M680X_REG_X, EOL
483 			}
484 		},
485 		{
486 			M680X_INS_EDIVS, mmrr, {
487 				M680X_REG_D, M680X_REG_Y, M680X_REG_X, EOL
488 			}
489 		},
490 		{ M680X_INS_EMACS, mrrr, { M680X_REG_X, M680X_REG_Y, EOL } },
491 		{ M680X_INS_EMAXM, rrrr, { M680X_REG_D, EOL } },
492 		{ M680X_INS_EMINM, rrrr, { M680X_REG_D, EOL } },
493 		{ M680X_INS_EMUL, mmrr, { M680X_REG_D, M680X_REG_Y, EOL } },
494 		{ M680X_INS_EMULS, mmrr, { M680X_REG_D, M680X_REG_Y, EOL } },
495 		{ M680X_INS_ETBL, wmmm, { M680X_REG_A, M680X_REG_B, EOL } },
496 		{ M680X_INS_FDIV, mmmm, { M680X_REG_D, M680X_REG_X, EOL } },
497 		{ M680X_INS_IDIV, mmmm, { M680X_REG_D, M680X_REG_X, EOL } },
498 		{ M680X_INS_IDIVS, mmmm, { M680X_REG_D, M680X_REG_X, EOL } },
499 		{ M680X_INS_JSR, mmmm, { M680X_REG_S, EOL } },
500 		{ M680X_INS_LBSR, mmmm, { M680X_REG_S, EOL } },
501 		{ M680X_INS_MAXM, rrrr, { M680X_REG_A, EOL } },
502 		{ M680X_INS_MINM, rrrr, { M680X_REG_A, EOL } },
503 		{
504 			M680X_INS_MEM, mmrr, {
505 				M680X_REG_X, M680X_REG_Y, M680X_REG_A, EOL
506 			}
507 		},
508 		{ M680X_INS_MUL, mmmm, { M680X_REG_A, M680X_REG_B, EOL } },
509 		{ M680X_INS_MULD, mwrr, { M680X_REG_D, M680X_REG_W, EOL } },
510 		{ M680X_INS_PSHA, rmmm, { M680X_REG_A, M680X_REG_S, EOL } },
511 		{ M680X_INS_PSHB, rmmm, { M680X_REG_B, M680X_REG_S, EOL } },
512 		{ M680X_INS_PSHC, rmmm, { M680X_REG_CC, M680X_REG_S, EOL } },
513 		{ M680X_INS_PSHD, rmmm, { M680X_REG_D, M680X_REG_S, EOL } },
514 		{ M680X_INS_PSHH, rmmm, { M680X_REG_H, M680X_REG_S, EOL } },
515 		{ M680X_INS_PSHX, rmmm, { M680X_REG_X, M680X_REG_S, EOL } },
516 		{ M680X_INS_PSHY, rmmm, { M680X_REG_Y, M680X_REG_S, EOL } },
517 		{ M680X_INS_PULA, wmmm, { M680X_REG_A, M680X_REG_S, EOL } },
518 		{ M680X_INS_PULB, wmmm, { M680X_REG_B, M680X_REG_S, EOL } },
519 		{ M680X_INS_PULC, wmmm, { M680X_REG_CC, M680X_REG_S, EOL } },
520 		{ M680X_INS_PULD, wmmm, { M680X_REG_D, M680X_REG_S, EOL } },
521 		{ M680X_INS_PULH, wmmm, { M680X_REG_H, M680X_REG_S, EOL } },
522 		{ M680X_INS_PULX, wmmm, { M680X_REG_X, M680X_REG_S, EOL } },
523 		{ M680X_INS_PULY, wmmm, { M680X_REG_Y, M680X_REG_S, EOL } },
524 		{
525 			M680X_INS_REV, mmrr, {
526 				M680X_REG_A, M680X_REG_X, M680X_REG_Y, EOL
527 			}
528 		},
529 		{
530 			M680X_INS_REVW, mmmm, {
531 				M680X_REG_A, M680X_REG_X, M680X_REG_Y, EOL
532 			}
533 		},
534 		{ M680X_INS_RTC, mwww, { M680X_REG_S, M680X_REG_PC, EOL } },
535 		{
536 			M680X_INS_RTI, mwww, {
537 				M680X_REG_S, M680X_REG_CC, M680X_REG_B,
538 				M680X_REG_A, M680X_REG_DP, M680X_REG_X,
539 				M680X_REG_Y, M680X_REG_U, M680X_REG_PC,
540 				EOL
541 			},
542 		},
543 		{ M680X_INS_RTS, mwww, { M680X_REG_S, M680X_REG_PC, EOL } },
544 		{ M680X_INS_SEX, wrrr, { M680X_REG_A, M680X_REG_B, EOL } },
545 		{ M680X_INS_SEXW, rwww, { M680X_REG_W, M680X_REG_D, EOL } },
546 		{
547 			M680X_INS_SWI, mmrr, {
548 				M680X_REG_S, M680X_REG_PC, M680X_REG_U,
549 				M680X_REG_Y, M680X_REG_X, M680X_REG_DP,
550 				M680X_REG_A, M680X_REG_B, M680X_REG_CC,
551 				EOL
552 			}
553 		},
554 		{
555 			M680X_INS_SWI2, mmrr, {
556 				M680X_REG_S, M680X_REG_PC, M680X_REG_U,
557 				M680X_REG_Y, M680X_REG_X, M680X_REG_DP,
558 				M680X_REG_A, M680X_REG_B, M680X_REG_CC,
559 				EOL
560 			},
561 		},
562 		{
563 			M680X_INS_SWI3, mmrr, {
564 				M680X_REG_S, M680X_REG_PC, M680X_REG_U,
565 				M680X_REG_Y, M680X_REG_X, M680X_REG_DP,
566 				M680X_REG_A, M680X_REG_B, M680X_REG_CC,
567 				EOL
568 			},
569 		},
570 		{ M680X_INS_TBL, wrrr, { M680X_REG_A, M680X_REG_B, EOL } },
571 		{
572 			M680X_INS_WAI, mrrr, {
573 				M680X_REG_S, M680X_REG_PC, M680X_REG_X,
574 				M680X_REG_A, M680X_REG_B, M680X_REG_CC,
575 				EOL
576 			}
577 		},
578 		{
579 			M680X_INS_WAV, rmmm, {
580 				M680X_REG_A, M680X_REG_B, M680X_REG_X,
581 				M680X_REG_Y, EOL
582 			}
583 		},
584 		{
585 			M680X_INS_WAVR, rmmm, {
586 				M680X_REG_A, M680X_REG_B, M680X_REG_X,
587 				M680X_REG_Y, EOL
588 			}
589 		},
590 	};
591 
592 	int i, j;
593 
594 	if (MI->flat_insn->detail == NULL)
595 		return;
596 
597 	for (i = 0; i < ARR_SIZE(changed_regs); ++i) {
598 		if (info->insn == changed_regs[i].insn) {
599 			e_access_mode access_mode = changed_regs[i].access_mode;
600 
601 			for (j = 0; changed_regs[i].regs[j] != EOL; ++j) {
602 				e_access access;
603 
604 				m680x_reg reg = changed_regs[i].regs[j];
605 
606 				if (!info->cpu->reg_byte_size[reg]) {
607 					if (info->insn != M680X_INS_MUL)
608 						continue;
609 
610 					// Hack for M68HC05: MUL uses reg. A,X
611 					reg = M680X_REG_X;
612 				}
613 
614 				access = get_access(j, access_mode);
615 				add_reg_to_rw_list(MI, reg, access);
616 			}
617 		}
618 	}
619 
620 #undef EOL
621 }
622 
623 typedef struct insn_desc {
624 	uint32_t opcode;
625 	m680x_insn insn;
626 	insn_hdlr_id hid[2];
627 	uint16_t insn_size;
628 } insn_desc;
629 
630 // If successfull return the additional byte size needed for M6809
631 // indexed addressing mode (including the indexed addressing post_byte).
632 // On error return -1.
get_indexed09_post_byte_size(const m680x_info * info,uint16_t address)633 static int get_indexed09_post_byte_size(const m680x_info *info,
634 					uint16_t address)
635 {
636 	uint8_t ir = 0;
637 	uint8_t post_byte;
638 
639 	// Read the indexed addressing post byte.
640 	if (!read_byte(info, &post_byte, address))
641 		return -1;
642 
643 	// Depending on the indexed addressing mode more bytes have to be read.
644 	switch (post_byte & 0x9F) {
645 	case 0x87:
646 	case 0x8A:
647 	case 0x8E:
648 	case 0x8F:
649 	case 0x90:
650 	case 0x92:
651 	case 0x97:
652 	case 0x9A:
653 	case 0x9E:
654 		return -1; // illegal indexed post bytes
655 
656 	case 0x88: // n8,R
657 	case 0x8C: // n8,PCR
658 	case 0x98: // [n8,R]
659 	case 0x9C: // [n8,PCR]
660 		if (!read_byte(info, &ir, address + 1))
661 			return -1;
662 		return 2;
663 
664 	case 0x89: // n16,R
665 	case 0x8D: // n16,PCR
666 	case 0x99: // [n16,R]
667 	case 0x9D: // [n16,PCR]
668 		if (!read_byte(info, &ir, address + 2))
669 			return -1;
670 		return 3;
671 
672 	case 0x9F: // [n]
673 		if ((post_byte & 0x60) != 0 ||
674 			!read_byte(info, &ir, address + 2))
675 			return -1;
676 		return  3;
677 	}
678 
679 	// Any other indexed post byte is valid and
680 	// no additional bytes have to be read.
681 	return 1;
682 }
683 
684 // If successfull return the additional byte size needed for CPU12
685 // indexed addressing mode (including the indexed addressing post_byte).
686 // On error return -1.
get_indexed12_post_byte_size(const m680x_info * info,uint16_t address,bool is_subset)687 static int get_indexed12_post_byte_size(const m680x_info *info,
688 					uint16_t address, bool is_subset)
689 {
690 	uint8_t ir;
691 	uint8_t post_byte;
692 
693 	// Read the indexed addressing post byte.
694 	if (!read_byte(info, &post_byte, address))
695 		return -1;
696 
697 	// Depending on the indexed addressing mode more bytes have to be read.
698 	if (!(post_byte & 0x20)) // n5,R
699 		return 1;
700 
701 	switch (post_byte & 0xe7) {
702 	case 0xe0:
703 	case 0xe1: // n9,R
704 		if (is_subset)
705 			return -1;
706 
707 		if (!read_byte(info, &ir, address))
708 			return -1;
709 		return 2;
710 
711 	case 0xe2: // n16,R
712 	case 0xe3: // [n16,R]
713 		if (is_subset)
714 			return -1;
715 
716 		if (!read_byte(info, &ir, address + 1))
717 			return -1;
718 		return 3;
719 
720 	case 0xe4: // A,R
721 	case 0xe5: // B,R
722 	case 0xe6: // D,R
723 	case 0xe7: // [D,R]
724 	default: // n,-r n,+r n,r- n,r+
725 		break;
726 	}
727 
728 	return 1;
729 }
730 
731 // Check for M6809/HD6309 TFR/EXG instruction for valid register
is_tfr09_reg_valid(const m680x_info * info,uint8_t reg_nibble)732 static bool is_tfr09_reg_valid(const m680x_info *info, uint8_t reg_nibble)
733 {
734 	if (info->cpu->tfr_reg_valid != NULL)
735 		return info->cpu->tfr_reg_valid[reg_nibble];
736 
737 	return true; // e.g. for the M6309 all registers are valid
738 }
739 
740 // Check for CPU12 TFR/EXG instruction for valid register
is_exg_tfr12_post_byte_valid(const m680x_info * info,uint8_t post_byte)741 static bool is_exg_tfr12_post_byte_valid(const m680x_info *info,
742 	uint8_t post_byte)
743 {
744 	return !(post_byte & 0x08);
745 }
746 
is_tfm_reg_valid(const m680x_info * info,uint8_t reg_nibble)747 static bool is_tfm_reg_valid(const m680x_info *info, uint8_t reg_nibble)
748 {
749 	// HD6809 TFM instruction: Only register X,Y,U,S,D is allowed
750 	return reg_nibble <= 4;
751 }
752 
753 // If successfull return the additional byte size needed for CPU12
754 // loop instructions DBEQ/DBNE/IBEQ/IBNE/TBEQ/TBNE (including the post byte).
755 // On error return -1.
get_loop_post_byte_size(const m680x_info * info,uint16_t address)756 static int get_loop_post_byte_size(const m680x_info *info, uint16_t address)
757 {
758 	uint8_t post_byte;
759 	uint8_t rr;
760 
761 	if (!read_byte(info, &post_byte, address))
762 		return -1;
763 
764 	// According to documentation bit 3 is don't care and not checked here.
765 	if ((post_byte >= 0xc0) ||
766 		((post_byte & 0x07) == 2) || ((post_byte & 0x07) == 3))
767 		return -1;
768 
769 	if (!read_byte(info, &rr, address + 1))
770 		return -1;
771 
772 	return 2;
773 }
774 
775 // If successfull return the additional byte size needed for HD6309
776 // bit move instructions BAND/BEOR/BIAND/BIEOR/BIOR/BOR/LDBT/STBT
777 // (including the post byte).
778 // On error return -1.
get_bitmv_post_byte_size(const m680x_info * info,uint16_t address)779 static int get_bitmv_post_byte_size(const m680x_info *info, uint16_t address)
780 {
781 	uint8_t post_byte;
782 	uint8_t rr;
783 
784 	if (!read_byte(info, &post_byte, address))
785 		return -1;
786 
787 	if ((post_byte & 0xc0) == 0xc0)
788 		return -1; // Invalid register specified
789 	else {
790 		if (!read_byte(info, &rr, address + 1))
791 			return -1;
792 	}
793 
794 	return 2;
795 }
796 
is_sufficient_code_size(const m680x_info * info,uint16_t address,insn_desc * insn_description)797 static bool is_sufficient_code_size(const m680x_info *info, uint16_t address,
798 	insn_desc *insn_description)
799 {
800 	int i;
801 	bool retval = true;
802 	uint16_t size = 0;
803 	int sz;
804 
805 	for (i = 0; i < 2; i++) {
806 		uint8_t ir = 0;
807 		bool is_subset = false;
808 
809 		switch (insn_description->hid[i]) {
810 
811 		case imm32_hid:
812 			if ((retval = read_byte(info, &ir, address + size + 3)))
813 				size += 4;
814 			break;
815 
816 		case ext_hid:
817 		case imm16_hid:
818 		case rel16_hid:
819 		case imm8rel_hid:
820 		case opidxdr_hid:
821 		case idxX16_hid:
822 		case idxS16_hid:
823 			if ((retval = read_byte(info, &ir, address + size + 1)))
824 				size += 2;
825 			break;
826 
827 		case rel8_hid:
828 		case dir_hid:
829 		case rbits_hid:
830 		case imm8_hid:
831 		case idxX_hid:
832 		case idxXp_hid:
833 		case idxY_hid:
834 		case idxS_hid:
835 		case index_hid:
836 			if ((retval = read_byte(info, &ir, address + size)))
837 				size++;
838 			break;
839 
840 		case illgl_hid:
841 		case inh_hid:
842 		case idxX0_hid:
843 		case idxX0p_hid:
844 		case opidx_hid:
845 			retval = true;
846 			break;
847 
848 		case idx09_hid:
849 			sz = get_indexed09_post_byte_size(info, address + size);
850 			if (sz >= 0)
851 				size += sz;
852 			else
853 				retval = false;
854 			break;
855 
856 		case idx12s_hid:
857 			is_subset = true;
858 
859 		// intentionally fall through
860 
861 		case idx12_hid:
862 			sz = get_indexed12_post_byte_size(info,
863 					address + size, is_subset);
864 			if (sz >= 0)
865 				size += sz;
866 			else
867 				retval = false;
868 			break;
869 
870 		case exti12x_hid:
871 		case imm16i12x_hid:
872 			sz = get_indexed12_post_byte_size(info,
873 					address + size, false);
874 			if (sz >= 0) {
875 				size += sz;
876 				if ((retval = read_byte(info, &ir,
877 						address + size + 1)))
878 					size += 2;
879 			} else
880 				retval = false;
881 			break;
882 
883 		case imm8i12x_hid:
884 			sz = get_indexed12_post_byte_size(info,
885 					address + size, false);
886 			if (sz >= 0) {
887 				size += sz;
888 				if ((retval = read_byte(info, &ir,
889 						address + size)))
890 					size++;
891 			} else
892 				retval = false;
893 			break;
894 
895 		case tfm_hid:
896 			if ((retval = read_byte(info, &ir, address + size))) {
897 				size++;
898 				retval = is_tfm_reg_valid(info, (ir >> 4) & 0x0F) &&
899 					is_tfm_reg_valid(info, ir & 0x0F);
900 			}
901 			break;
902 
903 		case rr09_hid:
904 			if ((retval = read_byte(info, &ir, address + size))) {
905 				size++;
906 				retval = is_tfr09_reg_valid(info, (ir >> 4) & 0x0F) &&
907 					is_tfr09_reg_valid(info, ir & 0x0F);
908 			}
909 			break;
910 
911 		case rr12_hid:
912 			if ((retval = read_byte(info, &ir, address + size))) {
913 				size++;
914 				retval = is_exg_tfr12_post_byte_valid(info, ir);
915 			}
916 			break;
917 
918 		case bitmv_hid:
919 			sz = get_bitmv_post_byte_size(info, address + size);
920 			if (sz >= 0)
921 				size += sz;
922 			else
923 				retval = false;
924 			break;
925 
926 		case loop_hid:
927 			sz = get_loop_post_byte_size(info, address + size);
928 			if (sz >= 0)
929 				size += sz;
930 			else
931 				retval = false;
932 			break;
933 
934 		default:
935 			CS_ASSERT(0 && "Unexpected instruction handler id");
936 			retval = false;
937 			break;
938 		}
939 
940 		if (!retval)
941 			return false;
942 	}
943 
944 	insn_description->insn_size += size;
945 
946 	return retval;
947 }
948 
949 // Check for a valid M680X instruction AND for enough bytes in the code buffer
950 // Return an instruction description in insn_desc.
decode_insn(const m680x_info * info,uint16_t address,insn_desc * insn_description)951 static bool decode_insn(const m680x_info *info, uint16_t address,
952 	insn_desc *insn_description)
953 {
954 	const inst_pageX *inst_table = NULL;
955 	const cpu_tables *cpu = info->cpu;
956 	size_t table_size = 0;
957 	uint16_t base_address = address;
958 	uint8_t ir; // instruction register
959 	int i;
960 	int index;
961 
962 	if (!read_byte(info, &ir, address++))
963 		return false;
964 
965 	insn_description->insn = M680X_INS_ILLGL;
966 	insn_description->opcode = ir;
967 
968 	// Check if a page prefix byte is present
969 	for (i = 0; i < ARR_SIZE(cpu->pageX_table_size); ++i) {
970 		if (cpu->pageX_table_size[i] == 0 ||
971 			(cpu->inst_pageX_table[i] == NULL))
972 			break;
973 
974 		if ((cpu->pageX_prefix[i] == ir)) {
975 			// Get pageX instruction and handler id.
976 			// Abort for illegal instr.
977 			inst_table = cpu->inst_pageX_table[i];
978 			table_size = cpu->pageX_table_size[i];
979 
980 			if (!read_byte(info, &ir, address++))
981 				return false;
982 
983 			insn_description->opcode =
984 				(insn_description->opcode << 8) | ir;
985 
986 			if ((index = binary_search(inst_table, table_size,
987 				ir)) < 0)
988 				return false;
989 
990 			insn_description->hid[0] =
991 				inst_table[index].handler_id1;
992 			insn_description->hid[1] =
993 				inst_table[index].handler_id2;
994 			insn_description->insn = inst_table[index].insn;
995 			break;
996 		}
997 	}
998 
999 	if (insn_description->insn == M680X_INS_ILLGL) {
1000 		// Get page1 insn description
1001 		insn_description->insn = cpu->inst_page1_table[ir].insn;
1002 		insn_description->hid[0] =
1003 			cpu->inst_page1_table[ir].handler_id1;
1004 		insn_description->hid[1] =
1005 			cpu->inst_page1_table[ir].handler_id2;
1006 	}
1007 
1008 	if (insn_description->insn == M680X_INS_ILLGL) {
1009 		// Check if opcode byte is present in an overlay table
1010 		for (i = 0; i < ARR_SIZE(cpu->overlay_table_size); ++i) {
1011 			if (cpu->overlay_table_size[i] == 0 ||
1012 				(cpu->inst_overlay_table[i] == NULL))
1013 				break;
1014 
1015 			inst_table = cpu->inst_overlay_table[i];
1016 			table_size = cpu->overlay_table_size[i];
1017 
1018 			if ((index = binary_search(inst_table, table_size,
1019 							ir)) >= 0) {
1020 				insn_description->hid[0] =
1021 					inst_table[index].handler_id1;
1022 				insn_description->hid[1] =
1023 					inst_table[index].handler_id2;
1024 				insn_description->insn = inst_table[index].insn;
1025 				break;
1026 			}
1027 		}
1028 	}
1029 
1030 	insn_description->insn_size = address - base_address;
1031 
1032 	return (insn_description->insn != M680X_INS_ILLGL) &&
1033 		(insn_description->insn != M680X_INS_INVLD) &&
1034 		is_sufficient_code_size(info, address, insn_description);
1035 }
1036 
illegal_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1037 static void illegal_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1038 {
1039 	cs_m680x_op *op0 = &info->m680x.operands[info->m680x.op_count++];
1040 	uint8_t temp8 = 0;
1041 
1042 	info->insn = M680X_INS_ILLGL;
1043 	read_byte(info, &temp8, (*address)++);
1044 	op0->imm = (int32_t)temp8 & 0xff;
1045 	op0->type = M680X_OP_IMMEDIATE;
1046 	op0->size = 1;
1047 }
1048 
inherent_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1049 static void inherent_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1050 {
1051 	// There is nothing to do here :-)
1052 }
1053 
add_reg_operand(m680x_info * info,m680x_reg reg)1054 static void add_reg_operand(m680x_info *info, m680x_reg reg)
1055 {
1056 	cs_m680x *m680x = &info->m680x;
1057 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1058 
1059 	op->type = M680X_OP_REGISTER;
1060 	op->reg = reg;
1061 	op->size = info->cpu->reg_byte_size[reg];
1062 }
1063 
set_operand_size(m680x_info * info,cs_m680x_op * op,uint8_t default_size)1064 static void set_operand_size(m680x_info *info, cs_m680x_op *op,
1065 	uint8_t default_size)
1066 {
1067 	cs_m680x *m680x = &info->m680x;
1068 
1069 	if (info->insn == M680X_INS_JMP || info->insn == M680X_INS_JSR)
1070 		op->size = 0;
1071 	else if (info->insn == M680X_INS_DIVD ||
1072 		((info->insn == M680X_INS_AIS || info->insn == M680X_INS_AIX) &&
1073 			op->type != M680X_OP_REGISTER))
1074 		op->size = 1;
1075 	else if (info->insn == M680X_INS_DIVQ ||
1076 		info->insn == M680X_INS_MOVW)
1077 		op->size = 2;
1078 	else if (info->insn == M680X_INS_EMACS)
1079 		op->size = 4;
1080 	else if ((m680x->op_count > 0) &&
1081 		(m680x->operands[0].type == M680X_OP_REGISTER))
1082 		op->size = m680x->operands[0].size;
1083 	else
1084 		op->size = default_size;
1085 }
1086 
1087 static const m680x_reg reg_s_reg_ids[] = {
1088 	M680X_REG_CC, M680X_REG_A, M680X_REG_B, M680X_REG_DP,
1089 	M680X_REG_X,  M680X_REG_Y, M680X_REG_U, M680X_REG_PC,
1090 };
1091 
1092 static const m680x_reg reg_u_reg_ids[] = {
1093 	M680X_REG_CC, M680X_REG_A, M680X_REG_B, M680X_REG_DP,
1094 	M680X_REG_X,  M680X_REG_Y, M680X_REG_S, M680X_REG_PC,
1095 };
1096 
reg_bits_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1097 static void reg_bits_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1098 {
1099 	cs_m680x_op *op0 = &info->m680x.operands[0];
1100 	uint8_t reg_bits = 0;
1101 	uint16_t bit_index;
1102 	const m680x_reg *reg_to_reg_ids = NULL;
1103 
1104 	read_byte(info, &reg_bits, (*address)++);
1105 
1106 	switch (op0->reg) {
1107 	case M680X_REG_U:
1108 		reg_to_reg_ids = &reg_u_reg_ids[0];
1109 		break;
1110 
1111 	case M680X_REG_S:
1112 		reg_to_reg_ids = &reg_s_reg_ids[0];
1113 		break;
1114 
1115 	default:
1116 		CS_ASSERT(0 && "Unexpected operand0 register");
1117 		break;
1118 	}
1119 
1120 	if ((info->insn == M680X_INS_PULU ||
1121 			(info->insn == M680X_INS_PULS)) &&
1122 		((reg_bits & 0x80) != 0))
1123 		// PULS xxx,PC or PULU xxx,PC which is like return from
1124 		// subroutine (RTS)
1125 		add_insn_group(MI->flat_insn->detail, M680X_GRP_RET);
1126 
1127 	for (bit_index = 0; bit_index < 8; ++bit_index) {
1128 		if (reg_bits & (1 << bit_index))
1129 			add_reg_operand(info, reg_to_reg_ids[bit_index]);
1130 	}
1131 }
1132 
1133 static const m680x_reg g_tfr_exg_reg_ids[] = {
1134 	/* 16-bit registers */
1135 	M680X_REG_D, M680X_REG_X,  M680X_REG_Y,  M680X_REG_U,
1136 	M680X_REG_S, M680X_REG_PC, M680X_REG_W,  M680X_REG_V,
1137 	/* 8-bit registers */
1138 	M680X_REG_A, M680X_REG_B,  M680X_REG_CC, M680X_REG_DP,
1139 	M680X_REG_0, M680X_REG_0,  M680X_REG_E,  M680X_REG_F,
1140 };
1141 
reg_reg09_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1142 static void reg_reg09_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1143 {
1144 	uint8_t regs = 0;
1145 
1146 	read_byte(info, &regs, (*address)++);
1147 
1148 	add_reg_operand(info, g_tfr_exg_reg_ids[regs >> 4]);
1149 	add_reg_operand(info, g_tfr_exg_reg_ids[regs & 0x0f]);
1150 
1151 	if ((regs & 0x0f) == 0x05) {
1152 		// EXG xxx,PC or TFR xxx,PC which is like a JMP
1153 		add_insn_group(MI->flat_insn->detail, M680X_GRP_JUMP);
1154 	}
1155 }
1156 
1157 
reg_reg12_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1158 static void reg_reg12_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1159 {
1160 	static const m680x_reg g_tfr_exg12_reg0_ids[] = {
1161 		M680X_REG_A, M680X_REG_B,  M680X_REG_CC,  M680X_REG_TMP3,
1162 		M680X_REG_D, M680X_REG_X, M680X_REG_Y,  M680X_REG_S,
1163 	};
1164 	static const m680x_reg g_tfr_exg12_reg1_ids[] = {
1165 		M680X_REG_A, M680X_REG_B,  M680X_REG_CC,  M680X_REG_TMP2,
1166 		M680X_REG_D, M680X_REG_X, M680X_REG_Y,  M680X_REG_S,
1167 	};
1168 	uint8_t regs = 0;
1169 
1170 	read_byte(info, &regs, (*address)++);
1171 
1172 	// The opcode of this instruction depends on
1173 	// the msb of its post byte.
1174 	if (regs & 0x80)
1175 		info->insn = M680X_INS_EXG;
1176 	else
1177 		info->insn = M680X_INS_TFR;
1178 
1179 	add_reg_operand(info, g_tfr_exg12_reg0_ids[(regs >> 4) & 0x07]);
1180 	add_reg_operand(info, g_tfr_exg12_reg1_ids[regs & 0x07]);
1181 }
1182 
add_rel_operand(m680x_info * info,int16_t offset,uint16_t address)1183 static void add_rel_operand(m680x_info *info, int16_t offset, uint16_t address)
1184 {
1185 	cs_m680x *m680x = &info->m680x;
1186 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1187 
1188 	op->type = M680X_OP_RELATIVE;
1189 	op->size = 0;
1190 	op->rel.offset = offset;
1191 	op->rel.address = address;
1192 }
1193 
relative8_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1194 static void relative8_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1195 {
1196 	int16_t offset = 0;
1197 
1198 	read_byte_sign_extended(info, &offset, (*address)++);
1199 	add_rel_operand(info, offset, *address + offset);
1200 	add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL);
1201 
1202 	if ((info->insn != M680X_INS_BRA) &&
1203 		(info->insn != M680X_INS_BSR) &&
1204 		(info->insn != M680X_INS_BRN))
1205 		add_reg_to_rw_list(MI, M680X_REG_CC, READ);
1206 }
1207 
relative16_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1208 static void relative16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1209 {
1210 	uint16_t offset = 0;
1211 
1212 	read_word(info, &offset, *address);
1213 	*address += 2;
1214 	add_rel_operand(info, (int16_t)offset, *address + offset);
1215 	add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL);
1216 
1217 	if ((info->insn != M680X_INS_LBRA) &&
1218 		(info->insn != M680X_INS_LBSR) &&
1219 		(info->insn != M680X_INS_LBRN))
1220 		add_reg_to_rw_list(MI, M680X_REG_CC, READ);
1221 }
1222 
1223 static const m680x_reg g_rr5_to_reg_ids[] = {
1224 	M680X_REG_X, M680X_REG_Y, M680X_REG_U, M680X_REG_S,
1225 };
1226 
add_indexed_operand(m680x_info * info,m680x_reg base_reg,bool post_inc_dec,uint8_t inc_dec,uint8_t offset_bits,uint16_t offset,bool no_comma)1227 static void add_indexed_operand(m680x_info *info, m680x_reg base_reg,
1228 	bool post_inc_dec, uint8_t inc_dec, uint8_t offset_bits,
1229 	uint16_t offset, bool no_comma)
1230 {
1231 	cs_m680x *m680x = &info->m680x;
1232 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1233 
1234 	op->type = M680X_OP_INDEXED;
1235 	set_operand_size(info, op, 1);
1236 	op->idx.base_reg = base_reg;
1237 	op->idx.offset_reg = M680X_REG_INVALID;
1238 	op->idx.inc_dec = inc_dec;
1239 
1240 	if (inc_dec && post_inc_dec)
1241 		op->idx.flags |= M680X_IDX_POST_INC_DEC;
1242 
1243 	if (offset_bits != M680X_OFFSET_NONE) {
1244 		op->idx.offset = offset;
1245 		op->idx.offset_addr = 0;
1246 	}
1247 
1248 	op->idx.offset_bits = offset_bits;
1249 	op->idx.flags |= (no_comma ? M680X_IDX_NO_COMMA : 0);
1250 }
1251 
1252 // M6800/1/2/3 indexed mode handler
indexedX_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1253 static void indexedX_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1254 {
1255 	uint8_t offset = 0;
1256 
1257 	read_byte(info, &offset, (*address)++);
1258 
1259 	add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_BITS_8,
1260 		(uint16_t)offset, false);
1261 }
1262 
indexedY_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1263 static void indexedY_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1264 {
1265 	uint8_t offset = 0;
1266 
1267 	read_byte(info, &offset, (*address)++);
1268 
1269 	add_indexed_operand(info, M680X_REG_Y, false, 0, M680X_OFFSET_BITS_8,
1270 		(uint16_t)offset, false);
1271 }
1272 
1273 // M6809/M6309 indexed mode handler
indexed09_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1274 static void indexed09_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1275 {
1276 	cs_m680x *m680x = &info->m680x;
1277 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1278 	uint8_t post_byte = 0;
1279 	uint16_t offset = 0;
1280 	int16_t soffset = 0;
1281 
1282 	read_byte(info, &post_byte, (*address)++);
1283 
1284 	op->type = M680X_OP_INDEXED;
1285 	set_operand_size(info, op, 1);
1286 	op->idx.base_reg = g_rr5_to_reg_ids[(post_byte >> 5) & 0x03];
1287 	op->idx.offset_reg = M680X_REG_INVALID;
1288 
1289 	if (!(post_byte & 0x80)) {
1290 		// n5,R
1291 		if ((post_byte & 0x10) == 0x10)
1292 			op->idx.offset = post_byte | 0xfff0;
1293 		else
1294 			op->idx.offset = post_byte & 0x0f;
1295 
1296 		op->idx.offset_addr = op->idx.offset + *address;
1297 		op->idx.offset_bits = M680X_OFFSET_BITS_5;
1298 	}
1299 	else {
1300 		if ((post_byte & 0x10) == 0x10)
1301 			op->idx.flags |= M680X_IDX_INDIRECT;
1302 
1303 		// indexed addressing
1304 		switch (post_byte & 0x1f) {
1305 		case 0x00: // ,R+
1306 			op->idx.inc_dec = 1;
1307 			op->idx.flags |= M680X_IDX_POST_INC_DEC;
1308 			break;
1309 
1310 		case 0x11: // [,R++]
1311 		case 0x01: // ,R++
1312 			op->idx.inc_dec = 2;
1313 			op->idx.flags |= M680X_IDX_POST_INC_DEC;
1314 			break;
1315 
1316 		case 0x02: // ,-R
1317 			op->idx.inc_dec = -1;
1318 			break;
1319 
1320 		case 0x13: // [,--R]
1321 		case 0x03: // ,--R
1322 			op->idx.inc_dec = -2;
1323 			break;
1324 
1325 		case 0x14: // [,R]
1326 		case 0x04: // ,R
1327 			break;
1328 
1329 		case 0x15: // [B,R]
1330 		case 0x05: // B,R
1331 			op->idx.offset_reg = M680X_REG_B;
1332 			break;
1333 
1334 		case 0x16: // [A,R]
1335 		case 0x06: // A,R
1336 			op->idx.offset_reg = M680X_REG_A;
1337 			break;
1338 
1339 		case 0x1c: // [n8,PCR]
1340 		case 0x0c: // n8,PCR
1341 			op->idx.base_reg = M680X_REG_PC;
1342 			read_byte_sign_extended(info, &soffset, (*address)++);
1343 			op->idx.offset_addr = offset + *address;
1344 			op->idx.offset = soffset;
1345 			op->idx.offset_bits = M680X_OFFSET_BITS_8;
1346 			break;
1347 
1348 		case 0x18: // [n8,R]
1349 		case 0x08: // n8,R
1350 			read_byte_sign_extended(info, &soffset, (*address)++);
1351 			op->idx.offset = soffset;
1352 			op->idx.offset_bits = M680X_OFFSET_BITS_8;
1353 			break;
1354 
1355 		case 0x1d: // [n16,PCR]
1356 		case 0x0d: // n16,PCR
1357 			op->idx.base_reg = M680X_REG_PC;
1358 			read_word(info, &offset, *address);
1359 			*address += 2;
1360 			op->idx.offset_addr = offset + *address;
1361 			op->idx.offset = (int16_t)offset;
1362 			op->idx.offset_bits = M680X_OFFSET_BITS_16;
1363 			break;
1364 
1365 		case 0x19: // [n16,R]
1366 		case 0x09: // n16,R
1367 			read_word(info, &offset, *address);
1368 			*address += 2;
1369 			op->idx.offset = (int16_t)offset;
1370 			op->idx.offset_bits = M680X_OFFSET_BITS_16;
1371 			break;
1372 
1373 		case 0x1b: // [D,R]
1374 		case 0x0b: // D,R
1375 			op->idx.offset_reg = M680X_REG_D;
1376 			break;
1377 
1378 		case 0x1f: // [n16]
1379 			op->type = M680X_OP_EXTENDED;
1380 			op->ext.indirect = true;
1381 			read_word(info, &op->ext.address, *address);
1382 			*address += 2;
1383 			break;
1384 
1385 		default:
1386 			op->idx.base_reg = M680X_REG_INVALID;
1387 			break;
1388 		}
1389 	}
1390 
1391 	if (((info->insn == M680X_INS_LEAU) ||
1392 			(info->insn == M680X_INS_LEAS) ||
1393 			(info->insn == M680X_INS_LEAX) ||
1394 			(info->insn == M680X_INS_LEAY)) &&
1395 		(m680x->operands[0].reg == M680X_REG_X ||
1396 			(m680x->operands[0].reg == M680X_REG_Y)))
1397 		// Only LEAX and LEAY modify CC register
1398 		add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY);
1399 }
1400 
1401 
1402 static const m680x_reg g_idx12_to_reg_ids[4] = {
1403 	M680X_REG_X, M680X_REG_Y, M680X_REG_S, M680X_REG_PC,
1404 };
1405 
1406 static const m680x_reg g_or12_to_reg_ids[3] = {
1407 	M680X_REG_A, M680X_REG_B, M680X_REG_D
1408 };
1409 
1410 // CPU12 indexed mode handler
indexed12_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1411 static void indexed12_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1412 {
1413 	cs_m680x *m680x = &info->m680x;
1414 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1415 	uint8_t post_byte = 0;
1416 	uint8_t offset8 = 0;
1417 
1418 	read_byte(info, &post_byte, (*address)++);
1419 
1420 	op->type = M680X_OP_INDEXED;
1421 	set_operand_size(info, op, 1);
1422 	op->idx.offset_reg = M680X_REG_INVALID;
1423 
1424 	if (!(post_byte & 0x20)) {
1425 		// n5,R      n5 is a 5-bit signed offset
1426 		op->idx.base_reg = g_idx12_to_reg_ids[(post_byte >> 6) & 0x03];
1427 
1428 		if ((post_byte & 0x10) == 0x10)
1429 			op->idx.offset = post_byte | 0xfff0;
1430 		else
1431 			op->idx.offset = post_byte & 0x0f;
1432 
1433 		op->idx.offset_addr = op->idx.offset + *address;
1434 		op->idx.offset_bits = M680X_OFFSET_BITS_5;
1435 	}
1436 	else {
1437 		if ((post_byte & 0xe0) == 0xe0)
1438 			op->idx.base_reg =
1439 				g_idx12_to_reg_ids[(post_byte >> 3) & 0x03];
1440 
1441 		switch (post_byte & 0xe7) {
1442 		case 0xe0:
1443 		case 0xe1: // n9,R
1444 			read_byte(info, &offset8, (*address)++);
1445 			op->idx.offset = offset8;
1446 
1447 			if (post_byte & 0x01) // sign extension
1448 				op->idx.offset |= 0xff00;
1449 
1450 			op->idx.offset_bits = M680X_OFFSET_BITS_9;
1451 
1452 			if (op->idx.base_reg == M680X_REG_PC)
1453 				op->idx.offset_addr = op->idx.offset + *address;
1454 
1455 			break;
1456 
1457 		case 0xe3: // [n16,R]
1458 			op->idx.flags |= M680X_IDX_INDIRECT;
1459 
1460 		// intentionally fall through
1461 		case 0xe2: // n16,R
1462 			read_word(info, (uint16_t *)&op->idx.offset, *address);
1463 			(*address) += 2;
1464 			op->idx.offset_bits = M680X_OFFSET_BITS_16;
1465 
1466 			if (op->idx.base_reg == M680X_REG_PC)
1467 				op->idx.offset_addr = op->idx.offset + *address;
1468 
1469 			break;
1470 
1471 		case 0xe4: // A,R
1472 		case 0xe5: // B,R
1473 		case 0xe6: // D,R
1474 			op->idx.offset_reg =
1475 				g_or12_to_reg_ids[post_byte & 0x03];
1476 			break;
1477 
1478 		case 0xe7: // [D,R]
1479 			op->idx.offset_reg = M680X_REG_D;
1480 			op->idx.flags |= M680X_IDX_INDIRECT;
1481 			break;
1482 
1483 		default: // n,-r n,+r n,r- n,r+
1484 			// PC is not allowed in this mode
1485 			op->idx.base_reg =
1486 				g_idx12_to_reg_ids[(post_byte >> 6) & 0x03];
1487 			op->idx.inc_dec = post_byte & 0x0f;
1488 
1489 			if (op->idx.inc_dec & 0x08) // evtl. sign extend value
1490 				op->idx.inc_dec |= 0xf0;
1491 
1492 			if (op->idx.inc_dec >= 0)
1493 				op->idx.inc_dec++;
1494 
1495 			if (post_byte & 0x10)
1496 				op->idx.flags |= M680X_IDX_POST_INC_DEC;
1497 
1498 			break;
1499 
1500 		}
1501 	}
1502 }
1503 
index_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1504 static void index_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1505 {
1506 	cs_m680x *m680x = &info->m680x;
1507 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1508 
1509 	op->type = M680X_OP_CONSTANT;
1510 	read_byte(info, &op->const_val, (*address)++);
1511 };
1512 
direct_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1513 static void direct_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1514 {
1515 	cs_m680x *m680x = &info->m680x;
1516 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1517 
1518 	op->type = M680X_OP_DIRECT;
1519 	set_operand_size(info, op, 1);
1520 	read_byte(info, &op->direct_addr, (*address)++);
1521 };
1522 
extended_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1523 static void extended_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1524 {
1525 	cs_m680x *m680x = &info->m680x;
1526 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1527 
1528 	op->type = M680X_OP_EXTENDED;
1529 	set_operand_size(info, op, 1);
1530 	read_word(info, &op->ext.address, *address);
1531 	*address += 2;
1532 }
1533 
immediate_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1534 static void immediate_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1535 {
1536 	cs_m680x *m680x = &info->m680x;
1537 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1538 	uint16_t word = 0;
1539 	int16_t sword = 0;
1540 
1541 	op->type = M680X_OP_IMMEDIATE;
1542 	set_operand_size(info, op, 1);
1543 
1544 	switch (op->size) {
1545 	case 1:
1546 		read_byte_sign_extended(info, &sword, *address);
1547 		op->imm = sword;
1548 		break;
1549 
1550 	case 2:
1551 		read_word(info, &word, *address);
1552 		op->imm = (int16_t)word;
1553 		break;
1554 
1555 	case 4:
1556 		read_sdword(info, &op->imm, *address);
1557 		break;
1558 
1559 	default:
1560 		op->imm = 0;
1561 		CS_ASSERT(0 && "Unexpected immediate byte size");
1562 	}
1563 
1564 	*address += op->size;
1565 }
1566 
1567 // handler for bit move instructions, e.g: BAND A,5,1,$40  Used by HD6309
bit_move_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1568 static void bit_move_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1569 {
1570 	static const m680x_reg m680x_reg[] = {
1571 		M680X_REG_CC, M680X_REG_A, M680X_REG_B, M680X_REG_INVALID,
1572 	};
1573 
1574 	uint8_t post_byte = 0;
1575 	cs_m680x *m680x = &info->m680x;
1576 	cs_m680x_op *op;
1577 
1578 	read_byte(info, &post_byte, *address);
1579 	(*address)++;
1580 
1581 	// operand[0] = register
1582 	add_reg_operand(info, m680x_reg[post_byte >> 6]);
1583 
1584 	// operand[1] = bit index in source operand
1585 	op = &m680x->operands[m680x->op_count++];
1586 	op->type = M680X_OP_CONSTANT;
1587 	op->const_val = (post_byte >> 3) & 0x07;
1588 
1589 	// operand[2] = bit index in destination operand
1590 	op = &m680x->operands[m680x->op_count++];
1591 	op->type = M680X_OP_CONSTANT;
1592 	op->const_val = post_byte & 0x07;
1593 
1594 	direct_hdlr(MI, info, address);
1595 }
1596 
1597 // handler for TFM instruction, e.g: TFM X+,Y+  Used by HD6309
tfm_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1598 static void tfm_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1599 {
1600 	static const uint8_t inc_dec_r0[] = {
1601 		1, -1, 1, 0,
1602 	};
1603 	static const uint8_t inc_dec_r1[] = {
1604 		1, -1, 0, 1,
1605 	};
1606 	uint8_t regs = 0;
1607 	uint8_t index = (MI->Opcode & 0xff) - 0x38;
1608 
1609 	read_byte(info, &regs, *address);
1610 
1611 	add_indexed_operand(info, g_tfr_exg_reg_ids[regs >> 4], true,
1612 		inc_dec_r0[index], M680X_OFFSET_NONE, 0, true);
1613 	add_indexed_operand(info, g_tfr_exg_reg_ids[regs & 0x0f], true,
1614 		inc_dec_r1[index], M680X_OFFSET_NONE, 0, true);
1615 
1616 	add_reg_to_rw_list(MI, M680X_REG_W, READ | WRITE);
1617 }
1618 
opidx_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1619 static void opidx_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1620 {
1621 	cs_m680x *m680x = &info->m680x;
1622 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1623 
1624 	// bit index is coded in Opcode
1625 	op->type = M680X_OP_CONSTANT;
1626 	op->const_val = (MI->Opcode & 0x0e) >> 1;
1627 }
1628 
1629 // handler for bit test and branch instruction. Used by M6805.
1630 // The bit index is part of the opcode.
1631 // Example: BRSET 3,<$40,LOOP
opidx_dir_rel_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1632 static void opidx_dir_rel_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1633 {
1634 	cs_m680x *m680x = &info->m680x;
1635 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1636 
1637 	// bit index is coded in Opcode
1638 	op->type = M680X_OP_CONSTANT;
1639 	op->const_val = (MI->Opcode & 0x0e) >> 1;
1640 	direct_hdlr(MI, info, address);
1641 	relative8_hdlr(MI, info, address);
1642 
1643 	add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY);
1644 }
1645 
indexedX0_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1646 static void indexedX0_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1647 {
1648 	add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_NONE,
1649 		0, false);
1650 }
1651 
indexedX16_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1652 static void indexedX16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1653 {
1654 	uint16_t offset = 0;
1655 
1656 	read_word(info, &offset, *address);
1657 	*address += 2;
1658 	add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_BITS_16,
1659 		offset, false);
1660 }
1661 
imm_rel_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1662 static void imm_rel_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1663 {
1664 	immediate_hdlr(MI, info, address);
1665 	relative8_hdlr(MI, info, address);
1666 }
1667 
indexedS_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1668 static void indexedS_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1669 {
1670 	uint8_t offset = 0;
1671 
1672 	read_byte(info, &offset, (*address)++);
1673 
1674 	add_indexed_operand(info, M680X_REG_S, false, 0, M680X_OFFSET_BITS_8,
1675 		(uint16_t)offset, false);
1676 }
1677 
indexedS16_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1678 static void indexedS16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1679 {
1680 	uint16_t offset = 0;
1681 
1682 	read_word(info, &offset, *address);
1683 	address += 2;
1684 
1685 	add_indexed_operand(info, M680X_REG_S, false, 0, M680X_OFFSET_BITS_16,
1686 		offset, false);
1687 }
1688 
indexedX0p_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1689 static void indexedX0p_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1690 {
1691 	add_indexed_operand(info, M680X_REG_X, true, 1, M680X_OFFSET_NONE,
1692 		0, true);
1693 }
1694 
indexedXp_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1695 static void indexedXp_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1696 {
1697 	uint8_t offset = 0;
1698 
1699 	read_byte(info, &offset, (*address)++);
1700 
1701 	add_indexed_operand(info, M680X_REG_X, true, 1, M680X_OFFSET_BITS_8,
1702 		(uint16_t)offset, false);
1703 }
1704 
imm_idx12_x_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1705 static void imm_idx12_x_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1706 {
1707 	cs_m680x *m680x = &info->m680x;
1708 	cs_m680x_op *op = &m680x->operands[m680x->op_count++];
1709 
1710 	indexed12_hdlr(MI, info, address);
1711 	op->type = M680X_OP_IMMEDIATE;
1712 
1713 	if (info->insn == M680X_INS_MOVW) {
1714 		uint16_t imm16 = 0;
1715 
1716 		read_word(info, &imm16, *address);
1717 		op->imm = (int16_t)imm16;
1718 		op->size = 2;
1719 	}
1720 	else {
1721 		uint8_t imm8 = 0;
1722 
1723 		read_byte(info, &imm8, *address);
1724 		op->imm = (int8_t)imm8;
1725 		op->size = 1;
1726 	}
1727 
1728 	set_operand_size(info, op, 1);
1729 }
1730 
ext_idx12_x_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1731 static void ext_idx12_x_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1732 {
1733 	cs_m680x *m680x = &info->m680x;
1734 	cs_m680x_op *op0 = &m680x->operands[m680x->op_count++];
1735 	uint16_t imm16 = 0;
1736 
1737 	indexed12_hdlr(MI, info, address);
1738 	read_word(info, &imm16, *address);
1739 	op0->type = M680X_OP_EXTENDED;
1740 	op0->ext.address = (int16_t)imm16;
1741 	set_operand_size(info, op0, 1);
1742 }
1743 
1744 // handler for CPU12 DBEQ/DNBE/IBEQ/IBNE/TBEQ/TBNE instructions.
1745 // Example: DBNE X,$1000
loop_hdlr(MCInst * MI,m680x_info * info,uint16_t * address)1746 static void loop_hdlr(MCInst *MI, m680x_info *info, uint16_t *address)
1747 {
1748 	static const m680x_reg index_to_reg_id[] = {
1749 		M680X_REG_A, M680X_REG_B, M680X_REG_INVALID, M680X_REG_INVALID,
1750 		M680X_REG_D, M680X_REG_X, M680X_REG_Y, M680X_REG_S,
1751 	};
1752 	static const m680x_insn index_to_insn_id[] = {
1753 		M680X_INS_DBEQ, M680X_INS_DBNE, M680X_INS_TBEQ, M680X_INS_TBNE,
1754 		M680X_INS_IBEQ, M680X_INS_IBNE, M680X_INS_ILLGL, M680X_INS_ILLGL
1755 	};
1756 	cs_m680x *m680x = &info->m680x;
1757 	uint8_t post_byte = 0;
1758 	uint8_t rel = 0;
1759 	cs_m680x_op *op;
1760 
1761 	read_byte(info, &post_byte, (*address)++);
1762 
1763 	info->insn = index_to_insn_id[(post_byte >> 5) & 0x07];
1764 
1765 	if (info->insn == M680X_INS_ILLGL) {
1766 		illegal_hdlr(MI, info, address);
1767 	};
1768 
1769 	read_byte(info, &rel, (*address)++);
1770 
1771 	add_reg_operand(info, index_to_reg_id[post_byte & 0x07]);
1772 
1773 	op = &m680x->operands[m680x->op_count++];
1774 
1775 	op->type = M680X_OP_RELATIVE;
1776 
1777 	op->rel.offset = (post_byte & 0x10) ? 0xff00 | rel : rel;
1778 
1779 	op->rel.address = *address + op->rel.offset;
1780 
1781 	add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL);
1782 }
1783 
1784 static void (*const g_insn_handler[])(MCInst *, m680x_info *, uint16_t *) = {
1785 	illegal_hdlr,
1786 	relative8_hdlr,
1787 	relative16_hdlr,
1788 	immediate_hdlr, // 8-bit
1789 	immediate_hdlr, // 16-bit
1790 	immediate_hdlr, // 32-bit
1791 	direct_hdlr,
1792 	extended_hdlr,
1793 	indexedX_hdlr,
1794 	indexedY_hdlr,
1795 	indexed09_hdlr,
1796 	inherent_hdlr,
1797 	reg_reg09_hdlr,
1798 	reg_bits_hdlr,
1799 	bit_move_hdlr,
1800 	tfm_hdlr,
1801 	opidx_hdlr,
1802 	opidx_dir_rel_hdlr,
1803 	indexedX0_hdlr,
1804 	indexedX16_hdlr,
1805 	imm_rel_hdlr,
1806 	indexedS_hdlr,
1807 	indexedS16_hdlr,
1808 	indexedXp_hdlr,
1809 	indexedX0p_hdlr,
1810 	indexed12_hdlr,
1811 	indexed12_hdlr, // subset of indexed12
1812 	reg_reg12_hdlr,
1813 	loop_hdlr,
1814 	index_hdlr,
1815 	imm_idx12_x_hdlr,
1816 	imm_idx12_x_hdlr,
1817 	ext_idx12_x_hdlr,
1818 }; /* handler function pointers */
1819 
1820 /* Disasemble one instruction at address and store in str_buff */
m680x_disassemble(MCInst * MI,m680x_info * info,uint16_t address)1821 static unsigned int m680x_disassemble(MCInst *MI, m680x_info *info,
1822 	uint16_t address)
1823 {
1824 	cs_m680x *m680x = &info->m680x;
1825 	cs_detail *detail = MI->flat_insn->detail;
1826 	uint16_t base_address = address;
1827 	insn_desc insn_description;
1828 	e_access_mode access_mode;
1829 
1830 	if (detail != NULL) {
1831 		memset(detail, 0, offsetof(cs_detail, m680x)+sizeof(cs_m680x));
1832 	}
1833 
1834 	memset(&insn_description, 0, sizeof(insn_description));
1835 	memset(m680x, 0, sizeof(*m680x));
1836 	info->insn_size = 1;
1837 
1838 	if (decode_insn(info, address, &insn_description)) {
1839 		m680x_reg reg;
1840 
1841 		if (insn_description.opcode > 0xff)
1842 			address += 2; // 8-bit opcode + page prefix
1843 		else
1844 			address++; // 8-bit opcode only
1845 
1846 		info->insn = insn_description.insn;
1847 
1848 		MCInst_setOpcode(MI, insn_description.opcode);
1849 
1850 		reg = g_insn_props[info->insn].reg0;
1851 
1852 		if (reg != M680X_REG_INVALID) {
1853 			if (reg == M680X_REG_HX &&
1854 				(!info->cpu->reg_byte_size[reg]))
1855 				reg = M680X_REG_X;
1856 
1857 			add_reg_operand(info, reg);
1858 			// First (or second) operand is a register which is
1859 			// part of the mnemonic
1860 			m680x->flags |= M680X_FIRST_OP_IN_MNEM;
1861 			reg = g_insn_props[info->insn].reg1;
1862 
1863 			if (reg != M680X_REG_INVALID) {
1864 				if (reg == M680X_REG_HX &&
1865 					(!info->cpu->reg_byte_size[reg]))
1866 					reg = M680X_REG_X;
1867 
1868 				add_reg_operand(info, reg);
1869 				m680x->flags |= M680X_SECOND_OP_IN_MNEM;
1870 			}
1871 		}
1872 
1873 		// Call addressing mode specific instruction handler
1874 		(g_insn_handler[insn_description.hid[0]])(MI, info,
1875 			&address);
1876 		(g_insn_handler[insn_description.hid[1]])(MI, info,
1877 			&address);
1878 
1879 		add_insn_group(detail, g_insn_props[info->insn].group);
1880 
1881 		if (g_insn_props[info->insn].cc_modified &&
1882 			(info->cpu->insn_cc_not_modified[0] != info->insn) &&
1883 			(info->cpu->insn_cc_not_modified[1] != info->insn))
1884 			add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY);
1885 
1886 		access_mode = g_insn_props[info->insn].access_mode;
1887 
1888 		// Fix for M6805 BSET/BCLR. It has a differnt operand order
1889 		// in comparison to the M6811
1890 		if ((info->cpu->insn_cc_not_modified[0] == info->insn) ||
1891 			(info->cpu->insn_cc_not_modified[1] == info->insn))
1892 			access_mode = rmmm;
1893 
1894 		build_regs_read_write_counts(MI, info, access_mode);
1895 		add_operators_access(MI, info, access_mode);
1896 
1897 		if (g_insn_props[info->insn].update_reg_access)
1898 			set_changed_regs_read_write_counts(MI, info);
1899 
1900 		info->insn_size = (uint8_t)insn_description.insn_size;
1901 
1902 		return info->insn_size;
1903 	}
1904 	else
1905 		MCInst_setOpcode(MI, insn_description.opcode);
1906 
1907 	// Illegal instruction
1908 	address = base_address;
1909 	illegal_hdlr(MI, info, &address);
1910 	return 1;
1911 }
1912 
1913 // Tables to get the byte size of a register on the CPU
1914 // based on an enum m680x_reg value.
1915 // Invalid registers return 0.
1916 static const uint8_t g_m6800_reg_byte_size[22] = {
1917 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1918 	0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0
1919 };
1920 
1921 static const uint8_t g_m6805_reg_byte_size[22] = {
1922 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1923 	0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0
1924 };
1925 
1926 static const uint8_t g_m6808_reg_byte_size[22] = {
1927 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1928 	0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, 1, 0, 2, 0, 0, 0, 2, 0, 0
1929 };
1930 
1931 static const uint8_t g_m6801_reg_byte_size[22] = {
1932 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1933 	0, 1, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0
1934 };
1935 
1936 static const uint8_t g_m6811_reg_byte_size[22] = {
1937 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1938 	0, 1, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 0, 0
1939 };
1940 
1941 static const uint8_t g_cpu12_reg_byte_size[22] = {
1942 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1943 	0, 1, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2
1944 };
1945 
1946 static const uint8_t g_m6809_reg_byte_size[22] = {
1947 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1948 	0, 1, 1, 0, 0, 0, 2, 0, 1, 1, 0, 0, 0, 2, 2, 2, 2, 0, 0, 2, 0, 0
1949 };
1950 
1951 static const uint8_t g_hd6309_reg_byte_size[22] = {
1952 	// A  B  E  F  0  D  W  CC DP MD HX H  X  Y  S  U  V  Q  PC T2 T3
1953 	0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 4, 2, 0, 0
1954 };
1955 
1956 // Table to check for a valid register nibble on the M6809 CPU
1957 // used for TFR and EXG instruction.
1958 static const bool m6809_tfr_reg_valid[16] = {
1959 	true, true, true, true, true,  true,  false, false,
1960 	true, true, true, true, false, false, false, false,
1961 };
1962 
1963 static const cpu_tables g_cpu_tables[] = {
1964 	{
1965 		// M680X_CPU_TYPE_INVALID
1966 		NULL,
1967 		{ NULL, NULL },
1968 		{ 0, 0 },
1969 		{ 0x00, 0x00, 0x00 },
1970 		{ NULL, NULL, NULL },
1971 		{ 0, 0, 0 },
1972 		NULL,
1973 		NULL,
1974 		{ M680X_INS_INVLD, M680X_INS_INVLD }
1975 	},
1976 	{
1977 		// M680X_CPU_TYPE_6301
1978 		&g_m6800_inst_page1_table[0],
1979 		{ &g_m6801_inst_overlay_table[0], &g_hd6301_inst_overlay_table[0] },
1980 		{
1981 			ARR_SIZE(g_m6801_inst_overlay_table),
1982 			ARR_SIZE(g_hd6301_inst_overlay_table)
1983 		},
1984 		{ 0x00, 0x00, 0x00 },
1985 		{ NULL, NULL, NULL },
1986 		{ 0, 0, 0 },
1987 		&g_m6801_reg_byte_size[0],
1988 		NULL,
1989 		{ M680X_INS_INVLD, M680X_INS_INVLD }
1990 	},
1991 	{
1992 		// M680X_CPU_TYPE_6309
1993 		&g_m6809_inst_page1_table[0],
1994 		{ &g_hd6309_inst_overlay_table[0], NULL },
1995 		{ ARR_SIZE(g_hd6309_inst_overlay_table), 0 },
1996 		{ 0x10, 0x11, 0x00 },
1997 		{ &g_hd6309_inst_page2_table[0], &g_hd6309_inst_page3_table[0], NULL },
1998 		{
1999 			ARR_SIZE(g_hd6309_inst_page2_table),
2000 			ARR_SIZE(g_hd6309_inst_page3_table),
2001 			0
2002 		},
2003 		&g_hd6309_reg_byte_size[0],
2004 		NULL,
2005 		{ M680X_INS_INVLD, M680X_INS_INVLD }
2006 	},
2007 	{
2008 		// M680X_CPU_TYPE_6800
2009 		&g_m6800_inst_page1_table[0],
2010 		{ NULL, NULL },
2011 		{ 0, 0 },
2012 		{ 0x00, 0x00, 0x00 },
2013 		{ NULL, NULL, NULL },
2014 		{ 0, 0, 0 },
2015 		&g_m6800_reg_byte_size[0],
2016 		NULL,
2017 		{ M680X_INS_INVLD, M680X_INS_INVLD }
2018 	},
2019 	{
2020 		// M680X_CPU_TYPE_6801
2021 		&g_m6800_inst_page1_table[0],
2022 		{ &g_m6801_inst_overlay_table[0], NULL },
2023 		{ ARR_SIZE(g_m6801_inst_overlay_table), 0 },
2024 		{ 0x00, 0x00, 0x00 },
2025 		{ NULL, NULL, NULL },
2026 		{ 0, 0, 0 },
2027 		&g_m6801_reg_byte_size[0],
2028 		NULL,
2029 		{ M680X_INS_INVLD, M680X_INS_INVLD }
2030 	},
2031 	{
2032 		// M680X_CPU_TYPE_6805
2033 		&g_m6805_inst_page1_table[0],
2034 		{ NULL, NULL },
2035 		{ 0, 0 },
2036 		{ 0x00, 0x00, 0x00 },
2037 		{ NULL, NULL, NULL },
2038 		{ 0, 0, 0 },
2039 		&g_m6805_reg_byte_size[0],
2040 		NULL,
2041 		{ M680X_INS_BCLR, M680X_INS_BSET }
2042 	},
2043 	{
2044 		// M680X_CPU_TYPE_6808
2045 		&g_m6805_inst_page1_table[0],
2046 		{ &g_m6808_inst_overlay_table[0], NULL },
2047 		{ ARR_SIZE(g_m6808_inst_overlay_table), 0 },
2048 		{ 0x9E, 0x00, 0x00 },
2049 		{ &g_m6808_inst_page2_table[0], NULL, NULL },
2050 		{ ARR_SIZE(g_m6808_inst_page2_table), 0, 0 },
2051 		&g_m6808_reg_byte_size[0],
2052 		NULL,
2053 		{ M680X_INS_BCLR, M680X_INS_BSET }
2054 	},
2055 	{
2056 		// M680X_CPU_TYPE_6809
2057 		&g_m6809_inst_page1_table[0],
2058 		{ NULL, NULL },
2059 		{ 0, 0 },
2060 		{ 0x10, 0x11, 0x00 },
2061 		{
2062 			&g_m6809_inst_page2_table[0],
2063 			&g_m6809_inst_page3_table[0],
2064 			NULL
2065 		},
2066 		{
2067 			ARR_SIZE(g_m6809_inst_page2_table),
2068 			ARR_SIZE(g_m6809_inst_page3_table),
2069 			0
2070 		},
2071 		&g_m6809_reg_byte_size[0],
2072 		&m6809_tfr_reg_valid[0],
2073 		{ M680X_INS_INVLD, M680X_INS_INVLD }
2074 	},
2075 	{
2076 		// M680X_CPU_TYPE_6811
2077 		&g_m6800_inst_page1_table[0],
2078 		{
2079 			&g_m6801_inst_overlay_table[0],
2080 			&g_m6811_inst_overlay_table[0]
2081 		},
2082 		{
2083 			ARR_SIZE(g_m6801_inst_overlay_table),
2084 			ARR_SIZE(g_m6811_inst_overlay_table)
2085 		},
2086 		{ 0x18, 0x1A, 0xCD },
2087 		{
2088 			&g_m6811_inst_page2_table[0],
2089 			&g_m6811_inst_page3_table[0],
2090 			&g_m6811_inst_page4_table[0]
2091 		},
2092 		{
2093 			ARR_SIZE(g_m6811_inst_page2_table),
2094 			ARR_SIZE(g_m6811_inst_page3_table),
2095 			ARR_SIZE(g_m6811_inst_page4_table)
2096 		},
2097 		&g_m6811_reg_byte_size[0],
2098 		NULL,
2099 		{ M680X_INS_INVLD, M680X_INS_INVLD }
2100 	},
2101 	{
2102 		// M680X_CPU_TYPE_CPU12
2103 		&g_cpu12_inst_page1_table[0],
2104 		{ NULL, NULL },
2105 		{ 0, 0 },
2106 		{ 0x18, 0x00, 0x00 },
2107 		{ &g_cpu12_inst_page2_table[0], NULL, NULL },
2108 		{ ARR_SIZE(g_cpu12_inst_page2_table), 0, 0 },
2109 		&g_cpu12_reg_byte_size[0],
2110 		NULL,
2111 		{ M680X_INS_INVLD, M680X_INS_INVLD }
2112 	},
2113 	{
2114 		// M680X_CPU_TYPE_HCS08
2115 		&g_m6805_inst_page1_table[0],
2116 		{
2117 			&g_m6808_inst_overlay_table[0],
2118 			&g_hcs08_inst_overlay_table[0]
2119 		},
2120 		{
2121 			ARR_SIZE(g_m6808_inst_overlay_table),
2122 			ARR_SIZE(g_hcs08_inst_overlay_table)
2123 		},
2124 		{ 0x9E, 0x00, 0x00 },
2125 		{ &g_hcs08_inst_page2_table[0], NULL, NULL },
2126 		{ ARR_SIZE(g_hcs08_inst_page2_table), 0, 0 },
2127 		&g_m6808_reg_byte_size[0],
2128 		NULL,
2129 		{ M680X_INS_BCLR, M680X_INS_BSET }
2130 	},
2131 };
2132 
2133 static const char * const s_cpu_type[] = {
2134 	"INVALID", "6301", "6309", "6800", "6801", "6805", "6808",
2135 	"6809", "6811", "CPU12", "HCS08",
2136 };
2137 
m680x_setup_internals(m680x_info * info,e_cpu_type cpu_type,uint16_t address,const uint8_t * code,uint16_t code_len)2138 static bool m680x_setup_internals(m680x_info *info, e_cpu_type cpu_type,
2139 	uint16_t address,
2140 	const uint8_t *code, uint16_t code_len)
2141 {
2142 	if (cpu_type == M680X_CPU_TYPE_INVALID) {
2143 		return false;
2144 	}
2145 
2146 	info->code = code;
2147 	info->size = code_len;
2148 	info->offset = address;
2149 	info->cpu_type = cpu_type;
2150 
2151 	info->cpu = &g_cpu_tables[info->cpu_type];
2152 
2153 	return true;
2154 }
2155 
M680X_getInstruction(csh ud,const uint8_t * code,size_t code_len,MCInst * MI,uint16_t * size,uint64_t address,void * inst_info)2156 bool M680X_getInstruction(csh ud, const uint8_t *code, size_t code_len,
2157 	MCInst *MI, uint16_t *size, uint64_t address, void *inst_info)
2158 {
2159 	unsigned int insn_size = 0;
2160 	e_cpu_type cpu_type = M680X_CPU_TYPE_INVALID; // No default CPU type
2161 	cs_struct *handle = (cs_struct *)ud;
2162 	m680x_info *info = (m680x_info *)handle->printer_info;
2163 
2164 	MCInst_clear(MI);
2165 
2166 	if (handle->mode & CS_MODE_M680X_6800)
2167 		cpu_type = M680X_CPU_TYPE_6800;
2168 
2169 	else if (handle->mode & CS_MODE_M680X_6801)
2170 		cpu_type = M680X_CPU_TYPE_6801;
2171 
2172 	else if (handle->mode & CS_MODE_M680X_6805)
2173 		cpu_type = M680X_CPU_TYPE_6805;
2174 
2175 	else if (handle->mode & CS_MODE_M680X_6808)
2176 		cpu_type = M680X_CPU_TYPE_6808;
2177 
2178 	else if (handle->mode & CS_MODE_M680X_HCS08)
2179 		cpu_type = M680X_CPU_TYPE_HCS08;
2180 
2181 	else if (handle->mode & CS_MODE_M680X_6809)
2182 		cpu_type = M680X_CPU_TYPE_6809;
2183 
2184 	else if (handle->mode & CS_MODE_M680X_6301)
2185 		cpu_type = M680X_CPU_TYPE_6301;
2186 
2187 	else if (handle->mode & CS_MODE_M680X_6309)
2188 		cpu_type = M680X_CPU_TYPE_6309;
2189 
2190 	else if (handle->mode & CS_MODE_M680X_6811)
2191 		cpu_type = M680X_CPU_TYPE_6811;
2192 
2193 	else if (handle->mode & CS_MODE_M680X_CPU12)
2194 		cpu_type = M680X_CPU_TYPE_CPU12;
2195 
2196 	if (cpu_type != M680X_CPU_TYPE_INVALID &&
2197 		m680x_setup_internals(info, cpu_type, (uint16_t)address, code,
2198 			(uint16_t)code_len))
2199 		insn_size = m680x_disassemble(MI, info, (uint16_t)address);
2200 
2201 	if (insn_size == 0) {
2202 		*size = 1;
2203 		return false;
2204 	}
2205 
2206 	// Make sure we always stay within range
2207 	if (insn_size > code_len) {
2208 		*size = (uint16_t)code_len;
2209 		return false;
2210 	}
2211 	else
2212 		*size = (uint16_t)insn_size;
2213 
2214 	return true;
2215 }
2216 
M680X_disassembler_init(cs_struct * ud)2217 cs_err M680X_disassembler_init(cs_struct *ud)
2218 {
2219 	if (M680X_REG_ENDING != ARR_SIZE(g_m6800_reg_byte_size)) {
2220 		CS_ASSERT(M680X_REG_ENDING == ARR_SIZE(g_m6800_reg_byte_size));
2221 
2222 		return CS_ERR_MODE;
2223 	}
2224 
2225 	if (M680X_REG_ENDING != ARR_SIZE(g_m6801_reg_byte_size)) {
2226 		CS_ASSERT(M680X_REG_ENDING == ARR_SIZE(g_m6801_reg_byte_size));
2227 
2228 		return CS_ERR_MODE;
2229 	}
2230 
2231 	if (M680X_REG_ENDING != ARR_SIZE(g_m6805_reg_byte_size)) {
2232 		CS_ASSERT(M680X_REG_ENDING == ARR_SIZE(g_m6805_reg_byte_size));
2233 
2234 		return CS_ERR_MODE;
2235 	}
2236 
2237 	if (M680X_REG_ENDING != ARR_SIZE(g_m6808_reg_byte_size)) {
2238 		CS_ASSERT(M680X_REG_ENDING == ARR_SIZE(g_m6808_reg_byte_size));
2239 
2240 		return CS_ERR_MODE;
2241 	}
2242 
2243 	if (M680X_REG_ENDING != ARR_SIZE(g_m6811_reg_byte_size)) {
2244 		CS_ASSERT(M680X_REG_ENDING == ARR_SIZE(g_m6811_reg_byte_size));
2245 
2246 		return CS_ERR_MODE;
2247 	}
2248 
2249 	if (M680X_REG_ENDING != ARR_SIZE(g_cpu12_reg_byte_size)) {
2250 		CS_ASSERT(M680X_REG_ENDING == ARR_SIZE(g_cpu12_reg_byte_size));
2251 
2252 		return CS_ERR_MODE;
2253 	}
2254 
2255 	if (M680X_REG_ENDING != ARR_SIZE(g_m6809_reg_byte_size)) {
2256 		CS_ASSERT(M680X_REG_ENDING == ARR_SIZE(g_m6809_reg_byte_size));
2257 
2258 		return CS_ERR_MODE;
2259 	}
2260 
2261 	if (M680X_INS_ENDING != ARR_SIZE(g_insn_props)) {
2262 		CS_ASSERT(M680X_INS_ENDING == ARR_SIZE(g_insn_props));
2263 
2264 		return CS_ERR_MODE;
2265 	}
2266 
2267 	if (M680X_CPU_TYPE_ENDING != ARR_SIZE(s_cpu_type)) {
2268 		CS_ASSERT(M680X_CPU_TYPE_ENDING == ARR_SIZE(s_cpu_type));
2269 
2270 		return CS_ERR_MODE;
2271 	}
2272 
2273 	if (M680X_CPU_TYPE_ENDING != ARR_SIZE(g_cpu_tables)) {
2274 		CS_ASSERT(M680X_CPU_TYPE_ENDING == ARR_SIZE(g_cpu_tables));
2275 
2276 		return CS_ERR_MODE;
2277 	}
2278 
2279 	if (HANDLER_ID_ENDING != ARR_SIZE(g_insn_handler)) {
2280 		CS_ASSERT(HANDLER_ID_ENDING == ARR_SIZE(g_insn_handler));
2281 
2282 		return CS_ERR_MODE;
2283 	}
2284 
2285 	if (ACCESS_MODE_ENDING !=  MATRIX_SIZE(g_access_mode_to_access)) {
2286 		CS_ASSERT(ACCESS_MODE_ENDING ==
2287 			MATRIX_SIZE(g_access_mode_to_access));
2288 
2289 		return CS_ERR_MODE;
2290 	}
2291 
2292 	return CS_ERR_OK;
2293 }
2294 
2295 #ifndef CAPSTONE_DIET
M680X_reg_access(const cs_insn * insn,cs_regs regs_read,uint8_t * regs_read_count,cs_regs regs_write,uint8_t * regs_write_count)2296 void M680X_reg_access(const cs_insn *insn,
2297 	cs_regs regs_read, uint8_t *regs_read_count,
2298 	cs_regs regs_write, uint8_t *regs_write_count)
2299 {
2300 	if (insn->detail == NULL) {
2301 		*regs_read_count = 0;
2302 		*regs_write_count = 0;
2303 	}
2304 	else {
2305 		*regs_read_count = insn->detail->regs_read_count;
2306 		*regs_write_count = insn->detail->regs_write_count;
2307 
2308 		memcpy(regs_read, insn->detail->regs_read,
2309 			*regs_read_count * sizeof(insn->detail->regs_read[0]));
2310 		memcpy(regs_write, insn->detail->regs_write,
2311 			*regs_write_count *
2312 			sizeof(insn->detail->regs_write[0]));
2313 	}
2314 }
2315 #endif
2316 
2317 #endif
2318 
2319