/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 | 254k | { |
247 | 254k | #ifndef CAPSTONE_DIET |
248 | 254k | if (reg >= ARR_SIZE(reg_name_maps)) |
249 | 0 | return NULL; |
250 | | |
251 | 254k | return reg_name_maps[reg].name; |
252 | | #else |
253 | | return NULL; |
254 | | #endif |
255 | 254k | } |
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 | 932k | { |
284 | | // binary searching since the IDs are sorted in order |
285 | 932k | unsigned int left, right, m; |
286 | 932k | unsigned int max = ARR_SIZE(insns); |
287 | | |
288 | 932k | right = max - 1; |
289 | | |
290 | 932k | if (id < insns[0].id || id > insns[right].id) |
291 | | // not found |
292 | 0 | return -1; |
293 | | |
294 | 932k | left = 0; |
295 | | |
296 | 9.75M | while(left <= right) { |
297 | 9.75M | m = (left + right) / 2; |
298 | 9.75M | if (id == insns[m].id) { |
299 | 932k | return m; |
300 | 932k | } |
301 | | |
302 | 8.82M | if (id < insns[m].id) |
303 | 2.74M | right = m - 1; |
304 | 6.08M | else |
305 | 6.08M | left = m + 1; |
306 | 8.82M | } |
307 | | |
308 | | // not found |
309 | | // printf("NOT FOUNDDDDDDDDDDDDDDD id = %u\n", id); |
310 | 0 | return -1; |
311 | 932k | } |
312 | | |
313 | | void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) |
314 | 932k | { |
315 | 932k | unsigned int i = find_insn(id); |
316 | 932k | if (i != -1) { |
317 | 932k | insn->id = insns[i].mapid; |
318 | | |
319 | | // printf("id = %u, mapid = %u\n", id, insn->id); |
320 | | |
321 | 932k | if (h->detail) { |
322 | 932k | #ifndef CAPSTONE_DIET |
323 | 932k | cs_struct handle; |
324 | 932k | handle.detail = h->detail; |
325 | | |
326 | 932k | memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use)); |
327 | 932k | insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use); |
328 | | |
329 | 932k | memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod)); |
330 | 932k | insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod); |
331 | | |
332 | 932k | memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups)); |
333 | 932k | insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups); |
334 | | |
335 | 932k | insn->detail->arm.update_flags = cs_reg_write((csh)&handle, insn, ARM_REG_CPSR); |
336 | | |
337 | 932k | if (insns[i].branch || insns[i].indirect_branch) { |
338 | | // this insn also belongs to JUMP group. add JUMP group |
339 | 57.7k | insn->detail->groups[insn->detail->groups_count] = ARM_GRP_JUMP; |
340 | 57.7k | insn->detail->groups_count++; |
341 | 57.7k | } |
342 | 932k | #endif |
343 | 932k | } |
344 | 932k | } |
345 | 932k | } |
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 | 932k | { |
356 | 932k | #ifndef CAPSTONE_DIET |
357 | 932k | if (id >= ARM_INS_ENDING) |
358 | 0 | return NULL; |
359 | | |
360 | 932k | return insn_name_maps[id]; |
361 | | #else |
362 | | return NULL; |
363 | | #endif |
364 | 932k | } |
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 | 3.56M | { |
414 | 3.56M | #ifndef CAPSTONE_DIET |
415 | 3.56M | return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); |
416 | | #else |
417 | | return NULL; |
418 | | #endif |
419 | 3.56M | } |
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 | 701k | { |
448 | 701k | int i; |
449 | | |
450 | 9.42M | for (i = 0; insn_rel[i]; i++) { |
451 | 8.78M | if (id == insn_rel[i]) { |
452 | 56.3k | return true; |
453 | 56.3k | } |
454 | 8.78M | } |
455 | | |
456 | | // not found |
457 | 644k | return false; |
458 | 701k | } |
459 | | |
460 | 44.9k | bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int id) { |
461 | 44.9k | int i; |
462 | | |
463 | 89.6k | for (i = 0; insn_blx_rel_to_arm[i]; i++) |
464 | 44.9k | if (id == insn_blx_rel_to_arm[i]) |
465 | 310 | return true; |
466 | | |
467 | | // not found |
468 | 44.6k | return false; |
469 | | |
470 | 44.9k | } |
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 | 1.58M | { |
490 | 1.58M | int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache); |
491 | 1.58M | if (i != 0) { |
492 | 1.58M | return insn_ops[i].access; |
493 | 1.58M | } |
494 | | |
495 | 0 | return NULL; |
496 | 1.58M | } |
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 |