/src/capstonev5/arch/ARM/ARMMapping.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* Capstone Disassembly Engine */ | 
| 2 |  | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */ | 
| 3 |  |  | 
| 4 |  | #ifdef CAPSTONE_HAS_ARM | 
| 5 |  |  | 
| 6 |  | #include <stdio.h>  // debug | 
| 7 |  | #include <string.h> | 
| 8 |  |  | 
| 9 |  | #include "../../cs_priv.h" | 
| 10 |  |  | 
| 11 |  | #include "ARMMapping.h" | 
| 12 |  |  | 
| 13 |  | #define GET_INSTRINFO_ENUM | 
| 14 |  | #include "ARMGenInstrInfo.inc" | 
| 15 |  |  | 
| 16 |  | #ifndef CAPSTONE_DIET | 
| 17 |  | static const name_map reg_name_maps[] = { | 
| 18 |  |   { ARM_REG_INVALID, NULL }, | 
| 19 |  |   { ARM_REG_APSR, "apsr"}, | 
| 20 |  |   { ARM_REG_APSR_NZCV, "apsr_nzcv"}, | 
| 21 |  |   { ARM_REG_CPSR, "cpsr"}, | 
| 22 |  |   { ARM_REG_FPEXC, "fpexc"}, | 
| 23 |  |   { ARM_REG_FPINST, "fpinst"}, | 
| 24 |  |   { ARM_REG_FPSCR, "fpscr"}, | 
| 25 |  |   { ARM_REG_FPSCR_NZCV, "fpscr_nzcv"}, | 
| 26 |  |   { ARM_REG_FPSID, "fpsid"}, | 
| 27 |  |   { ARM_REG_ITSTATE, "itstate"}, | 
| 28 |  |   { ARM_REG_LR, "lr"}, | 
| 29 |  |   { ARM_REG_PC, "pc"}, | 
| 30 |  |   { ARM_REG_SP, "sp"}, | 
| 31 |  |   { ARM_REG_SPSR, "spsr"}, | 
| 32 |  |   { ARM_REG_D0, "d0"}, | 
| 33 |  |   { ARM_REG_D1, "d1"}, | 
| 34 |  |   { ARM_REG_D2, "d2"}, | 
| 35 |  |   { ARM_REG_D3, "d3"}, | 
| 36 |  |   { ARM_REG_D4, "d4"}, | 
| 37 |  |   { ARM_REG_D5, "d5"}, | 
| 38 |  |   { ARM_REG_D6, "d6"}, | 
| 39 |  |   { ARM_REG_D7, "d7"}, | 
| 40 |  |   { ARM_REG_D8, "d8"}, | 
| 41 |  |   { ARM_REG_D9, "d9"}, | 
| 42 |  |   { ARM_REG_D10, "d10"}, | 
| 43 |  |   { ARM_REG_D11, "d11"}, | 
| 44 |  |   { ARM_REG_D12, "d12"}, | 
| 45 |  |   { ARM_REG_D13, "d13"}, | 
| 46 |  |   { ARM_REG_D14, "d14"}, | 
| 47 |  |   { ARM_REG_D15, "d15"}, | 
| 48 |  |   { ARM_REG_D16, "d16"}, | 
| 49 |  |   { ARM_REG_D17, "d17"}, | 
| 50 |  |   { ARM_REG_D18, "d18"}, | 
| 51 |  |   { ARM_REG_D19, "d19"}, | 
| 52 |  |   { ARM_REG_D20, "d20"}, | 
| 53 |  |   { ARM_REG_D21, "d21"}, | 
| 54 |  |   { ARM_REG_D22, "d22"}, | 
| 55 |  |   { ARM_REG_D23, "d23"}, | 
| 56 |  |   { ARM_REG_D24, "d24"}, | 
| 57 |  |   { ARM_REG_D25, "d25"}, | 
| 58 |  |   { ARM_REG_D26, "d26"}, | 
| 59 |  |   { ARM_REG_D27, "d27"}, | 
| 60 |  |   { ARM_REG_D28, "d28"}, | 
| 61 |  |   { ARM_REG_D29, "d29"}, | 
| 62 |  |   { ARM_REG_D30, "d30"}, | 
| 63 |  |   { ARM_REG_D31, "d31"}, | 
| 64 |  |   { ARM_REG_FPINST2, "fpinst2"}, | 
| 65 |  |   { ARM_REG_MVFR0, "mvfr0"}, | 
| 66 |  |   { ARM_REG_MVFR1, "mvfr1"}, | 
| 67 |  |   { ARM_REG_MVFR2, "mvfr2"}, | 
| 68 |  |   { ARM_REG_Q0, "q0"}, | 
| 69 |  |   { ARM_REG_Q1, "q1"}, | 
| 70 |  |   { ARM_REG_Q2, "q2"}, | 
| 71 |  |   { ARM_REG_Q3, "q3"}, | 
| 72 |  |   { ARM_REG_Q4, "q4"}, | 
| 73 |  |   { ARM_REG_Q5, "q5"}, | 
| 74 |  |   { ARM_REG_Q6, "q6"}, | 
| 75 |  |   { ARM_REG_Q7, "q7"}, | 
| 76 |  |   { ARM_REG_Q8, "q8"}, | 
| 77 |  |   { ARM_REG_Q9, "q9"}, | 
| 78 |  |   { ARM_REG_Q10, "q10"}, | 
| 79 |  |   { ARM_REG_Q11, "q11"}, | 
| 80 |  |   { ARM_REG_Q12, "q12"}, | 
| 81 |  |   { ARM_REG_Q13, "q13"}, | 
| 82 |  |   { ARM_REG_Q14, "q14"}, | 
| 83 |  |   { ARM_REG_Q15, "q15"}, | 
| 84 |  |   { ARM_REG_R0, "r0"}, | 
| 85 |  |   { ARM_REG_R1, "r1"}, | 
| 86 |  |   { ARM_REG_R2, "r2"}, | 
| 87 |  |   { ARM_REG_R3, "r3"}, | 
| 88 |  |   { ARM_REG_R4, "r4"}, | 
| 89 |  |   { ARM_REG_R5, "r5"}, | 
| 90 |  |   { ARM_REG_R6, "r6"}, | 
| 91 |  |   { ARM_REG_R7, "r7"}, | 
| 92 |  |   { ARM_REG_R8, "r8"}, | 
| 93 |  |   { ARM_REG_R9, "sb"}, | 
| 94 |  |   { ARM_REG_R10, "sl"}, | 
| 95 |  |   { ARM_REG_R11, "fp"}, | 
| 96 |  |   { ARM_REG_R12, "ip"}, | 
| 97 |  |   { ARM_REG_S0, "s0"}, | 
| 98 |  |   { ARM_REG_S1, "s1"}, | 
| 99 |  |   { ARM_REG_S2, "s2"}, | 
| 100 |  |   { ARM_REG_S3, "s3"}, | 
| 101 |  |   { ARM_REG_S4, "s4"}, | 
| 102 |  |   { ARM_REG_S5, "s5"}, | 
| 103 |  |   { ARM_REG_S6, "s6"}, | 
| 104 |  |   { ARM_REG_S7, "s7"}, | 
| 105 |  |   { ARM_REG_S8, "s8"}, | 
| 106 |  |   { ARM_REG_S9, "s9"}, | 
| 107 |  |   { ARM_REG_S10, "s10"}, | 
| 108 |  |   { ARM_REG_S11, "s11"}, | 
| 109 |  |   { ARM_REG_S12, "s12"}, | 
| 110 |  |   { ARM_REG_S13, "s13"}, | 
| 111 |  |   { ARM_REG_S14, "s14"}, | 
| 112 |  |   { ARM_REG_S15, "s15"}, | 
| 113 |  |   { ARM_REG_S16, "s16"}, | 
| 114 |  |   { ARM_REG_S17, "s17"}, | 
| 115 |  |   { ARM_REG_S18, "s18"}, | 
| 116 |  |   { ARM_REG_S19, "s19"}, | 
| 117 |  |   { ARM_REG_S20, "s20"}, | 
| 118 |  |   { ARM_REG_S21, "s21"}, | 
| 119 |  |   { ARM_REG_S22, "s22"}, | 
| 120 |  |   { ARM_REG_S23, "s23"}, | 
| 121 |  |   { ARM_REG_S24, "s24"}, | 
| 122 |  |   { ARM_REG_S25, "s25"}, | 
| 123 |  |   { ARM_REG_S26, "s26"}, | 
| 124 |  |   { ARM_REG_S27, "s27"}, | 
| 125 |  |   { ARM_REG_S28, "s28"}, | 
| 126 |  |   { ARM_REG_S29, "s29"}, | 
| 127 |  |   { ARM_REG_S30, "s30"}, | 
| 128 |  |   { ARM_REG_S31, "s31"}, | 
| 129 |  | }; | 
| 130 |  | static const name_map reg_name_maps2[] = { | 
| 131 |  |   { ARM_REG_INVALID, NULL }, | 
| 132 |  |   { ARM_REG_APSR, "apsr"}, | 
| 133 |  |   { ARM_REG_APSR_NZCV, "apsr_nzcv"}, | 
| 134 |  |   { ARM_REG_CPSR, "cpsr"}, | 
| 135 |  |   { ARM_REG_FPEXC, "fpexc"}, | 
| 136 |  |   { ARM_REG_FPINST, "fpinst"}, | 
| 137 |  |   { ARM_REG_FPSCR, "fpscr"}, | 
| 138 |  |   { ARM_REG_FPSCR_NZCV, "fpscr_nzcv"}, | 
| 139 |  |   { ARM_REG_FPSID, "fpsid"}, | 
| 140 |  |   { ARM_REG_ITSTATE, "itstate"}, | 
| 141 |  |   { ARM_REG_LR, "lr"}, | 
| 142 |  |   { ARM_REG_PC, "pc"}, | 
| 143 |  |   { ARM_REG_SP, "sp"}, | 
| 144 |  |   { ARM_REG_SPSR, "spsr"}, | 
| 145 |  |   { ARM_REG_D0, "d0"}, | 
| 146 |  |   { ARM_REG_D1, "d1"}, | 
| 147 |  |   { ARM_REG_D2, "d2"}, | 
| 148 |  |   { ARM_REG_D3, "d3"}, | 
| 149 |  |   { ARM_REG_D4, "d4"}, | 
| 150 |  |   { ARM_REG_D5, "d5"}, | 
| 151 |  |   { ARM_REG_D6, "d6"}, | 
| 152 |  |   { ARM_REG_D7, "d7"}, | 
| 153 |  |   { ARM_REG_D8, "d8"}, | 
| 154 |  |   { ARM_REG_D9, "d9"}, | 
| 155 |  |   { ARM_REG_D10, "d10"}, | 
| 156 |  |   { ARM_REG_D11, "d11"}, | 
| 157 |  |   { ARM_REG_D12, "d12"}, | 
| 158 |  |   { ARM_REG_D13, "d13"}, | 
| 159 |  |   { ARM_REG_D14, "d14"}, | 
| 160 |  |   { ARM_REG_D15, "d15"}, | 
| 161 |  |   { ARM_REG_D16, "d16"}, | 
| 162 |  |   { ARM_REG_D17, "d17"}, | 
| 163 |  |   { ARM_REG_D18, "d18"}, | 
| 164 |  |   { ARM_REG_D19, "d19"}, | 
| 165 |  |   { ARM_REG_D20, "d20"}, | 
| 166 |  |   { ARM_REG_D21, "d21"}, | 
| 167 |  |   { ARM_REG_D22, "d22"}, | 
| 168 |  |   { ARM_REG_D23, "d23"}, | 
| 169 |  |   { ARM_REG_D24, "d24"}, | 
| 170 |  |   { ARM_REG_D25, "d25"}, | 
| 171 |  |   { ARM_REG_D26, "d26"}, | 
| 172 |  |   { ARM_REG_D27, "d27"}, | 
| 173 |  |   { ARM_REG_D28, "d28"}, | 
| 174 |  |   { ARM_REG_D29, "d29"}, | 
| 175 |  |   { ARM_REG_D30, "d30"}, | 
| 176 |  |   { ARM_REG_D31, "d31"}, | 
| 177 |  |   { ARM_REG_FPINST2, "fpinst2"}, | 
| 178 |  |   { ARM_REG_MVFR0, "mvfr0"}, | 
| 179 |  |   { ARM_REG_MVFR1, "mvfr1"}, | 
| 180 |  |   { ARM_REG_MVFR2, "mvfr2"}, | 
| 181 |  |   { ARM_REG_Q0, "q0"}, | 
| 182 |  |   { ARM_REG_Q1, "q1"}, | 
| 183 |  |   { ARM_REG_Q2, "q2"}, | 
| 184 |  |   { ARM_REG_Q3, "q3"}, | 
| 185 |  |   { ARM_REG_Q4, "q4"}, | 
| 186 |  |   { ARM_REG_Q5, "q5"}, | 
| 187 |  |   { ARM_REG_Q6, "q6"}, | 
| 188 |  |   { ARM_REG_Q7, "q7"}, | 
| 189 |  |   { ARM_REG_Q8, "q8"}, | 
| 190 |  |   { ARM_REG_Q9, "q9"}, | 
| 191 |  |   { ARM_REG_Q10, "q10"}, | 
| 192 |  |   { ARM_REG_Q11, "q11"}, | 
| 193 |  |   { ARM_REG_Q12, "q12"}, | 
| 194 |  |   { ARM_REG_Q13, "q13"}, | 
| 195 |  |   { ARM_REG_Q14, "q14"}, | 
| 196 |  |   { ARM_REG_Q15, "q15"}, | 
| 197 |  |   { ARM_REG_R0, "r0"}, | 
| 198 |  |   { ARM_REG_R1, "r1"}, | 
| 199 |  |   { ARM_REG_R2, "r2"}, | 
| 200 |  |   { ARM_REG_R3, "r3"}, | 
| 201 |  |   { ARM_REG_R4, "r4"}, | 
| 202 |  |   { ARM_REG_R5, "r5"}, | 
| 203 |  |   { ARM_REG_R6, "r6"}, | 
| 204 |  |   { ARM_REG_R7, "r7"}, | 
| 205 |  |   { ARM_REG_R8, "r8"}, | 
| 206 |  |   { ARM_REG_R9, "r9"}, | 
| 207 |  |   { ARM_REG_R10, "r10"}, | 
| 208 |  |   { ARM_REG_R11, "r11"}, | 
| 209 |  |   { ARM_REG_R12, "r12"}, | 
| 210 |  |   { ARM_REG_S0, "s0"}, | 
| 211 |  |   { ARM_REG_S1, "s1"}, | 
| 212 |  |   { ARM_REG_S2, "s2"}, | 
| 213 |  |   { ARM_REG_S3, "s3"}, | 
| 214 |  |   { ARM_REG_S4, "s4"}, | 
| 215 |  |   { ARM_REG_S5, "s5"}, | 
| 216 |  |   { ARM_REG_S6, "s6"}, | 
| 217 |  |   { ARM_REG_S7, "s7"}, | 
| 218 |  |   { ARM_REG_S8, "s8"}, | 
| 219 |  |   { ARM_REG_S9, "s9"}, | 
| 220 |  |   { ARM_REG_S10, "s10"}, | 
| 221 |  |   { ARM_REG_S11, "s11"}, | 
| 222 |  |   { ARM_REG_S12, "s12"}, | 
| 223 |  |   { ARM_REG_S13, "s13"}, | 
| 224 |  |   { ARM_REG_S14, "s14"}, | 
| 225 |  |   { ARM_REG_S15, "s15"}, | 
| 226 |  |   { ARM_REG_S16, "s16"}, | 
| 227 |  |   { ARM_REG_S17, "s17"}, | 
| 228 |  |   { ARM_REG_S18, "s18"}, | 
| 229 |  |   { ARM_REG_S19, "s19"}, | 
| 230 |  |   { ARM_REG_S20, "s20"}, | 
| 231 |  |   { ARM_REG_S21, "s21"}, | 
| 232 |  |   { ARM_REG_S22, "s22"}, | 
| 233 |  |   { ARM_REG_S23, "s23"}, | 
| 234 |  |   { ARM_REG_S24, "s24"}, | 
| 235 |  |   { ARM_REG_S25, "s25"}, | 
| 236 |  |   { ARM_REG_S26, "s26"}, | 
| 237 |  |   { ARM_REG_S27, "s27"}, | 
| 238 |  |   { ARM_REG_S28, "s28"}, | 
| 239 |  |   { ARM_REG_S29, "s29"}, | 
| 240 |  |   { ARM_REG_S30, "s30"}, | 
| 241 |  |   { ARM_REG_S31, "s31"}, | 
| 242 |  | }; | 
| 243 |  | #endif | 
| 244 |  |  | 
| 245 |  | const char *ARM_reg_name(csh handle, unsigned int reg) | 
| 246 | 76.5k | { | 
| 247 | 76.5k | #ifndef CAPSTONE_DIET | 
| 248 | 76.5k |   if (reg >= ARR_SIZE(reg_name_maps)) | 
| 249 | 0 |     return NULL; | 
| 250 |  |  | 
| 251 | 76.5k |   return reg_name_maps[reg].name; | 
| 252 |  | #else | 
| 253 |  |   return NULL; | 
| 254 |  | #endif | 
| 255 | 76.5k | } | 
| 256 |  |  | 
| 257 |  | const char *ARM_reg_name2(csh handle, unsigned int reg) | 
| 258 | 0 | { | 
| 259 | 0 | #ifndef CAPSTONE_DIET | 
| 260 | 0 |   if (reg >= ARR_SIZE(reg_name_maps2)) | 
| 261 | 0 |     return NULL; | 
| 262 |  |  | 
| 263 | 0 |   return reg_name_maps2[reg].name; | 
| 264 |  | #else | 
| 265 |  |   return NULL; | 
| 266 |  | #endif | 
| 267 | 0 | } | 
| 268 |  |  | 
| 269 |  | static const insn_map insns[] = { | 
| 270 |  |   // dummy item | 
| 271 |  |   { | 
| 272 |  |     0, 0, | 
| 273 |  | #ifndef CAPSTONE_DIET | 
| 274 |  |     { 0 }, { 0 }, { 0 }, 0, 0 | 
| 275 |  | #endif | 
| 276 |  |   }, | 
| 277 |  | #include "ARMMappingInsn.inc" | 
| 278 |  | }; | 
| 279 |  |  | 
| 280 |  | // look for @id in @insns | 
| 281 |  | // return -1 if not found | 
| 282 |  | static unsigned int find_insn(unsigned int id) | 
| 283 | 306k | { | 
| 284 |  |   // binary searching since the IDs are sorted in order | 
| 285 | 306k |   unsigned int left, right, m; | 
| 286 | 306k |   unsigned int max = ARR_SIZE(insns); | 
| 287 |  |  | 
| 288 | 306k |   right = max - 1; | 
| 289 |  |  | 
| 290 | 306k |   if (id < insns[0].id || id > insns[right].id) | 
| 291 |  |     // not found | 
| 292 | 0 |     return -1; | 
| 293 |  |  | 
| 294 | 306k |   left = 0; | 
| 295 |  |  | 
| 296 | 3.19M |   while(left <= right) { | 
| 297 | 3.19M |     m = (left + right) / 2; | 
| 298 | 3.19M |     if (id == insns[m].id) { | 
| 299 | 306k |       return m; | 
| 300 | 306k |     } | 
| 301 |  |  | 
| 302 | 2.88M |     if (id < insns[m].id) | 
| 303 | 962k |       right = m - 1; | 
| 304 | 1.92M |     else | 
| 305 | 1.92M |       left = m + 1; | 
| 306 | 2.88M |   } | 
| 307 |  |  | 
| 308 |  |   // not found | 
| 309 |  |   // printf("NOT FOUNDDDDDDDDDDDDDDD id = %u\n", id); | 
| 310 | 0 |   return -1; | 
| 311 | 306k | } | 
| 312 |  |  | 
| 313 |  | void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) | 
| 314 | 306k | { | 
| 315 | 306k |   unsigned int i = find_insn(id); | 
| 316 | 306k |   if (i != -1) { | 
| 317 | 306k |     insn->id = insns[i].mapid; | 
| 318 |  |  | 
| 319 |  |     // printf("id = %u, mapid = %u\n", id, insn->id); | 
| 320 |  |  | 
| 321 | 306k |     if (h->detail) { | 
| 322 | 306k | #ifndef CAPSTONE_DIET | 
| 323 | 306k |       cs_struct handle; | 
| 324 | 306k |       handle.detail = h->detail; | 
| 325 |  |  | 
| 326 | 306k |       memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); | 
| 327 | 306k |       insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use); | 
| 328 |  |  | 
| 329 | 306k |       memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); | 
| 330 | 306k |       insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod); | 
| 331 |  |  | 
| 332 | 306k |       memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups)); | 
| 333 | 306k |       insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups); | 
| 334 |  |  | 
| 335 | 306k |       insn->detail->arm.update_flags = cs_reg_write((csh)&handle, insn, ARM_REG_CPSR); | 
| 336 |  |  | 
| 337 | 306k |       if (insns[i].branch || insns[i].indirect_branch) { | 
| 338 |  |         // this insn also belongs to JUMP group. add JUMP group | 
| 339 | 18.2k |         insn->detail->groups[insn->detail->groups_count] = ARM_GRP_JUMP; | 
| 340 | 18.2k |         insn->detail->groups_count++; | 
| 341 | 18.2k |       } | 
| 342 | 306k | #endif | 
| 343 | 306k |     } | 
| 344 | 306k |   } | 
| 345 | 306k | } | 
| 346 |  |  | 
| 347 |  | #ifndef CAPSTONE_DIET | 
| 348 |  | static const char * const insn_name_maps[] = { | 
| 349 |  |   NULL, // ARM_INS_INVALID | 
| 350 |  | #include "ARMMappingInsnName.inc" | 
| 351 |  | }; | 
| 352 |  | #endif | 
| 353 |  |  | 
| 354 |  | const char *ARM_insn_name(csh handle, unsigned int id) | 
| 355 | 306k | { | 
| 356 | 306k | #ifndef CAPSTONE_DIET | 
| 357 | 306k |   if (id >= ARM_INS_ENDING) | 
| 358 | 0 |     return NULL; | 
| 359 |  |  | 
| 360 | 306k |   return insn_name_maps[id]; | 
| 361 |  | #else | 
| 362 |  |   return NULL; | 
| 363 |  | #endif | 
| 364 | 306k | } | 
| 365 |  |  | 
| 366 |  | #ifndef CAPSTONE_DIET | 
| 367 |  | static const name_map group_name_maps[] = { | 
| 368 |  |   // generic groups | 
| 369 |  |   { ARM_GRP_INVALID, NULL }, | 
| 370 |  |   { ARM_GRP_JUMP, "jump" }, | 
| 371 |  |   { ARM_GRP_CALL, "call" }, | 
| 372 |  |   { ARM_GRP_INT,  "int" }, | 
| 373 |  |   { ARM_GRP_PRIVILEGE, "privilege" }, | 
| 374 |  |   { ARM_GRP_BRANCH_RELATIVE, "branch_relative" }, | 
| 375 |  |  | 
| 376 |  |   // architecture-specific groups | 
| 377 |  |   { ARM_GRP_CRYPTO, "crypto" }, | 
| 378 |  |   { ARM_GRP_DATABARRIER, "databarrier" }, | 
| 379 |  |   { ARM_GRP_DIVIDE, "divide" }, | 
| 380 |  |   { ARM_GRP_FPARMV8, "fparmv8" }, | 
| 381 |  |   { ARM_GRP_MULTPRO, "multpro" }, | 
| 382 |  |   { ARM_GRP_NEON, "neon" }, | 
| 383 |  |   { ARM_GRP_T2EXTRACTPACK, "T2EXTRACTPACK" }, | 
| 384 |  |   { ARM_GRP_THUMB2DSP, "THUMB2DSP" }, | 
| 385 |  |   { ARM_GRP_TRUSTZONE, "TRUSTZONE" }, | 
| 386 |  |   { ARM_GRP_V4T, "v4t" }, | 
| 387 |  |   { ARM_GRP_V5T, "v5t" }, | 
| 388 |  |   { ARM_GRP_V5TE, "v5te" }, | 
| 389 |  |   { ARM_GRP_V6, "v6" }, | 
| 390 |  |   { ARM_GRP_V6T2, "v6t2" }, | 
| 391 |  |   { ARM_GRP_V7, "v7" }, | 
| 392 |  |   { ARM_GRP_V8, "v8" }, | 
| 393 |  |   { ARM_GRP_VFP2, "vfp2" }, | 
| 394 |  |   { ARM_GRP_VFP3, "vfp3" }, | 
| 395 |  |   { ARM_GRP_VFP4, "vfp4" }, | 
| 396 |  |   { ARM_GRP_ARM, "arm" }, | 
| 397 |  |   { ARM_GRP_MCLASS, "mclass" }, | 
| 398 |  |   { ARM_GRP_NOTMCLASS, "notmclass" }, | 
| 399 |  |   { ARM_GRP_THUMB, "thumb" }, | 
| 400 |  |   { ARM_GRP_THUMB1ONLY, "thumb1only" }, | 
| 401 |  |   { ARM_GRP_THUMB2, "thumb2" }, | 
| 402 |  |   { ARM_GRP_PREV8, "prev8" }, | 
| 403 |  |   { ARM_GRP_FPVMLX, "fpvmlx" }, | 
| 404 |  |   { ARM_GRP_MULOPS, "mulops" }, | 
| 405 |  |   { ARM_GRP_CRC, "crc" }, | 
| 406 |  |   { ARM_GRP_DPVFP, "dpvfp" }, | 
| 407 |  |   { ARM_GRP_V6M, "v6m" }, | 
| 408 |  |   { ARM_GRP_VIRTUALIZATION, "virtualization" }, | 
| 409 |  | }; | 
| 410 |  | #endif | 
| 411 |  |  | 
| 412 |  | const char *ARM_group_name(csh handle, unsigned int id) | 
| 413 | 544k | { | 
| 414 | 544k | #ifndef CAPSTONE_DIET | 
| 415 | 544k |   return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); | 
| 416 |  | #else | 
| 417 |  |   return NULL; | 
| 418 |  | #endif | 
| 419 | 544k | } | 
| 420 |  |  | 
| 421 |  | // list all relative branch instructions | 
| 422 |  | // ie: insns[i].branch && !insns[i].indirect_branch | 
| 423 |  | static const unsigned int insn_rel[] = { | 
| 424 |  |   ARM_BL, | 
| 425 |  |   ARM_BLX_pred, | 
| 426 |  |   ARM_Bcc, | 
| 427 |  |   ARM_t2B, | 
| 428 |  |   ARM_t2Bcc, | 
| 429 |  |   ARM_tB, | 
| 430 |  |   ARM_tBcc, | 
| 431 |  |   ARM_tCBNZ, | 
| 432 |  |   ARM_tCBZ, | 
| 433 |  |   ARM_BL_pred, | 
| 434 |  |   ARM_BLXi, | 
| 435 |  |   ARM_tBL, | 
| 436 |  |   ARM_tBLXi, | 
| 437 |  |   0 | 
| 438 |  | }; | 
| 439 |  |  | 
| 440 |  | static const unsigned int insn_blx_rel_to_arm[] = { | 
| 441 |  |   ARM_tBLXi, | 
| 442 |  |   0 | 
| 443 |  | }; | 
| 444 |  |  | 
| 445 |  | // check if this insn is relative branch | 
| 446 |  | bool ARM_rel_branch(cs_struct *h, unsigned int id) | 
| 447 | 82.8k | { | 
| 448 | 82.8k |   int i; | 
| 449 |  |  | 
| 450 | 1.03M |   for (i = 0; insn_rel[i]; i++) { | 
| 451 | 966k |     if (id == insn_rel[i]) { | 
| 452 | 17.8k |       return true; | 
| 453 | 17.8k |     } | 
| 454 | 966k |   } | 
| 455 |  |  | 
| 456 |  |   // not found | 
| 457 | 65.0k |   return false; | 
| 458 | 82.8k | } | 
| 459 |  |  | 
| 460 | 12.8k | bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int id) { | 
| 461 | 12.8k |   int i; | 
| 462 |  |  | 
| 463 | 25.5k |   for (i = 0; insn_blx_rel_to_arm[i]; i++) | 
| 464 | 12.8k |     if (id == insn_blx_rel_to_arm[i]) | 
| 465 | 171 |       return true; | 
| 466 |  |  | 
| 467 |  |   // not found | 
| 468 | 12.6k |   return false; | 
| 469 |  |  | 
| 470 | 12.8k | } | 
| 471 |  |  | 
| 472 |  | #ifndef CAPSTONE_DIET | 
| 473 |  | // map instruction to its characteristics | 
| 474 |  | typedef struct insn_op { | 
| 475 |  |   uint8_t access[7]; | 
| 476 |  | } insn_op; | 
| 477 |  |  | 
| 478 |  | static const insn_op insn_ops[] = { | 
| 479 |  |   { | 
| 480 |  |     // NULL item | 
| 481 |  |     { 0 } | 
| 482 |  |   }, | 
| 483 |  |  | 
| 484 |  | #include "ARMMappingInsnOp.inc" | 
| 485 |  | }; | 
| 486 |  |  | 
| 487 |  | // given internal insn id, return operand access info | 
| 488 |  | const uint8_t *ARM_get_op_access(cs_struct *h, unsigned int id) | 
| 489 | 529k | { | 
| 490 | 529k |   int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache); | 
| 491 | 529k |   if (i != 0) { | 
| 492 | 529k |     return insn_ops[i].access; | 
| 493 | 529k |   } | 
| 494 |  |  | 
| 495 | 0 |   return NULL; | 
| 496 | 529k | } | 
| 497 |  |  | 
| 498 |  | void ARM_reg_access(const cs_insn *insn, | 
| 499 |  |     cs_regs regs_read, uint8_t *regs_read_count, | 
| 500 |  |     cs_regs regs_write, uint8_t *regs_write_count) | 
| 501 | 0 | { | 
| 502 | 0 |   uint8_t i; | 
| 503 | 0 |   uint8_t read_count, write_count; | 
| 504 | 0 |   cs_arm *arm = &(insn->detail->arm); | 
| 505 |  | 
 | 
| 506 | 0 |   read_count = insn->detail->regs_read_count; | 
| 507 | 0 |   write_count = insn->detail->regs_write_count; | 
| 508 |  |  | 
| 509 |  |   // implicit registers | 
| 510 | 0 |   memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0])); | 
| 511 | 0 |   memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0])); | 
| 512 |  |  | 
| 513 |  |   // explicit registers | 
| 514 | 0 |   for (i = 0; i < arm->op_count; i++) { | 
| 515 | 0 |     cs_arm_op *op = &(arm->operands[i]); | 
| 516 | 0 |     switch((int)op->type) { | 
| 517 | 0 |       case ARM_OP_REG: | 
| 518 | 0 |         if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) { | 
| 519 | 0 |           regs_read[read_count] = (uint16_t)op->reg; | 
| 520 | 0 |           read_count++; | 
| 521 | 0 |         } | 
| 522 | 0 |         if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) { | 
| 523 | 0 |           regs_write[write_count] = (uint16_t)op->reg; | 
| 524 | 0 |           write_count++; | 
| 525 | 0 |         } | 
| 526 | 0 |         break; | 
| 527 | 0 |       case ARM_OP_MEM: | 
| 528 |  |         // registers appeared in memory references always being read | 
| 529 | 0 |         if ((op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) { | 
| 530 | 0 |           regs_read[read_count] = (uint16_t)op->mem.base; | 
| 531 | 0 |           read_count++; | 
| 532 | 0 |         } | 
| 533 | 0 |         if ((op->mem.index != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) { | 
| 534 | 0 |           regs_read[read_count] = (uint16_t)op->mem.index; | 
| 535 | 0 |           read_count++; | 
| 536 | 0 |         } | 
| 537 | 0 |         if ((arm->writeback) && (op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) { | 
| 538 | 0 |           regs_write[write_count] = (uint16_t)op->mem.base; | 
| 539 | 0 |           write_count++; | 
| 540 | 0 |         } | 
| 541 | 0 |       default: | 
| 542 | 0 |         break; | 
| 543 | 0 |     } | 
| 544 | 0 |   } | 
| 545 |  |  | 
| 546 | 0 |   *regs_read_count = read_count; | 
| 547 | 0 |   *regs_write_count = write_count; | 
| 548 | 0 | } | 
| 549 |  | #endif | 
| 550 |  |  | 
| 551 |  | #endif |