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