/src/capstonenext/arch/M680X/M680XDisassembler.c
| Line | Count | Source (jump to first uncovered line) | 
| 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 | 471k | { | 
| 157 | 471k |   if (address < info->offset || | 
| 158 | 471k |     (uint32_t)(address - info->offset) >= info->size) | 
| 159 |  |     // out of code buffer range | 
| 160 | 1.09k |     return false; | 
| 161 |  |  | 
| 162 | 470k |   *byte = info->code[address - info->offset]; | 
| 163 |  |  | 
| 164 | 470k |   return true; | 
| 165 | 471k | } | 
| 166 |  |  | 
| 167 |  | static bool read_byte_sign_extended(const m680x_info *info, int16_t *word, | 
| 168 |  |   uint16_t address) | 
| 169 | 29.0k | { | 
| 170 | 29.0k |   if (address < info->offset || | 
| 171 | 29.0k |     (uint32_t)(address - info->offset) >= info->size) | 
| 172 |  |     // out of code buffer range | 
| 173 | 0 |     return false; | 
| 174 |  |  | 
| 175 | 29.0k |   *word = (int16_t) info->code[address - info->offset]; | 
| 176 |  |  | 
| 177 | 29.0k |   if (*word & 0x80) | 
| 178 | 11.3k |     *word |= 0xFF00; | 
| 179 |  |  | 
| 180 | 29.0k |   return true; | 
| 181 | 29.0k | } | 
| 182 |  |  | 
| 183 |  | static bool read_word(const m680x_info *info, uint16_t *word, uint16_t address) | 
| 184 | 35.2k | { | 
| 185 | 35.2k |   if (address < info->offset || | 
| 186 | 35.2k |     (uint32_t)(address + 1 - info->offset) >= info->size) | 
| 187 |  |     // out of code buffer range | 
| 188 | 10 |     return false; | 
| 189 |  |  | 
| 190 | 35.2k |   *word = (uint16_t)info->code[address - info->offset] << 8; | 
| 191 | 35.2k |   *word |= (uint16_t)info->code[address + 1 - info->offset]; | 
| 192 |  |  | 
| 193 | 35.2k |   return true; | 
| 194 | 35.2k | } | 
| 195 |  |  | 
| 196 |  | static bool read_sdword(const m680x_info *info, int32_t *sdword, | 
| 197 |  |   uint16_t address) | 
| 198 | 264 | { | 
| 199 | 264 |   if (address < info->offset || | 
| 200 | 264 |     (uint32_t)(address + 3 - info->offset) >= info->size) | 
| 201 |  |     // out of code buffer range | 
| 202 | 0 |     return false; | 
| 203 |  |  | 
| 204 | 264 |   *sdword = (uint32_t)info->code[address - info->offset] << 24; | 
| 205 | 264 |   *sdword |= (uint32_t)info->code[address + 1 - info->offset] << 16; | 
| 206 | 264 |   *sdword |= (uint32_t)info->code[address + 2 - info->offset] << 8; | 
| 207 | 264 |   *sdword |= (uint32_t)info->code[address + 3 - info->offset]; | 
| 208 |  |  | 
| 209 | 264 |   return true; | 
| 210 | 264 | } | 
| 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 | 81.2k | { | 
| 219 |  |   // As part of the algorithm last may get negative. | 
| 220 |  |   // => signed integer has to be used. | 
| 221 | 81.2k |   int first = 0; | 
| 222 | 81.2k |   int last = (int)table_size - 1; | 
| 223 | 81.2k |   int middle = (first + last) / 2; | 
| 224 |  |  | 
| 225 | 399k |   while (first <= last) { | 
| 226 | 366k |     if (inst_pageX_table[middle].opcode < opcode) { | 
| 227 | 124k |       first = middle + 1; | 
| 228 | 124k |     } | 
| 229 | 242k |     else if (inst_pageX_table[middle].opcode == opcode) { | 
| 230 | 48.2k |       return middle;  /* item found */ | 
| 231 | 48.2k |     } | 
| 232 | 194k |     else | 
| 233 | 194k |       last = middle - 1; | 
| 234 |  |  | 
| 235 | 318k |     middle = (first + last) / 2; | 
| 236 | 318k |   } | 
| 237 |  |  | 
| 238 | 32.9k |   if (first > last) | 
| 239 | 32.9k |     return -1;  /* item not found */ | 
| 240 |  |  | 
| 241 | 0 |   return -2; | 
| 242 | 32.9k | } | 
| 243 |  |  | 
| 244 |  | void M680X_get_insn_id(cs_struct *handle, cs_insn *insn, unsigned int id) | 
| 245 | 197k | { | 
| 246 | 197k |   const m680x_info *const info = (const m680x_info *)handle->printer_info; | 
| 247 | 197k |   const cpu_tables *cpu = info->cpu; | 
| 248 | 197k |   uint8_t insn_prefix = (id >> 8) & 0xff; | 
| 249 |  |   // opcode is the first instruction byte without the prefix. | 
| 250 | 197k |   uint8_t opcode = id & 0xff; | 
| 251 | 197k |   int index; | 
| 252 | 197k |   int i; | 
| 253 |  |  | 
| 254 | 197k |   insn->id = M680X_INS_ILLGL; | 
| 255 |  |  | 
| 256 | 466k |   for (i = 0; i < ARR_SIZE(cpu->pageX_prefix); ++i) { | 
| 257 | 454k |     if (cpu->pageX_table_size[i] == 0 || | 
| 258 | 454k |       (cpu->inst_pageX_table[i] == NULL)) | 
| 259 | 169k |       break; | 
| 260 |  |  | 
| 261 | 285k |     if (cpu->pageX_prefix[i] == insn_prefix) { | 
| 262 | 17.2k |       index = binary_search(cpu->inst_pageX_table[i], | 
| 263 | 17.2k |           cpu->pageX_table_size[i], opcode); | 
| 264 | 17.2k |       insn->id = (index >= 0) ? | 
| 265 | 12.9k |         cpu->inst_pageX_table[i][index].insn : | 
| 266 | 17.2k |         M680X_INS_ILLGL; | 
| 267 | 17.2k |       return; | 
| 268 | 17.2k |     } | 
| 269 | 285k |   } | 
| 270 |  |  | 
| 271 | 180k |   if (insn_prefix != 0) | 
| 272 | 0 |     return; | 
| 273 |  |  | 
| 274 | 180k |   insn->id = cpu->inst_page1_table[id].insn; | 
| 275 |  |  | 
| 276 | 180k |   if (insn->id != M680X_INS_ILLGL) | 
| 277 | 158k |     return; | 
| 278 |  |  | 
| 279 |  |   // Check if opcode byte is present in an overlay table | 
| 280 | 34.6k |   for (i = 0; i < ARR_SIZE(cpu->overlay_table_size); ++i) { | 
| 281 | 33.7k |     if (cpu->overlay_table_size[i] == 0 || | 
| 282 | 33.7k |       (cpu->inst_overlay_table[i] == NULL)) | 
| 283 | 10.2k |       break; | 
| 284 |  |  | 
| 285 | 23.4k |     if ((index = binary_search(cpu->inst_overlay_table[i], | 
| 286 | 23.4k |             cpu->overlay_table_size[i], | 
| 287 | 23.4k |             opcode)) >= 0) { | 
| 288 | 11.2k |       insn->id = cpu->inst_overlay_table[i][index].insn; | 
| 289 | 11.2k |       return; | 
| 290 | 11.2k |     } | 
| 291 | 23.4k |   } | 
| 292 | 22.4k | } | 
| 293 |  |  | 
| 294 |  | static void add_insn_group(cs_detail *detail, m680x_group_type group) | 
| 295 | 189k | { | 
| 296 | 189k |   if (detail != NULL && | 
| 297 | 189k |     (group != M680X_GRP_INVALID) && (group != M680X_GRP_ENDING)) | 
| 298 | 42.2k |     detail->groups[detail->groups_count++] = (uint8_t)group; | 
| 299 | 189k | } | 
| 300 |  |  | 
| 301 |  | static bool exists_reg_list(uint16_t *regs, uint8_t count, m680x_reg reg) | 
| 302 | 538k | { | 
| 303 | 538k |   uint8_t i; | 
| 304 |  |  | 
| 305 | 894k |   for (i = 0; i < count; ++i) { | 
| 306 | 373k |     if (regs[i] == (uint16_t)reg) | 
| 307 | 17.3k |       return true; | 
| 308 | 373k |   } | 
| 309 |  |  | 
| 310 | 520k |   return false; | 
| 311 | 538k | } | 
| 312 |  |  | 
| 313 |  | static void add_reg_to_rw_list(MCInst *MI, m680x_reg reg, e_access access) | 
| 314 | 355k | { | 
| 315 | 355k |   cs_detail *detail = MI->flat_insn->detail; | 
| 316 |  |  | 
| 317 | 355k |   if (detail == NULL || (reg == M680X_REG_INVALID)) | 
| 318 | 0 |     return; | 
| 319 |  |  | 
| 320 | 355k |   switch (access) { | 
| 321 | 182k |   case MODIFY: | 
| 322 | 182k |     if (!exists_reg_list(detail->regs_read, | 
| 323 | 182k |         detail->regs_read_count, reg)) | 
| 324 | 178k |       detail->regs_read[detail->regs_read_count++] = | 
| 325 | 178k |         (uint16_t)reg; | 
| 326 |  |  | 
| 327 |  |   // intentionally fall through | 
| 328 |  |  | 
| 329 | 235k |   case WRITE: | 
| 330 | 235k |     if (!exists_reg_list(detail->regs_write, | 
| 331 | 235k |         detail->regs_write_count, reg)) | 
| 332 | 230k |       detail->regs_write[detail->regs_write_count++] = | 
| 333 | 230k |         (uint16_t)reg; | 
| 334 |  |  | 
| 335 | 235k |     break; | 
| 336 |  |  | 
| 337 | 120k |   case READ: | 
| 338 | 120k |     if (!exists_reg_list(detail->regs_read, | 
| 339 | 120k |         detail->regs_read_count, reg)) | 
| 340 | 112k |       detail->regs_read[detail->regs_read_count++] = | 
| 341 | 112k |         (uint16_t)reg; | 
| 342 |  |  | 
| 343 | 120k |     break; | 
| 344 |  |  | 
| 345 | 0 |   case UNCHANGED: | 
| 346 | 0 |   default: | 
| 347 | 0 |     break; | 
| 348 | 355k |   } | 
| 349 | 355k | } | 
| 350 |  |  | 
| 351 |  | static void update_am_reg_list(MCInst *MI, m680x_info *info, cs_m680x_op *op, | 
| 352 |  |   e_access access) | 
| 353 | 251k | { | 
| 354 | 251k |   if (MI->flat_insn->detail == NULL) | 
| 355 | 0 |     return; | 
| 356 |  |  | 
| 357 | 251k |   switch (op->type) { | 
| 358 | 110k |   case M680X_OP_REGISTER: | 
| 359 | 110k |     add_reg_to_rw_list(MI, op->reg, access); | 
| 360 | 110k |     break; | 
| 361 |  |  | 
| 362 | 50.5k |   case M680X_OP_INDEXED: | 
| 363 | 50.5k |     add_reg_to_rw_list(MI, op->idx.base_reg, READ); | 
| 364 |  |  | 
| 365 | 50.5k |     if (op->idx.base_reg == M680X_REG_X && | 
| 366 | 50.5k |       info->cpu->reg_byte_size[M680X_REG_H]) | 
| 367 | 5.95k |       add_reg_to_rw_list(MI, M680X_REG_H, READ); | 
| 368 |  |  | 
| 369 |  |  | 
| 370 | 50.5k |     if (op->idx.offset_reg != M680X_REG_INVALID) | 
| 371 | 4.30k |       add_reg_to_rw_list(MI, op->idx.offset_reg, READ); | 
| 372 |  |  | 
| 373 | 50.5k |     if (op->idx.inc_dec) { | 
| 374 | 10.7k |       add_reg_to_rw_list(MI, op->idx.base_reg, WRITE); | 
| 375 |  |  | 
| 376 | 10.7k |       if (op->idx.base_reg == M680X_REG_X && | 
| 377 | 10.7k |         info->cpu->reg_byte_size[M680X_REG_H]) | 
| 378 | 896 |         add_reg_to_rw_list(MI, M680X_REG_H, WRITE); | 
| 379 | 10.7k |     } | 
| 380 |  |  | 
| 381 | 50.5k |     break; | 
| 382 |  |  | 
| 383 | 90.2k |   default: | 
| 384 | 90.2k |     break; | 
| 385 | 251k |   } | 
| 386 | 251k | } | 
| 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 | 539k | { | 
| 409 | 539k |   int idx = (operator_index > 3) ? 3 : operator_index; | 
| 410 |  |  | 
| 411 | 539k |   return g_access_mode_to_access[idx][access_mode]; | 
| 412 | 539k | } | 
| 413 |  |  | 
| 414 |  | static void build_regs_read_write_counts(MCInst *MI, m680x_info *info, | 
| 415 |  |   e_access_mode access_mode) | 
| 416 | 174k | { | 
| 417 | 174k |   cs_m680x *m680x = &info->m680x; | 
| 418 | 174k |   int i; | 
| 419 |  |  | 
| 420 | 174k |   if (MI->flat_insn->detail == NULL || (!m680x->op_count)) | 
| 421 | 27.2k |     return; | 
| 422 |  |  | 
| 423 | 398k |   for (i = 0; i < m680x->op_count; ++i) { | 
| 424 |  |  | 
| 425 | 251k |     e_access access = get_access(i, access_mode); | 
| 426 | 251k |     update_am_reg_list(MI, info, &m680x->operands[i], access); | 
| 427 | 251k |   } | 
| 428 | 146k | } | 
| 429 |  |  | 
| 430 |  | static void add_operators_access(MCInst *MI, m680x_info *info, | 
| 431 |  |   e_access_mode access_mode) | 
| 432 | 174k | { | 
| 433 | 174k |   cs_m680x *m680x = &info->m680x; | 
| 434 | 174k |   int offset = 0; | 
| 435 | 174k |   int i; | 
| 436 |  |  | 
| 437 | 174k |   if (MI->flat_insn->detail == NULL || (!m680x->op_count) || | 
| 438 | 174k |     (access_mode == uuuu)) | 
| 439 | 43.1k |     return; | 
| 440 |  |  | 
| 441 | 366k |   for (i = 0; i < m680x->op_count; ++i) { | 
| 442 | 234k |     e_access access; | 
| 443 |  |  | 
| 444 |  |     // Ugly fix: MULD has a register operand, an immediate operand | 
| 445 |  |     // AND an implicitly changed register W | 
| 446 | 234k |     if (info->insn == M680X_INS_MULD && (i == 1)) | 
| 447 | 232 |       offset = 1; | 
| 448 |  |  | 
| 449 | 234k |     access = get_access(i + offset, access_mode); | 
| 450 | 234k |     m680x->operands[i].access = access; | 
| 451 | 234k |   } | 
| 452 | 131k | } | 
| 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 | 19.9k | { | 
| 462 |  |   //TABLE | 
| 463 | 1.09M | #define EOL M680X_REG_INVALID | 
| 464 | 19.9k |   static const insn_to_changed_regs changed_regs[] = { | 
| 465 | 19.9k |     { M680X_INS_BSR, mmmm, { M680X_REG_S, EOL } }, | 
| 466 | 19.9k |     { M680X_INS_CALL, mmmm, { M680X_REG_S, EOL } }, | 
| 467 | 19.9k |     { | 
| 468 | 19.9k |       M680X_INS_CWAI, mrrr, { | 
| 469 | 19.9k |         M680X_REG_S, M680X_REG_PC, M680X_REG_U, | 
| 470 | 19.9k |         M680X_REG_Y, M680X_REG_X, M680X_REG_DP, | 
| 471 | 19.9k |         M680X_REG_D, M680X_REG_CC, EOL | 
| 472 | 19.9k |       }, | 
| 473 | 19.9k |     }, | 
| 474 | 19.9k |     { M680X_INS_DAA, mrrr, { M680X_REG_A, EOL } }, | 
| 475 | 19.9k |     { | 
| 476 | 19.9k |       M680X_INS_DIV, mmrr, { | 
| 477 | 19.9k |         M680X_REG_A, M680X_REG_H, M680X_REG_X, EOL | 
| 478 | 19.9k |       } | 
| 479 | 19.9k |     }, | 
| 480 | 19.9k |     { | 
| 481 | 19.9k |       M680X_INS_EDIV, mmrr, { | 
| 482 | 19.9k |         M680X_REG_D, M680X_REG_Y, M680X_REG_X, EOL | 
| 483 | 19.9k |       } | 
| 484 | 19.9k |     }, | 
| 485 | 19.9k |     { | 
| 486 | 19.9k |       M680X_INS_EDIVS, mmrr, { | 
| 487 | 19.9k |         M680X_REG_D, M680X_REG_Y, M680X_REG_X, EOL | 
| 488 | 19.9k |       } | 
| 489 | 19.9k |     }, | 
| 490 | 19.9k |     { M680X_INS_EMACS, mrrr, { M680X_REG_X, M680X_REG_Y, EOL } }, | 
| 491 | 19.9k |     { M680X_INS_EMAXM, rrrr, { M680X_REG_D, EOL } }, | 
| 492 | 19.9k |     { M680X_INS_EMINM, rrrr, { M680X_REG_D, EOL } }, | 
| 493 | 19.9k |     { M680X_INS_EMUL, mmrr, { M680X_REG_D, M680X_REG_Y, EOL } }, | 
| 494 | 19.9k |     { M680X_INS_EMULS, mmrr, { M680X_REG_D, M680X_REG_Y, EOL } }, | 
| 495 | 19.9k |     { M680X_INS_ETBL, wmmm, { M680X_REG_A, M680X_REG_B, EOL } }, | 
| 496 | 19.9k |     { M680X_INS_FDIV, mmmm, { M680X_REG_D, M680X_REG_X, EOL } }, | 
| 497 | 19.9k |     { M680X_INS_IDIV, mmmm, { M680X_REG_D, M680X_REG_X, EOL } }, | 
| 498 | 19.9k |     { M680X_INS_IDIVS, mmmm, { M680X_REG_D, M680X_REG_X, EOL } }, | 
| 499 | 19.9k |     { M680X_INS_JSR, mmmm, { M680X_REG_S, EOL } }, | 
| 500 | 19.9k |     { M680X_INS_LBSR, mmmm, { M680X_REG_S, EOL } }, | 
| 501 | 19.9k |     { M680X_INS_MAXM, rrrr, { M680X_REG_A, EOL } }, | 
| 502 | 19.9k |     { M680X_INS_MINM, rrrr, { M680X_REG_A, EOL } }, | 
| 503 | 19.9k |     { | 
| 504 | 19.9k |       M680X_INS_MEM, mmrr, { | 
| 505 | 19.9k |         M680X_REG_X, M680X_REG_Y, M680X_REG_A, EOL | 
| 506 | 19.9k |       } | 
| 507 | 19.9k |     }, | 
| 508 | 19.9k |     { M680X_INS_MUL, mmmm, { M680X_REG_A, M680X_REG_B, EOL } }, | 
| 509 | 19.9k |     { M680X_INS_MULD, mwrr, { M680X_REG_D, M680X_REG_W, EOL } }, | 
| 510 | 19.9k |     { M680X_INS_PSHA, rmmm, { M680X_REG_A, M680X_REG_S, EOL } }, | 
| 511 | 19.9k |     { M680X_INS_PSHB, rmmm, { M680X_REG_B, M680X_REG_S, EOL } }, | 
| 512 | 19.9k |     { M680X_INS_PSHC, rmmm, { M680X_REG_CC, M680X_REG_S, EOL } }, | 
| 513 | 19.9k |     { M680X_INS_PSHD, rmmm, { M680X_REG_D, M680X_REG_S, EOL } }, | 
| 514 | 19.9k |     { M680X_INS_PSHH, rmmm, { M680X_REG_H, M680X_REG_S, EOL } }, | 
| 515 | 19.9k |     { M680X_INS_PSHX, rmmm, { M680X_REG_X, M680X_REG_S, EOL } }, | 
| 516 | 19.9k |     { M680X_INS_PSHY, rmmm, { M680X_REG_Y, M680X_REG_S, EOL } }, | 
| 517 | 19.9k |     { M680X_INS_PULA, wmmm, { M680X_REG_A, M680X_REG_S, EOL } }, | 
| 518 | 19.9k |     { M680X_INS_PULB, wmmm, { M680X_REG_B, M680X_REG_S, EOL } }, | 
| 519 | 19.9k |     { M680X_INS_PULC, wmmm, { M680X_REG_CC, M680X_REG_S, EOL } }, | 
| 520 | 19.9k |     { M680X_INS_PULD, wmmm, { M680X_REG_D, M680X_REG_S, EOL } }, | 
| 521 | 19.9k |     { M680X_INS_PULH, wmmm, { M680X_REG_H, M680X_REG_S, EOL } }, | 
| 522 | 19.9k |     { M680X_INS_PULX, wmmm, { M680X_REG_X, M680X_REG_S, EOL } }, | 
| 523 | 19.9k |     { M680X_INS_PULY, wmmm, { M680X_REG_Y, M680X_REG_S, EOL } }, | 
| 524 | 19.9k |     { | 
| 525 | 19.9k |       M680X_INS_REV, mmrr, { | 
| 526 | 19.9k |         M680X_REG_A, M680X_REG_X, M680X_REG_Y, EOL | 
| 527 | 19.9k |       } | 
| 528 | 19.9k |     }, | 
| 529 | 19.9k |     { | 
| 530 | 19.9k |       M680X_INS_REVW, mmmm, { | 
| 531 | 19.9k |         M680X_REG_A, M680X_REG_X, M680X_REG_Y, EOL | 
| 532 | 19.9k |       } | 
| 533 | 19.9k |     }, | 
| 534 | 19.9k |     { M680X_INS_RTC, mwww, { M680X_REG_S, M680X_REG_PC, EOL } }, | 
| 535 | 19.9k |     { | 
| 536 | 19.9k |       M680X_INS_RTI, mwww, { | 
| 537 | 19.9k |         M680X_REG_S, M680X_REG_CC, M680X_REG_B, | 
| 538 | 19.9k |         M680X_REG_A, M680X_REG_DP, M680X_REG_X, | 
| 539 | 19.9k |         M680X_REG_Y, M680X_REG_U, M680X_REG_PC, | 
| 540 | 19.9k |         EOL | 
| 541 | 19.9k |       }, | 
| 542 | 19.9k |     }, | 
| 543 | 19.9k |     { M680X_INS_RTS, mwww, { M680X_REG_S, M680X_REG_PC, EOL } }, | 
| 544 | 19.9k |     { M680X_INS_SEX, wrrr, { M680X_REG_A, M680X_REG_B, EOL } }, | 
| 545 | 19.9k |     { M680X_INS_SEXW, rwww, { M680X_REG_W, M680X_REG_D, EOL } }, | 
| 546 | 19.9k |     { | 
| 547 | 19.9k |       M680X_INS_SWI, mmrr, { | 
| 548 | 19.9k |         M680X_REG_S, M680X_REG_PC, M680X_REG_U, | 
| 549 | 19.9k |         M680X_REG_Y, M680X_REG_X, M680X_REG_DP, | 
| 550 | 19.9k |         M680X_REG_A, M680X_REG_B, M680X_REG_CC, | 
| 551 | 19.9k |         EOL | 
| 552 | 19.9k |       } | 
| 553 | 19.9k |     }, | 
| 554 | 19.9k |     { | 
| 555 | 19.9k |       M680X_INS_SWI2, mmrr, { | 
| 556 | 19.9k |         M680X_REG_S, M680X_REG_PC, M680X_REG_U, | 
| 557 | 19.9k |         M680X_REG_Y, M680X_REG_X, M680X_REG_DP, | 
| 558 | 19.9k |         M680X_REG_A, M680X_REG_B, M680X_REG_CC, | 
| 559 | 19.9k |         EOL | 
| 560 | 19.9k |       }, | 
| 561 | 19.9k |     }, | 
| 562 | 19.9k |     { | 
| 563 | 19.9k |       M680X_INS_SWI3, mmrr, { | 
| 564 | 19.9k |         M680X_REG_S, M680X_REG_PC, M680X_REG_U, | 
| 565 | 19.9k |         M680X_REG_Y, M680X_REG_X, M680X_REG_DP, | 
| 566 | 19.9k |         M680X_REG_A, M680X_REG_B, M680X_REG_CC, | 
| 567 | 19.9k |         EOL | 
| 568 | 19.9k |       }, | 
| 569 | 19.9k |     }, | 
| 570 | 19.9k |     { M680X_INS_TBL, wrrr, { M680X_REG_A, M680X_REG_B, EOL } }, | 
| 571 | 19.9k |     { | 
| 572 | 19.9k |       M680X_INS_WAI, mrrr, { | 
| 573 | 19.9k |         M680X_REG_S, M680X_REG_PC, M680X_REG_X, | 
| 574 | 19.9k |         M680X_REG_A, M680X_REG_B, M680X_REG_CC, | 
| 575 | 19.9k |         EOL | 
| 576 | 19.9k |       } | 
| 577 | 19.9k |     }, | 
| 578 | 19.9k |     { | 
| 579 | 19.9k |       M680X_INS_WAV, rmmm, { | 
| 580 | 19.9k |         M680X_REG_A, M680X_REG_B, M680X_REG_X, | 
| 581 | 19.9k |         M680X_REG_Y, EOL | 
| 582 | 19.9k |       } | 
| 583 | 19.9k |     }, | 
| 584 | 19.9k |     { | 
| 585 | 19.9k |       M680X_INS_WAVR, rmmm, { | 
| 586 | 19.9k |         M680X_REG_A, M680X_REG_B, M680X_REG_X, | 
| 587 | 19.9k |         M680X_REG_Y, EOL | 
| 588 | 19.9k |       } | 
| 589 | 19.9k |     }, | 
| 590 | 19.9k |   }; | 
| 591 |  |  | 
| 592 | 19.9k |   int i, j; | 
| 593 |  |  | 
| 594 | 19.9k |   if (MI->flat_insn->detail == NULL) | 
| 595 | 0 |     return; | 
| 596 |  |  | 
| 597 | 1.03M |   for (i = 0; i < ARR_SIZE(changed_regs); ++i) { | 
| 598 | 1.01M |     if (info->insn == changed_regs[i].insn) { | 
| 599 | 19.9k |       e_access_mode access_mode = changed_regs[i].access_mode; | 
| 600 |  |  | 
| 601 | 76.0k |       for (j = 0; changed_regs[i].regs[j] != EOL; ++j) { | 
| 602 | 56.0k |         e_access access; | 
| 603 |  |  | 
| 604 | 56.0k |         m680x_reg reg = changed_regs[i].regs[j]; | 
| 605 |  |  | 
| 606 | 56.0k |         if (!info->cpu->reg_byte_size[reg]) { | 
| 607 | 3.74k |           if (info->insn != M680X_INS_MUL) | 
| 608 | 3.40k |             continue; | 
| 609 |  |  | 
| 610 |  |           // Hack for M68HC05: MUL uses reg. A,X | 
| 611 | 344 |           reg = M680X_REG_X; | 
| 612 | 344 |         } | 
| 613 |  |  | 
| 614 | 52.6k |         access = get_access(j, access_mode); | 
| 615 | 52.6k |         add_reg_to_rw_list(MI, reg, access); | 
| 616 | 52.6k |       } | 
| 617 | 19.9k |     } | 
| 618 | 1.01M |   } | 
| 619 |  |  | 
| 620 | 19.9k | #undef EOL | 
| 621 | 19.9k | } | 
| 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 | 21.0k | { | 
| 636 | 21.0k |   uint8_t ir = 0; | 
| 637 | 21.0k |   uint8_t post_byte; | 
| 638 |  |  | 
| 639 |  |   // Read the indexed addressing post byte. | 
| 640 | 21.0k |   if (!read_byte(info, &post_byte, address)) | 
| 641 | 117 |     return -1; | 
| 642 |  |  | 
| 643 |  |   // Depending on the indexed addressing mode more bytes have to be read. | 
| 644 | 20.9k |   switch (post_byte & 0x9F) { | 
| 645 | 337 |   case 0x87: | 
| 646 | 1.04k |   case 0x8A: | 
| 647 | 1.53k |   case 0x8E: | 
| 648 | 2.32k |   case 0x8F: | 
| 649 | 2.67k |   case 0x90: | 
| 650 | 3.13k |   case 0x92: | 
| 651 | 3.38k |   case 0x97: | 
| 652 | 3.85k |   case 0x9A: | 
| 653 | 4.10k |   case 0x9E: | 
| 654 | 4.10k |     return -1; // illegal indexed post bytes | 
| 655 |  |  | 
| 656 | 620 |   case 0x88: // n8,R | 
| 657 | 1.08k |   case 0x8C: // n8,PCR | 
| 658 | 1.43k |   case 0x98: // [n8,R] | 
| 659 | 1.95k |   case 0x9C: // [n8,PCR] | 
| 660 | 1.95k |     if (!read_byte(info, &ir, address + 1)) | 
| 661 | 20 |       return -1; | 
| 662 | 1.93k |     return 2; | 
| 663 |  |  | 
| 664 | 332 |   case 0x89: // n16,R | 
| 665 | 1.29k |   case 0x8D: // n16,PCR | 
| 666 | 1.91k |   case 0x99: // [n16,R] | 
| 667 | 2.20k |   case 0x9D: // [n16,PCR] | 
| 668 | 2.20k |     if (!read_byte(info, &ir, address + 2)) | 
| 669 | 47 |       return -1; | 
| 670 | 2.15k |     return 3; | 
| 671 |  |  | 
| 672 | 889 |   case 0x9F: // [n] | 
| 673 | 889 |     if ((post_byte & 0x60) != 0 || | 
| 674 | 889 |       !read_byte(info, &ir, address + 2)) | 
| 675 | 662 |       return -1; | 
| 676 | 227 |     return  3; | 
| 677 | 20.9k |   } | 
| 678 |  |  | 
| 679 |  |   // Any other indexed post byte is valid and | 
| 680 |  |   // no additional bytes have to be read. | 
| 681 | 11.8k |   return 1; | 
| 682 | 20.9k | } | 
| 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 | 23.2k | { | 
| 690 | 23.2k |   uint8_t ir; | 
| 691 | 23.2k |   uint8_t post_byte; | 
| 692 |  |  | 
| 693 |  |   // Read the indexed addressing post byte. | 
| 694 | 23.2k |   if (!read_byte(info, &post_byte, address)) | 
| 695 | 99 |     return -1; | 
| 696 |  |  | 
| 697 |  |   // Depending on the indexed addressing mode more bytes have to be read. | 
| 698 | 23.1k |   if (!(post_byte & 0x20)) // n5,R | 
| 699 | 7.97k |     return 1; | 
| 700 |  |  | 
| 701 | 15.2k |   switch (post_byte & 0xe7) { | 
| 702 | 912 |   case 0xe0: | 
| 703 | 2.60k |   case 0xe1: // n9,R | 
| 704 | 2.60k |     if (is_subset) | 
| 705 | 366 |       return -1; | 
| 706 |  |  | 
| 707 | 2.23k |     if (!read_byte(info, &ir, address)) | 
| 708 | 0 |       return -1; | 
| 709 | 2.23k |     return 2; | 
| 710 |  |  | 
| 711 | 1.55k |   case 0xe2: // n16,R | 
| 712 | 2.66k |   case 0xe3: // [n16,R] | 
| 713 | 2.66k |     if (is_subset) | 
| 714 | 295 |       return -1; | 
| 715 |  |  | 
| 716 | 2.37k |     if (!read_byte(info, &ir, address + 1)) | 
| 717 | 17 |       return -1; | 
| 718 | 2.35k |     return 3; | 
| 719 |  |  | 
| 720 | 717 |   case 0xe4: // A,R | 
| 721 | 1.06k |   case 0xe5: // B,R | 
| 722 | 1.89k |   case 0xe6: // D,R | 
| 723 | 2.57k |   case 0xe7: // [D,R] | 
| 724 | 9.93k |   default: // n,-r n,+r n,r- n,r+ | 
| 725 | 9.93k |     break; | 
| 726 | 15.2k |   } | 
| 727 |  |  | 
| 728 | 9.93k |   return 1; | 
| 729 | 15.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 | 2.62k | { | 
| 734 | 2.62k |   if (info->cpu->tfr_reg_valid != NULL) | 
| 735 | 1.11k |     return info->cpu->tfr_reg_valid[reg_nibble]; | 
| 736 |  |  | 
| 737 | 1.50k |   return true; // e.g. for the M6309 all registers are valid | 
| 738 | 2.62k | } | 
| 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 | 1.25k | { | 
| 744 | 1.25k |   return !(post_byte & 0x08); | 
| 745 | 1.25k | } | 
| 746 |  |  | 
| 747 |  | static bool is_tfm_reg_valid(const m680x_info *info, uint8_t reg_nibble) | 
| 748 | 893 | { | 
| 749 |  |   // HD6809 TFM instruction: Only register X,Y,U,S,D is allowed | 
| 750 | 893 |   return reg_nibble <= 4; | 
| 751 | 893 | } | 
| 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 | 1.91k | { | 
| 758 | 1.91k |   uint8_t post_byte; | 
| 759 | 1.91k |   uint8_t rr; | 
| 760 |  |  | 
| 761 | 1.91k |   if (!read_byte(info, &post_byte, address)) | 
| 762 | 7 |     return -1; | 
| 763 |  |  | 
| 764 |  |   // According to documentation bit 3 is don't care and not checked here. | 
| 765 | 1.90k |   if ((post_byte >= 0xc0) || | 
| 766 | 1.90k |     ((post_byte & 0x07) == 2) || ((post_byte & 0x07) == 3)) | 
| 767 | 805 |     return -1; | 
| 768 |  |  | 
| 769 | 1.09k |   if (!read_byte(info, &rr, address + 1)) | 
| 770 | 8 |     return -1; | 
| 771 |  |  | 
| 772 | 1.09k |   return 2; | 
| 773 | 1.09k | } | 
| 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 | 751 | { | 
| 781 | 751 |   uint8_t post_byte; | 
| 782 | 751 |   uint8_t rr; | 
| 783 |  |  | 
| 784 | 751 |   if (!read_byte(info, &post_byte, address)) | 
| 785 | 6 |     return -1; | 
| 786 |  |  | 
| 787 | 745 |   if ((post_byte & 0xc0) == 0xc0) | 
| 788 | 220 |     return -1; // Invalid register specified | 
| 789 | 525 |   else { | 
| 790 | 525 |     if (!read_byte(info, &rr, address + 1)) | 
| 791 | 3 |       return -1; | 
| 792 | 525 |   } | 
| 793 |  |  | 
| 794 | 522 |   return 2; | 
| 795 | 745 | } | 
| 796 |  |  | 
| 797 |  | static bool is_sufficient_code_size(const m680x_info *info, uint16_t address, | 
| 798 |  |   insn_desc *insn_description) | 
| 799 | 182k | { | 
| 800 | 182k |   int i; | 
| 801 | 182k |   bool retval = true; | 
| 802 | 182k |   uint16_t size = 0; | 
| 803 | 182k |   int sz; | 
| 804 |  |  | 
| 805 | 531k |   for (i = 0; i < 2; i++) { | 
| 806 | 356k |     uint8_t ir = 0; | 
| 807 | 356k |     bool is_subset = false; | 
| 808 |  |  | 
| 809 | 356k |     switch (insn_description->hid[i]) { | 
| 810 |  |  | 
| 811 | 278 |     case imm32_hid: | 
| 812 | 278 |       if ((retval = read_byte(info, &ir, address + size + 3))) | 
| 813 | 264 |         size += 4; | 
| 814 | 278 |       break; | 
| 815 |  |  | 
| 816 | 24.1k |     case ext_hid: | 
| 817 | 26.0k |     case imm16_hid: | 
| 818 | 27.0k |     case rel16_hid: | 
| 819 | 29.0k |     case imm8rel_hid: | 
| 820 | 31.5k |     case opidxdr_hid: | 
| 821 | 32.5k |     case idxX16_hid: | 
| 822 | 32.8k |     case idxS16_hid: | 
| 823 | 32.8k |       if ((retval = read_byte(info, &ir, address + size + 1))) | 
| 824 | 32.4k |         size += 2; | 
| 825 | 32.8k |       break; | 
| 826 |  |  | 
| 827 | 8.76k |     case rel8_hid: | 
| 828 | 30.9k |     case dir_hid: | 
| 829 | 33.4k |     case rbits_hid: | 
| 830 | 45.6k |     case imm8_hid: | 
| 831 | 49.6k |     case idxX_hid: | 
| 832 | 50.0k |     case idxXp_hid: | 
| 833 | 51.0k |     case idxY_hid: | 
| 834 | 51.4k |     case idxS_hid: | 
| 835 | 52.1k |     case index_hid: | 
| 836 | 52.1k |       if ((retval = read_byte(info, &ir, address + size))) | 
| 837 | 51.8k |         size++; | 
| 838 | 52.1k |       break; | 
| 839 |  |  | 
| 840 | 0 |     case illgl_hid: | 
| 841 | 215k |     case inh_hid: | 
| 842 | 219k |     case idxX0_hid: | 
| 843 | 220k |     case idxX0p_hid: | 
| 844 | 221k |     case opidx_hid: | 
| 845 | 221k |       retval = true; | 
| 846 | 221k |       break; | 
| 847 |  |  | 
| 848 | 21.0k |     case idx09_hid: | 
| 849 | 21.0k |       sz = get_indexed09_post_byte_size(info, address + size); | 
| 850 | 21.0k |       if (sz >= 0) | 
| 851 | 16.1k |         size += sz; | 
| 852 | 4.94k |       else | 
| 853 | 4.94k |         retval = false; | 
| 854 | 21.0k |       break; | 
| 855 |  |  | 
| 856 | 1.19k |     case idx12s_hid: | 
| 857 | 1.19k |       is_subset = true; | 
| 858 |  |  | 
| 859 |  |     // intentionally fall through | 
| 860 |  |  | 
| 861 | 18.9k |     case idx12_hid: | 
| 862 | 18.9k |       sz = get_indexed12_post_byte_size(info, | 
| 863 | 18.9k |           address + size, is_subset); | 
| 864 | 18.9k |       if (sz >= 0) | 
| 865 | 18.1k |         size += sz; | 
| 866 | 756 |       else | 
| 867 | 756 |         retval = false; | 
| 868 | 18.9k |       break; | 
| 869 |  |  | 
| 870 | 1.39k |     case exti12x_hid: | 
| 871 | 2.53k |     case imm16i12x_hid: | 
| 872 | 2.53k |       sz = get_indexed12_post_byte_size(info, | 
| 873 | 2.53k |           address + size, false); | 
| 874 | 2.53k |       if (sz >= 0) { | 
| 875 | 2.52k |         size += sz; | 
| 876 | 2.52k |         if ((retval = read_byte(info, &ir, | 
| 877 | 2.52k |             address + size + 1))) | 
| 878 | 2.49k |           size += 2; | 
| 879 | 2.52k |       } else | 
| 880 | 16 |         retval = false; | 
| 881 | 2.53k |       break; | 
| 882 |  |  | 
| 883 | 1.84k |     case imm8i12x_hid: | 
| 884 | 1.84k |       sz = get_indexed12_post_byte_size(info, | 
| 885 | 1.84k |           address + size, false); | 
| 886 | 1.84k |       if (sz >= 0) { | 
| 887 | 1.83k |         size += sz; | 
| 888 | 1.83k |         if ((retval = read_byte(info, &ir, | 
| 889 | 1.83k |             address + size))) | 
| 890 | 1.81k |           size++; | 
| 891 | 1.83k |       } else | 
| 892 | 5 |         retval = false; | 
| 893 | 1.84k |       break; | 
| 894 |  |  | 
| 895 | 556 |     case tfm_hid: | 
| 896 | 556 |       if ((retval = read_byte(info, &ir, address + size))) { | 
| 897 | 549 |         size++; | 
| 898 | 549 |         retval = is_tfm_reg_valid(info, (ir >> 4) & 0x0F) && | 
| 899 | 549 |           is_tfm_reg_valid(info, ir & 0x0F); | 
| 900 | 549 |       } | 
| 901 | 556 |       break; | 
| 902 |  |  | 
| 903 | 1.42k |     case rr09_hid: | 
| 904 | 1.42k |       if ((retval = read_byte(info, &ir, address + size))) { | 
| 905 | 1.41k |         size++; | 
| 906 | 1.41k |         retval = is_tfr09_reg_valid(info, (ir >> 4) & 0x0F) && | 
| 907 | 1.41k |           is_tfr09_reg_valid(info, ir & 0x0F); | 
| 908 | 1.41k |       } | 
| 909 | 1.42k |       break; | 
| 910 |  |  | 
| 911 | 1.25k |     case rr12_hid: | 
| 912 | 1.25k |       if ((retval = read_byte(info, &ir, address + size))) { | 
| 913 | 1.25k |         size++; | 
| 914 | 1.25k |         retval = is_exg_tfr12_post_byte_valid(info, ir); | 
| 915 | 1.25k |       } | 
| 916 | 1.25k |       break; | 
| 917 |  |  | 
| 918 | 751 |     case bitmv_hid: | 
| 919 | 751 |       sz = get_bitmv_post_byte_size(info, address + size); | 
| 920 | 751 |       if (sz >= 0) | 
| 921 | 522 |         size += sz; | 
| 922 | 229 |       else | 
| 923 | 229 |         retval = false; | 
| 924 | 751 |       break; | 
| 925 |  |  | 
| 926 | 1.91k |     case loop_hid: | 
| 927 | 1.91k |       sz = get_loop_post_byte_size(info, address + size); | 
| 928 | 1.91k |       if (sz >= 0) | 
| 929 | 1.09k |         size += sz; | 
| 930 | 820 |       else | 
| 931 | 820 |         retval = false; | 
| 932 | 1.91k |       break; | 
| 933 |  |  | 
| 934 | 0 |     default: | 
| 935 | 0 |       CS_ASSERT(0 && "Unexpected instruction handler id"); | 
| 936 | 0 |       retval = false; | 
| 937 | 0 |       break; | 
| 938 | 356k |     } | 
| 939 |  |  | 
| 940 | 356k |     if (!retval) | 
| 941 | 8.32k |       return false; | 
| 942 | 356k |   } | 
| 943 |  |  | 
| 944 | 174k |   insn_description->insn_size += size; | 
| 945 |  |  | 
| 946 | 174k |   return retval; | 
| 947 | 182k | } | 
| 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 | 197k | { | 
| 954 | 197k |   const inst_pageX *inst_table = NULL; | 
| 955 | 197k |   const cpu_tables *cpu = info->cpu; | 
| 956 | 197k |   size_t table_size = 0; | 
| 957 | 197k |   uint16_t base_address = address; | 
| 958 | 197k |   uint8_t ir; // instruction register | 
| 959 | 197k |   int i; | 
| 960 | 197k |   int index; | 
| 961 |  |  | 
| 962 | 197k |   if (!read_byte(info, &ir, address++)) | 
| 963 | 0 |     return false; | 
| 964 |  |  | 
| 965 | 197k |   insn_description->insn = M680X_INS_ILLGL; | 
| 966 | 197k |   insn_description->opcode = ir; | 
| 967 |  |  | 
| 968 |  |   // Check if a page prefix byte is present | 
| 969 | 466k |   for (i = 0; i < ARR_SIZE(cpu->pageX_table_size); ++i) { | 
| 970 | 454k |     if (cpu->pageX_table_size[i] == 0 || | 
| 971 | 454k |       (cpu->inst_pageX_table[i] == NULL)) | 
| 972 | 169k |       break; | 
| 973 |  |  | 
| 974 | 285k |     if ((cpu->pageX_prefix[i] == ir)) { | 
| 975 |  |       // Get pageX instruction and handler id. | 
| 976 |  |       // Abort for illegal instr. | 
| 977 | 17.2k |       inst_table = cpu->inst_pageX_table[i]; | 
| 978 | 17.2k |       table_size = cpu->pageX_table_size[i]; | 
| 979 |  |  | 
| 980 | 17.2k |       if (!read_byte(info, &ir, address++)) | 
| 981 | 31 |         return false; | 
| 982 |  |  | 
| 983 | 17.2k |       insn_description->opcode = | 
| 984 | 17.2k |         (insn_description->opcode << 8) | ir; | 
| 985 |  |  | 
| 986 | 17.2k |       if ((index = binary_search(inst_table, table_size, | 
| 987 | 17.2k |         ir)) < 0) | 
| 988 | 4.30k |         return false; | 
| 989 |  |  | 
| 990 | 12.9k |       insn_description->hid[0] = | 
| 991 | 12.9k |         inst_table[index].handler_id1; | 
| 992 | 12.9k |       insn_description->hid[1] = | 
| 993 | 12.9k |         inst_table[index].handler_id2; | 
| 994 | 12.9k |       insn_description->insn = inst_table[index].insn; | 
| 995 | 12.9k |       break; | 
| 996 | 17.2k |     } | 
| 997 | 285k |   } | 
| 998 |  |  | 
| 999 | 193k |   if (insn_description->insn == M680X_INS_ILLGL) { | 
| 1000 |  |     // Get page1 insn description | 
| 1001 | 180k |     insn_description->insn = cpu->inst_page1_table[ir].insn; | 
| 1002 | 180k |     insn_description->hid[0] = | 
| 1003 | 180k |       cpu->inst_page1_table[ir].handler_id1; | 
| 1004 | 180k |     insn_description->hid[1] = | 
| 1005 | 180k |       cpu->inst_page1_table[ir].handler_id2; | 
| 1006 | 180k |   } | 
| 1007 |  |  | 
| 1008 | 193k |   if (insn_description->insn == M680X_INS_ILLGL) { | 
| 1009 |  |     // Check if opcode byte is present in an overlay table | 
| 1010 | 34.5k |     for (i = 0; i < ARR_SIZE(cpu->overlay_table_size); ++i) { | 
| 1011 | 33.6k |       if (cpu->overlay_table_size[i] == 0 || | 
| 1012 | 33.6k |         (cpu->inst_overlay_table[i] == NULL)) | 
| 1013 | 10.2k |         break; | 
| 1014 |  |  | 
| 1015 | 23.4k |       inst_table = cpu->inst_overlay_table[i]; | 
| 1016 | 23.4k |       table_size = cpu->overlay_table_size[i]; | 
| 1017 |  |  | 
| 1018 | 23.4k |       if ((index = binary_search(inst_table, table_size, | 
| 1019 | 23.4k |               ir)) >= 0) { | 
| 1020 | 11.2k |         insn_description->hid[0] = | 
| 1021 | 11.2k |           inst_table[index].handler_id1; | 
| 1022 | 11.2k |         insn_description->hid[1] = | 
| 1023 | 11.2k |           inst_table[index].handler_id2; | 
| 1024 | 11.2k |         insn_description->insn = inst_table[index].insn; | 
| 1025 | 11.2k |         break; | 
| 1026 | 11.2k |       } | 
| 1027 | 23.4k |     } | 
| 1028 | 22.3k |   } | 
| 1029 |  |  | 
| 1030 | 193k |   insn_description->insn_size = address - base_address; | 
| 1031 |  |  | 
| 1032 | 193k |   return (insn_description->insn != M680X_INS_ILLGL) && | 
| 1033 | 193k |     (insn_description->insn != M680X_INS_INVLD) && | 
| 1034 | 193k |     is_sufficient_code_size(info, address, insn_description); | 
| 1035 | 197k | } | 
| 1036 |  |  | 
| 1037 |  | static void illegal_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1038 | 23.8k | { | 
| 1039 | 23.8k |   cs_m680x_op *op0 = &info->m680x.operands[info->m680x.op_count++]; | 
| 1040 | 23.8k |   uint8_t temp8 = 0; | 
| 1041 |  |  | 
| 1042 | 23.8k |   info->insn = M680X_INS_ILLGL; | 
| 1043 | 23.8k |   read_byte(info, &temp8, (*address)++); | 
| 1044 | 23.8k |   op0->imm = (int32_t)temp8 & 0xff; | 
| 1045 | 23.8k |   op0->type = M680X_OP_IMMEDIATE; | 
| 1046 | 23.8k |   op0->size = 1; | 
| 1047 | 23.8k | } | 
| 1048 |  |  | 
| 1049 |  | static void inherent_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1050 | 215k | { | 
| 1051 |  |   // There is nothing to do here :-) | 
| 1052 | 215k | } | 
| 1053 |  |  | 
| 1054 |  | static void add_reg_operand(m680x_info *info, m680x_reg reg) | 
| 1055 | 110k | { | 
| 1056 | 110k |   cs_m680x *m680x = &info->m680x; | 
| 1057 | 110k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1058 |  |  | 
| 1059 | 110k |   op->type = M680X_OP_REGISTER; | 
| 1060 | 110k |   op->reg = reg; | 
| 1061 | 110k |   op->size = info->cpu->reg_byte_size[reg]; | 
| 1062 | 110k | } | 
| 1063 |  |  | 
| 1064 |  | static void set_operand_size(m680x_info *info, cs_m680x_op *op, | 
| 1065 |  |   uint8_t default_size) | 
| 1066 | 120k | { | 
| 1067 | 120k |   cs_m680x *m680x = &info->m680x; | 
| 1068 |  |  | 
| 1069 | 120k |   if (info->insn == M680X_INS_JMP || info->insn == M680X_INS_JSR) | 
| 1070 | 6.16k |     op->size = 0; | 
| 1071 | 113k |   else if (info->insn == M680X_INS_DIVD || | 
| 1072 | 113k |     ((info->insn == M680X_INS_AIS || info->insn == M680X_INS_AIX) && | 
| 1073 | 112k |       op->type != M680X_OP_REGISTER)) | 
| 1074 | 1.44k |     op->size = 1; | 
| 1075 | 112k |   else if (info->insn == M680X_INS_DIVQ || | 
| 1076 | 112k |     info->insn == M680X_INS_MOVW) | 
| 1077 | 5.98k |     op->size = 2; | 
| 1078 | 106k |   else if (info->insn == M680X_INS_EMACS) | 
| 1079 | 212 |     op->size = 4; | 
| 1080 | 106k |   else if ((m680x->op_count > 0) && | 
| 1081 | 106k |     (m680x->operands[0].type == M680X_OP_REGISTER)) | 
| 1082 | 63.7k |     op->size = m680x->operands[0].size; | 
| 1083 | 42.5k |   else | 
| 1084 | 42.5k |     op->size = default_size; | 
| 1085 | 120k | } | 
| 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.51k | { | 
| 1099 | 2.51k |   cs_m680x_op *op0 = &info->m680x.operands[0]; | 
| 1100 | 2.51k |   uint8_t reg_bits = 0; | 
| 1101 | 2.51k |   uint16_t bit_index; | 
| 1102 | 2.51k |   const m680x_reg *reg_to_reg_ids = NULL; | 
| 1103 |  |  | 
| 1104 | 2.51k |   read_byte(info, ®_bits, (*address)++); | 
| 1105 |  |  | 
| 1106 | 2.51k |   switch (op0->reg) { | 
| 1107 | 1.36k |   case M680X_REG_U: | 
| 1108 | 1.36k |     reg_to_reg_ids = ®_u_reg_ids[0]; | 
| 1109 | 1.36k |     break; | 
| 1110 |  |  | 
| 1111 | 1.14k |   case M680X_REG_S: | 
| 1112 | 1.14k |     reg_to_reg_ids = ®_s_reg_ids[0]; | 
| 1113 | 1.14k |     break; | 
| 1114 |  |  | 
| 1115 | 0 |   default: | 
| 1116 | 0 |     CS_ASSERT(0 && "Unexpected operand0 register"); | 
| 1117 | 0 |     break; | 
| 1118 | 2.51k |   } | 
| 1119 |  |  | 
| 1120 | 2.51k |   if ((info->insn == M680X_INS_PULU || | 
| 1121 | 2.51k |       (info->insn == M680X_INS_PULS)) && | 
| 1122 | 2.51k |     ((reg_bits & 0x80) != 0)) | 
| 1123 |  |     // PULS xxx,PC or PULU xxx,PC which is like return from | 
| 1124 |  |     // subroutine (RTS) | 
| 1125 | 393 |     add_insn_group(MI->flat_insn->detail, M680X_GRP_RET); | 
| 1126 |  |  | 
| 1127 | 22.5k |   for (bit_index = 0; bit_index < 8; ++bit_index) { | 
| 1128 | 20.0k |     if (reg_bits & (1 << bit_index)) | 
| 1129 | 10.3k |       add_reg_operand(info, reg_to_reg_ids[bit_index]); | 
| 1130 | 20.0k |   } | 
| 1131 | 2.51k | } | 
| 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 | 820 | { | 
| 1144 | 820 |   uint8_t regs = 0; | 
| 1145 |  |  | 
| 1146 | 820 |   read_byte(info, ®s, (*address)++); | 
| 1147 |  |  | 
| 1148 | 820 |   add_reg_operand(info, g_tfr_exg_reg_ids[regs >> 4]); | 
| 1149 | 820 |   add_reg_operand(info, g_tfr_exg_reg_ids[regs & 0x0f]); | 
| 1150 |  |  | 
| 1151 | 820 |   if ((regs & 0x0f) == 0x05) { | 
| 1152 |  |     // EXG xxx,PC or TFR xxx,PC which is like a JMP | 
| 1153 | 197 |     add_insn_group(MI->flat_insn->detail, M680X_GRP_JUMP); | 
| 1154 | 197 |   } | 
| 1155 | 820 | } | 
| 1156 |  |  | 
| 1157 |  |  | 
| 1158 |  | static void reg_reg12_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1159 | 1.22k | { | 
| 1160 | 1.22k |   static const m680x_reg g_tfr_exg12_reg0_ids[] = { | 
| 1161 | 1.22k |     M680X_REG_A, M680X_REG_B,  M680X_REG_CC,  M680X_REG_TMP3, | 
| 1162 | 1.22k |     M680X_REG_D, M680X_REG_X, M680X_REG_Y,  M680X_REG_S, | 
| 1163 | 1.22k |   }; | 
| 1164 | 1.22k |   static const m680x_reg g_tfr_exg12_reg1_ids[] = { | 
| 1165 | 1.22k |     M680X_REG_A, M680X_REG_B,  M680X_REG_CC,  M680X_REG_TMP2, | 
| 1166 | 1.22k |     M680X_REG_D, M680X_REG_X, M680X_REG_Y,  M680X_REG_S, | 
| 1167 | 1.22k |   }; | 
| 1168 | 1.22k |   uint8_t regs = 0; | 
| 1169 |  |  | 
| 1170 | 1.22k |   read_byte(info, ®s, (*address)++); | 
| 1171 |  |  | 
| 1172 |  |   // The opcode of this instruction depends on | 
| 1173 |  |   // the msb of its post byte. | 
| 1174 | 1.22k |   if (regs & 0x80) | 
| 1175 | 978 |     info->insn = M680X_INS_EXG; | 
| 1176 | 247 |   else | 
| 1177 | 247 |     info->insn = M680X_INS_TFR; | 
| 1178 |  |  | 
| 1179 | 1.22k |   add_reg_operand(info, g_tfr_exg12_reg0_ids[(regs >> 4) & 0x07]); | 
| 1180 | 1.22k |   add_reg_operand(info, g_tfr_exg12_reg1_ids[regs & 0x07]); | 
| 1181 | 1.22k | } | 
| 1182 |  |  | 
| 1183 |  | static void add_rel_operand(m680x_info *info, int16_t offset, uint16_t address) | 
| 1184 | 14.1k | { | 
| 1185 | 14.1k |   cs_m680x *m680x = &info->m680x; | 
| 1186 | 14.1k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1187 |  |  | 
| 1188 | 14.1k |   op->type = M680X_OP_RELATIVE; | 
| 1189 | 14.1k |   op->size = 0; | 
| 1190 | 14.1k |   op->rel.offset = offset; | 
| 1191 | 14.1k |   op->rel.address = address; | 
| 1192 | 14.1k | } | 
| 1193 |  |  | 
| 1194 |  | static void relative8_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1195 | 13.1k | { | 
| 1196 | 13.1k |   int16_t offset = 0; | 
| 1197 |  |  | 
| 1198 | 13.1k |   read_byte_sign_extended(info, &offset, (*address)++); | 
| 1199 | 13.1k |   add_rel_operand(info, offset, *address + offset); | 
| 1200 | 13.1k |   add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL); | 
| 1201 |  |  | 
| 1202 | 13.1k |   if ((info->insn != M680X_INS_BRA) && | 
| 1203 | 13.1k |     (info->insn != M680X_INS_BSR) && | 
| 1204 | 13.1k |     (info->insn != M680X_INS_BRN)) | 
| 1205 | 10.9k |     add_reg_to_rw_list(MI, M680X_REG_CC, READ); | 
| 1206 | 13.1k | } | 
| 1207 |  |  | 
| 1208 |  | static void relative16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1209 | 1.02k | { | 
| 1210 | 1.02k |   uint16_t offset = 0; | 
| 1211 |  |  | 
| 1212 | 1.02k |   read_word(info, &offset, *address); | 
| 1213 | 1.02k |   *address += 2; | 
| 1214 | 1.02k |   add_rel_operand(info, (int16_t)offset, *address + offset); | 
| 1215 | 1.02k |   add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL); | 
| 1216 |  |  | 
| 1217 | 1.02k |   if ((info->insn != M680X_INS_LBRA) && | 
| 1218 | 1.02k |     (info->insn != M680X_INS_LBSR) && | 
| 1219 | 1.02k |     (info->insn != M680X_INS_LBRN)) | 
| 1220 | 277 |     add_reg_to_rw_list(MI, M680X_REG_CC, READ); | 
| 1221 | 1.02k | } | 
| 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 | 12.2k | { | 
| 1231 | 12.2k |   cs_m680x *m680x = &info->m680x; | 
| 1232 | 12.2k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1233 |  |  | 
| 1234 | 12.2k |   op->type = M680X_OP_INDEXED; | 
| 1235 | 12.2k |   set_operand_size(info, op, 1); | 
| 1236 | 12.2k |   op->idx.base_reg = base_reg; | 
| 1237 | 12.2k |   op->idx.offset_reg = M680X_REG_INVALID; | 
| 1238 | 12.2k |   op->idx.inc_dec = inc_dec; | 
| 1239 |  |  | 
| 1240 | 12.2k |   if (inc_dec && post_inc_dec) | 
| 1241 | 1.23k |     op->idx.flags |= M680X_IDX_POST_INC_DEC; | 
| 1242 |  |  | 
| 1243 | 12.2k |   if (offset_bits != M680X_OFFSET_NONE) { | 
| 1244 | 6.96k |     op->idx.offset = offset; | 
| 1245 | 6.96k |     op->idx.offset_addr = 0; | 
| 1246 | 6.96k |   } | 
| 1247 |  |  | 
| 1248 | 12.2k |   op->idx.offset_bits = offset_bits; | 
| 1249 | 12.2k |   op->idx.flags |= (no_comma ? M680X_IDX_NO_COMMA : 0); | 
| 1250 | 12.2k | } | 
| 1251 |  |  | 
| 1252 |  | // M6800/1/2/3 indexed mode handler | 
| 1253 |  | static void indexedX_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1254 | 3.94k | { | 
| 1255 | 3.94k |   uint8_t offset = 0; | 
| 1256 |  |  | 
| 1257 | 3.94k |   read_byte(info, &offset, (*address)++); | 
| 1258 |  |  | 
| 1259 | 3.94k |   add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_BITS_8, | 
| 1260 | 3.94k |     (uint16_t)offset, false); | 
| 1261 | 3.94k | } | 
| 1262 |  |  | 
| 1263 |  | static void indexedY_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1264 | 1.00k | { | 
| 1265 | 1.00k |   uint8_t offset = 0; | 
| 1266 |  |  | 
| 1267 | 1.00k |   read_byte(info, &offset, (*address)++); | 
| 1268 |  |  | 
| 1269 | 1.00k |   add_indexed_operand(info, M680X_REG_Y, false, 0, M680X_OFFSET_BITS_8, | 
| 1270 | 1.00k |     (uint16_t)offset, false); | 
| 1271 | 1.00k | } | 
| 1272 |  |  | 
| 1273 |  | // M6809/M6309 indexed mode handler | 
| 1274 |  | static void indexed09_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1275 | 16.1k | { | 
| 1276 | 16.1k |   cs_m680x *m680x = &info->m680x; | 
| 1277 | 16.1k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1278 | 16.1k |   uint8_t post_byte = 0; | 
| 1279 | 16.1k |   uint16_t offset = 0; | 
| 1280 | 16.1k |   int16_t soffset = 0; | 
| 1281 |  |  | 
| 1282 | 16.1k |   read_byte(info, &post_byte, (*address)++); | 
| 1283 |  |  | 
| 1284 | 16.1k |   op->type = M680X_OP_INDEXED; | 
| 1285 | 16.1k |   set_operand_size(info, op, 1); | 
| 1286 | 16.1k |   op->idx.base_reg = g_rr5_to_reg_ids[(post_byte >> 5) & 0x03]; | 
| 1287 | 16.1k |   op->idx.offset_reg = M680X_REG_INVALID; | 
| 1288 |  |  | 
| 1289 | 16.1k |   if (!(post_byte & 0x80)) { | 
| 1290 |  |     // n5,R | 
| 1291 | 7.37k |     if ((post_byte & 0x10) == 0x10) | 
| 1292 | 2.23k |       op->idx.offset = post_byte | 0xfff0; | 
| 1293 | 5.14k |     else | 
| 1294 | 5.14k |       op->idx.offset = post_byte & 0x0f; | 
| 1295 |  |  | 
| 1296 | 7.37k |     op->idx.offset_addr = op->idx.offset + *address; | 
| 1297 | 7.37k |     op->idx.offset_bits = M680X_OFFSET_BITS_5; | 
| 1298 | 7.37k |   } | 
| 1299 | 8.76k |   else { | 
| 1300 | 8.76k |     if ((post_byte & 0x10) == 0x10) | 
| 1301 | 3.79k |       op->idx.flags |= M680X_IDX_INDIRECT; | 
| 1302 |  |  | 
| 1303 |  |     // indexed addressing | 
| 1304 | 8.76k |     switch (post_byte & 0x1f) { | 
| 1305 | 387 |     case 0x00: // ,R+ | 
| 1306 | 387 |       op->idx.inc_dec = 1; | 
| 1307 | 387 |       op->idx.flags |= M680X_IDX_POST_INC_DEC; | 
| 1308 | 387 |       break; | 
| 1309 |  |  | 
| 1310 | 299 |     case 0x11: // [,R++] | 
| 1311 | 790 |     case 0x01: // ,R++ | 
| 1312 | 790 |       op->idx.inc_dec = 2; | 
| 1313 | 790 |       op->idx.flags |= M680X_IDX_POST_INC_DEC; | 
| 1314 | 790 |       break; | 
| 1315 |  |  | 
| 1316 | 291 |     case 0x02: // ,-R | 
| 1317 | 291 |       op->idx.inc_dec = -1; | 
| 1318 | 291 |       break; | 
| 1319 |  |  | 
| 1320 | 389 |     case 0x13: // [,--R] | 
| 1321 | 693 |     case 0x03: // ,--R | 
| 1322 | 693 |       op->idx.inc_dec = -2; | 
| 1323 | 693 |       break; | 
| 1324 |  |  | 
| 1325 | 311 |     case 0x14: // [,R] | 
| 1326 | 545 |     case 0x04: // ,R | 
| 1327 | 545 |       break; | 
| 1328 |  |  | 
| 1329 | 270 |     case 0x15: // [B,R] | 
| 1330 | 606 |     case 0x05: // B,R | 
| 1331 | 606 |       op->idx.offset_reg = M680X_REG_B; | 
| 1332 | 606 |       break; | 
| 1333 |  |  | 
| 1334 | 322 |     case 0x16: // [A,R] | 
| 1335 | 624 |     case 0x06: // A,R | 
| 1336 | 624 |       op->idx.offset_reg = M680X_REG_A; | 
| 1337 | 624 |       break; | 
| 1338 |  |  | 
| 1339 | 516 |     case 0x1c: // [n8,PCR] | 
| 1340 | 977 |     case 0x0c: // n8,PCR | 
| 1341 | 977 |       op->idx.base_reg = M680X_REG_PC; | 
| 1342 | 977 |       read_byte_sign_extended(info, &soffset, (*address)++); | 
| 1343 | 977 |       op->idx.offset_addr = offset + *address; | 
| 1344 | 977 |       op->idx.offset = soffset; | 
| 1345 | 977 |       op->idx.offset_bits = M680X_OFFSET_BITS_8; | 
| 1346 | 977 |       break; | 
| 1347 |  |  | 
| 1348 | 348 |     case 0x18: // [n8,R] | 
| 1349 | 962 |     case 0x08: // n8,R | 
| 1350 | 962 |       read_byte_sign_extended(info, &soffset, (*address)++); | 
| 1351 | 962 |       op->idx.offset = soffset; | 
| 1352 | 962 |       op->idx.offset_bits = M680X_OFFSET_BITS_8; | 
| 1353 | 962 |       break; | 
| 1354 |  |  | 
| 1355 | 272 |     case 0x1d: // [n16,PCR] | 
| 1356 | 1.21k |     case 0x0d: // n16,PCR | 
| 1357 | 1.21k |       op->idx.base_reg = M680X_REG_PC; | 
| 1358 | 1.21k |       read_word(info, &offset, *address); | 
| 1359 | 1.21k |       *address += 2; | 
| 1360 | 1.21k |       op->idx.offset_addr = offset + *address; | 
| 1361 | 1.21k |       op->idx.offset = (int16_t)offset; | 
| 1362 | 1.21k |       op->idx.offset_bits = M680X_OFFSET_BITS_16; | 
| 1363 | 1.21k |       break; | 
| 1364 |  |  | 
| 1365 | 612 |     case 0x19: // [n16,R] | 
| 1366 | 936 |     case 0x09: // n16,R | 
| 1367 | 936 |       read_word(info, &offset, *address); | 
| 1368 | 936 |       *address += 2; | 
| 1369 | 936 |       op->idx.offset = (int16_t)offset; | 
| 1370 | 936 |       op->idx.offset_bits = M680X_OFFSET_BITS_16; | 
| 1371 | 936 |       break; | 
| 1372 |  |  | 
| 1373 | 228 |     case 0x1b: // [D,R] | 
| 1374 | 506 |     case 0x0b: // D,R | 
| 1375 | 506 |       op->idx.offset_reg = M680X_REG_D; | 
| 1376 | 506 |       break; | 
| 1377 |  |  | 
| 1378 | 227 |     case 0x1f: // [n16] | 
| 1379 | 227 |       op->type = M680X_OP_EXTENDED; | 
| 1380 | 227 |       op->ext.indirect = true; | 
| 1381 | 227 |       read_word(info, &op->ext.address, *address); | 
| 1382 | 227 |       *address += 2; | 
| 1383 | 227 |       break; | 
| 1384 |  |  | 
| 1385 | 0 |     default: | 
| 1386 | 0 |       op->idx.base_reg = M680X_REG_INVALID; | 
| 1387 | 0 |       break; | 
| 1388 | 8.76k |     } | 
| 1389 | 8.76k |   } | 
| 1390 |  |  | 
| 1391 | 16.1k |   if (((info->insn == M680X_INS_LEAU) || | 
| 1392 | 16.1k |       (info->insn == M680X_INS_LEAS) || | 
| 1393 | 16.1k |       (info->insn == M680X_INS_LEAX) || | 
| 1394 | 16.1k |       (info->insn == M680X_INS_LEAY)) && | 
| 1395 | 16.1k |     (m680x->operands[0].reg == M680X_REG_X || | 
| 1396 | 1.86k |       (m680x->operands[0].reg == M680X_REG_Y))) | 
| 1397 |  |     // Only LEAX and LEAY modify CC register | 
| 1398 | 1.00k |     add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY); | 
| 1399 | 16.1k | } | 
| 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 | 22.4k | { | 
| 1413 | 22.4k |   cs_m680x *m680x = &info->m680x; | 
| 1414 | 22.4k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1415 | 22.4k |   uint8_t post_byte = 0; | 
| 1416 | 22.4k |   uint8_t offset8 = 0; | 
| 1417 |  |  | 
| 1418 | 22.4k |   read_byte(info, &post_byte, (*address)++); | 
| 1419 |  |  | 
| 1420 | 22.4k |   op->type = M680X_OP_INDEXED; | 
| 1421 | 22.4k |   set_operand_size(info, op, 1); | 
| 1422 | 22.4k |   op->idx.offset_reg = M680X_REG_INVALID; | 
| 1423 |  |  | 
| 1424 | 22.4k |   if (!(post_byte & 0x20)) { | 
| 1425 |  |     // n5,R      n5 is a 5-bit signed offset | 
| 1426 | 7.95k |     op->idx.base_reg = g_idx12_to_reg_ids[(post_byte >> 6) & 0x03]; | 
| 1427 |  |  | 
| 1428 | 7.95k |     if ((post_byte & 0x10) == 0x10) | 
| 1429 | 3.14k |       op->idx.offset = post_byte | 0xfff0; | 
| 1430 | 4.81k |     else | 
| 1431 | 4.81k |       op->idx.offset = post_byte & 0x0f; | 
| 1432 |  |  | 
| 1433 | 7.95k |     op->idx.offset_addr = op->idx.offset + *address; | 
| 1434 | 7.95k |     op->idx.offset_bits = M680X_OFFSET_BITS_5; | 
| 1435 | 7.95k |   } | 
| 1436 | 14.4k |   else { | 
| 1437 | 14.4k |     if ((post_byte & 0xe0) == 0xe0) | 
| 1438 | 7.11k |       op->idx.base_reg = | 
| 1439 | 7.11k |         g_idx12_to_reg_ids[(post_byte >> 3) & 0x03]; | 
| 1440 |  |  | 
| 1441 | 14.4k |     switch (post_byte & 0xe7) { | 
| 1442 | 899 |     case 0xe0: | 
| 1443 | 2.21k |     case 0xe1: // n9,R | 
| 1444 | 2.21k |       read_byte(info, &offset8, (*address)++); | 
| 1445 | 2.21k |       op->idx.offset = offset8; | 
| 1446 |  |  | 
| 1447 | 2.21k |       if (post_byte & 0x01) // sign extension | 
| 1448 | 1.31k |         op->idx.offset |= 0xff00; | 
| 1449 |  |  | 
| 1450 | 2.21k |       op->idx.offset_bits = M680X_OFFSET_BITS_9; | 
| 1451 |  |  | 
| 1452 | 2.21k |       if (op->idx.base_reg == M680X_REG_PC) | 
| 1453 | 1.17k |         op->idx.offset_addr = op->idx.offset + *address; | 
| 1454 |  |  | 
| 1455 | 2.21k |       break; | 
| 1456 |  |  | 
| 1457 | 881 |     case 0xe3: // [n16,R] | 
| 1458 | 881 |       op->idx.flags |= M680X_IDX_INDIRECT; | 
| 1459 |  |  | 
| 1460 |  |     // intentionally fall through | 
| 1461 | 2.33k |     case 0xe2: // n16,R | 
| 1462 | 2.33k |       read_word(info, (uint16_t *)&op->idx.offset, *address); | 
| 1463 | 2.33k |       (*address) += 2; | 
| 1464 | 2.33k |       op->idx.offset_bits = M680X_OFFSET_BITS_16; | 
| 1465 |  |  | 
| 1466 | 2.33k |       if (op->idx.base_reg == M680X_REG_PC) | 
| 1467 | 478 |         op->idx.offset_addr = op->idx.offset + *address; | 
| 1468 |  |  | 
| 1469 | 2.33k |       break; | 
| 1470 |  |  | 
| 1471 | 717 |     case 0xe4: // A,R | 
| 1472 | 1.06k |     case 0xe5: // B,R | 
| 1473 | 1.89k |     case 0xe6: // D,R | 
| 1474 | 1.89k |       op->idx.offset_reg = | 
| 1475 | 1.89k |         g_or12_to_reg_ids[post_byte & 0x03]; | 
| 1476 | 1.89k |       break; | 
| 1477 |  |  | 
| 1478 | 678 |     case 0xe7: // [D,R] | 
| 1479 | 678 |       op->idx.offset_reg = M680X_REG_D; | 
| 1480 | 678 |       op->idx.flags |= M680X_IDX_INDIRECT; | 
| 1481 | 678 |       break; | 
| 1482 |  |  | 
| 1483 | 7.36k |     default: // n,-r n,+r n,r- n,r+ | 
| 1484 |  |       // PC is not allowed in this mode | 
| 1485 | 7.36k |       op->idx.base_reg = | 
| 1486 | 7.36k |         g_idx12_to_reg_ids[(post_byte >> 6) & 0x03]; | 
| 1487 | 7.36k |       op->idx.inc_dec = post_byte & 0x0f; | 
| 1488 |  |  | 
| 1489 | 7.36k |       if (op->idx.inc_dec & 0x08) // evtl. sign extend value | 
| 1490 | 3.82k |         op->idx.inc_dec |= 0xf0; | 
| 1491 |  |  | 
| 1492 | 7.36k |       if (op->idx.inc_dec >= 0) | 
| 1493 | 3.53k |         op->idx.inc_dec++; | 
| 1494 |  |  | 
| 1495 | 7.36k |       if (post_byte & 0x10) | 
| 1496 | 2.56k |         op->idx.flags |= M680X_IDX_POST_INC_DEC; | 
| 1497 |  |  | 
| 1498 | 7.36k |       break; | 
| 1499 |  |  | 
| 1500 | 14.4k |     } | 
| 1501 | 14.4k |   } | 
| 1502 | 22.4k | } | 
| 1503 |  |  | 
| 1504 |  | static void index_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1505 | 688 | { | 
| 1506 | 688 |   cs_m680x *m680x = &info->m680x; | 
| 1507 | 688 |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1508 |  |  | 
| 1509 | 688 |   op->type = M680X_OP_CONSTANT; | 
| 1510 | 688 |   read_byte(info, &op->const_val, (*address)++); | 
| 1511 | 688 | }; | 
| 1512 |  |  | 
| 1513 |  | static void direct_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1514 | 25.0k | { | 
| 1515 | 25.0k |   cs_m680x *m680x = &info->m680x; | 
| 1516 | 25.0k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1517 |  |  | 
| 1518 | 25.0k |   op->type = M680X_OP_DIRECT; | 
| 1519 | 25.0k |   set_operand_size(info, op, 1); | 
| 1520 | 25.0k |   read_byte(info, &op->direct_addr, (*address)++); | 
| 1521 | 25.0k | }; | 
| 1522 |  |  | 
| 1523 |  | static void extended_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1524 | 23.9k | { | 
| 1525 | 23.9k |   cs_m680x *m680x = &info->m680x; | 
| 1526 | 23.9k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1527 |  |  | 
| 1528 | 23.9k |   op->type = M680X_OP_EXTENDED; | 
| 1529 | 23.9k |   set_operand_size(info, op, 1); | 
| 1530 | 23.9k |   read_word(info, &op->ext.address, *address); | 
| 1531 | 23.9k |   *address += 2; | 
| 1532 | 23.9k | } | 
| 1533 |  |  | 
| 1534 |  | static void immediate_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1535 | 16.0k | { | 
| 1536 | 16.0k |   cs_m680x *m680x = &info->m680x; | 
| 1537 | 16.0k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1538 | 16.0k |   uint16_t word = 0; | 
| 1539 | 16.0k |   int16_t sword = 0; | 
| 1540 |  |  | 
| 1541 | 16.0k |   op->type = M680X_OP_IMMEDIATE; | 
| 1542 | 16.0k |   set_operand_size(info, op, 1); | 
| 1543 |  |  | 
| 1544 | 16.0k |   switch (op->size) { | 
| 1545 | 13.9k |   case 1: | 
| 1546 | 13.9k |     read_byte_sign_extended(info, &sword, *address); | 
| 1547 | 13.9k |     op->imm = sword; | 
| 1548 | 13.9k |     break; | 
| 1549 |  |  | 
| 1550 | 1.82k |   case 2: | 
| 1551 | 1.82k |     read_word(info, &word, *address); | 
| 1552 | 1.82k |     op->imm = (int16_t)word; | 
| 1553 | 1.82k |     break; | 
| 1554 |  |  | 
| 1555 | 264 |   case 4: | 
| 1556 | 264 |     read_sdword(info, &op->imm, *address); | 
| 1557 | 264 |     break; | 
| 1558 |  |  | 
| 1559 | 0 |   default: | 
| 1560 | 0 |     op->imm = 0; | 
| 1561 | 0 |     CS_ASSERT(0 && "Unexpected immediate byte size"); | 
| 1562 | 16.0k |   } | 
| 1563 |  |  | 
| 1564 | 16.0k |   *address += op->size; | 
| 1565 | 16.0k | } | 
| 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 | 522 | { | 
| 1570 | 522 |   static const m680x_reg m680x_reg[] = { | 
| 1571 | 522 |     M680X_REG_CC, M680X_REG_A, M680X_REG_B, M680X_REG_INVALID, | 
| 1572 | 522 |   }; | 
| 1573 |  |  | 
| 1574 | 522 |   uint8_t post_byte = 0; | 
| 1575 | 522 |   cs_m680x *m680x = &info->m680x; | 
| 1576 | 522 |   cs_m680x_op *op; | 
| 1577 |  |  | 
| 1578 | 522 |   read_byte(info, &post_byte, *address); | 
| 1579 | 522 |   (*address)++; | 
| 1580 |  |  | 
| 1581 |  |   // operand[0] = register | 
| 1582 | 522 |   add_reg_operand(info, m680x_reg[post_byte >> 6]); | 
| 1583 |  |  | 
| 1584 |  |   // operand[1] = bit index in source operand | 
| 1585 | 522 |   op = &m680x->operands[m680x->op_count++]; | 
| 1586 | 522 |   op->type = M680X_OP_CONSTANT; | 
| 1587 | 522 |   op->const_val = (post_byte >> 3) & 0x07; | 
| 1588 |  |  | 
| 1589 |  |   // operand[2] = bit index in destination operand | 
| 1590 | 522 |   op = &m680x->operands[m680x->op_count++]; | 
| 1591 | 522 |   op->type = M680X_OP_CONSTANT; | 
| 1592 | 522 |   op->const_val = post_byte & 0x07; | 
| 1593 |  |  | 
| 1594 | 522 |   direct_hdlr(MI, info, address); | 
| 1595 | 522 | } | 
| 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 | 337 | { | 
| 1600 | 337 |   static const uint8_t inc_dec_r0[] = { | 
| 1601 | 337 |     1, -1, 1, 0, | 
| 1602 | 337 |   }; | 
| 1603 | 337 |   static const uint8_t inc_dec_r1[] = { | 
| 1604 | 337 |     1, -1, 0, 1, | 
| 1605 | 337 |   }; | 
| 1606 | 337 |   uint8_t regs = 0; | 
| 1607 | 337 |   uint8_t index = (MI->Opcode & 0xff) - 0x38; | 
| 1608 |  |  | 
| 1609 | 337 |   read_byte(info, ®s, *address); | 
| 1610 |  |  | 
| 1611 | 337 |   add_indexed_operand(info, g_tfr_exg_reg_ids[regs >> 4], true, | 
| 1612 | 337 |     inc_dec_r0[index], M680X_OFFSET_NONE, 0, true); | 
| 1613 | 337 |   add_indexed_operand(info, g_tfr_exg_reg_ids[regs & 0x0f], true, | 
| 1614 | 337 |     inc_dec_r1[index], M680X_OFFSET_NONE, 0, true); | 
| 1615 |  |  | 
| 1616 | 337 |   add_reg_to_rw_list(MI, M680X_REG_W, READ | WRITE); | 
| 1617 | 337 | } | 
| 1618 |  |  | 
| 1619 |  | static void opidx_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1620 | 1.34k | { | 
| 1621 | 1.34k |   cs_m680x *m680x = &info->m680x; | 
| 1622 | 1.34k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1623 |  |  | 
| 1624 |  |   // bit index is coded in Opcode | 
| 1625 | 1.34k |   op->type = M680X_OP_CONSTANT; | 
| 1626 | 1.34k |   op->const_val = (MI->Opcode & 0x0e) >> 1; | 
| 1627 | 1.34k | } | 
| 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 | 2.42k | { | 
| 1634 | 2.42k |   cs_m680x *m680x = &info->m680x; | 
| 1635 | 2.42k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1636 |  |  | 
| 1637 |  |   // bit index is coded in Opcode | 
| 1638 | 2.42k |   op->type = M680X_OP_CONSTANT; | 
| 1639 | 2.42k |   op->const_val = (MI->Opcode & 0x0e) >> 1; | 
| 1640 | 2.42k |   direct_hdlr(MI, info, address); | 
| 1641 | 2.42k |   relative8_hdlr(MI, info, address); | 
| 1642 |  |  | 
| 1643 | 2.42k |   add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY); | 
| 1644 | 2.42k | } | 
| 1645 |  |  | 
| 1646 |  | static void indexedX0_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1647 | 3.97k | { | 
| 1648 | 3.97k |   add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_NONE, | 
| 1649 | 3.97k |     0, false); | 
| 1650 | 3.97k | } | 
| 1651 |  |  | 
| 1652 |  | static void indexedX16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1653 | 1.04k | { | 
| 1654 | 1.04k |   uint16_t offset = 0; | 
| 1655 |  |  | 
| 1656 | 1.04k |   read_word(info, &offset, *address); | 
| 1657 | 1.04k |   *address += 2; | 
| 1658 | 1.04k |   add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_BITS_16, | 
| 1659 | 1.04k |     offset, false); | 
| 1660 | 1.04k | } | 
| 1661 |  |  | 
| 1662 |  | static void imm_rel_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1663 | 1.99k | { | 
| 1664 | 1.99k |   immediate_hdlr(MI, info, address); | 
| 1665 | 1.99k |   relative8_hdlr(MI, info, address); | 
| 1666 | 1.99k | } | 
| 1667 |  |  | 
| 1668 |  | static void indexedS_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1669 | 452 | { | 
| 1670 | 452 |   uint8_t offset = 0; | 
| 1671 |  |  | 
| 1672 | 452 |   read_byte(info, &offset, (*address)++); | 
| 1673 |  |  | 
| 1674 | 452 |   add_indexed_operand(info, M680X_REG_S, false, 0, M680X_OFFSET_BITS_8, | 
| 1675 | 452 |     (uint16_t)offset, false); | 
| 1676 | 452 | } | 
| 1677 |  |  | 
| 1678 |  | static void indexedS16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1679 | 208 | { | 
| 1680 | 208 |   uint16_t offset = 0; | 
| 1681 |  |  | 
| 1682 | 208 |   read_word(info, &offset, *address); | 
| 1683 | 208 |   address += 2; | 
| 1684 |  |  | 
| 1685 | 208 |   add_indexed_operand(info, M680X_REG_S, false, 0, M680X_OFFSET_BITS_16, | 
| 1686 | 208 |     offset, false); | 
| 1687 | 208 | } | 
| 1688 |  |  | 
| 1689 |  | static void indexedX0p_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1690 | 584 | { | 
| 1691 | 584 |   add_indexed_operand(info, M680X_REG_X, true, 1, M680X_OFFSET_NONE, | 
| 1692 | 584 |     0, true); | 
| 1693 | 584 | } | 
| 1694 |  |  | 
| 1695 |  | static void indexedXp_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1696 | 312 | { | 
| 1697 | 312 |   uint8_t offset = 0; | 
| 1698 |  |  | 
| 1699 | 312 |   read_byte(info, &offset, (*address)++); | 
| 1700 |  |  | 
| 1701 | 312 |   add_indexed_operand(info, M680X_REG_X, true, 1, M680X_OFFSET_BITS_8, | 
| 1702 | 312 |     (uint16_t)offset, false); | 
| 1703 | 312 | } | 
| 1704 |  |  | 
| 1705 |  | static void imm_idx12_x_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1706 | 2.93k | { | 
| 1707 | 2.93k |   cs_m680x *m680x = &info->m680x; | 
| 1708 | 2.93k |   cs_m680x_op *op = &m680x->operands[m680x->op_count++]; | 
| 1709 |  |  | 
| 1710 | 2.93k |   indexed12_hdlr(MI, info, address); | 
| 1711 | 2.93k |   op->type = M680X_OP_IMMEDIATE; | 
| 1712 |  |  | 
| 1713 | 2.93k |   if (info->insn == M680X_INS_MOVW) { | 
| 1714 | 1.11k |     uint16_t imm16 = 0; | 
| 1715 |  |  | 
| 1716 | 1.11k |     read_word(info, &imm16, *address); | 
| 1717 | 1.11k |     op->imm = (int16_t)imm16; | 
| 1718 | 1.11k |     op->size = 2; | 
| 1719 | 1.11k |   } | 
| 1720 | 1.81k |   else { | 
| 1721 | 1.81k |     uint8_t imm8 = 0; | 
| 1722 |  |  | 
| 1723 | 1.81k |     read_byte(info, &imm8, *address); | 
| 1724 | 1.81k |     op->imm = (int8_t)imm8; | 
| 1725 | 1.81k |     op->size = 1; | 
| 1726 | 1.81k |   } | 
| 1727 |  |  | 
| 1728 | 2.93k |   set_operand_size(info, op, 1); | 
| 1729 | 2.93k | } | 
| 1730 |  |  | 
| 1731 |  | static void ext_idx12_x_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) | 
| 1732 | 1.37k | { | 
| 1733 | 1.37k |   cs_m680x *m680x = &info->m680x; | 
| 1734 | 1.37k |   cs_m680x_op *op0 = &m680x->operands[m680x->op_count++]; | 
| 1735 | 1.37k |   uint16_t imm16 = 0; | 
| 1736 |  |  | 
| 1737 | 1.37k |   indexed12_hdlr(MI, info, address); | 
| 1738 | 1.37k |   read_word(info, &imm16, *address); | 
| 1739 | 1.37k |   op0->type = M680X_OP_EXTENDED; | 
| 1740 | 1.37k |   op0->ext.address = (int16_t)imm16; | 
| 1741 | 1.37k |   set_operand_size(info, op0, 1); | 
| 1742 | 1.37k | } | 
| 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 | 1.09k | { | 
| 1748 | 1.09k |   static const m680x_reg index_to_reg_id[] = { | 
| 1749 | 1.09k |     M680X_REG_A, M680X_REG_B, M680X_REG_INVALID, M680X_REG_INVALID, | 
| 1750 | 1.09k |     M680X_REG_D, M680X_REG_X, M680X_REG_Y, M680X_REG_S, | 
| 1751 | 1.09k |   }; | 
| 1752 | 1.09k |   static const m680x_insn index_to_insn_id[] = { | 
| 1753 | 1.09k |     M680X_INS_DBEQ, M680X_INS_DBNE, M680X_INS_TBEQ, M680X_INS_TBNE, | 
| 1754 | 1.09k |     M680X_INS_IBEQ, M680X_INS_IBNE, M680X_INS_ILLGL, M680X_INS_ILLGL | 
| 1755 | 1.09k |   }; | 
| 1756 | 1.09k |   cs_m680x *m680x = &info->m680x; | 
| 1757 | 1.09k |   uint8_t post_byte = 0; | 
| 1758 | 1.09k |   uint8_t rel = 0; | 
| 1759 | 1.09k |   cs_m680x_op *op; | 
| 1760 |  |  | 
| 1761 | 1.09k |   read_byte(info, &post_byte, (*address)++); | 
| 1762 |  |  | 
| 1763 | 1.09k |   info->insn = index_to_insn_id[(post_byte >> 5) & 0x07]; | 
| 1764 |  |  | 
| 1765 | 1.09k |   if (info->insn == M680X_INS_ILLGL) { | 
| 1766 | 0 |     illegal_hdlr(MI, info, address); | 
| 1767 | 0 |   }; | 
| 1768 |  |  | 
| 1769 | 1.09k |   read_byte(info, &rel, (*address)++); | 
| 1770 |  |  | 
| 1771 | 1.09k |   add_reg_operand(info, index_to_reg_id[post_byte & 0x07]); | 
| 1772 |  |  | 
| 1773 | 1.09k |   op = &m680x->operands[m680x->op_count++]; | 
| 1774 |  |  | 
| 1775 | 1.09k |   op->type = M680X_OP_RELATIVE; | 
| 1776 |  |  | 
| 1777 | 1.09k |   op->rel.offset = (post_byte & 0x10) ? 0xff00 | rel : rel; | 
| 1778 |  |  | 
| 1779 | 1.09k |   op->rel.address = *address + op->rel.offset; | 
| 1780 |  |  | 
| 1781 | 1.09k |   add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL); | 
| 1782 | 1.09k | } | 
| 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 | 197k | { | 
| 1824 | 197k |   cs_m680x *m680x = &info->m680x; | 
| 1825 | 197k |   cs_detail *detail = MI->flat_insn->detail; | 
| 1826 | 197k |   uint16_t base_address = address; | 
| 1827 | 197k |   insn_desc insn_description; | 
| 1828 | 197k |   e_access_mode access_mode; | 
| 1829 |  |  | 
| 1830 | 197k |   if (detail != NULL) { | 
| 1831 | 197k |     memset(detail, 0, offsetof(cs_detail, m680x)+sizeof(cs_m680x)); | 
| 1832 | 197k |   } | 
| 1833 |  |  | 
| 1834 | 197k |   memset(&insn_description, 0, sizeof(insn_description)); | 
| 1835 | 197k |   memset(m680x, 0, sizeof(*m680x)); | 
| 1836 | 197k |   info->insn_size = 1; | 
| 1837 |  |  | 
| 1838 | 197k |   if (decode_insn(info, address, &insn_description)) { | 
| 1839 | 174k |     m680x_reg reg; | 
| 1840 |  |  | 
| 1841 | 174k |     if (insn_description.opcode > 0xff) | 
| 1842 | 11.6k |       address += 2; // 8-bit opcode + page prefix | 
| 1843 | 162k |     else | 
| 1844 | 162k |       address++; // 8-bit opcode only | 
| 1845 |  |  | 
| 1846 | 174k |     info->insn = insn_description.insn; | 
| 1847 |  |  | 
| 1848 | 174k |     MCInst_setOpcode(MI, insn_description.opcode); | 
| 1849 |  |  | 
| 1850 | 174k |     reg = g_insn_props[info->insn].reg0; | 
| 1851 |  |  | 
| 1852 | 174k |     if (reg != M680X_REG_INVALID) { | 
| 1853 | 90.8k |       if (reg == M680X_REG_HX && | 
| 1854 | 90.8k |         (!info->cpu->reg_byte_size[reg])) | 
| 1855 | 303 |         reg = M680X_REG_X; | 
| 1856 |  |  | 
| 1857 | 90.8k |       add_reg_operand(info, reg); | 
| 1858 |  |       // First (or second) operand is a register which is | 
| 1859 |  |       // part of the mnemonic | 
| 1860 | 90.8k |       m680x->flags |= M680X_FIRST_OP_IN_MNEM; | 
| 1861 | 90.8k |       reg = g_insn_props[info->insn].reg1; | 
| 1862 |  |  | 
| 1863 | 90.8k |       if (reg != M680X_REG_INVALID) { | 
| 1864 | 3.85k |         if (reg == M680X_REG_HX && | 
| 1865 | 3.85k |           (!info->cpu->reg_byte_size[reg])) | 
| 1866 | 428 |           reg = M680X_REG_X; | 
| 1867 |  |  | 
| 1868 | 3.85k |         add_reg_operand(info, reg); | 
| 1869 | 3.85k |         m680x->flags |= M680X_SECOND_OP_IN_MNEM; | 
| 1870 | 3.85k |       } | 
| 1871 | 90.8k |     } | 
| 1872 |  |  | 
| 1873 |  |     // Call addressing mode specific instruction handler | 
| 1874 | 174k |     (g_insn_handler[insn_description.hid[0]])(MI, info, | 
| 1875 | 174k |       &address); | 
| 1876 | 174k |     (g_insn_handler[insn_description.hid[1]])(MI, info, | 
| 1877 | 174k |       &address); | 
| 1878 |  |  | 
| 1879 | 174k |     add_insn_group(detail, g_insn_props[info->insn].group); | 
| 1880 |  |  | 
| 1881 | 174k |     if (g_insn_props[info->insn].cc_modified && | 
| 1882 | 174k |       (info->cpu->insn_cc_not_modified[0] != info->insn) && | 
| 1883 | 174k |       (info->cpu->insn_cc_not_modified[1] != info->insn)) | 
| 1884 | 104k |       add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY); | 
| 1885 |  |  | 
| 1886 | 174k |     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 | 174k |     if ((info->cpu->insn_cc_not_modified[0] == info->insn) || | 
| 1891 | 174k |       (info->cpu->insn_cc_not_modified[1] == info->insn)) | 
| 1892 | 1.34k |       access_mode = rmmm; | 
| 1893 |  |  | 
| 1894 | 174k |     build_regs_read_write_counts(MI, info, access_mode); | 
| 1895 | 174k |     add_operators_access(MI, info, access_mode); | 
| 1896 |  |  | 
| 1897 | 174k |     if (g_insn_props[info->insn].update_reg_access) | 
| 1898 | 19.9k |       set_changed_regs_read_write_counts(MI, info); | 
| 1899 |  |  | 
| 1900 | 174k |     info->insn_size = (uint8_t)insn_description.insn_size; | 
| 1901 |  |  | 
| 1902 | 174k |     return info->insn_size; | 
| 1903 | 174k |   } | 
| 1904 | 23.8k |   else | 
| 1905 | 23.8k |     MCInst_setOpcode(MI, insn_description.opcode); | 
| 1906 |  |  | 
| 1907 |  |   // Illegal instruction | 
| 1908 | 23.8k |   address = base_address; | 
| 1909 | 23.8k |   illegal_hdlr(MI, info, &address); | 
| 1910 | 23.8k |   return 1; | 
| 1911 | 197k | } | 
| 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 | 197k | { | 
| 2137 | 197k |   if (cpu_type == M680X_CPU_TYPE_INVALID) { | 
| 2138 | 0 |     return false; | 
| 2139 | 0 |   } | 
| 2140 |  |  | 
| 2141 | 197k |   info->code = code; | 
| 2142 | 197k |   info->size = code_len; | 
| 2143 | 197k |   info->offset = address; | 
| 2144 | 197k |   info->cpu_type = cpu_type; | 
| 2145 |  |  | 
| 2146 | 197k |   info->cpu = &g_cpu_tables[info->cpu_type]; | 
| 2147 |  |  | 
| 2148 | 197k |   return true; | 
| 2149 | 197k | } | 
| 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 | 197k | { | 
| 2154 | 197k |   unsigned int insn_size = 0; | 
| 2155 | 197k |   e_cpu_type cpu_type = M680X_CPU_TYPE_INVALID; // No default CPU type | 
| 2156 | 197k |   cs_struct *handle = (cs_struct *)ud; | 
| 2157 | 197k |   m680x_info *info = (m680x_info *)handle->printer_info; | 
| 2158 |  |  | 
| 2159 | 197k |   MCInst_clear(MI); | 
| 2160 |  |  | 
| 2161 | 197k |   if (handle->mode & CS_MODE_M680X_6800) | 
| 2162 | 1.64k |     cpu_type = M680X_CPU_TYPE_6800; | 
| 2163 |  |  | 
| 2164 | 196k |   else if (handle->mode & CS_MODE_M680X_6801) | 
| 2165 | 5.79k |     cpu_type = M680X_CPU_TYPE_6801; | 
| 2166 |  |  | 
| 2167 | 190k |   else if (handle->mode & CS_MODE_M680X_6805) | 
| 2168 | 4.33k |     cpu_type = M680X_CPU_TYPE_6805; | 
| 2169 |  |  | 
| 2170 | 186k |   else if (handle->mode & CS_MODE_M680X_6808) | 
| 2171 | 7.49k |     cpu_type = M680X_CPU_TYPE_6808; | 
| 2172 |  |  | 
| 2173 | 178k |   else if (handle->mode & CS_MODE_M680X_HCS08) | 
| 2174 | 8.61k |     cpu_type = M680X_CPU_TYPE_HCS08; | 
| 2175 |  |  | 
| 2176 | 170k |   else if (handle->mode & CS_MODE_M680X_6809) | 
| 2177 | 20.7k |     cpu_type = M680X_CPU_TYPE_6809; | 
| 2178 |  |  | 
| 2179 | 149k |   else if (handle->mode & CS_MODE_M680X_6301) | 
| 2180 | 711 |     cpu_type = M680X_CPU_TYPE_6301; | 
| 2181 |  |  | 
| 2182 | 148k |   else if (handle->mode & CS_MODE_M680X_6309) | 
| 2183 | 56.1k |     cpu_type = M680X_CPU_TYPE_6309; | 
| 2184 |  |  | 
| 2185 | 92.4k |   else if (handle->mode & CS_MODE_M680X_6811) | 
| 2186 | 13.6k |     cpu_type = M680X_CPU_TYPE_6811; | 
| 2187 |  |  | 
| 2188 | 78.8k |   else if (handle->mode & CS_MODE_M680X_CPU12) | 
| 2189 | 78.8k |     cpu_type = M680X_CPU_TYPE_CPU12; | 
| 2190 |  |  | 
| 2191 | 197k |   if (cpu_type != M680X_CPU_TYPE_INVALID && | 
| 2192 | 197k |     m680x_setup_internals(info, cpu_type, (uint16_t)address, code, | 
| 2193 | 197k |       (uint16_t)code_len)) | 
| 2194 | 197k |     insn_size = m680x_disassemble(MI, info, (uint16_t)address); | 
| 2195 |  |  | 
| 2196 | 197k |   if (insn_size == 0) { | 
| 2197 | 0 |     *size = 1; | 
| 2198 | 0 |     return false; | 
| 2199 | 0 |   } | 
| 2200 |  |  | 
| 2201 |  |   // Make sure we always stay within range | 
| 2202 | 197k |   if (insn_size > code_len) { | 
| 2203 | 28 |     *size = (uint16_t)code_len; | 
| 2204 | 28 |     return false; | 
| 2205 | 28 |   } | 
| 2206 | 197k |   else | 
| 2207 | 197k |     *size = (uint16_t)insn_size; | 
| 2208 |  |  | 
| 2209 | 197k |   return true; | 
| 2210 | 197k | } | 
| 2211 |  |  | 
| 2212 |  | cs_err M680X_disassembler_init(cs_struct *ud) | 
| 2213 | 2.13k | { | 
| 2214 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   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 | 2.13k |   return CS_ERR_OK; | 
| 2282 | 2.13k | } | 
| 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 |  |  |