/src/capstonenext/arch/SH/SHDisassembler.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* Capstone Disassembly Engine */ | 
| 2 |  | /* By Yoshinori Sato, 2022 */ | 
| 3 |  |  | 
| 4 |  | #include <string.h> | 
| 5 |  | #include <stdarg.h> | 
| 6 |  | #include "../../cs_priv.h" | 
| 7 |  | #include "../../MCInst.h" | 
| 8 |  | #include "../../MCDisassembler.h" | 
| 9 |  | #include "../../utils.h" | 
| 10 |  | #include "SHDisassembler.h" | 
| 11 |  | #include "capstone/sh.h" | 
| 12 |  |  | 
| 13 |  | #define regs_read(_detail, _reg)          \ | 
| 14 | 0 |   if (_detail)             \ | 
| 15 | 0 |     _detail->regs_read[_detail->regs_read_count++] = _reg | 
| 16 |  | #define regs_write(_detail, _reg)         \ | 
| 17 | 0 |   if (_detail)             \ | 
| 18 | 0 |     _detail->regs_write[_detail->regs_write_count++] = _reg | 
| 19 |  |  | 
| 20 |  | enum direction {read, write}; | 
| 21 |  |  | 
| 22 |  | static void regs_rw(cs_detail *detail, enum direction rw, sh_reg reg) | 
| 23 | 0 | { | 
| 24 | 0 |   switch(rw) { | 
| 25 | 0 |   case read: | 
| 26 | 0 |     regs_read(detail, reg); | 
| 27 | 0 |     break; | 
| 28 | 0 |   case write: | 
| 29 | 0 |     regs_write(detail, reg); | 
| 30 | 0 |     break; | 
| 31 | 0 |   } | 
| 32 | 0 | } | 
| 33 |  |  | 
| 34 |  | static void set_reg_n(sh_info *info, sh_reg reg, int pos, | 
| 35 |  |           enum direction rw, cs_detail *detail) | 
| 36 | 0 | { | 
| 37 | 0 |   info->op.operands[pos].type = SH_OP_REG; | 
| 38 | 0 |   info->op.operands[pos].reg = reg; | 
| 39 | 0 |   regs_rw(detail, rw, reg); | 
| 40 | 0 | } | 
| 41 |  |  | 
| 42 |  | static void set_reg(sh_info *info, sh_reg reg, enum direction rw, | 
| 43 |  |         cs_detail *detail) | 
| 44 | 0 | { | 
| 45 | 0 |   set_reg_n(info, reg, info->op.op_count, rw, detail); | 
| 46 | 0 |   info->op.op_count++; | 
| 47 | 0 | } | 
| 48 |  |  | 
| 49 |  | static void set_mem_n(sh_info *info, sh_op_mem_type address, | 
| 50 |  |           sh_reg reg, uint32_t disp, int sz, int pos, | 
| 51 |  |           cs_detail *detail) | 
| 52 | 0 | { | 
| 53 | 0 |   info->op.operands[pos].type = SH_OP_MEM; | 
| 54 | 0 |   info->op.operands[pos].mem.address = address; | 
| 55 | 0 |   info->op.operands[pos].mem.reg = reg; | 
| 56 | 0 |   info->op.operands[pos].mem.disp = disp; | 
| 57 | 0 |   if (sz > 0) | 
| 58 | 0 |     info->op.size = sz; | 
| 59 | 0 |   switch (address) { | 
| 60 | 0 |   case SH_OP_MEM_REG_POST: | 
| 61 | 0 |   case SH_OP_MEM_REG_PRE: | 
| 62 | 0 |     regs_write(detail, reg); | 
| 63 | 0 |     break; | 
| 64 | 0 |   case SH_OP_MEM_GBR_R0: | 
| 65 | 0 |     regs_read(detail, SH_REG_GBR); | 
| 66 | 0 |     regs_read(detail, SH_REG_R0); | 
| 67 | 0 |     break; | 
| 68 | 0 |   case SH_OP_MEM_REG_R0: | 
| 69 | 0 |     regs_read(detail, SH_REG_R0); | 
| 70 | 0 |     regs_read(detail, reg); | 
| 71 | 0 |     break; | 
| 72 | 0 |   case SH_OP_MEM_PCR: | 
| 73 | 0 |     break; | 
| 74 | 0 |   default: | 
| 75 | 0 |     regs_read(detail, reg); | 
| 76 | 0 |     break; | 
| 77 | 0 |   } | 
| 78 | 0 | } | 
| 79 |  |  | 
| 80 |  | static void set_mem(sh_info *info, sh_op_mem_type address, | 
| 81 |  |         sh_reg reg, uint32_t disp, int sz, cs_detail *detail) | 
| 82 | 0 | { | 
| 83 | 0 |   set_mem_n(info, address, reg, disp, sz, info->op.op_count, detail); | 
| 84 | 0 |   info->op.op_count++; | 
| 85 | 0 | } | 
| 86 |  |  | 
| 87 |  | static void set_imm(sh_info *info, int sign, uint64_t imm) | 
| 88 | 0 | { | 
| 89 | 0 |   info->op.operands[info->op.op_count].type = SH_OP_IMM; | 
| 90 | 0 |   if (sign && imm >= 128) | 
| 91 | 0 |     imm = -256 + imm; | 
| 92 | 0 |   info->op.operands[info->op.op_count].imm = imm; | 
| 93 | 0 |   info->op.op_count++; | 
| 94 | 0 | } | 
| 95 |  |  | 
| 96 |  | static void set_groups(cs_detail *detail, int n, ...) | 
| 97 | 0 | { | 
| 98 | 0 |   va_list g; | 
| 99 | 0 |   va_start(g, n); | 
| 100 | 0 |   while (n > 0) { | 
| 101 | 0 |     sh_insn_group grp; | 
| 102 | 0 |     grp = va_arg(g, sh_insn_group); | 
| 103 | 0 |     if (detail) { | 
| 104 | 0 |       detail->groups[detail->groups_count] = grp; | 
| 105 | 0 |       detail->groups_count++; | 
| 106 | 0 |     } | 
| 107 | 0 |     n--; | 
| 108 | 0 |   } | 
| 109 | 0 |   va_end(g); | 
| 110 | 0 | } | 
| 111 |  |  | 
| 112 |  | enum { | 
| 113 |  |   ISA_ALL = 1, | 
| 114 |  |   ISA_SH2 = 2, | 
| 115 |  |   ISA_SH2A = 3, | 
| 116 |  |   ISA_SH3 = 4, | 
| 117 |  |   ISA_SH4 = 5, | 
| 118 |  |   ISA_SH4A = 6, | 
| 119 |  |   ISA_MAX = 7, | 
| 120 |  | }; | 
| 121 |  |  | 
| 122 |  | static int isalevel(cs_mode mode) | 
| 123 | 0 | { | 
| 124 | 0 |   int level; | 
| 125 | 0 |   mode >>= 1; /* skip endian */ | 
| 126 | 0 |   for (level = 2; level < ISA_MAX; level++) { | 
| 127 | 0 |     if (mode & 1) | 
| 128 | 0 |       return level; | 
| 129 | 0 |     mode >>= 1; | 
| 130 | 0 |   } | 
| 131 | 0 |   return ISA_ALL; | 
| 132 | 0 | } | 
| 133 |  |  | 
| 134 |  | enum co_processor {none, shfpu, shdsp}; | 
| 135 |  | typedef union reg_insn { | 
| 136 |  |   sh_reg reg; | 
| 137 |  |   sh_insn insn; | 
| 138 |  | } reg_insn; | 
| 139 |  | struct ri_list { | 
| 140 |  |   int no; | 
| 141 |  |   int /* reg_insn */ri; | 
| 142 |  |   int level; | 
| 143 |  |   enum co_processor cp; | 
| 144 |  | }; | 
| 145 |  |  | 
| 146 |  | static const struct ri_list ldc_stc_regs[] = { | 
| 147 |  |     {0, SH_REG_SR, ISA_ALL, none}, | 
| 148 |  |     {1, SH_REG_GBR, ISA_ALL, none}, | 
| 149 |  |     {2, SH_REG_VBR, ISA_ALL, none}, | 
| 150 |  |     {3, SH_REG_SSR, ISA_SH3, none}, | 
| 151 |  |     {4, SH_REG_SPC, ISA_SH3, none}, | 
| 152 |  |     {5, SH_REG_MOD, ISA_ALL, shdsp}, | 
| 153 |  |     {6, SH_REG_RS, ISA_ALL, shdsp}, | 
| 154 |  |     {7, SH_REG_RE, ISA_ALL, shdsp}, | 
| 155 |  |     {8, SH_REG_R0_BANK, ISA_SH3, none}, | 
| 156 |  |     {9, SH_REG_R1_BANK, ISA_SH3, none}, | 
| 157 |  |     {10, SH_REG_R2_BANK, ISA_SH3, none}, | 
| 158 |  |     {11, SH_REG_R3_BANK, ISA_SH3, none}, | 
| 159 |  |     {12, SH_REG_R4_BANK, ISA_SH3, none}, | 
| 160 |  |     {13, SH_REG_R5_BANK, ISA_SH3, none}, | 
| 161 |  |     {14, SH_REG_R6_BANK, ISA_SH3, none}, | 
| 162 |  |     {15, SH_REG_R7_BANK, ISA_SH3, none}, | 
| 163 |  |     {-1, SH_REG_INVALID, ISA_ALL, none}, | 
| 164 |  | }; | 
| 165 |  |  | 
| 166 |  | static sh_insn lookup_insn(const struct ri_list *list, | 
| 167 |  |            int no, cs_mode mode) | 
| 168 | 0 | { | 
| 169 | 0 |   int level = isalevel(mode); | 
| 170 | 0 |   sh_insn error = SH_INS_INVALID; | 
| 171 | 0 |   for(; list->no >= 0; list++) { | 
| 172 | 0 |     if (no != list->no) | 
| 173 | 0 |       continue; | 
| 174 | 0 |     if (((level >= 0) && (level < list->level)) || | 
| 175 | 0 |         ((level < 0) && (-(level) != list->level))) | 
| 176 | 0 |       continue; | 
| 177 | 0 |     if ((list->cp == none) || | 
| 178 | 0 |         ((list->cp == shfpu) && (mode & CS_MODE_SHFPU)) || | 
| 179 | 0 |         ((list->cp == shdsp) && (mode & CS_MODE_SHDSP))) { | 
| 180 | 0 |       return list->ri; | 
| 181 | 0 |     } | 
| 182 | 0 |   } | 
| 183 | 0 |   return error; | 
| 184 | 0 | } | 
| 185 |  |  | 
| 186 |  | static sh_reg lookup_regs(const struct ri_list *list, | 
| 187 |  |            int no, cs_mode mode) | 
| 188 | 0 | { | 
| 189 | 0 |   int level = isalevel(mode); | 
| 190 | 0 |   sh_reg error = SH_REG_INVALID; | 
| 191 | 0 |   for(; list->no >= 0; list++) { | 
| 192 | 0 |     if (no != list->no) | 
| 193 | 0 |       continue; | 
| 194 | 0 |     if (((level >= 0) && (level < list->level)) || | 
| 195 | 0 |         ((level < 0) && (-(level) != list->level))) | 
| 196 | 0 |       continue; | 
| 197 | 0 |     if ((list->cp == none) || | 
| 198 | 0 |         ((list->cp == shfpu) && (mode & CS_MODE_SHFPU)) || | 
| 199 | 0 |         ((list->cp == shdsp) && (mode & CS_MODE_SHDSP))) { | 
| 200 | 0 |       return list->ri; | 
| 201 | 0 |     } | 
| 202 | 0 |   } | 
| 203 | 0 |   return error; | 
| 204 | 0 | } | 
| 205 |  |  | 
| 206 |  | // #define lookup_regs(list, no, mode) ((reg_insn)(lookup(reg, list, no, mode).reg)) | 
| 207 |  | // #define lookup_insn(list, no, mode) ((sh_insn)(lookup(insn, list, no, mode).insn)) | 
| 208 |  |  | 
| 209 |  | static sh_reg opSTCsrc(uint16_t code, MCInst *MI, cs_mode mode, | 
| 210 |  |            sh_info *info, cs_detail *detail) | 
| 211 | 0 | { | 
| 212 | 0 |   int s = (code >> 4) & 0x0f; | 
| 213 | 0 |   int d = (code >> 8) & 0x0f; | 
| 214 | 0 |   sh_reg sreg; | 
| 215 | 0 |   MCInst_setOpcode(MI, SH_INS_STC); | 
| 216 | 0 |   sreg = lookup_regs(ldc_stc_regs, s, mode); | 
| 217 | 0 |   if (sreg != SH_REG_INVALID) { | 
| 218 | 0 |     set_reg(info, sreg, read, detail); | 
| 219 | 0 |     return SH_REG_R0 + d; | 
| 220 | 0 |   } else { | 
| 221 | 0 |     return SH_REG_INVALID; | 
| 222 | 0 |   } | 
| 223 | 0 | } | 
| 224 |  |  | 
| 225 |  | static bool opSTC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 226 |  |       sh_info *info, cs_detail *detail) | 
| 227 | 0 | { | 
| 228 | 0 |   sh_reg d; | 
| 229 | 0 |   d = opSTCsrc(code, MI, mode, info, detail); | 
| 230 | 0 |   if (d != SH_REG_INVALID) { | 
| 231 | 0 |     set_reg(info, d, write, detail); | 
| 232 | 0 |     return MCDisassembler_Success; | 
| 233 | 0 |   } else { | 
| 234 | 0 |     return MCDisassembler_Fail; | 
| 235 | 0 |   }     | 
| 236 | 0 | } | 
| 237 |  |  | 
| 238 |  | static bool op0xx3(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 239 |  |        sh_info *info, cs_detail *detail) | 
| 240 | 0 | { | 
| 241 | 0 |   int r = (code >> 8) & 0x0f; | 
| 242 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 243 | 0 |   static const struct ri_list list[] = { | 
| 244 | 0 |     {0, SH_INS_BSRF, ISA_SH2, none}, | 
| 245 | 0 |     {2, SH_INS_BRAF, ISA_SH2, none}, | 
| 246 | 0 |     {6, SH_INS_MOVLI, ISA_SH4A, none}, | 
| 247 | 0 |     {7, SH_INS_MOVCO, ISA_SH4A, none}, | 
| 248 | 0 |     {8, SH_INS_PREF, ISA_SH2A, none}, | 
| 249 | 0 |     {9, SH_INS_OCBI, ISA_SH4, none}, | 
| 250 | 0 |     {10, SH_INS_OCBP, ISA_SH4, none}, | 
| 251 | 0 |     {11, SH_INS_OCBWB, ISA_SH4, none}, | 
| 252 | 0 |     {12, SH_INS_MOVCA, ISA_SH4, none}, | 
| 253 | 0 |     {13, SH_INS_PREFI, ISA_SH4A, none}, | 
| 254 | 0 |     {14, SH_INS_ICBI, ISA_SH4A, none}, | 
| 255 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 256 | 0 |   }; | 
| 257 | 0 |   sh_insn insn = lookup_insn(list, insn_code, mode); | 
| 258 |  | 
 | 
| 259 | 0 |   if (insn != SH_INS_INVALID) { | 
| 260 | 0 |     MCInst_setOpcode(MI, insn); | 
| 261 | 0 |     switch (insn_code) { | 
| 262 | 0 |     case 0: /// bsrf Rn | 
| 263 | 0 |     case 2: /// braf Rn | 
| 264 | 0 |       set_reg(info, SH_REG_R0 + r, read, detail); | 
| 265 | 0 |       if (detail) | 
| 266 | 0 |         set_groups(detail, 2, | 
| 267 | 0 |              SH_GRP_JUMP, | 
| 268 | 0 |              SH_GRP_BRANCH_RELATIVE); | 
| 269 | 0 |       break; | 
| 270 | 0 |     case 8: /// pref @Rn | 
| 271 | 0 |     case 9: /// ocbi @Rn | 
| 272 | 0 |     case 10: /// ocbp @Rn | 
| 273 | 0 |     case 11: /// ocbwb @Rn | 
| 274 | 0 |     case 13: /// prefi @Rn | 
| 275 | 0 |     case 14: /// icbi @Rn | 
| 276 | 0 |       set_mem(info, SH_OP_MEM_REG_IND, | 
| 277 | 0 |         SH_REG_R0 + r, 0, 0, detail); | 
| 278 | 0 |       break; | 
| 279 | 0 |     case 6: /// movli @Rn, R0 | 
| 280 | 0 |       set_mem(info, SH_OP_MEM_REG_IND, | 
| 281 | 0 |         SH_REG_R0 + r, 0, 32, detail); | 
| 282 | 0 |       set_reg(info, SH_REG_R0, write, detail); | 
| 283 | 0 |       break; | 
| 284 | 0 |     case 7: /// movco R0,@Rn | 
| 285 | 0 |     case 12: /// movca R0,@Rn | 
| 286 | 0 |       set_reg(info, SH_REG_R0, read, detail); | 
| 287 | 0 |       set_mem(info, SH_OP_MEM_REG_IND, | 
| 288 | 0 |         SH_REG_R0 + r, 0, 32, detail); | 
| 289 | 0 |       break; | 
| 290 | 0 |     } | 
| 291 | 0 |     return MCDisassembler_Success; | 
| 292 | 0 |   } else { | 
| 293 | 0 |     return MCDisassembler_Fail; | 
| 294 | 0 |   }     | 
| 295 | 0 | } | 
| 296 |  |  | 
| 297 |  | #define nm(code, dir)       \ | 
| 298 | 0 |   int m, n;       \ | 
| 299 | 0 |   m = (code >> (4 * (dir + 1))) & 0x0f; \ | 
| 300 | 0 |   n = (code >> (8 - 4 * dir)) & 0x0f | 
| 301 |  |  | 
| 302 |  | static bool opMOVx(uint16_t code, uint64_t address, MCInst *MI, | 
| 303 |  |        cs_mode mode, int size, sh_info *info, cs_detail *detail) | 
| 304 | 0 | { | 
| 305 | 0 |   int ad = ((code >> 10) & 0x3c) | ((code >> 2) & 0x03); | 
| 306 | 0 |   enum direction rw; | 
| 307 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 308 | 0 |   switch (ad) { | 
| 309 | 0 |   case 0x01: /// mov.X Rs,@(R0, Rd) | 
| 310 | 0 |   case 0x03: /// mov.X @(R0, Rs), Rd | 
| 311 | 0 |     rw = (ad >> 1); | 
| 312 | 0 |     { | 
| 313 | 0 |       nm(code, rw); | 
| 314 | 0 |       set_reg_n(info, SH_REG_R0 + m, rw, rw, detail); | 
| 315 | 0 |       set_mem_n(info, SH_OP_MEM_REG_R0, SH_REG_R0 + n, | 
| 316 | 0 |           0, size, 1 - rw, detail); | 
| 317 | 0 |       info->op.op_count = 2; | 
| 318 | 0 |     } | 
| 319 | 0 |     break; | 
| 320 | 0 |   case 0x20: /// mov.X Rs,@-Rd | 
| 321 | 0 |   case 0x60: /// mov.X @Rs+,Rd | 
| 322 | 0 |     rw = (ad >> 6) & 1; | 
| 323 | 0 |     { | 
| 324 | 0 |       nm(code, rw); | 
| 325 | 0 |       set_reg_n(info, SH_REG_R0 + m, rw, rw, detail); | 
| 326 | 0 |       set_mem_n(info, SH_OP_MEM_REG_PRE, SH_REG_R0 + n, | 
| 327 | 0 |           0, size, 1 - rw, detail); | 
| 328 | 0 |     } | 
| 329 | 0 |     break; | 
| 330 | 0 |   default: | 
| 331 | 0 |     return MCDisassembler_Fail; | 
| 332 | 0 |   } | 
| 333 | 0 |   return MCDisassembler_Success; | 
| 334 | 0 | } | 
| 335 |  |  | 
| 336 |  | static bool opMOV_B(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 337 |  |         sh_info *info, cs_detail *detail) | 
| 338 | 0 | { | 
| 339 | 0 |   return opMOVx(code, address, MI, mode, 8, info, detail); | 
| 340 | 0 | } | 
| 341 |  |  | 
| 342 |  | static bool opMOV_W(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 343 |  |         sh_info *info, cs_detail *detail) | 
| 344 | 0 | { | 
| 345 | 0 |   return opMOVx(code, address, MI, mode, 16, info, detail); | 
| 346 | 0 | } | 
| 347 |  |  | 
| 348 |  | static bool opMOV_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 349 |  |         sh_info *info, cs_detail *detail) | 
| 350 | 0 | { | 
| 351 | 0 |   return opMOVx(code, address, MI, mode, 32, info, detail); | 
| 352 | 0 | } | 
| 353 |  |  | 
| 354 |  | static bool opRRfn(uint16_t code, MCInst *MI, sh_insn insn, cs_mode mode, | 
| 355 |  |        int size, int level, sh_info *info, cs_detail *detail) | 
| 356 | 0 | { | 
| 357 | 0 |   int m = (code >> 4) & 0x0f; | 
| 358 | 0 |   int n = (code >> 8) & 0x0f; | 
| 359 | 0 |   if (level > isalevel(mode)) | 
| 360 | 0 |     return MCDisassembler_Fail; | 
| 361 | 0 |   MCInst_setOpcode(MI, insn); | 
| 362 | 0 |   set_reg(info, SH_REG_R0 + m, read, detail); | 
| 363 | 0 |   set_reg(info, SH_REG_R0 + n, write, detail); | 
| 364 | 0 |   info->op.size = size; | 
| 365 | 0 |   return MCDisassembler_Success; | 
| 366 | 0 | } | 
| 367 |  |  | 
| 368 |  | #define opRR(level, __insn, __size)         \ | 
| 369 |  | static bool op##__insn(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 370 | 0 |            cs_mode mode, sh_info *info, cs_detail *detail)  \ | 
| 371 | 0 | {                 \ | 
| 372 | 0 |   return opRRfn(code, MI, SH_INS_##__insn, mode, __size, level, \ | 
| 373 | 0 |           info, detail);          \ | 
| 374 | 0 | } Unexecuted instantiation: SHDisassembler.c:opMUL_LUnexecuted instantiation: SHDisassembler.c:opDIV0SUnexecuted instantiation: SHDisassembler.c:opTSTUnexecuted instantiation: SHDisassembler.c:opANDUnexecuted instantiation: SHDisassembler.c:opXORUnexecuted instantiation: SHDisassembler.c:opORUnexecuted instantiation: SHDisassembler.c:opCMP_STRUnexecuted instantiation: SHDisassembler.c:opXTRCTUnexecuted instantiation: SHDisassembler.c:opMULU_WUnexecuted instantiation: SHDisassembler.c:opMULS_WUnexecuted instantiation: SHDisassembler.c:opCMP_EQUnexecuted instantiation: SHDisassembler.c:opCMP_HSUnexecuted instantiation: SHDisassembler.c:opCMP_GEUnexecuted instantiation: SHDisassembler.c:opDIV1Unexecuted instantiation: SHDisassembler.c:opDMULU_LUnexecuted instantiation: SHDisassembler.c:opCMP_HIUnexecuted instantiation: SHDisassembler.c:opCMP_GTUnexecuted instantiation: SHDisassembler.c:opSUBUnexecuted instantiation: SHDisassembler.c:opSUBCUnexecuted instantiation: SHDisassembler.c:opSUBVUnexecuted instantiation: SHDisassembler.c:opADD_rUnexecuted instantiation: SHDisassembler.c:opDMULS_LUnexecuted instantiation: SHDisassembler.c:opADDCUnexecuted instantiation: SHDisassembler.c:opADDVUnexecuted instantiation: SHDisassembler.c:opSHADUnexecuted instantiation: SHDisassembler.c:opSHLDUnexecuted instantiation: SHDisassembler.c:opMOVUnexecuted instantiation: SHDisassembler.c:opNOTUnexecuted instantiation: SHDisassembler.c:opSWAP_BUnexecuted instantiation: SHDisassembler.c:opSWAP_WUnexecuted instantiation: SHDisassembler.c:opNEGCUnexecuted instantiation: SHDisassembler.c:opNEGUnexecuted instantiation: SHDisassembler.c:opEXTU_BUnexecuted instantiation: SHDisassembler.c:opEXTU_WUnexecuted instantiation: SHDisassembler.c:opEXTS_BUnexecuted instantiation: SHDisassembler.c:opEXTS_W | 
| 375 |  |  | 
| 376 |  | /* mul.l - SH2 */ | 
| 377 |  | opRR(ISA_SH2, MUL_L, 0) | 
| 378 |  |  | 
| 379 |  | static bool op0xx8(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 380 |  |        sh_info *info, cs_detail *detail) | 
| 381 | 0 | { | 
| 382 | 0 |   int insn_code = (code >> 4) & 0xf; | 
| 383 | 0 |   static const struct ri_list list[] = { | 
| 384 | 0 |     {0, SH_INS_CLRT, ISA_ALL, none}, | 
| 385 | 0 |     {1, SH_INS_SETT, ISA_ALL, none}, | 
| 386 | 0 |     {2, SH_INS_CLRMAC, ISA_ALL, none}, | 
| 387 | 0 |     {3, SH_INS_LDTLB, ISA_SH3, none}, | 
| 388 | 0 |     {4, SH_INS_CLRS, ISA_SH3, none}, | 
| 389 | 0 |     {5, SH_INS_SETS, ISA_SH3, none}, | 
| 390 | 0 |     {6, SH_INS_NOTT, -(ISA_SH2A), none}, | 
| 391 | 0 |     {8, SH_INS_CLRDMXY, ISA_SH4A, shdsp}, | 
| 392 | 0 |     {9, SH_INS_SETDMX, ISA_SH4A, shdsp}, | 
| 393 | 0 |     {12, SH_INS_SETDMY, ISA_SH4A, shdsp}, | 
| 394 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 395 | 0 |   }; | 
| 396 |  |    | 
| 397 | 0 |   sh_insn insn = lookup_insn(list, insn_code, mode); | 
| 398 | 0 |   if (code & 0x0f00) | 
| 399 | 0 |     return MCDisassembler_Fail; | 
| 400 |  |      | 
| 401 | 0 |   if (insn != SH_INS_INVALID) { | 
| 402 | 0 |     MCInst_setOpcode(MI, insn); | 
| 403 | 0 |     return MCDisassembler_Success; | 
| 404 | 0 |   } else { | 
| 405 | 0 |     return MCDisassembler_Fail; | 
| 406 | 0 |   } | 
| 407 | 0 | } | 
| 408 |  |  | 
| 409 |  | static bool op0xx9(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 410 |  |        sh_info *info, cs_detail *detail) | 
| 411 | 0 | { | 
| 412 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 413 | 0 |   int r = (code >> 8) & 0x0f; | 
| 414 | 0 |   static const struct ri_list list[] = { | 
| 415 | 0 |     {0, SH_INS_NOP, ISA_ALL, none}, | 
| 416 | 0 |     {1, SH_INS_DIV0U, ISA_ALL, none}, | 
| 417 | 0 |     {2, SH_INS_MOVT, ISA_ALL, none}, | 
| 418 | 0 |     {3, SH_INS_MOVRT, -(ISA_SH2A), none}, | 
| 419 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 420 | 0 |   }; | 
| 421 | 0 |   sh_insn insn = lookup_insn(list, insn_code, mode); | 
| 422 | 0 |   if (insn != SH_INS_INVALID) { | 
| 423 | 0 |     if (insn_code >= 2) { | 
| 424 |  |       /// movt / movrt Rn | 
| 425 | 0 |       set_reg(info, SH_REG_R0 + r, write, detail); | 
| 426 | 0 |     } else if (r > 0) { | 
| 427 | 0 |       insn = SH_INS_INVALID; | 
| 428 | 0 |     } | 
| 429 | 0 |   } | 
| 430 | 0 |   if (insn != SH_INS_INVALID) { | 
| 431 | 0 |     MCInst_setOpcode(MI, insn); | 
| 432 | 0 |     return MCDisassembler_Success; | 
| 433 | 0 |   } else { | 
| 434 | 0 |     return MCDisassembler_Fail; | 
| 435 | 0 |   } | 
| 436 | 0 | } | 
| 437 |  |  | 
| 438 |  | static const struct ri_list sts_lds_regs[] = { | 
| 439 |  |   {0, SH_REG_MACH, ISA_ALL, none}, | 
| 440 |  |   {1, SH_REG_MACL, ISA_ALL, none}, | 
| 441 |  |   {2, SH_REG_PR, ISA_ALL, none}, | 
| 442 |  |   {3, SH_REG_SGR, ISA_SH4, none}, | 
| 443 |  |   {4, SH_REG_TBR, -(ISA_SH2A), none}, | 
| 444 |  |   {5, SH_REG_FPUL, ISA_ALL, shfpu}, | 
| 445 |  |   {6, SH_REG_FPSCR, ISA_ALL, shfpu}, | 
| 446 |  |   {6, SH_REG_DSP_DSR, ISA_ALL, shdsp}, | 
| 447 |  |   {7, SH_REG_DSP_A0, ISA_ALL, shdsp}, | 
| 448 |  |   {8, SH_REG_DSP_X0, ISA_ALL, shdsp}, | 
| 449 |  |   {9, SH_REG_DSP_X1, ISA_ALL, shdsp}, | 
| 450 |  |   {10, SH_REG_DSP_Y0, ISA_ALL, shdsp}, | 
| 451 |  |   {11, SH_REG_DSP_Y1, ISA_ALL, shdsp}, | 
| 452 |  |   {15, SH_REG_DBR, ISA_SH4, none}, | 
| 453 |  |   {-1, SH_REG_INVALID, ISA_ALL, none}, | 
| 454 |  | }; | 
| 455 |  |  | 
| 456 |  | static sh_reg opSTCSTS(uint16_t code, MCInst *MI, cs_mode mode, sh_info *info, | 
| 457 |  |            cs_detail *detail) | 
| 458 | 0 | { | 
| 459 | 0 |   int s = (code >> 4) & 0x0f; | 
| 460 | 0 |   int d = (code >> 8) & 0x0f; | 
| 461 | 0 |   sh_reg reg; | 
| 462 | 0 |   sh_insn insn; | 
| 463 |  | 
 | 
| 464 | 0 |   reg = lookup_regs(sts_lds_regs, s, mode); | 
| 465 | 0 |   if (reg != SH_REG_INVALID) { | 
| 466 | 0 |     if (s == 3 || s == 4 || s == 15) { | 
| 467 | 0 |       insn = SH_INS_STC; | 
| 468 | 0 |     } else { | 
| 469 | 0 |       insn = SH_INS_STS; | 
| 470 | 0 |     } | 
| 471 | 0 |     MCInst_setOpcode(MI, insn); | 
| 472 | 0 |     set_reg(info, reg, read, detail); | 
| 473 | 0 |     return SH_REG_R0 + d; | 
| 474 | 0 |   } else { | 
| 475 | 0 |     return SH_REG_INVALID; | 
| 476 | 0 |   } | 
| 477 | 0 | } | 
| 478 |  |  | 
| 479 |  | static bool op0xxa(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 480 |  |        sh_info *info, cs_detail *detail) | 
| 481 | 0 | { | 
| 482 | 0 |   sh_reg r = opSTCSTS(code, MI, mode, info, detail); | 
| 483 | 0 |   if (r != SH_REG_INVALID) { | 
| 484 | 0 |     set_reg(info, r, write, detail); | 
| 485 | 0 |     return MCDisassembler_Success; | 
| 486 | 0 |   } else | 
| 487 | 0 |     return MCDisassembler_Fail; | 
| 488 | 0 | } | 
| 489 |  |  | 
| 490 |  | static bool op0xxb(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 491 |  |        sh_info *info, cs_detail *detail) | 
| 492 | 0 | { | 
| 493 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 494 | 0 |   int r = (code >> 8) & 0x0f; | 
| 495 | 0 |   static const struct ri_list list[] = { | 
| 496 | 0 |     {0, SH_INS_RTS, ISA_ALL, none}, | 
| 497 | 0 |     {1, SH_INS_SLEEP, ISA_ALL, none}, | 
| 498 | 0 |     {2, SH_INS_RTE, ISA_ALL, none}, | 
| 499 | 0 |     {5, SH_INS_RESBANK, -(ISA_SH2A), none}, | 
| 500 | 0 |     {6, SH_INS_RTS_N, -(ISA_SH2A), none}, | 
| 501 | 0 |     {7, SH_INS_RTV_N, -(ISA_SH2A), none}, | 
| 502 | 0 |     {10, SH_INS_SYNCO, -(ISA_SH4A), none}, | 
| 503 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 504 | 0 |   }; | 
| 505 |  | 
 | 
| 506 | 0 |   sh_insn insn = lookup_insn(list, insn_code, mode); | 
| 507 | 0 |   if (insn_code == 7) { | 
| 508 | 0 |     set_reg(info, SH_REG_R0 + r, read, detail); | 
| 509 | 0 |     regs_write(detail, SH_REG_R0); | 
| 510 | 0 |   } else if (r > 0) { | 
| 511 | 0 |     insn = SH_INS_INVALID; | 
| 512 | 0 |   } | 
| 513 | 0 |   if (insn != SH_INS_INVALID) { | 
| 514 | 0 |     MCInst_setOpcode(MI, insn); | 
| 515 | 0 |     return MCDisassembler_Success; | 
| 516 | 0 |   } else { | 
| 517 | 0 |     return MCDisassembler_Fail; | 
| 518 | 0 |   }     | 
| 519 | 0 | } | 
| 520 |  |  | 
| 521 |  | static bool opMAC(uint16_t code, sh_insn op, MCInst *MI, sh_info *info, | 
| 522 |  |       cs_detail *detail) | 
| 523 | 0 | { | 
| 524 | 0 |   nm(code, 0); | 
| 525 | 0 |   MCInst_setOpcode(MI, op); | 
| 526 | 0 |   set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + m, 0, 0, detail); | 
| 527 | 0 |   set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + n, 0, 0, detail); | 
| 528 | 0 |   return MCDisassembler_Success; | 
| 529 | 0 | } | 
| 530 |  |  | 
| 531 |  | /// mac.l - sh2+ | 
| 532 |  | static bool opMAC_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 533 |  |         sh_info *info, cs_detail *detail) | 
| 534 | 0 | { | 
| 535 | 0 |   if (isalevel(mode) < ISA_SH2) | 
| 536 | 0 |     return MCDisassembler_Fail; | 
| 537 | 0 |   return opMAC(code, SH_INS_MAC_L, MI, info, detail); | 
| 538 | 0 | } | 
| 539 |  |  | 
| 540 |  | static bool opMAC_W(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 541 |  |         sh_info *info, cs_detail *detail) | 
| 542 | 0 | { | 
| 543 | 0 |   return opMAC(code, SH_INS_MAC_W, MI, info, detail); | 
| 544 | 0 | } | 
| 545 |  |  | 
| 546 |  | static bool opMOV_L_dsp(uint16_t code, uint64_t address, MCInst *MI, | 
| 547 |  |       cs_mode mode, sh_info *info, cs_detail *detail) | 
| 548 | 0 | { | 
| 549 | 0 |   int dsp = (code & 0x0f) * 4; | 
| 550 | 0 |   int rw = (code >> 14) & 1; | 
| 551 | 0 |   nm(code, rw); | 
| 552 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 553 | 0 |   set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + n, dsp, | 
| 554 | 0 |       32, 1 - rw, detail); | 
| 555 | 0 |   set_reg_n(info, SH_REG_R0 + m, rw, rw, detail); | 
| 556 | 0 |   info->op.op_count = 2; | 
| 557 | 0 |   return MCDisassembler_Success; | 
| 558 | 0 | } | 
| 559 |  |  | 
| 560 |  | static bool opMOV_rind(uint16_t code, uint64_t address, MCInst *MI, | 
| 561 |  |            cs_mode mode, sh_info *info, cs_detail *detail) | 
| 562 | 0 | { | 
| 563 | 0 |   int sz = (code & 0x03); | 
| 564 | 0 |   int rw = (code >> 14) & 1; | 
| 565 | 0 |   nm(code, rw); | 
| 566 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 567 | 0 |   sz = 8 << sz; | 
| 568 | 0 |   set_mem_n(info, SH_OP_MEM_REG_IND, SH_REG_R0 + n, 0, | 
| 569 | 0 |       sz, 1 - rw, detail); | 
| 570 | 0 |   set_reg_n(info, SH_REG_R0 + m, rw, rw, detail); | 
| 571 | 0 |   info->op.op_count = 2; | 
| 572 | 0 |   return MCDisassembler_Success; | 
| 573 | 0 | } | 
| 574 |  |  | 
| 575 |  | static bool opMOV_rpd(uint16_t code, uint64_t address, MCInst *MI, | 
| 576 |  |           cs_mode mode, sh_info *info, cs_detail *detail) | 
| 577 | 0 | { | 
| 578 | 0 |   nm(code, 0); | 
| 579 | 0 |   int sz = (code & 0x03); | 
| 580 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 581 | 0 |   set_reg(info, SH_REG_R0 + m, read, detail); | 
| 582 | 0 |   set_mem(info, SH_OP_MEM_REG_PRE, SH_REG_R0 + n, 0, 8 << sz, detail); | 
| 583 | 0 |   return MCDisassembler_Success; | 
| 584 | 0 | } | 
| 585 |  |  | 
| 586 |  | opRR(ISA_ALL, TST, 0) | 
| 587 |  | opRR(ISA_ALL, AND, 0) | 
| 588 |  | opRR(ISA_ALL, XOR, 0) | 
| 589 |  | opRR(ISA_ALL, OR, 0) | 
| 590 |  | opRR(ISA_ALL, CMP_STR, 0) | 
| 591 |  | opRR(ISA_ALL, XTRCT, 0) | 
| 592 |  | opRR(ISA_ALL, MULU_W, 16) | 
| 593 |  | opRR(ISA_ALL, MULS_W, 16) | 
| 594 |  | opRR(ISA_ALL, CMP_EQ, 0) | 
| 595 |  | opRR(ISA_ALL, CMP_HI, 0) | 
| 596 |  | opRR(ISA_ALL, CMP_HS, 0) | 
| 597 |  | opRR(ISA_ALL, CMP_GE, 0) | 
| 598 |  | opRR(ISA_ALL, CMP_GT, 0) | 
| 599 |  | opRR(ISA_ALL, SUB, 0) | 
| 600 |  | opRR(ISA_ALL, SUBC, 0) | 
| 601 |  | opRR(ISA_ALL, SUBV, 0) | 
| 602 |  | opRR(ISA_ALL, ADD_r, 0) | 
| 603 |  | opRR(ISA_ALL, ADDC, 0) | 
| 604 |  | opRR(ISA_ALL, ADDV, 0) | 
| 605 |  | opRR(ISA_ALL, DIV0S, 0) | 
| 606 |  | opRR(ISA_ALL, DIV1, 0) | 
| 607 |  | /// DMULS / DMULU - SH2 | 
| 608 |  | opRR(ISA_SH2, DMULS_L, 0) | 
| 609 |  | opRR(ISA_SH2, DMULU_L, 0) | 
| 610 |  |  | 
| 611 |  | static bool op4xx0(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 612 |  |        sh_info *info, cs_detail *detail) | 
| 613 | 0 | { | 
| 614 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 615 | 0 |   int r = (code >> 8) & 0x0f; | 
| 616 | 0 |   static const struct ri_list list[] = { | 
| 617 | 0 |     {0, SH_INS_SHLL, ISA_ALL, none}, | 
| 618 | 0 |     {1, SH_INS_DT, ISA_SH2, none}, | 
| 619 | 0 |     {2, SH_INS_SHAL, ISA_ALL, none}, | 
| 620 | 0 |     {8, SH_INS_MULR, -(ISA_SH2A), none}, | 
| 621 | 0 |     {15, SH_INS_MOVMU, -(ISA_SH2A), none}, | 
| 622 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 623 | 0 |   }; | 
| 624 | 0 |   sh_insn insn = lookup_insn(list, insn_code,mode); | 
| 625 | 0 |   if (insn != SH_INS_INVALID) { | 
| 626 | 0 |     MCInst_setOpcode(MI, insn); | 
| 627 | 0 |     if (insn_code < 8) { | 
| 628 | 0 |       set_reg(info, SH_REG_R0 + r, write, detail); | 
| 629 | 0 |     } else { | 
| 630 | 0 |       switch(insn_code) { | 
| 631 | 0 |       case 0x08: | 
| 632 | 0 |         set_reg(info, SH_REG_R0, read, detail); | 
| 633 | 0 |         set_reg(info, SH_REG_R0 + r, write, detail); | 
| 634 | 0 |         break; | 
| 635 | 0 |       case 0x0f: | 
| 636 | 0 |         set_reg(info, SH_REG_R0 + r, read, detail); | 
| 637 | 0 |         set_mem(info, SH_OP_MEM_REG_PRE, SH_REG_R15, 0, 32, detail); | 
| 638 | 0 |         break; | 
| 639 | 0 |       } | 
| 640 | 0 |     } | 
| 641 | 0 |     return MCDisassembler_Success; | 
| 642 | 0 |   } else { | 
| 643 | 0 |     return MCDisassembler_Fail; | 
| 644 | 0 |   } | 
| 645 | 0 | } | 
| 646 |  |  | 
| 647 |  | static bool op4xx1(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 648 |  |        sh_info *info, cs_detail *detail) | 
| 649 | 0 | { | 
| 650 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 651 | 0 |   int r = (code >> 8) & 0x0f; | 
| 652 | 0 |   static const struct ri_list list[] = { | 
| 653 | 0 |     {0, SH_INS_SHLR, ISA_ALL, none}, | 
| 654 | 0 |     {1, SH_INS_CMP_PZ, ISA_ALL, none}, | 
| 655 | 0 |     {2, SH_INS_SHAR, ISA_ALL, none}, | 
| 656 | 0 |     {8, SH_INS_CLIPU, -(ISA_SH2A), none}, | 
| 657 | 0 |     {9, SH_INS_CLIPS, -(ISA_SH2A), none}, | 
| 658 | 0 |     {14, SH_INS_STBANK, -(ISA_SH2A), none}, | 
| 659 | 0 |     {15, SH_INS_MOVML, -(ISA_SH2A), none}, | 
| 660 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 661 | 0 |   }; | 
| 662 | 0 |   sh_insn insn = lookup_insn(list, insn_code,mode); | 
| 663 | 0 |   if (insn != SH_INS_INVALID) { | 
| 664 | 0 |     MCInst_setOpcode(MI, insn); | 
| 665 | 0 |     switch(insn_code) { | 
| 666 | 0 |     case 14: | 
| 667 | 0 |       set_reg(info, SH_REG_R0, read, detail); | 
| 668 | 0 |       set_mem(info, SH_OP_MEM_REG_IND, SH_REG_R0 + r, 0, | 
| 669 | 0 |         0, detail); | 
| 670 | 0 |       break; | 
| 671 | 0 |     case 15: | 
| 672 | 0 |       set_reg(info, SH_REG_R0 + r, read, detail); | 
| 673 | 0 |       set_mem(info, SH_OP_MEM_REG_PRE, SH_REG_R15, 0, | 
| 674 | 0 |         32, detail); | 
| 675 | 0 |       break; | 
| 676 | 0 |     default: | 
| 677 | 0 |       set_reg(info, SH_REG_R0 + r, write, detail); | 
| 678 | 0 |       if (insn_code >= 8) | 
| 679 | 0 |         info->op.size = 8; | 
| 680 | 0 |       break; | 
| 681 | 0 |     } | 
| 682 | 0 |     return MCDisassembler_Success; | 
| 683 | 0 |   } else { | 
| 684 | 0 |     return MCDisassembler_Fail; | 
| 685 | 0 |   } | 
| 686 | 0 | } | 
| 687 |  |  | 
| 688 |  | static bool op4xx2(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 689 |  |        sh_info *info, cs_detail *detail) | 
| 690 | 0 | { | 
| 691 | 0 |   sh_reg r = opSTCSTS(code, MI, mode, info, detail); | 
| 692 | 0 |   if (r != SH_REG_INVALID) { | 
| 693 | 0 |     set_mem(info, SH_OP_MEM_REG_PRE, r, 0, 32, detail); | 
| 694 | 0 |     return MCDisassembler_Success; | 
| 695 | 0 |   } else { | 
| 696 | 0 |     return MCDisassembler_Fail; | 
| 697 | 0 |   } | 
| 698 | 0 | } | 
| 699 |  |  | 
| 700 |  | static bool opSTC_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 701 |  |         sh_info *info, cs_detail *detail) | 
| 702 | 0 | { | 
| 703 | 0 |   sh_reg r = opSTCsrc(code, MI, mode, info, detail); | 
| 704 | 0 |   if (r != SH_REG_INVALID) { | 
| 705 | 0 |     set_mem(info, SH_OP_MEM_REG_PRE, r, 0, 32, detail); | 
| 706 | 0 |     return MCDisassembler_Success; | 
| 707 | 0 |   } else { | 
| 708 | 0 |     return MCDisassembler_Fail; | 
| 709 | 0 |   }     | 
| 710 | 0 | } | 
| 711 |  |  | 
| 712 |  | static bool op4xx4(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 713 |  |        sh_info *info, cs_detail *detail) | 
| 714 | 0 | { | 
| 715 | 0 |   int r = (code >> 8) & 0x0f; | 
| 716 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 717 | 0 |   static const struct ri_list list[] = { | 
| 718 | 0 |     {0, SH_INS_ROTL, ISA_ALL, none}, | 
| 719 | 0 |     {1, SH_INS_SETRC, ISA_ALL, shdsp}, | 
| 720 | 0 |     {2, SH_INS_ROTCL, ISA_ALL, none}, | 
| 721 | 0 |     {3, SH_INS_LDRC, ISA_ALL, shdsp}, | 
| 722 | 0 |     {8, SH_INS_DIVU, -(ISA_SH2A), none}, | 
| 723 | 0 |     {9, SH_INS_DIVS, -(ISA_SH2A), none}, | 
| 724 | 0 |     {15, SH_INS_MOVMU, -(ISA_SH2A), none}, | 
| 725 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 726 | 0 |   }; | 
| 727 | 0 |   sh_insn insn = lookup_insn(list, insn_code, mode); | 
| 728 | 0 |   if (insn != SH_INS_INVALID) { | 
| 729 | 0 |     MCInst_setOpcode(MI, insn); | 
| 730 | 0 |     switch(insn_code) { | 
| 731 | 0 |     case 8: | 
| 732 | 0 |     case 9: | 
| 733 | 0 |       set_reg(info, SH_REG_R0, read, detail); | 
| 734 | 0 |       break; | 
| 735 | 0 |     case 15: | 
| 736 | 0 |       set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R15, 0, | 
| 737 | 0 |         32, detail); | 
| 738 | 0 |       set_reg(info, SH_REG_R0 + r, read, detail); | 
| 739 | 0 |       return MCDisassembler_Success; | 
| 740 | 0 |     } | 
| 741 | 0 |     set_reg(info, SH_REG_R0 + r, write, detail); | 
| 742 | 0 |     return MCDisassembler_Success; | 
| 743 | 0 |   } else { | 
| 744 | 0 |     return MCDisassembler_Fail; | 
| 745 | 0 |   } | 
| 746 | 0 | } | 
| 747 |  |  | 
| 748 |  | static bool op4xx5(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 749 |  |        sh_info *info, cs_detail *detail) | 
| 750 | 0 | { | 
| 751 | 0 |   int r = (code >> 8) & 0x0f; | 
| 752 | 0 |   enum direction rw = read; | 
| 753 | 0 |   static const struct ri_list list[] = { | 
| 754 | 0 |     {0, SH_INS_ROTR, ISA_ALL, none}, | 
| 755 | 0 |     {1, SH_INS_CMP_PL, ISA_ALL, none}, | 
| 756 | 0 |     {2, SH_INS_ROTCR, ISA_ALL, none}, | 
| 757 | 0 |     {8, SH_INS_CLIPU, -(ISA_SH2A), none}, | 
| 758 | 0 |     {9, SH_INS_CLIPS, -(ISA_SH2A), none}, | 
| 759 | 0 |     {14, SH_INS_LDBANK, -(ISA_SH2A), none}, | 
| 760 | 0 |     {15, SH_INS_MOVML, -(ISA_SH2A), none}, | 
| 761 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 762 | 0 |   }; | 
| 763 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 764 | 0 |   sh_insn insn = lookup_insn(list, insn_code,mode); | 
| 765 | 0 |   if (insn != SH_INS_INVALID) { | 
| 766 | 0 |     MCInst_setOpcode(MI, insn); | 
| 767 | 0 |     switch (insn_code) { | 
| 768 | 0 |     case 0: | 
| 769 | 0 |     case 2: | 
| 770 | 0 |       rw = write; | 
| 771 | 0 |       break; | 
| 772 | 0 |     case 1: | 
| 773 | 0 |       rw = read; | 
| 774 | 0 |       break; | 
| 775 | 0 |     case 8: | 
| 776 | 0 |     case 9: | 
| 777 | 0 |       info->op.size = 16; | 
| 778 | 0 |       rw = write; | 
| 779 | 0 |       break; | 
| 780 | 0 |     case 0x0e: | 
| 781 | 0 |       set_mem(info, SH_OP_MEM_REG_IND, SH_REG_R0 + r, 0, | 
| 782 | 0 |         0, detail); | 
| 783 | 0 |       set_reg(info, SH_REG_R0, write, detail); | 
| 784 | 0 |       return MCDisassembler_Success; | 
| 785 | 0 |     case 0x0f: | 
| 786 | 0 |       set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R15, 0, | 
| 787 | 0 |         32, detail); | 
| 788 | 0 |       set_reg(info, SH_REG_R0 + r, write, detail); | 
| 789 | 0 |       return MCDisassembler_Success; | 
| 790 | 0 |     } | 
| 791 | 0 |     set_reg(info, SH_REG_R0 + r, rw, detail); | 
| 792 | 0 |     return MCDisassembler_Success; | 
| 793 | 0 |   } else { | 
| 794 | 0 |     return MCDisassembler_Fail; | 
| 795 | 0 |   } | 
| 796 | 0 | } | 
| 797 |  |  | 
| 798 |  | static bool opLDCLDS(uint16_t code, MCInst *MI, cs_mode mode, | 
| 799 |  |          sh_info *info, cs_detail *detail) | 
| 800 | 0 | { | 
| 801 | 0 |   int d = (code >> 4) & 0x0f; | 
| 802 | 0 |   sh_reg reg = lookup_regs(sts_lds_regs, d, mode); | 
| 803 | 0 |   sh_insn insn; | 
| 804 | 0 |   if (reg != SH_REG_INVALID) { | 
| 805 | 0 |     if (d == 3 || d == 4 || d == 15) { | 
| 806 | 0 |       insn = SH_INS_LDC; | 
| 807 | 0 |     } else { | 
| 808 | 0 |       insn = SH_INS_LDS; | 
| 809 | 0 |     } | 
| 810 | 0 |     MCInst_setOpcode(MI, insn); | 
| 811 | 0 |     set_reg(info, reg, write, detail); | 
| 812 | 0 |     return MCDisassembler_Success; | 
| 813 | 0 |   } else { | 
| 814 | 0 |     return MCDisassembler_Fail; | 
| 815 | 0 |   } | 
| 816 | 0 | } | 
| 817 |  |  | 
| 818 |  | static bool op4xx6(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 819 |  |        sh_info *info, cs_detail *detail) | 
| 820 | 0 | { | 
| 821 | 0 |   int r = (code >> 8) & 0x0f; | 
| 822 | 0 |   set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + r, 0, 32, detail); | 
| 823 | 0 |   return opLDCLDS(code, MI, mode, info, detail); | 
| 824 | 0 | } | 
| 825 |  |  | 
| 826 |  | static bool opLDCdst(uint16_t code, MCInst *MI, cs_mode mode, | 
| 827 |  |          sh_info *info, cs_detail *detail) | 
| 828 | 0 | { | 
| 829 | 0 |   int d = (code >> 4) & 0x0f; | 
| 830 | 0 |   sh_reg dreg = lookup_regs(ldc_stc_regs, d, mode); | 
| 831 | 0 |   if (dreg == SH_REG_INVALID) | 
| 832 | 0 |     return MCDisassembler_Fail; | 
| 833 | 0 |   MCInst_setOpcode(MI, SH_INS_LDC); | 
| 834 | 0 |   set_reg(info, dreg, write, detail); | 
| 835 | 0 |   return MCDisassembler_Success; | 
| 836 | 0 | } | 
| 837 |  |  | 
| 838 |  | static bool opLDC_L(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 839 |  |         sh_info *info, cs_detail *detail) | 
| 840 | 0 | { | 
| 841 | 0 |   int s = (code >> 8) & 0x0f; | 
| 842 | 0 |   set_mem(info,  SH_OP_MEM_REG_POST, SH_REG_R0 + s, 0, 32, detail); | 
| 843 | 0 |   return opLDCdst(code, MI, mode, info, detail); | 
| 844 |  |    | 
| 845 | 0 | } | 
| 846 |  |  | 
| 847 |  | static bool op4xx8(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 848 |  |        sh_info *info, cs_detail *detail) | 
| 849 | 0 | { | 
| 850 | 0 |   int r = (code >> 8) & 0x0f; | 
| 851 | 0 |   sh_insn insn[] = { SH_INS_SHLL2, SH_INS_SHLL8, SH_INS_SHLL16}; | 
| 852 | 0 |   int size = (code >> 4) & 0x0f; | 
| 853 | 0 |   if (size >= ARR_SIZE(insn)) { | 
| 854 | 0 |     return MCDisassembler_Fail; | 
| 855 | 0 |   } | 
| 856 | 0 |   MCInst_setOpcode(MI, insn[size]); | 
| 857 | 0 |   set_reg(info, SH_REG_R0 + r, write, detail); | 
| 858 | 0 |   return MCDisassembler_Success; | 
| 859 | 0 | } | 
| 860 |  |  | 
| 861 |  | static bool op4xx9(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 862 |  |        sh_info *info, cs_detail *detail) | 
| 863 | 0 | { | 
| 864 | 0 |   int r = (code >> 8) & 0x0f; | 
| 865 | 0 |   static const struct ri_list list[] = { | 
| 866 | 0 |     {0, SH_INS_SHLR2, ISA_ALL, none}, | 
| 867 | 0 |     {1, SH_INS_SHLR8, ISA_ALL, none}, | 
| 868 | 0 |     {2, SH_INS_SHLR16, ISA_ALL, none}, | 
| 869 | 0 |     {10, SH_INS_MOVUA, -(ISA_SH4A), none}, | 
| 870 | 0 |     {14, SH_INS_MOVUA, -(ISA_SH4A), none}, | 
| 871 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 872 | 0 |   }; | 
| 873 | 0 |   int op = (code >> 4) & 0x0f; | 
| 874 | 0 |   sh_insn insn = lookup_insn(list, op, mode); | 
| 875 | 0 |   sh_op_mem_type memop = SH_OP_MEM_INVALID; | 
| 876 | 0 |   if (insn != SH_INS_INVALID) { | 
| 877 | 0 |     MCInst_setOpcode(MI, insn); | 
| 878 | 0 |     if (op < 8) { | 
| 879 | 0 |       set_reg(info, SH_REG_R0 + r, write, detail); | 
| 880 | 0 |     } else { | 
| 881 | 0 |       memop = (op&4)?SH_OP_MEM_REG_POST:SH_OP_MEM_REG_IND; | 
| 882 | 0 |       set_mem(info, memop, SH_REG_R0 + r, 0, 32, detail); | 
| 883 | 0 |       set_reg(info, SH_REG_R0, write, detail); | 
| 884 | 0 |     } | 
| 885 | 0 |     return MCDisassembler_Success; | 
| 886 | 0 |   } else { | 
| 887 | 0 |     return MCDisassembler_Fail; | 
| 888 | 0 |   } | 
| 889 | 0 | } | 
| 890 |  |  | 
| 891 |  | static bool op4xxa(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 892 |  |        sh_info *info, cs_detail *detail) | 
| 893 | 0 | { | 
| 894 | 0 |   int r = (code >> 8) & 0x0f; | 
| 895 | 0 |   set_reg(info, SH_REG_R0 + r, read, detail); | 
| 896 | 0 |   return opLDCLDS(code, MI, mode, info, detail); | 
| 897 | 0 | } | 
| 898 |  |  | 
| 899 |  | static bool op4xxb(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 900 |  |        sh_info *info, cs_detail *detail) | 
| 901 | 0 | { | 
| 902 | 0 |   int r = (code >> 8) & 0x0f; | 
| 903 | 0 |   int insn_code = (code >> 4) & 0x0f; | 
| 904 | 0 |   int sz = 0; | 
| 905 | 0 |   int grp = SH_GRP_INVALID; | 
| 906 | 0 |   sh_op_mem_type memop = SH_OP_MEM_INVALID; | 
| 907 | 0 |   enum direction rw = read; | 
| 908 | 0 |   static const struct ri_list list[] = { | 
| 909 | 0 |     {0, SH_INS_JSR, ISA_ALL, none}, | 
| 910 | 0 |     {1, SH_INS_TAS, ISA_ALL, none}, | 
| 911 | 0 |     {2, SH_INS_JMP, ISA_ALL, none}, | 
| 912 | 0 |     {4, SH_INS_JSR_N, -(ISA_SH2A), none}, | 
| 913 | 0 |     {8, SH_INS_MOV, -(ISA_SH2A), none}, | 
| 914 | 0 |     {9, SH_INS_MOV, -(ISA_SH2A), none}, | 
| 915 | 0 |     {10, SH_INS_MOV, -(ISA_SH2A), none}, | 
| 916 | 0 |     {12, SH_INS_MOV, -(ISA_SH2A), none}, | 
| 917 | 0 |     {13, SH_INS_MOV, -(ISA_SH2A), none}, | 
| 918 | 0 |     {14, SH_INS_MOV, -(ISA_SH2A), none}, | 
| 919 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 920 | 0 |   }; | 
| 921 | 0 |   sh_insn insn = lookup_insn(list, insn_code, mode); | 
| 922 | 0 |   if (insn != SH_INS_INVALID) { | 
| 923 | 0 |     MCInst_setOpcode(MI, insn); | 
| 924 | 0 |     sz = 8 << ((code >> 4) & 3); | 
| 925 | 0 |     switch (insn_code) { | 
| 926 | 0 |     case 0: | 
| 927 | 0 |     case 4: | 
| 928 | 0 |       memop = SH_OP_MEM_REG_IND; | 
| 929 | 0 |       grp = SH_GRP_CALL; | 
| 930 | 0 |       break; | 
| 931 | 0 |     case 1: | 
| 932 | 0 |       memop = SH_OP_MEM_REG_IND; | 
| 933 | 0 |       sz = 8; | 
| 934 | 0 |       rw = write; | 
| 935 | 0 |       break; | 
| 936 | 0 |     case 2: | 
| 937 | 0 |       insn = SH_INS_JMP; | 
| 938 | 0 |       grp = SH_GRP_JUMP; | 
| 939 | 0 |       break; | 
| 940 | 0 |     case 8: | 
| 941 | 0 |     case 9: | 
| 942 | 0 |     case 10: | 
| 943 | 0 |       memop = SH_OP_MEM_REG_POST; | 
| 944 | 0 |       rw = read; | 
| 945 | 0 |       break; | 
| 946 | 0 |     case 12: | 
| 947 | 0 |     case 13: | 
| 948 | 0 |     case 14: | 
| 949 | 0 |       memop = SH_OP_MEM_REG_PRE; | 
| 950 | 0 |       rw = write; | 
| 951 | 0 |       break; | 
| 952 | 0 |     } | 
| 953 | 0 |     if (grp != SH_GRP_INVALID) { | 
| 954 | 0 |       set_mem(info, SH_OP_MEM_REG_IND, SH_REG_R0 + r, 0, | 
| 955 | 0 |         0, detail); | 
| 956 | 0 |       if (detail) | 
| 957 | 0 |         set_groups(detail, 1, grp); | 
| 958 | 0 |     } else { | 
| 959 | 0 |       if (insn_code != 1) { | 
| 960 | 0 |         set_reg_n(info, SH_REG_R0, rw, rw, detail); | 
| 961 | 0 |         info->op.op_count++; | 
| 962 | 0 |       } | 
| 963 | 0 |       set_mem_n(info, memop, SH_REG_R0 + r, 0, sz, | 
| 964 | 0 |           1 - rw, detail); | 
| 965 | 0 |       info->op.op_count++; | 
| 966 | 0 |     } | 
| 967 | 0 |     return MCDisassembler_Success; | 
| 968 | 0 |   } else { | 
| 969 | 0 |     return MCDisassembler_Fail; | 
| 970 | 0 |   } | 
| 971 | 0 | } | 
| 972 |  |  | 
| 973 |  | /* SHAD / SHLD - SH2A */ | 
| 974 |  | opRR(ISA_SH2A, SHAD, 0) | 
| 975 |  | opRR(ISA_SH2A, SHLD, 0) | 
| 976 |  |    | 
| 977 |  | static bool opLDC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 978 |  |       sh_info *info, cs_detail *detail) | 
| 979 | 0 | { | 
| 980 | 0 |   int s = (code >> 8) & 0x0f; | 
| 981 | 0 |   set_reg(info, SH_REG_R0 + s, read, detail); | 
| 982 | 0 |   return opLDCdst(code, MI, mode, info, detail); | 
| 983 | 0 | } | 
| 984 |  |  | 
| 985 |  | opRR(ISA_ALL, MOV, 0) | 
| 986 |  |  | 
| 987 |  | static bool opMOV_rpi(uint16_t code, uint64_t address, MCInst *MI, | 
| 988 |  |           cs_mode mode, sh_info *info, cs_detail *detail) | 
| 989 | 0 | { | 
| 990 | 0 |   int sz = (code & 0x03); | 
| 991 | 0 |   nm(code, 0); | 
| 992 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 993 | 0 |   set_mem(info, SH_OP_MEM_REG_POST, SH_REG_R0 + m, 0, 8 << sz, detail); | 
| 994 | 0 |   set_reg(info, SH_REG_R0 + n, write, detail); | 
| 995 | 0 |   return MCDisassembler_Success; | 
| 996 | 0 | } | 
| 997 |  |  | 
| 998 |  | opRR(ISA_ALL, NOT, 0) | 
| 999 |  | opRR(ISA_ALL, SWAP_B, 8) | 
| 1000 |  | opRR(ISA_ALL, SWAP_W, 16) | 
| 1001 |  | opRR(ISA_ALL, NEGC, 0) | 
| 1002 |  | opRR(ISA_ALL, NEG, 0) | 
| 1003 |  | opRR(ISA_ALL, EXTU_B, 8) | 
| 1004 |  | opRR(ISA_ALL, EXTU_W, 16) | 
| 1005 |  | opRR(ISA_ALL, EXTS_B, 8) | 
| 1006 |  | opRR(ISA_ALL, EXTS_W, 16) | 
| 1007 |  |  | 
| 1008 |  | static bool opADD_i(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1009 |  |         sh_info *info, cs_detail *detail) | 
| 1010 | 0 | { | 
| 1011 | 0 |   int r = (code >> 8) & 0x0f; | 
| 1012 | 0 |   MCInst_setOpcode(MI, SH_INS_ADD); | 
| 1013 | 0 |   set_imm(info, 1, code & 0xff); | 
| 1014 | 0 |   set_reg(info, SH_REG_R0 + r, write, detail); | 
| 1015 | 0 |   return MCDisassembler_Success; | 
| 1016 |  |    | 
| 1017 | 0 | } | 
| 1018 |  |    | 
| 1019 |  | static bool opMOV_BW_dsp(uint16_t code, uint64_t address, MCInst *MI, | 
| 1020 |  |        cs_mode mode, sh_info *info, cs_detail *detail) | 
| 1021 | 0 | { | 
| 1022 | 0 |   int dsp = (code & 0x0f); | 
| 1023 | 0 |   int r = (code >> 4) & 0x0f; | 
| 1024 | 0 |   int size = 1 + ((code >> 8) & 1); | 
| 1025 | 0 |   int rw = (code >> 10) & 1; | 
| 1026 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 1027 | 0 |   set_mem_n(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + r, dsp * size, | 
| 1028 | 0 |       8 * size, 1 - rw, detail); | 
| 1029 | 0 |   set_reg_n(info, SH_REG_R0, rw, rw, detail); | 
| 1030 | 0 |   info->op.op_count = 2; | 
| 1031 | 0 |   return MCDisassembler_Success; | 
| 1032 | 0 | } | 
| 1033 |  |  | 
| 1034 |  | static bool opSETRC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1035 |  |         sh_info *info, cs_detail *detail) | 
| 1036 | 0 | { | 
| 1037 | 0 |   int imm = code & 0xff; | 
| 1038 | 0 |   if (!(mode & CS_MODE_SHDSP)) | 
| 1039 | 0 |     return MCDisassembler_Fail; | 
| 1040 | 0 |   MCInst_setOpcode(MI, SH_INS_SETRC); | 
| 1041 | 0 |   set_imm(info, 0, imm); | 
| 1042 | 0 |   return MCDisassembler_Success; | 
| 1043 | 0 | } | 
| 1044 |  |  | 
| 1045 |  | static bool opJSR_N(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1046 |  |         sh_info *info, cs_detail *detail) | 
| 1047 | 0 | { | 
| 1048 | 0 |   int dsp = code & 0xff; | 
| 1049 | 0 |   if (isalevel(mode) != ISA_SH2A) | 
| 1050 | 0 |     return MCDisassembler_Fail; | 
| 1051 | 0 |   MCInst_setOpcode(MI, SH_INS_JSR_N); | 
| 1052 | 0 |   set_mem(info, SH_OP_MEM_TBR_DISP, SH_REG_INVALID, dsp * 4, 0, detail); | 
| 1053 | 0 |   return MCDisassembler_Success; | 
| 1054 | 0 | } | 
| 1055 |  |  | 
| 1056 |  | #define boperand(_code, _op, _imm, _reg)    \ | 
| 1057 | 0 |   int _op = (code >> 3) & 1;      \ | 
| 1058 | 0 |   int _imm = code & 7;        \ | 
| 1059 | 0 |   int _reg = (code >> 4) & 0x0f | 
| 1060 |  |  | 
| 1061 |  | static bool op86xx(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1062 |  |        sh_info *info, cs_detail *detail) | 
| 1063 | 0 | { | 
| 1064 | 0 |   static const sh_insn bop[] = {SH_INS_BCLR, SH_INS_BSET}; | 
| 1065 | 0 |   boperand(code, op, imm, reg); | 
| 1066 | 0 |   if (isalevel(mode) != ISA_SH2A) | 
| 1067 | 0 |     return MCDisassembler_Fail; | 
| 1068 | 0 |   MCInst_setOpcode(MI, bop[op]); | 
| 1069 | 0 |   set_imm(info, 0, imm); | 
| 1070 | 0 |   set_reg(info, SH_REG_R0 + reg, write, detail); | 
| 1071 | 0 |   return MCDisassembler_Success; | 
| 1072 | 0 | } | 
| 1073 |  |  | 
| 1074 |  | static bool op87xx(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1075 |  |        sh_info *info, cs_detail *detail) | 
| 1076 | 0 | { | 
| 1077 | 0 |   static const sh_insn bop[] = {SH_INS_BST, SH_INS_BLD}; | 
| 1078 | 0 |   boperand(code, op, imm, reg); | 
| 1079 | 0 |   if (isalevel(mode) != ISA_SH2A) | 
| 1080 | 0 |     return MCDisassembler_Fail; | 
| 1081 | 0 |   MCInst_setOpcode(MI, bop[op]); | 
| 1082 | 0 |   set_imm(info, 0, imm); | 
| 1083 | 0 |   set_reg(info, SH_REG_R0 + reg, op?read:write, detail); | 
| 1084 | 0 |   return MCDisassembler_Success; | 
| 1085 | 0 | } | 
| 1086 |  |  | 
| 1087 |  | static bool opCMP_EQi(uint16_t code, uint64_t address, MCInst *MI, | 
| 1088 |  |           cs_mode mode, sh_info *info, cs_detail *detail) | 
| 1089 | 0 | { | 
| 1090 | 0 |   MCInst_setOpcode(MI, SH_INS_CMP_EQ); | 
| 1091 | 0 |   set_imm(info, 1, code & 0x00ff); | 
| 1092 | 0 |   set_reg(info, SH_REG_R0, read, detail); | 
| 1093 | 0 |   return MCDisassembler_Success; | 
| 1094 | 0 | } | 
| 1095 |  |  | 
| 1096 |  | #define opBranch(level, insn)           \ | 
| 1097 |  | static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 1098 | 0 |          cs_mode mode, sh_info *info, cs_detail *detail)  \ | 
| 1099 | 0 | {                 \ | 
| 1100 | 0 |   int dsp = code & 0x00ff;          \ | 
| 1101 | 0 |   if (level > isalevel(mode))         \ | 
| 1102 | 0 |     return MCDisassembler_Fail;       \ | 
| 1103 | 0 |   if (dsp >= 0x80)           \ | 
| 1104 | 0 |     dsp = -256 + dsp;         \ | 
| 1105 | 0 |   MCInst_setOpcode(MI, SH_INS_##insn);        \ | 
| 1106 | 0 |   set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp * 2, \ | 
| 1107 | 0 |     0, detail);           \ | 
| 1108 | 0 |   if (detail)             \ | 
| 1109 | 0 |     set_groups(detail, 2, SH_GRP_JUMP, SH_GRP_BRANCH_RELATIVE); \ | 
| 1110 | 0 |   return MCDisassembler_Success;          \ | 
| 1111 | 0 | } Unexecuted instantiation: SHDisassembler.c:opBTUnexecuted instantiation: SHDisassembler.c:opBFUnexecuted instantiation: SHDisassembler.c:opBT_SUnexecuted instantiation: SHDisassembler.c:opBF_S | 
| 1112 |  |  | 
| 1113 |  | opBranch(ISA_ALL, BT) | 
| 1114 |  | opBranch(ISA_ALL, BF) | 
| 1115 |  | /* bt/s / bf/s - SH2 */ | 
| 1116 |  | opBranch(ISA_SH2, BT_S) | 
| 1117 |  | opBranch(ISA_SH2, BF_S) | 
| 1118 |  |  | 
| 1119 |  | #define opLDRSE(insn)             \ | 
| 1120 |  | static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 1121 | 0 |          cs_mode mode, sh_info *info, cs_detail *detail)  \ | 
| 1122 | 0 | {                 \ | 
| 1123 | 0 |   int dsp = code & 0xff;            \ | 
| 1124 | 0 |   if (!(mode & CS_MODE_SHDSP))         \ | 
| 1125 | 0 |     return MCDisassembler_Fail;       \ | 
| 1126 | 0 |   MCInst_setOpcode(MI, SH_INS_##insn);        \ | 
| 1127 | 0 |   set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp * 2, \ | 
| 1128 | 0 |     0, detail);           \ | 
| 1129 | 0 |   return MCDisassembler_Success;\ | 
| 1130 | 0 | } Unexecuted instantiation: SHDisassembler.c:opLDRSUnexecuted instantiation: SHDisassembler.c:opLDRE | 
| 1131 |  |  | 
| 1132 |  | static bool opLDRC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1133 |  |        sh_info *info, cs_detail *detail) | 
| 1134 | 0 | { | 
| 1135 | 0 |   int imm = code & 0xff; | 
| 1136 | 0 |   if (!(mode & CS_MODE_SHDSP) || isalevel(mode) != ISA_SH4A) | 
| 1137 | 0 |     return MCDisassembler_Fail; | 
| 1138 | 0 |   MCInst_setOpcode(MI, SH_INS_LDRC); | 
| 1139 | 0 |   set_imm(info, 0, imm); | 
| 1140 | 0 |   return MCDisassembler_Success; | 
| 1141 | 0 | } | 
| 1142 |  |  | 
| 1143 |  | opLDRSE(LDRS) | 
| 1144 |  | opLDRSE(LDRE) | 
| 1145 |  |    | 
| 1146 |  | #define opImmR0(insn) \ | 
| 1147 |  | static bool op##insn##_i(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 1148 | 0 |        cs_mode mode, sh_info *info, cs_detail *detail) \ | 
| 1149 | 0 | {                 \ | 
| 1150 | 0 |   MCInst_setOpcode(MI, SH_INS_##insn);        \ | 
| 1151 | 0 |   set_imm(info, 0, code & 0xff);          \ | 
| 1152 | 0 |   set_reg(info, SH_REG_R0, write, detail);      \ | 
| 1153 | 0 |   return MCDisassembler_Success;          \ | 
| 1154 | 0 | } Unexecuted instantiation: SHDisassembler.c:opTST_iUnexecuted instantiation: SHDisassembler.c:opAND_iUnexecuted instantiation: SHDisassembler.c:opXOR_iUnexecuted instantiation: SHDisassembler.c:opOR_i | 
| 1155 |  |  | 
| 1156 |  | opImmR0(TST) | 
| 1157 |  | opImmR0(AND) | 
| 1158 |  | opImmR0(XOR) | 
| 1159 |  | opImmR0(OR) | 
| 1160 |  |    | 
| 1161 |  | #define opImmMem(insn) \ | 
| 1162 |  | static bool op##insn##_B(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 1163 | 0 |        cs_mode mode, sh_info *info, cs_detail *detail) \ | 
| 1164 | 0 | {                 \ | 
| 1165 | 0 |   MCInst_setOpcode(MI, SH_INS_##insn);        \ | 
| 1166 | 0 |   set_imm(info, 0, code & 0xff);          \ | 
| 1167 | 0 |   set_mem(info, SH_OP_MEM_GBR_R0, SH_REG_R0, 0, 8, detail); \ | 
| 1168 | 0 |   return MCDisassembler_Success;          \ | 
| 1169 | 0 | } Unexecuted instantiation: SHDisassembler.c:opTST_BUnexecuted instantiation: SHDisassembler.c:opAND_BUnexecuted instantiation: SHDisassembler.c:opXOR_BUnexecuted instantiation: SHDisassembler.c:opOR_B | 
| 1170 |  |  | 
| 1171 |  | opImmMem(TST) | 
| 1172 |  | opImmMem(AND) | 
| 1173 |  | opImmMem(XOR) | 
| 1174 |  | opImmMem(OR) | 
| 1175 |  |    | 
| 1176 |  | static bool opMOV_pc(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1177 |  |          sh_info *info, cs_detail *detail) | 
| 1178 | 0 | { | 
| 1179 | 0 |   int sz = 16 << ((code >> 14) & 1); | 
| 1180 | 0 |   int dsp = (code & 0x00ff) * (sz / 8); | 
| 1181 | 0 |   int r = (code >> 8) & 0x0f; | 
| 1182 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 1183 | 0 |   if (sz == 32) | 
| 1184 | 0 |     address &= ~3; | 
| 1185 | 0 |   set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp, | 
| 1186 | 0 |     sz, detail); | 
| 1187 | 0 |   set_reg(info, SH_REG_R0 + r, write, detail); | 
| 1188 | 0 |   return MCDisassembler_Success; | 
| 1189 | 0 | } | 
| 1190 |  |  | 
| 1191 |  | #define opBxx(insn, grp)            \ | 
| 1192 |  | static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 1193 | 0 |          cs_mode mode, sh_info *info, cs_detail *detail)  \ | 
| 1194 | 0 | {                 \ | 
| 1195 | 0 |   int dsp = (code & 0x0fff);          \ | 
| 1196 | 0 |   if (dsp >= 0x800)           \ | 
| 1197 | 0 |     dsp = -0x1000 + dsp;         \ | 
| 1198 | 0 |   MCInst_setOpcode(MI, SH_INS_##insn);        \ | 
| 1199 | 0 |   set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, address + 4 + dsp * 2, \ | 
| 1200 | 0 |     0, detail);           \ | 
| 1201 | 0 |   if (detail)             \ | 
| 1202 | 0 |     set_groups(detail, 2, grp, SH_GRP_BRANCH_RELATIVE); \ | 
| 1203 | 0 |   return MCDisassembler_Success;          \ | 
| 1204 | 0 | } Unexecuted instantiation: SHDisassembler.c:opBRAUnexecuted instantiation: SHDisassembler.c:opBSR | 
| 1205 |  |  | 
| 1206 |  | opBxx(BRA, SH_GRP_JUMP) | 
| 1207 |  | opBxx(BSR, SH_GRP_CALL) | 
| 1208 |  |  | 
| 1209 |  | static bool opMOV_gbr(uint16_t code, uint64_t address, MCInst *MI, | 
| 1210 |  |           cs_mode mode, sh_info *info, cs_detail *detail) | 
| 1211 | 0 | { | 
| 1212 | 0 |   int sz = 8 << ((code >> 8) & 0x03); | 
| 1213 | 0 |   int dsp = (code & 0x00ff) * (sz / 8); | 
| 1214 | 0 |   int rw = (code >> 10) & 1; | 
| 1215 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 1216 | 0 |   set_mem_n(info, SH_OP_MEM_GBR_DISP, SH_REG_GBR, dsp, sz, | 
| 1217 | 0 |       1 - rw, detail); | 
| 1218 | 0 |   set_reg_n(info, SH_REG_R0, rw, rw, detail); | 
| 1219 | 0 |   info->op.op_count = 2; | 
| 1220 | 0 |   return MCDisassembler_Success; | 
| 1221 | 0 | } | 
| 1222 |  |  | 
| 1223 |  | static bool opTRAPA(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1224 |  |         sh_info *info, cs_detail *detail) | 
| 1225 | 0 | { | 
| 1226 | 0 |   MCInst_setOpcode(MI, SH_INS_TRAPA); | 
| 1227 | 0 |   set_imm(info, 0, code & 0xff); | 
| 1228 | 0 |   if (detail) | 
| 1229 | 0 |     set_groups(detail, 1,  SH_GRP_INT); | 
| 1230 | 0 |   return MCDisassembler_Success; | 
| 1231 | 0 | } | 
| 1232 |  |  | 
| 1233 |  | static bool opMOVA(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1234 |  |        sh_info *info, cs_detail *detail) | 
| 1235 | 0 | { | 
| 1236 | 0 |   int dsp = (code & 0x00ff) * 4; | 
| 1237 | 0 |   MCInst_setOpcode(MI, SH_INS_MOVA); | 
| 1238 | 0 |   set_mem(info, SH_OP_MEM_PCR, SH_REG_INVALID, (address & ~3) + 4 + dsp, | 
| 1239 | 0 |     0, detail); | 
| 1240 | 0 |   set_reg(info, SH_REG_R0, write, detail); | 
| 1241 | 0 |   return MCDisassembler_Success; | 
| 1242 | 0 | } | 
| 1243 |  |  | 
| 1244 |  | static bool opMOV_i(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1245 |  |         sh_info *info, cs_detail *detail) | 
| 1246 | 0 | { | 
| 1247 | 0 |   int imm = (code & 0x00ff); | 
| 1248 | 0 |   int r = (code >> 8) & 0x0f; | 
| 1249 | 0 |   MCInst_setOpcode(MI, SH_INS_MOV); | 
| 1250 | 0 |   set_imm(info, 1, imm); | 
| 1251 | 0 |   set_reg(info, SH_REG_R0 + r, write, detail); | 
| 1252 | 0 |   return MCDisassembler_Success; | 
| 1253 | 0 | } | 
| 1254 |  |  | 
| 1255 |  | /* FPU instructions */ | 
| 1256 |  | #define opFRR(insn)             \ | 
| 1257 |  | static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 1258 | 0 |          cs_mode mode, sh_info *info, cs_detail *detail)  \ | 
| 1259 | 0 | {                 \ | 
| 1260 | 0 |   int m = (code >> 4) & 0x0f;         \ | 
| 1261 | 0 |   int n = (code >> 8) & 0x0f;         \ | 
| 1262 | 0 |   MCInst_setOpcode(MI, SH_INS_##insn);        \ | 
| 1263 | 0 |   set_reg(info, SH_REG_FR0 + m, read, detail);      \ | 
| 1264 | 0 |   set_reg(info, SH_REG_FR0 + n, write, detail);     \ | 
| 1265 | 0 |   return MCDisassembler_Success;          \ | 
| 1266 | 0 | } Unexecuted instantiation: SHDisassembler.c:opFADDUnexecuted instantiation: SHDisassembler.c:opFSUBUnexecuted instantiation: SHDisassembler.c:opFMULUnexecuted instantiation: SHDisassembler.c:opFDIV | 
| 1267 |  |  | 
| 1268 |  | #define opFRRcmp(insn)              \ | 
| 1269 |  | static bool op##insn(uint16_t code, uint64_t address, MCInst *MI, \ | 
| 1270 | 0 |          cs_mode mode, sh_info *info, cs_detail *detail)  \ | 
| 1271 | 0 | {                 \ | 
| 1272 | 0 |   int m = (code >> 4) & 0x0f;         \ | 
| 1273 | 0 |   int n = (code >> 8) & 0x0f;         \ | 
| 1274 | 0 |   MCInst_setOpcode(MI, SH_INS_##insn);        \ | 
| 1275 | 0 |   set_reg(info, SH_REG_FR0 + m, read, detail);      \ | 
| 1276 | 0 |   set_reg(info, SH_REG_FR0 + n, read, detail);      \ | 
| 1277 | 0 |   return MCDisassembler_Success;          \ | 
| 1278 | 0 | } Unexecuted instantiation: SHDisassembler.c:opFCMP_EQUnexecuted instantiation: SHDisassembler.c:opFCMP_GT | 
| 1279 |  |  | 
| 1280 |  | opFRR(FADD) | 
| 1281 |  | opFRR(FSUB) | 
| 1282 |  | opFRR(FMUL) | 
| 1283 |  | opFRR(FDIV) | 
| 1284 |  | opFRRcmp(FCMP_EQ) | 
| 1285 |  | opFRRcmp(FCMP_GT) | 
| 1286 |  |  | 
| 1287 |  | static bool opFMOVm(MCInst *MI, enum direction rw, uint16_t code, | 
| 1288 |  |         sh_op_mem_type address, sh_info *info, cs_detail *detail) | 
| 1289 | 0 | { | 
| 1290 | 0 |   nm(code, (1 - rw)); | 
| 1291 | 0 |   MCInst_setOpcode(MI, SH_INS_FMOV); | 
| 1292 | 0 |   set_mem_n(info, address, SH_REG_R0 + m, 0, 0, 1 - rw, detail); | 
| 1293 | 0 |   set_reg_n(info, SH_REG_FR0 + n, rw, rw, detail); | 
| 1294 | 0 |   info->op.op_count = 2; | 
| 1295 | 0 |   return MCDisassembler_Success; | 
| 1296 | 0 | } | 
| 1297 |  |  | 
| 1298 |  | static bool opfxx6(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1299 |  |        sh_info *info, cs_detail *detail) | 
| 1300 | 0 | { | 
| 1301 | 0 |   return opFMOVm(MI, write, code, SH_OP_MEM_REG_R0, info, detail); | 
| 1302 | 0 | } | 
| 1303 |  |    | 
| 1304 |  | static bool opfxx7(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1305 |  |        sh_info *info, cs_detail *detail) | 
| 1306 | 0 | { | 
| 1307 | 0 |   return opFMOVm(MI, read, code, SH_OP_MEM_REG_R0, info, detail); | 
| 1308 | 0 | } | 
| 1309 |  |    | 
| 1310 |  | static bool opfxx8(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1311 |  |        sh_info *info, cs_detail *detail) | 
| 1312 | 0 | { | 
| 1313 | 0 |   return opFMOVm(MI, write, code, SH_OP_MEM_REG_IND, info, detail); | 
| 1314 | 0 | } | 
| 1315 |  |    | 
| 1316 |  | static bool opfxx9(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1317 |  |        sh_info *info, cs_detail *detail) | 
| 1318 | 0 | { | 
| 1319 | 0 |   return opFMOVm(MI, write, code, SH_OP_MEM_REG_POST, info, detail); | 
| 1320 | 0 | } | 
| 1321 |  |    | 
| 1322 |  | static bool opfxxa(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1323 |  |        sh_info *info, cs_detail *detail) | 
| 1324 | 0 | { | 
| 1325 | 0 |   return opFMOVm(MI, read, code, SH_OP_MEM_REG_IND, info, detail); | 
| 1326 | 0 | } | 
| 1327 |  |    | 
| 1328 |  | static bool opfxxb(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1329 |  |        sh_info *info, cs_detail *detail) | 
| 1330 | 0 | { | 
| 1331 | 0 |   return opFMOVm(MI, read, code, SH_OP_MEM_REG_PRE, info, detail); | 
| 1332 | 0 | } | 
| 1333 |  |    | 
| 1334 |  | static bool opFMOV(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1335 |  |        sh_info *info, cs_detail *detail) | 
| 1336 | 0 | { | 
| 1337 | 0 |   nm(code, 0); | 
| 1338 | 0 |   MCInst_setOpcode(MI, SH_INS_FMOV); | 
| 1339 | 0 |   set_reg(info, SH_REG_FR0 + m, read, detail); | 
| 1340 | 0 |   set_reg(info, SH_REG_FR0 + n, write, detail); | 
| 1341 | 0 |   return MCDisassembler_Success; | 
| 1342 | 0 | } | 
| 1343 |  |    | 
| 1344 |  | static bool opfxxd(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1345 |  |        sh_info *info, cs_detail *detail) | 
| 1346 | 0 | { | 
| 1347 | 0 |   int fr = (code >> 8) & 0x0f; | 
| 1348 | 0 |   int dr = (code >> 9) & 0x07; | 
| 1349 | 0 |   int fvn = (code >> 10) & 0x03; | 
| 1350 | 0 |   int fvm = (code >> 8) & 0x03; | 
| 1351 | 0 |   sh_insn insn = SH_INS_INVALID; | 
| 1352 | 0 |   sh_reg s, d; | 
| 1353 | 0 |   static const struct ri_list list[] = { | 
| 1354 | 0 |     {0, SH_INS_FSTS, ISA_ALL, shfpu}, | 
| 1355 | 0 |     {1, SH_INS_FLDS, ISA_ALL, shfpu}, | 
| 1356 | 0 |     {2, SH_INS_FLOAT, ISA_ALL, shfpu}, | 
| 1357 | 0 |     {3, SH_INS_FTRC, ISA_ALL, shfpu}, | 
| 1358 | 0 |     {4, SH_INS_FNEG, ISA_ALL, shfpu}, | 
| 1359 | 0 |     {5, SH_INS_FABS, ISA_ALL, shfpu}, | 
| 1360 | 0 |     {6, SH_INS_FSQRT, ISA_ALL, shfpu}, | 
| 1361 | 0 |     {7, SH_INS_FSRRA, ISA_ALL, shfpu}, | 
| 1362 | 0 |     {8, SH_INS_FLDI0, ISA_ALL, shfpu}, | 
| 1363 | 0 |     {9, SH_INS_FLDI1, ISA_ALL, shfpu}, | 
| 1364 | 0 |     {10, SH_INS_FCNVSD, ISA_SH4A, shfpu}, | 
| 1365 | 0 |     {11, SH_INS_FCNVDS, ISA_SH4A, shfpu}, | 
| 1366 | 0 |     {14, SH_INS_FIPR, ISA_SH4A, shfpu}, | 
| 1367 | 0 |     {-1, SH_INS_INVALID, ISA_ALL, none}, | 
| 1368 | 0 |   }; | 
| 1369 | 0 |   static const sh_insn chg[] = { | 
| 1370 | 0 |     SH_INS_FSCHG, SH_INS_FPCHG, SH_INS_FRCHG, SH_INS_INVALID | 
| 1371 | 0 |   }; | 
| 1372 | 0 |   insn = lookup_insn(list, (code >> 4) & 0x0f, mode); | 
| 1373 | 0 |   s = d = SH_REG_FPUL; | 
| 1374 | 0 |   if (insn != SH_INS_INVALID) { | 
| 1375 | 0 |     switch((code >> 4) & 0x0f) { | 
| 1376 | 0 |     case 0: | 
| 1377 | 0 |     case 2: | 
| 1378 | 0 |       d = SH_REG_FR0 + fr; | 
| 1379 | 0 |       break; | 
| 1380 | 0 |     case 1: | 
| 1381 | 0 |     case 3: | 
| 1382 | 0 |       s = SH_REG_FR0 + fr; | 
| 1383 | 0 |       break; | 
| 1384 | 0 |     case 10: | 
| 1385 | 0 |       d = SH_REG_DR0 + dr; | 
| 1386 | 0 |       break; | 
| 1387 | 0 |     case 11: | 
| 1388 | 0 |       s = SH_REG_DR0 + dr; | 
| 1389 | 0 |       break; | 
| 1390 | 0 |     case 14: | 
| 1391 | 0 |       s = SH_REG_FV0 + fvm; | 
| 1392 | 0 |       d = SH_REG_FV0 + fvn; | 
| 1393 | 0 |       break; | 
| 1394 | 0 |     default: | 
| 1395 | 0 |       s = SH_REG_FR0 + fr; | 
| 1396 | 0 |       d = SH_REG_INVALID; | 
| 1397 | 0 |       break; | 
| 1398 | 0 |     } | 
| 1399 | 0 |   } else if ((code & 0x00f0) == 0x00f0) { | 
| 1400 | 0 |     if ((code & 0x01ff) == 0x00fd) { | 
| 1401 | 0 |       insn = SH_INS_FSCA; | 
| 1402 | 0 |       d = SH_REG_DR0 + dr; | 
| 1403 | 0 |     } | 
| 1404 | 0 |     if ((code & 0x03ff) == 0x01fd) { | 
| 1405 | 0 |       insn = SH_INS_FTRV; | 
| 1406 | 0 |       s = SH_REG_XMATRX; | 
| 1407 | 0 |       d = SH_REG_FV0 + fvn; | 
| 1408 | 0 |     } | 
| 1409 | 0 |     if ((code & 0x03ff) == 0x03fd) { | 
| 1410 | 0 |       insn = chg[(code >> 10) & 3]; | 
| 1411 | 0 |       s = d = SH_REG_INVALID; | 
| 1412 | 0 |     } | 
| 1413 | 0 |   } | 
| 1414 | 0 |   if (insn == SH_INS_INVALID) { | 
| 1415 | 0 |     return MCDisassembler_Fail; | 
| 1416 | 0 |   } | 
| 1417 | 0 |   MCInst_setOpcode(MI, insn); | 
| 1418 | 0 |   if (s != SH_REG_INVALID) { | 
| 1419 | 0 |     set_reg(info, s, read, detail); | 
| 1420 | 0 |   } | 
| 1421 | 0 |   if (d != SH_REG_INVALID) { | 
| 1422 | 0 |     set_reg(info, d, write, detail); | 
| 1423 | 0 |   } | 
| 1424 | 0 |   return MCDisassembler_Success; | 
| 1425 | 0 | } | 
| 1426 |  |  | 
| 1427 |  | static bool opFMAC(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, | 
| 1428 |  |        sh_info *info, cs_detail *detail) | 
| 1429 | 0 | { | 
| 1430 | 0 |   int m = (code >> 4) & 0x0f; | 
| 1431 | 0 |   int n = (code >> 8) & 0x0f; | 
| 1432 | 0 |   MCInst_setOpcode(MI, SH_INS_FMAC); | 
| 1433 | 0 |   set_reg(info, SH_REG_FR0, read, detail); | 
| 1434 | 0 |   set_reg(info, SH_REG_FR0 + m, read, detail); | 
| 1435 | 0 |   set_reg(info, SH_REG_FR0 + n, write, detail); | 
| 1436 | 0 |   return MCDisassembler_Success; | 
| 1437 | 0 | } | 
| 1438 |  |  | 
| 1439 |  | #include "SHInsnTable.inc" | 
| 1440 |  |  | 
| 1441 |  | static bool decode_long(uint32_t code, uint64_t address, MCInst *MI, | 
| 1442 |  |       sh_info *info, cs_detail *detail) | 
| 1443 | 0 | { | 
| 1444 | 0 |   uint32_t imm; | 
| 1445 | 0 |   sh_insn insn = SH_INS_INVALID; | 
| 1446 | 0 |   int m,n; | 
| 1447 | 0 |   int dsp; | 
| 1448 | 0 |   int sz; | 
| 1449 | 0 |   static const sh_insn bop[] = { | 
| 1450 | 0 |     SH_INS_BCLR, SH_INS_BSET, SH_INS_BST, SH_INS_BLD, | 
| 1451 | 0 |     SH_INS_BAND, SH_INS_BOR, SH_INS_BXOR, SH_INS_INVALID, | 
| 1452 | 0 |     SH_INS_INVALID, SH_INS_INVALID, SH_INS_INVALID, SH_INS_BLDNOT, | 
| 1453 | 0 |     SH_INS_BANDNOT, SH_INS_BORNOT, SH_INS_INVALID, SH_INS_INVALID, | 
| 1454 | 0 |   }; | 
| 1455 | 0 |   switch (code >> 28) { | 
| 1456 | 0 |   case 0x0: | 
| 1457 | 0 |     imm = ((code >> 4) & 0x000f0000) | (code & 0xffff); | 
| 1458 | 0 |     n = (code >> 24) & 0x0f; | 
| 1459 | 0 |     if (code & 0x00010000) { | 
| 1460 |  |       // movi20s #imm, | 
| 1461 | 0 |       imm <<= 8; | 
| 1462 | 0 |       if (imm >= 1 << 27) | 
| 1463 | 0 |         imm = -((1 << 28) - imm); | 
| 1464 | 0 |       insn = SH_INS_MOVI20S; | 
| 1465 | 0 |     } else { | 
| 1466 |  |       // MOVI20 | 
| 1467 | 0 |       if (imm >= 1 << 19) | 
| 1468 | 0 |         imm = -((1 << 20) - imm); | 
| 1469 | 0 |       insn = SH_INS_MOVI20; | 
| 1470 | 0 |     } | 
| 1471 | 0 |     set_imm(info, 0, imm); | 
| 1472 | 0 |     set_reg(info, SH_REG_R0 + n, write, detail); | 
| 1473 | 0 |     break; | 
| 1474 | 0 |   case 0x3: | 
| 1475 | 0 |     n = (code >> 24) & 0x0f; | 
| 1476 | 0 |     m = (code >> 20) & 0x0f; | 
| 1477 | 0 |     sz = (code >> 12) & 0x03; | 
| 1478 | 0 |     dsp = code & 0xfff; | 
| 1479 | 0 |     if (!(code & 0x80000)) { | 
| 1480 | 0 |       dsp <<= sz; | 
| 1481 | 0 |       switch((code >> 14) & 0x3) { | 
| 1482 | 0 |       case 0: // mov.[bwl] Rm,@(disp,Rn) | 
| 1483 |  |         // fmov.s DRm,@(disp,Rn) | 
| 1484 | 0 |         if (sz < 3) { | 
| 1485 | 0 |           insn = SH_INS_MOV; | 
| 1486 | 0 |           set_reg(info, SH_REG_R0 + m, | 
| 1487 | 0 |             read, detail); | 
| 1488 | 0 |         } else { | 
| 1489 | 0 |           insn = SH_INS_FMOV; | 
| 1490 | 0 |           set_reg(info, SH_REG_DR0 + (m >> 1), | 
| 1491 | 0 |             read, detail); | 
| 1492 | 0 |         } | 
| 1493 | 0 |         set_mem(info, SH_OP_MEM_REG_DISP, | 
| 1494 | 0 |           SH_REG_R0 + n, dsp, 8 << sz, detail); | 
| 1495 | 0 |         break; | 
| 1496 | 0 |       case 1: // mov.[bwl] @(disp,Rm),Rn | 
| 1497 |  |         // fmov.s @(disp,Rm),DRn | 
| 1498 | 0 |         set_mem(info, SH_OP_MEM_REG_DISP, | 
| 1499 | 0 |           SH_REG_R0 + m, dsp, 8 << sz, detail); | 
| 1500 | 0 |         if (sz < 3) { | 
| 1501 | 0 |           insn = SH_INS_MOV; | 
| 1502 | 0 |           set_reg(info, SH_REG_R0 + n, | 
| 1503 | 0 |             write, detail); | 
| 1504 | 0 |         } else { | 
| 1505 | 0 |           insn = SH_INS_FMOV; | 
| 1506 | 0 |           set_reg(info, SH_REG_DR0 + (n >> 1), | 
| 1507 | 0 |             write, detail); | 
| 1508 | 0 |         } | 
| 1509 | 0 |         break; | 
| 1510 | 0 |       case 2: // movu.[bwl] @(disp,Rm),Rn | 
| 1511 | 0 |         if (sz < 2) { | 
| 1512 | 0 |           insn = SH_INS_MOVU; | 
| 1513 | 0 |           set_mem(info, SH_OP_MEM_REG_DISP, | 
| 1514 | 0 |             SH_REG_R0 + m, dsp, | 
| 1515 | 0 |             8 << sz, detail); | 
| 1516 | 0 |           set_reg(info, SH_REG_R0 + n, | 
| 1517 | 0 |             write, detail); | 
| 1518 | 0 |         } | 
| 1519 | 0 |         break; | 
| 1520 | 0 |       } | 
| 1521 | 0 |     } else { | 
| 1522 |  |       // bitop #imm,@(disp,Rn) | 
| 1523 | 0 |       insn = bop[(code >> 12) & 0x0f]; | 
| 1524 | 0 |       set_imm(info, 0, m & 7); | 
| 1525 | 0 |       set_mem(info, SH_OP_MEM_REG_DISP, SH_REG_R0 + n, | 
| 1526 | 0 |         dsp, 8, detail); | 
| 1527 | 0 |     } | 
| 1528 | 0 |   } | 
| 1529 | 0 |   if (insn != SH_INS_INVALID) { | 
| 1530 | 0 |     MCInst_setOpcode(MI, insn); | 
| 1531 | 0 |     return MCDisassembler_Success; | 
| 1532 | 0 |   } else { | 
| 1533 | 0 |     return MCDisassembler_Fail; | 
| 1534 | 0 |   } | 
| 1535 | 0 | } | 
| 1536 |  |  | 
| 1537 |  | static const sh_reg dsp_areg[2][4] = { | 
| 1538 |  |   {SH_REG_R4, SH_REG_R0, SH_REG_R5, SH_REG_R1}, | 
| 1539 |  |   {SH_REG_R6, SH_REG_R7, SH_REG_R2, SH_REG_R3}, | 
| 1540 |  | }; | 
| 1541 |  |  | 
| 1542 |  | static bool decode_dsp_xy(sh_info *info, int xy, uint16_t code, | 
| 1543 |  |         cs_detail *detail) | 
| 1544 | 0 | { | 
| 1545 | 0 |   int a = (code >> 8) & 3; | 
| 1546 | 0 |   int d = (code >> 6) & 3; | 
| 1547 | 0 |   int dir; | 
| 1548 | 0 |   int sz; | 
| 1549 | 0 |   int op; | 
| 1550 |  | 
 | 
| 1551 | 0 |   static const sh_reg dreg[4][4] = { | 
| 1552 | 0 |     {SH_REG_DSP_A0, SH_REG_DSP_X0, SH_REG_DSP_A1, SH_REG_DSP_X1}, | 
| 1553 | 0 |     {SH_REG_DSP_A0, SH_REG_DSP_A1, SH_REG_DSP_Y0, SH_REG_DSP_Y1}, | 
| 1554 | 0 |     {SH_REG_DSP_X0, SH_REG_DSP_Y0, SH_REG_DSP_X1, SH_REG_DSP_Y1}, | 
| 1555 | 0 |     {SH_REG_DSP_Y0, SH_REG_DSP_Y1, SH_REG_DSP_X0, SH_REG_DSP_X1}, | 
| 1556 | 0 |   }; | 
| 1557 |  |    | 
| 1558 | 0 |   if (xy) { | 
| 1559 | 0 |     op = code & 3; | 
| 1560 | 0 |     dir = 1 - ((code >> 4) & 1); | 
| 1561 | 0 |     sz = (code >> 5) & 1; | 
| 1562 | 0 |     if (code & 0x0c) { | 
| 1563 | 0 |       info->op.operands[xy].dsp.insn = SH_INS_DSP_NOP; | 
| 1564 | 0 |       return MCDisassembler_Success; | 
| 1565 | 0 |     } | 
| 1566 | 0 |   } else { | 
| 1567 | 0 |     op = (code >> 2) & 3; | 
| 1568 | 0 |     dir = 1 - ((code >> 5) & 1); | 
| 1569 | 0 |     sz = (code >> 4) & 1; | 
| 1570 | 0 |     if (code & 0x03) { | 
| 1571 | 0 |       info->op.operands[xy].dsp.insn = SH_INS_DSP_NOP; | 
| 1572 | 0 |       return MCDisassembler_Success; | 
| 1573 | 0 |     } | 
| 1574 | 0 |   } | 
| 1575 | 0 |   info->op.operands[xy].dsp.size = 16 << sz; | 
| 1576 | 0 |   info->op.operands[xy].dsp.insn = SH_INS_DSP_MOV; | 
| 1577 | 0 |   info->op.operands[xy].dsp.operand[1 - dir] = | 
| 1578 | 0 |     SH_OP_DSP_REG_IND + (op - 1); | 
| 1579 | 0 |   info->op.operands[xy].dsp.operand[dir] = SH_OP_DSP_REG; | 
| 1580 | 0 |   info->op.operands[xy].dsp.r[1 - dir] = dsp_areg[xy][a]; | 
| 1581 | 0 |   info->op.operands[xy].dsp.size = 16 << sz; | 
| 1582 | 0 |   regs_rw(detail, dir, | 
| 1583 | 0 |     info->op.operands[xy].dsp.r[dir] = dreg[xy * 2 + dir][d]); | 
| 1584 | 0 |   switch(op) { | 
| 1585 | 0 |   case 0x03: | 
| 1586 | 0 |     regs_read(detail, SH_REG_R8 + xy); | 
| 1587 |  |     // Fail through | 
| 1588 | 0 |   case 0x02: | 
| 1589 | 0 |     regs_write(detail, dsp_areg[xy][a]); | 
| 1590 | 0 |     break; | 
| 1591 | 0 |   case 0x01: | 
| 1592 | 0 |     regs_read(detail, dsp_areg[xy][a]); | 
| 1593 | 0 |     break; | 
| 1594 | 0 |   default: | 
| 1595 | 0 |     return MCDisassembler_Fail; | 
| 1596 | 0 |   } | 
| 1597 | 0 |   return MCDisassembler_Success; | 
| 1598 | 0 | } | 
| 1599 |  |  | 
| 1600 |  | static bool set_dsp_move_d(sh_info *info, int xy, uint16_t code, cs_mode mode, cs_detail *detail) | 
| 1601 | 0 | { | 
| 1602 | 0 |   int a; | 
| 1603 | 0 |   int d; | 
| 1604 | 0 |   int dir; | 
| 1605 | 0 |   int op; | 
| 1606 | 0 |   static const sh_reg base[] = {SH_REG_DSP_A0, SH_REG_DSP_X0}; | 
| 1607 | 0 |   switch (xy) { | 
| 1608 | 0 |   case 0: | 
| 1609 | 0 |     op = (code >> 2) & 3; | 
| 1610 | 0 |     dir = 1 - ((code >> 5) & 1); | 
| 1611 | 0 |     d = (code >> 7) & 1; | 
| 1612 | 0 |     a = (code >> 9) & 1; | 
| 1613 | 0 |     break; | 
| 1614 | 0 |   case 1: | 
| 1615 | 0 |     op = (code >> 0) & 3; | 
| 1616 | 0 |     dir = 1 - ((code >> 4) & 1); | 
| 1617 | 0 |     d = (code >> 6) & 1; | 
| 1618 | 0 |     a = (code >> 8) & 1; | 
| 1619 | 0 |     break; | 
| 1620 | 0 |   } | 
| 1621 | 0 |   if (op == 0x00) { | 
| 1622 | 0 |     if ((a || d || dir) && !(code & 0x0f)) | 
| 1623 | 0 |       return MCDisassembler_Fail; | 
| 1624 | 0 |     info->op.operands[xy].dsp.insn = SH_INS_DSP_NOP; | 
| 1625 | 0 |   } else { | 
| 1626 | 0 |     info->op.operands[xy].dsp.insn = SH_INS_DSP_MOV; | 
| 1627 | 0 |     info->op.operands[xy].dsp.operand[1 - dir] = | 
| 1628 | 0 |       SH_OP_DSP_REG_IND + (op - 1); | 
| 1629 | 0 |     info->op.operands[xy].dsp.operand[dir] = SH_OP_DSP_REG; | 
| 1630 | 0 |     info->op.operands[xy].dsp.r[1 - dir] = SH_REG_R4 + xy * 2 + a; | 
| 1631 | 0 |     info->op.operands[xy].dsp.size = 16; | 
| 1632 | 0 |     regs_rw(detail, dir, | 
| 1633 | 0 |       info->op.operands[xy].dsp.r[dir] = | 
| 1634 | 0 |       base[dir] + d + dir?(xy * 2):0); | 
| 1635 | 0 |     switch(op) { | 
| 1636 | 0 |     case 0x03: | 
| 1637 | 0 |       regs_read(detail, SH_REG_R8 + a); | 
| 1638 |  |       // Fail through | 
| 1639 | 0 |     case 0x02: | 
| 1640 | 0 |       regs_write(detail, SH_REG_R4 + xy * 2 + a); | 
| 1641 | 0 |       break; | 
| 1642 | 0 |     case 0x01: | 
| 1643 | 0 |       regs_read(detail, SH_REG_R4 + xy * 2 + a); | 
| 1644 | 0 |       break; | 
| 1645 | 0 |     } | 
| 1646 | 0 |   } | 
| 1647 | 0 |   return MCDisassembler_Success; | 
| 1648 | 0 | } | 
| 1649 |  |  | 
| 1650 |  | static bool decode_dsp_d(const uint16_t code, MCInst *MI, cs_mode mode, | 
| 1651 |  |        sh_info *info, cs_detail *detail) | 
| 1652 | 0 | { | 
| 1653 | 0 |   bool ret, dsp_long; | 
| 1654 | 0 |   MCInst_setOpcode(MI, SH_INS_DSP); | 
| 1655 | 0 |   if ((code & 0x3ff) == 0) { | 
| 1656 | 0 |     info->op.operands[0].dsp.insn =  | 
| 1657 | 0 |       info->op.operands[1].dsp.insn = SH_INS_DSP_NOP; | 
| 1658 | 0 |     info->op.op_count = 2; | 
| 1659 | 0 |     return MCDisassembler_Success; | 
| 1660 | 0 |   } | 
| 1661 | 0 |   dsp_long = false; | 
| 1662 | 0 |   if (isalevel(mode) == ISA_SH4A) { | 
| 1663 | 0 |     if (!(code & 0x03) && (code & 0x0f) >= 0x04) { | 
| 1664 | 0 |       ret = decode_dsp_xy(info, 0, code, detail); | 
| 1665 | 0 |       ret &= set_dsp_move_d(info, 1, code, mode, detail); | 
| 1666 | 0 |       dsp_long |= true; | 
| 1667 | 0 |     } | 
| 1668 | 0 |     if ((code & 0x0f) <= 0x03 && (code & 0xff)) { | 
| 1669 | 0 |       ret = decode_dsp_xy(info, 1, code, detail); | 
| 1670 | 0 |       ret &= set_dsp_move_d(info, 0, code, mode, detail); | 
| 1671 | 0 |       dsp_long |= true; | 
| 1672 | 0 |     } | 
| 1673 | 0 |   } | 
| 1674 | 0 |   if (!dsp_long) { | 
| 1675 |  |     /* X op */ | 
| 1676 | 0 |     ret = set_dsp_move_d(info, 0, code, mode, detail); | 
| 1677 |  |     /* Y op */ | 
| 1678 | 0 |     ret &= set_dsp_move_d(info, 1, code, mode, detail); | 
| 1679 | 0 |   } | 
| 1680 |  | 
 | 
| 1681 | 0 |   info->op.op_count = 2; | 
| 1682 | 0 |   return ret; | 
| 1683 | 0 | } | 
| 1684 |  |  | 
| 1685 |  | static bool decode_dsp_s(const uint16_t code, MCInst *MI, | 
| 1686 |  |        sh_info *info, cs_detail *detail) | 
| 1687 | 0 | { | 
| 1688 | 0 |   int d = code & 1; | 
| 1689 | 0 |   int s = (code >> 1) & 1; | 
| 1690 | 0 |   int opr = (code >> 2) & 3; | 
| 1691 | 0 |   int as = (code >> 8) & 3; | 
| 1692 | 0 |   int ds = (code >> 4) & 0x0f; | 
| 1693 | 0 |   static const sh_reg regs[] = { | 
| 1694 | 0 |     SH_REG_DSP_RSV0, SH_REG_DSP_RSV1, SH_REG_DSP_RSV2, | 
| 1695 | 0 |     SH_REG_DSP_RSV3, | 
| 1696 | 0 |     SH_REG_DSP_RSV4, SH_REG_DSP_A1, SH_REG_DSP_RSV6, SH_REG_DSP_A0, | 
| 1697 | 0 |     SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_Y0, SH_REG_DSP_Y1, | 
| 1698 | 0 |     SH_REG_DSP_M0, SH_REG_DSP_A1G, SH_REG_DSP_M1, SH_REG_DSP_A0G, | 
| 1699 | 0 |   }; | 
| 1700 |  | 
 | 
| 1701 | 0 |   if (regs[ds] == SH_REG_INVALID) | 
| 1702 | 0 |     return MCDisassembler_Fail; | 
| 1703 |  |      | 
| 1704 | 0 |   MCInst_setOpcode(MI, SH_INS_DSP); | 
| 1705 | 0 |   info->op.operands[0].dsp.insn = SH_INS_DSP_MOV; | 
| 1706 | 0 |   info->op.operands[0].dsp.operand[1 - d] = SH_OP_DSP_REG; | 
| 1707 | 0 |   info->op.operands[0].dsp.operand[d] = SH_OP_DSP_REG_PRE + opr; | 
| 1708 | 0 |   info->op.operands[0].dsp.r[1 - d] = regs[ds]; | 
| 1709 | 0 |   info->op.operands[0].dsp.r[d] = SH_REG_R2 + ((as < 2)?(as+2):(as-2)); | 
| 1710 | 0 |   switch (opr) { | 
| 1711 | 0 |   case 3: | 
| 1712 | 0 |     regs_read(detail, SH_REG_R8); | 
| 1713 |  |     /* Fail through */ | 
| 1714 | 0 |   case 1: | 
| 1715 | 0 |     regs_read(detail, info->op.operands[0].dsp.r[d]); | 
| 1716 | 0 |     break; | 
| 1717 | 0 |   case 0: | 
| 1718 | 0 |   case 2: | 
| 1719 | 0 |     regs_write(detail,  info->op.operands[0].dsp.r[d]); | 
| 1720 | 0 |   } | 
| 1721 | 0 |   regs_rw(detail, d, regs[ds]); | 
| 1722 | 0 |   info->op.operands[0].dsp.size = 16 << s; | 
| 1723 | 0 |   info->op.op_count = 1; | 
| 1724 | 0 |   return MCDisassembler_Success; | 
| 1725 | 0 | } | 
| 1726 |  |  | 
| 1727 |  | static const sh_reg dsp_reg_sd[6][4] = { | 
| 1728 |  |   {SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_Y0, SH_REG_DSP_A1}, | 
| 1729 |  |   {SH_REG_DSP_Y0, SH_REG_DSP_Y1, SH_REG_DSP_X0, SH_REG_DSP_A1}, | 
| 1730 |  |   {SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_A0, SH_REG_DSP_A1}, | 
| 1731 |  |   {SH_REG_DSP_Y0, SH_REG_DSP_Y1, SH_REG_DSP_M0, SH_REG_DSP_M1}, | 
| 1732 |  |   {SH_REG_DSP_M0, SH_REG_DSP_M1, SH_REG_DSP_A0, SH_REG_DSP_A1}, | 
| 1733 |  |   {SH_REG_DSP_X0, SH_REG_DSP_Y0, SH_REG_DSP_A0, SH_REG_DSP_A1}, | 
| 1734 |  | }; | 
| 1735 |  | typedef enum {f_se, f_sf, f_sx, f_sy, f_dg, f_du} dsp_reg_opr; | 
| 1736 |  | static void set_reg_dsp_read(sh_info *info, int pos, dsp_reg_opr f, int r, | 
| 1737 |  |            cs_detail *detail) | 
| 1738 | 0 | { | 
| 1739 | 0 |   info->op.operands[2].dsp.r[pos] = dsp_reg_sd[f][r]; | 
| 1740 | 0 |   regs_read(detail, dsp_reg_sd[f][r]); | 
| 1741 | 0 | }   | 
| 1742 |  |  | 
| 1743 |  | static void set_reg_dsp_write_gu(sh_info *info, int pos, dsp_reg_opr f, int r, | 
| 1744 |  |          cs_detail *detail) | 
| 1745 | 0 | { | 
| 1746 | 0 |   info->op.operands[2].dsp.r[pos] = dsp_reg_sd[f][r]; | 
| 1747 | 0 |   regs_write(detail, dsp_reg_sd[f][r]); | 
| 1748 | 0 | }   | 
| 1749 |  |  | 
| 1750 |  | static const sh_reg regs_dz[] = { | 
| 1751 |  |   SH_REG_DSP_RSV0, SH_REG_DSP_RSV1, SH_REG_DSP_RSV2, SH_REG_DSP_RSV3, | 
| 1752 |  |   SH_REG_DSP_RSV4, SH_REG_DSP_A1, SH_REG_DSP_RSV6, SH_REG_DSP_A0, | 
| 1753 |  |   SH_REG_DSP_X0, SH_REG_DSP_X1, SH_REG_DSP_Y0, SH_REG_DSP_Y1, | 
| 1754 |  |   SH_REG_DSP_M0, SH_REG_DSP_A1G, SH_REG_DSP_M1, SH_REG_DSP_A0G, | 
| 1755 |  | }; | 
| 1756 |  |  | 
| 1757 |  | static void set_reg_dsp_write_z(sh_info *info, int pos, int r, | 
| 1758 |  |         cs_detail *detail) | 
| 1759 | 0 | { | 
| 1760 | 0 |   info->op.operands[2].dsp.r[pos] = regs_dz[r]; | 
| 1761 | 0 |   regs_write(detail, regs_dz[r]); | 
| 1762 | 0 | }   | 
| 1763 |  |  | 
| 1764 |  | static bool dsp_op_cc_3opr(uint32_t code, sh_info *info, sh_dsp_insn insn, | 
| 1765 |  |          sh_dsp_insn_type insn2, cs_detail *detail) | 
| 1766 | 0 | { | 
| 1767 | 0 |   info->op.operands[2].dsp.cc = (code >> 8) & 3; | 
| 1768 | 0 |   if (info->op.operands[2].dsp.cc > 0) { | 
| 1769 | 0 |     info->op.operands[2].dsp.insn = insn; | 
| 1770 | 0 |   } else { | 
| 1771 | 0 |     if (insn2 != SH_INS_DSP_INVALID) | 
| 1772 | 0 |       info->op.operands[2].dsp.insn = (sh_dsp_insn) insn2; | 
| 1773 | 0 |     else | 
| 1774 | 0 |       return MCDisassembler_Fail; | 
| 1775 | 0 |   } | 
| 1776 | 0 |   if (info->op.operands[2].dsp.insn != SH_INS_DSP_PSUBr) { | 
| 1777 | 0 |     set_reg_dsp_read(info, 0, f_sx, (code >> 6) & 3, detail); | 
| 1778 | 0 |     set_reg_dsp_read(info, 1, f_sy, (code >> 4) & 3, detail); | 
| 1779 | 0 |   } else { | 
| 1780 | 0 |     set_reg_dsp_read(info, 1, f_sx, (code >> 6) & 3, detail); | 
| 1781 | 0 |     set_reg_dsp_read(info, 0, f_sy, (code >> 4) & 3, detail); | 
| 1782 | 0 |   } | 
| 1783 | 0 |   set_reg_dsp_write_z(info, 2, code & 0x0f, detail); | 
| 1784 | 0 |   info->op.op_count = 3; | 
| 1785 | 0 |   return MCDisassembler_Success; | 
| 1786 | 0 | } | 
| 1787 |  |  | 
| 1788 |  | static bool dsp_op_cc_2opr(uint32_t code, sh_info *info, sh_dsp_insn insn, | 
| 1789 |  |          int xy, int b, cs_detail *detail) | 
| 1790 | 0 | { | 
| 1791 | 0 |   if (((code >> 8) & 3) == 0) | 
| 1792 | 0 |     return MCDisassembler_Fail; | 
| 1793 | 0 |   info->op.operands[2].dsp.insn = (sh_dsp_insn) insn; | 
| 1794 | 0 |   set_reg_dsp_read(info, 0, xy, (code >> b) & 3, detail); | 
| 1795 | 0 |   set_reg_dsp_write_z(info, 2, code & 0x0f, detail); | 
| 1796 | 0 |   info->op.operands[2].dsp.cc = (code >> 8) & 3; | 
| 1797 | 0 |   info->op.op_count = 3; | 
| 1798 | 0 |   return MCDisassembler_Success; | 
| 1799 | 0 | } | 
| 1800 |  |    | 
| 1801 |  | static bool dsp_op_cc0_2opr(uint32_t code, sh_info *info, sh_dsp_insn insn, | 
| 1802 |  |           int xy, int b, cs_detail *detail) | 
| 1803 | 0 | { | 
| 1804 | 0 |   info->op.operands[2].dsp.insn = (sh_dsp_insn) insn; | 
| 1805 | 0 |   set_reg_dsp_read(info, 0, xy, (code >> b) & 3, detail); | 
| 1806 | 0 |   set_reg_dsp_write_z(info, 2, code & 0x0f, detail); | 
| 1807 | 0 |   info->op.operands[2].dsp.cc = (code >> 8) & 3;   | 
| 1808 | 0 |   if (info->op.operands[2].dsp.cc == 1) | 
| 1809 | 0 |     return MCDisassembler_Fail; | 
| 1810 | 0 |   if (info->op.operands[2].dsp.cc == 0) | 
| 1811 | 0 |     info->op.operands[2].dsp.cc = SH_DSP_CC_NONE; | 
| 1812 | 0 |   info->op.op_count = 3; | 
| 1813 | 0 |   return MCDisassembler_Success; | 
| 1814 | 0 | } | 
| 1815 |  |    | 
| 1816 |  | static bool decode_dsp_3op(const uint32_t code, sh_info *info, | 
| 1817 |  |          cs_detail *detail) | 
| 1818 | 0 | { | 
| 1819 | 0 |   int cc = (code >> 8) & 3; | 
| 1820 | 0 |   int sx = (code >> 6) & 3; | 
| 1821 | 0 |   int sy = (code >> 4) & 3; | 
| 1822 | 0 |   int dz = (code >> 0) & 0x0f; | 
| 1823 |  | 
 | 
| 1824 | 0 |   if ((code & 0xef00) == 0x8000) | 
| 1825 | 0 |     return MCDisassembler_Fail; | 
| 1826 | 0 |   switch((code >> 10) & 0x1f) { | 
| 1827 | 0 |   case 0x00: | 
| 1828 | 0 |     return dsp_op_cc_3opr(code, info, | 
| 1829 | 0 |               SH_INS_DSP_PSHL, SH_INS_DSP_INVALID, | 
| 1830 | 0 |               detail); | 
| 1831 | 0 |   case 0x01: | 
| 1832 | 0 |     if (cc == 0) { | 
| 1833 | 0 |       info->op.operands[2].dsp.insn = SH_INS_DSP_PCMP; | 
| 1834 | 0 |       set_reg_dsp_read(info, 0, f_sx, sx, detail); | 
| 1835 | 0 |       set_reg_dsp_read(info, 1, f_sy, sy, detail); | 
| 1836 | 0 |       info->op.op_count = 3; | 
| 1837 | 0 |       return MCDisassembler_Success; | 
| 1838 | 0 |     } else { | 
| 1839 | 0 |       return dsp_op_cc_3opr(code, info, | 
| 1840 | 0 |                 SH_INS_DSP_PSUBr, | 
| 1841 | 0 |                 SH_INS_DSP_INVALID, detail); | 
| 1842 | 0 |     } | 
| 1843 | 0 |   case 0x02: | 
| 1844 | 0 |     switch (sy) { | 
| 1845 | 0 |     case 0: | 
| 1846 | 0 |       if(cc == 0) { | 
| 1847 | 0 |         info->op.operands[2].dsp.insn = SH_INS_DSP_PABS; | 
| 1848 | 0 |         set_reg_dsp_read(info, 0, f_sx, sx, detail); | 
| 1849 | 0 |         set_reg_dsp_write_z(info, 1, dz, detail); | 
| 1850 | 0 |         info->op.op_count = 3; | 
| 1851 | 0 |         return MCDisassembler_Success; | 
| 1852 | 0 |       } else { | 
| 1853 | 0 |         return dsp_op_cc_2opr(code, info, | 
| 1854 | 0 |                   SH_INS_DSP_PDEC, | 
| 1855 | 0 |                   f_sx, 6, detail); | 
| 1856 | 0 |       } | 
| 1857 | 0 |     case 1: | 
| 1858 | 0 |       return dsp_op_cc0_2opr(code, info, | 
| 1859 | 0 |                  SH_INS_DSP_PABS, | 
| 1860 | 0 |                  f_sx, 6, detail); | 
| 1861 | 0 |     default: | 
| 1862 | 0 |       return MCDisassembler_Fail; | 
| 1863 | 0 |     }      | 
| 1864 | 0 |   case 0x03: | 
| 1865 | 0 |     if (cc != 0) { | 
| 1866 | 0 |       info->op.operands[2].dsp.insn = SH_INS_DSP_PCLR; | 
| 1867 | 0 |       info->op.operands[2].dsp.cc = cc; | 
| 1868 | 0 |       set_reg_dsp_write_z(info, 0, dz, detail); | 
| 1869 | 0 |       info->op.op_count = 3; | 
| 1870 | 0 |       return MCDisassembler_Success; | 
| 1871 | 0 |     } else | 
| 1872 | 0 |       return MCDisassembler_Fail; | 
| 1873 | 0 |   case 0x04: | 
| 1874 | 0 |     return dsp_op_cc_3opr(code, info, | 
| 1875 | 0 |               SH_INS_DSP_PSHA, SH_INS_DSP_INVALID, | 
| 1876 | 0 |               detail); | 
| 1877 | 0 |   case 0x05: | 
| 1878 | 0 |     return dsp_op_cc_3opr(code, info, | 
| 1879 | 0 |               SH_INS_DSP_PAND, SH_INS_DSP_INVALID, | 
| 1880 | 0 |               detail); | 
| 1881 | 0 |   case 0x06: | 
| 1882 | 0 |     switch (sy) { | 
| 1883 | 0 |     case 0: | 
| 1884 | 0 |       if (cc == 0) { | 
| 1885 | 0 |         info->op.operands[2].dsp.insn = SH_INS_DSP_PRND; | 
| 1886 | 0 |         set_reg_dsp_read(info, 0, f_sx, sx, detail); | 
| 1887 | 0 |         set_reg_dsp_write_z(info, 1, dz, detail); | 
| 1888 | 0 |         info->op.op_count = 3; | 
| 1889 | 0 |         return MCDisassembler_Success; | 
| 1890 | 0 |       } else { | 
| 1891 | 0 |         return dsp_op_cc_2opr(code, info, | 
| 1892 | 0 |                   SH_INS_DSP_PINC, | 
| 1893 | 0 |                   f_sx, 6, detail); | 
| 1894 | 0 |       } | 
| 1895 | 0 |     case 1: | 
| 1896 | 0 |       return dsp_op_cc0_2opr(code, info, | 
| 1897 | 0 |                  SH_INS_DSP_PRND, | 
| 1898 | 0 |                  f_sx, 6, detail); | 
| 1899 | 0 |     default: | 
| 1900 | 0 |       return MCDisassembler_Fail; | 
| 1901 | 0 |     } | 
| 1902 | 0 |   case 0x07: | 
| 1903 | 0 |     switch(sy) { | 
| 1904 | 0 |     case 0: | 
| 1905 | 0 |       return dsp_op_cc_2opr(code, info, | 
| 1906 | 0 |                 SH_INS_DSP_PDMSB, | 
| 1907 | 0 |                 f_sx, 6, detail); | 
| 1908 | 0 |     case 1: | 
| 1909 | 0 |       return dsp_op_cc_2opr(code, info, | 
| 1910 | 0 |                 SH_INS_DSP_PSWAP, | 
| 1911 | 0 |                 f_sx, 6, detail); | 
| 1912 | 0 |     default: | 
| 1913 | 0 |       return MCDisassembler_Fail; | 
| 1914 | 0 |     } | 
| 1915 | 0 |   case 0x08: | 
| 1916 | 0 |     return dsp_op_cc_3opr(code, info, | 
| 1917 | 0 |               SH_INS_DSP_PSUB, (sh_dsp_insn_type) SH_INS_DSP_PSUBC, | 
| 1918 | 0 |               detail); | 
| 1919 | 0 |   case 0x09: | 
| 1920 | 0 |     return dsp_op_cc_3opr(code, info, | 
| 1921 | 0 |               SH_INS_DSP_PXOR, (sh_dsp_insn_type) SH_INS_DSP_PWSB, | 
| 1922 | 0 |               detail); | 
| 1923 | 0 |   case 0x0a: | 
| 1924 | 0 |     switch(sx) { | 
| 1925 | 0 |     case 0: | 
| 1926 | 0 |       if (cc == 0) { | 
| 1927 | 0 |         info->op.operands[2].dsp.insn = SH_INS_DSP_PABS; | 
| 1928 | 0 |         set_reg_dsp_read(info, 0, f_sy, sy, detail); | 
| 1929 | 0 |         set_reg_dsp_write_z(info, 1, dz, detail); | 
| 1930 | 0 |         info->op.op_count = 3; | 
| 1931 | 0 |         return MCDisassembler_Success; | 
| 1932 | 0 |       } else { | 
| 1933 | 0 |         return dsp_op_cc_2opr(code, info, | 
| 1934 | 0 |                   SH_INS_DSP_PDEC, | 
| 1935 | 0 |                   f_sy, 4, detail); | 
| 1936 | 0 |       } | 
| 1937 | 0 |     case 1: | 
| 1938 | 0 |       return dsp_op_cc_2opr(code, info, | 
| 1939 | 0 |                 SH_INS_DSP_PABS, | 
| 1940 | 0 |                 f_sy, 4, detail); | 
| 1941 | 0 |     default: | 
| 1942 | 0 |       return MCDisassembler_Fail; | 
| 1943 | 0 |     } | 
| 1944 | 0 |   case 0x0c: | 
| 1945 | 0 |     if (cc == 0) { | 
| 1946 | 0 |         info->op.operands[2].dsp.insn | 
| 1947 | 0 |           = SH_INS_DSP_PADDC; | 
| 1948 | 0 |         set_reg_dsp_read(info, 0, f_sx, sx, detail); | 
| 1949 | 0 |         set_reg_dsp_read(info, 1, f_sy, sy, detail); | 
| 1950 | 0 |         set_reg_dsp_write_z(info, 2, dz, detail); | 
| 1951 | 0 |         info->op.op_count = 3; | 
| 1952 | 0 |         return MCDisassembler_Success; | 
| 1953 | 0 |     } else { | 
| 1954 | 0 |       return dsp_op_cc_3opr(code, info, | 
| 1955 | 0 |                 SH_INS_DSP_PADD, | 
| 1956 | 0 |                 SH_INS_DSP_INVALID, detail); | 
| 1957 | 0 |     } | 
| 1958 | 0 |   case 0x0d: | 
| 1959 | 0 |     return dsp_op_cc_3opr(code, info, | 
| 1960 | 0 |                 SH_INS_DSP_POR, | 
| 1961 | 0 |                 (sh_dsp_insn_type) SH_INS_DSP_PWAD, | 
| 1962 | 0 |                 detail); | 
| 1963 | 0 |   case 0x0e: | 
| 1964 | 0 |     if (cc == 0) { | 
| 1965 | 0 |       if (sx != 0) | 
| 1966 | 0 |         return MCDisassembler_Fail; | 
| 1967 | 0 |       info->op.operands[2].dsp.insn = SH_INS_DSP_PRND; | 
| 1968 | 0 |       set_reg_dsp_read(info, 0, f_sy, sy, detail); | 
| 1969 | 0 |       set_reg_dsp_write_z(info, 1, dz, detail); | 
| 1970 | 0 |       info->op.op_count = 3; | 
| 1971 | 0 |       return MCDisassembler_Success; | 
| 1972 | 0 |     } else { | 
| 1973 | 0 |       switch(sx) { | 
| 1974 | 0 |       case 0: | 
| 1975 | 0 |         return dsp_op_cc_2opr(code, info, | 
| 1976 | 0 |                   SH_INS_DSP_PINC, | 
| 1977 | 0 |                   f_sy, 4, detail); | 
| 1978 | 0 |       case 1: | 
| 1979 | 0 |         return dsp_op_cc_2opr(code, info, | 
| 1980 | 0 |                   SH_INS_DSP_PRND, | 
| 1981 | 0 |                   f_sy, 4, detail); | 
| 1982 | 0 |       default: | 
| 1983 | 0 |         return MCDisassembler_Fail; | 
| 1984 | 0 |       } | 
| 1985 | 0 |     } | 
| 1986 | 0 |   case 0x0f: | 
| 1987 | 0 |     switch(sx) { | 
| 1988 | 0 |     case 0: | 
| 1989 | 0 |       return dsp_op_cc_2opr(code, info, | 
| 1990 | 0 |                 SH_INS_DSP_PDMSB, | 
| 1991 | 0 |                 f_sy, 4, detail); | 
| 1992 | 0 |     case 1: | 
| 1993 | 0 |       return dsp_op_cc_2opr(code, info, | 
| 1994 | 0 |                 SH_INS_DSP_PSWAP, | 
| 1995 | 0 |                 f_sy, 4, detail); | 
| 1996 | 0 |     default: | 
| 1997 | 0 |       return MCDisassembler_Fail; | 
| 1998 | 0 |     } | 
| 1999 | 0 |   case 0x12: | 
| 2000 | 0 |     return dsp_op_cc_2opr(code, info, | 
| 2001 | 0 |               SH_INS_DSP_PNEG, f_sx, 6, detail); | 
| 2002 | 0 |   case 0x13: | 
| 2003 | 0 |   case 0x17: | 
| 2004 | 0 |     if (cc > 0) { | 
| 2005 | 0 |       info->op.operands[2].dsp.insn = SH_INS_DSP_PSTS; | 
| 2006 | 0 |       info->op.operands[2].dsp.cc = cc; | 
| 2007 | 0 |       regs_read(detail,  | 
| 2008 | 0 |           info->op.operands[2].dsp.r[0] | 
| 2009 | 0 |           = SH_REG_MACH + ((code >> 12) & 1)); | 
| 2010 | 0 |       set_reg_dsp_write_z(info, 1, dz, detail); | 
| 2011 | 0 |       info->op.op_count = 3; | 
| 2012 | 0 |       return MCDisassembler_Success; | 
| 2013 | 0 |     } else { | 
| 2014 | 0 |       return MCDisassembler_Fail; | 
| 2015 | 0 |     } | 
| 2016 | 0 |   case 0x16: | 
| 2017 | 0 |     return dsp_op_cc_2opr(code, info, | 
| 2018 | 0 |               SH_INS_DSP_PCOPY, f_sx, 6, detail); | 
| 2019 | 0 |   case 0x1a: | 
| 2020 | 0 |     return dsp_op_cc_2opr(code, info, | 
| 2021 | 0 |               SH_INS_DSP_PNEG, f_sy, 4, detail); | 
| 2022 | 0 |   case 0x1b: | 
| 2023 | 0 |   case 0x1f: | 
| 2024 | 0 |     if (cc > 0) { | 
| 2025 | 0 |       info->op.operands[2].dsp.insn = SH_INS_DSP_PLDS; | 
| 2026 | 0 |       info->op.operands[2].dsp.cc = cc; | 
| 2027 | 0 |       info->op.operands[2].dsp.r[0] = regs_dz[dz]; | 
| 2028 | 0 |       regs_read(detail, regs_dz[dz]); | 
| 2029 | 0 |       regs_write(detail,  | 
| 2030 | 0 |            info->op.operands[2].dsp.r[1] | 
| 2031 | 0 |            = SH_REG_MACH + ((code >> 12) & 1)); | 
| 2032 | 0 |       info->op.op_count = 3; | 
| 2033 | 0 |       return MCDisassembler_Success; | 
| 2034 | 0 |     } else { | 
| 2035 | 0 |       return MCDisassembler_Fail; | 
| 2036 | 0 |     } | 
| 2037 | 0 |   case 0x1e: | 
| 2038 | 0 |     return dsp_op_cc_2opr(code, info, SH_INS_DSP_PCOPY, f_sy, 4, detail); | 
| 2039 | 0 |   default: | 
| 2040 | 0 |     return MCDisassembler_Fail; | 
| 2041 | 0 |   }    | 
| 2042 | 0 | } | 
| 2043 |  |  | 
| 2044 |  | static bool decode_dsp_p(const uint32_t code, MCInst *MI, cs_mode mode, | 
| 2045 |  |        sh_info *info, cs_detail *detail) | 
| 2046 | 0 | { | 
| 2047 | 0 |   int dz = code & 0x0f; | 
| 2048 | 0 |   MCInst_setOpcode(MI, SH_INS_DSP); | 
| 2049 | 0 |   if (!decode_dsp_d(code >> 16, MI, mode, info, detail)) | 
| 2050 | 0 |     return MCDisassembler_Fail; | 
| 2051 |  |      | 
| 2052 | 0 |   switch((code >> 12) & 0x0f) { | 
| 2053 | 0 |   case 0x00: | 
| 2054 | 0 |   case 0x01: | 
| 2055 | 0 |     if ((code >> 11) & 1) | 
| 2056 | 0 |       return MCDisassembler_Fail; | 
| 2057 | 0 |     info->op.operands[2].dsp.insn | 
| 2058 | 0 |       = SH_INS_DSP_PSHL + ((code >> 12) & 1); | 
| 2059 | 0 |     info->op.operands[2].dsp.imm = (code >> 4) & 0x7f; | 
| 2060 | 0 |     set_reg_dsp_write_z(info, 1, dz, detail); | 
| 2061 | 0 |     info->op.op_count = 3; | 
| 2062 | 0 |     return MCDisassembler_Success; | 
| 2063 | 0 |   case 0x04: | 
| 2064 | 0 |     if ((((code >> 4) & 1) && isalevel(mode) != ISA_SH4A) || | 
| 2065 | 0 |         (!((code >> 4) & 1) && (code &3)) || | 
| 2066 | 0 |         ((code >> 4) & 0x0f) >= 2) | 
| 2067 | 0 |       return MCDisassembler_Fail; | 
| 2068 |  |        | 
| 2069 | 0 |     info->op.operands[2].dsp.insn | 
| 2070 | 0 |       = SH_INS_DSP_PMULS + ((code >> 4) & 1); | 
| 2071 | 0 |     set_reg_dsp_read(info, 0, f_se, (code >> 10) & 3, detail); | 
| 2072 | 0 |     set_reg_dsp_read(info, 1, f_sf, (code >> 8) & 3, detail); | 
| 2073 | 0 |     set_reg_dsp_write_gu(info, 2, f_dg, (code >> 2) & 3, detail); | 
| 2074 | 0 |     if ((code >> 4) & 1) | 
| 2075 | 0 |       set_reg_dsp_write_gu(info, 3, f_du, | 
| 2076 | 0 |                (code >> 0) & 3, detail); | 
| 2077 | 0 |     info->op.op_count = 3; | 
| 2078 | 0 |     return MCDisassembler_Success; | 
| 2079 | 0 |   case 0x06: | 
| 2080 | 0 |   case 0x07: | 
| 2081 | 0 |     info->op.operands[2].dsp.insn | 
| 2082 | 0 |       = SH_INS_DSP_PSUB_PMULS + ((code >> 12) & 1); | 
| 2083 | 0 |     set_reg_dsp_read(info, 0, f_sx, (code >> 6) & 3, detail); | 
| 2084 | 0 |     set_reg_dsp_read(info, 1, f_sy, (code >> 4) & 3, detail); | 
| 2085 | 0 |     set_reg_dsp_write_gu(info, 2, f_du, (code >> 0) & 3, detail); | 
| 2086 | 0 |     set_reg_dsp_read(info, 3, f_se, (code >> 10) & 3, detail); | 
| 2087 | 0 |     set_reg_dsp_read(info, 4, f_sf, (code >> 8) & 3, detail); | 
| 2088 | 0 |     set_reg_dsp_write_gu(info, 5, f_dg, (code >> 2) & 3, detail); | 
| 2089 | 0 |     info->op.op_count = 3; | 
| 2090 | 0 |     return MCDisassembler_Success; | 
| 2091 | 0 |   default: | 
| 2092 | 0 |     if ((code >> 15) & 1) | 
| 2093 | 0 |       return decode_dsp_3op(code, info, detail); | 
| 2094 | 0 |   } | 
| 2095 | 0 |   return MCDisassembler_Fail; | 
| 2096 | 0 | } | 
| 2097 |  |  | 
| 2098 |  | static bool sh_disassemble(const uint8_t *code, MCInst *MI, uint64_t address, | 
| 2099 |  |          cs_mode mode, uint16_t *size, int code_len, | 
| 2100 |  |          sh_info *info, cs_detail *detail) | 
| 2101 | 0 | { | 
| 2102 | 0 |   int idx; | 
| 2103 | 0 |   uint32_t insn; | 
| 2104 | 0 |   bool dsp_result; | 
| 2105 | 0 |   if (MODE_IS_BIG_ENDIAN(mode)) { | 
| 2106 | 0 |     insn = code[0] << 8 | code[1]; | 
| 2107 | 0 |   } else { | 
| 2108 | 0 |     insn = code[1] << 8 | code[0]; | 
| 2109 | 0 |   } | 
| 2110 | 0 |   if (mode & CS_MODE_SH2A) { | 
| 2111 |  |     /* SH2A 32bit instrcution test */ | 
| 2112 | 0 |     if (((insn & 0xf007) == 0x3001 || | 
| 2113 | 0 |          (insn & 0xf00e) == 0x0000)) { | 
| 2114 | 0 |       if (code_len < 4) | 
| 2115 | 0 |         return MCDisassembler_Fail; | 
| 2116 | 0 |       *size = 4; | 
| 2117 |  |       // SH2A is only BIG ENDIAN. | 
| 2118 | 0 |       insn <<= 16; | 
| 2119 | 0 |       insn |= code[2] << 8 | code[3]; | 
| 2120 | 0 |       if (decode_long(insn, address,  MI, info, detail)) | 
| 2121 | 0 |         return MCDisassembler_Success; | 
| 2122 | 0 |     } | 
| 2123 | 0 |   } | 
| 2124 |  |   /* Co-processor instructions */ | 
| 2125 | 0 |   if ((insn & 0xf000) == 0xf000) { | 
| 2126 | 0 |     if (mode & CS_MODE_SHDSP) { | 
| 2127 | 0 |       dsp_result = MCDisassembler_Fail; | 
| 2128 | 0 |       switch(insn >> 10 & 3) { | 
| 2129 | 0 |       case 0: | 
| 2130 | 0 |         *size = 2; | 
| 2131 | 0 |         dsp_result = decode_dsp_d(insn, MI, mode, | 
| 2132 | 0 |                 info, detail); | 
| 2133 | 0 |         break; | 
| 2134 | 0 |       case 1: | 
| 2135 | 0 |         *size = 2; | 
| 2136 | 0 |         dsp_result = decode_dsp_s(insn, MI, | 
| 2137 | 0 |                 info, detail); | 
| 2138 | 0 |         break; | 
| 2139 | 0 |       case 2: | 
| 2140 | 0 |         if (code_len < 4) | 
| 2141 | 0 |           return MCDisassembler_Fail; | 
| 2142 | 0 |         *size = 4; | 
| 2143 | 0 |         if (MODE_IS_BIG_ENDIAN(mode)) { | 
| 2144 | 0 |           insn <<= 16; | 
| 2145 | 0 |           insn |= code[2] << 8 | code[3]; | 
| 2146 | 0 |         } else | 
| 2147 | 0 |           insn |= (code[3] << 24) | 
| 2148 | 0 |             | (code[2] << 16); | 
| 2149 | 0 |         dsp_result = decode_dsp_p(insn, MI, mode, | 
| 2150 | 0 |                 info, detail); | 
| 2151 | 0 |         break; | 
| 2152 | 0 |       } | 
| 2153 | 0 |       return dsp_result; | 
| 2154 | 0 |     } | 
| 2155 | 0 |     if ((mode & CS_MODE_SHFPU) == 0) | 
| 2156 | 0 |       return MCDisassembler_Fail; | 
| 2157 | 0 |   } | 
| 2158 |  |    | 
| 2159 | 0 |   *size = 2; | 
| 2160 | 0 |   if ((insn & 0xf000) >= 0x8000 && (insn & 0xf000) < 0xf000) { | 
| 2161 | 0 |     idx = insn >> 8; | 
| 2162 | 0 |   } else { | 
| 2163 | 0 |     idx = ((insn >> 8) & 0xf0) | (insn & 0x000f); | 
| 2164 | 0 |   } | 
| 2165 |  | 
 | 
| 2166 | 0 |   if (decode[idx]) { | 
| 2167 | 0 |     return decode[idx](insn, address, MI, mode, info, detail); | 
| 2168 | 0 |   } else { | 
| 2169 | 0 |     return MCDisassembler_Fail; | 
| 2170 | 0 |   } | 
| 2171 | 0 | } | 
| 2172 |  |        | 
| 2173 |  | bool SH_getInstruction(csh ud, const uint8_t *code, size_t code_len, | 
| 2174 |  |   MCInst *MI, uint16_t *size, uint64_t address, void *inst_info) | 
| 2175 | 0 | { | 
| 2176 |  |    | 
| 2177 | 0 |   cs_struct* handle = (cs_struct *)ud; | 
| 2178 | 0 |   sh_info *info = (sh_info *)handle->printer_info; | 
| 2179 | 0 |   cs_detail *detail = MI->flat_insn->detail; | 
| 2180 |  | 
 | 
| 2181 | 0 |   if (code_len < 2) { | 
| 2182 | 0 |     *size = 0; | 
| 2183 | 0 |     return MCDisassembler_Fail; | 
| 2184 | 0 |   } | 
| 2185 |  |  | 
| 2186 | 0 |   if (detail) { | 
| 2187 | 0 |     memset(detail, 0, offsetof(cs_detail, sh)+sizeof(cs_sh)); | 
| 2188 | 0 |   } | 
| 2189 | 0 |   memset(info, 0, sizeof(sh_info)); | 
| 2190 | 0 |   if (sh_disassemble(code, MI, address, handle->mode, | 
| 2191 | 0 |          size, code_len, info, detail) == MCDisassembler_Fail) { | 
| 2192 | 0 |     *size = 0; | 
| 2193 | 0 |     return MCDisassembler_Fail; | 
| 2194 | 0 |   } else { | 
| 2195 | 0 |     return MCDisassembler_Success; | 
| 2196 | 0 |   }     | 
| 2197 | 0 | } | 
| 2198 |  |  | 
| 2199 |  | #ifndef CAPSTONE_DIET | 
| 2200 |  | void SH_reg_access(const cs_insn *insn, | 
| 2201 |  |        cs_regs regs_read, uint8_t *regs_read_count, | 
| 2202 |  |        cs_regs regs_write, uint8_t *regs_write_count) | 
| 2203 | 0 | { | 
| 2204 | 0 |         if (insn->detail == NULL) { | 
| 2205 | 0 |                 *regs_read_count = 0; | 
| 2206 | 0 |                 *regs_write_count = 0; | 
| 2207 | 0 |         } | 
| 2208 | 0 |         else { | 
| 2209 | 0 |                 *regs_read_count = insn->detail->regs_read_count; | 
| 2210 | 0 |                 *regs_write_count = insn->detail->regs_write_count; | 
| 2211 |  | 
 | 
| 2212 | 0 |                 memcpy(regs_read, insn->detail->regs_read, | 
| 2213 | 0 |                         *regs_read_count * sizeof(insn->detail->regs_read[0])); | 
| 2214 | 0 |                 memcpy(regs_write, insn->detail->regs_write, | 
| 2215 | 0 |                         *regs_write_count * | 
| 2216 | 0 |                         sizeof(insn->detail->regs_write[0])); | 
| 2217 | 0 |         } | 
| 2218 | 0 | } | 
| 2219 |  | #endif | 
| 2220 |  |  | 
| 2221 |  |  |