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