/src/capstonenext/arch/Mips/MipsMapping.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine */ |
2 | | /* By Giovanni Dante Grazioli, deroad <wargio@libero.it>, 2024 */ |
3 | | |
4 | | #ifdef CAPSTONE_HAS_MIPS |
5 | | |
6 | | #include <stdio.h> |
7 | | #include <string.h> |
8 | | |
9 | | #include <capstone/capstone.h> |
10 | | #include <capstone/mips.h> |
11 | | |
12 | | #include "../../Mapping.h" |
13 | | #include "../../MCDisassembler.h" |
14 | | #include "../../cs_priv.h" |
15 | | #include "../../cs_simple_types.h" |
16 | | |
17 | | #include "MipsMapping.h" |
18 | | #include "MipsLinkage.h" |
19 | | #include "MipsDisassembler.h" |
20 | | |
21 | | #define GET_REGINFO_ENUM |
22 | | #define GET_REGINFO_MC_DESC |
23 | | #include "MipsGenRegisterInfo.inc" |
24 | | |
25 | | #define GET_INSTRINFO_ENUM |
26 | | #include "MipsGenInstrInfo.inc" |
27 | | |
28 | | void Mips_init_mri(MCRegisterInfo *MRI) |
29 | 2.88k | { |
30 | 2.88k | MCRegisterInfo_InitMCRegisterInfo(MRI, MipsRegDesc, sizeof(MipsRegDesc), |
31 | 2.88k | 0, 0, MipsMCRegisterClasses, |
32 | 2.88k | ARR_SIZE(MipsMCRegisterClasses), 0, 0, |
33 | 2.88k | MipsRegDiffLists, 0, |
34 | 2.88k | MipsSubRegIdxLists, |
35 | 2.88k | ARR_SIZE(MipsSubRegIdxLists), 0); |
36 | 2.88k | } |
37 | | |
38 | | const char *Mips_reg_name(csh handle, unsigned int reg) |
39 | 14.7k | { |
40 | 14.7k | int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax; |
41 | 14.7k | return Mips_LLVM_getRegisterName(reg, |
42 | 14.7k | syntax_opt & CS_OPT_SYNTAX_NOREGNAME); |
43 | 14.7k | } |
44 | | |
45 | | void Mips_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) |
46 | 67.9k | { |
47 | | // Not used by Mips. Information is set after disassembly. |
48 | 67.9k | } |
49 | | |
50 | | static const char *const insn_name_maps[] = { |
51 | | #include "MipsGenCSMappingInsnName.inc" |
52 | | }; |
53 | | |
54 | | const char *Mips_insn_name(csh handle, unsigned int id) |
55 | 67.9k | { |
56 | 67.9k | #ifndef CAPSTONE_DIET |
57 | 67.9k | if (id < ARR_SIZE(insn_name_maps)) |
58 | 67.9k | return insn_name_maps[id]; |
59 | | // not found |
60 | 0 | return NULL; |
61 | | #else |
62 | | return NULL; |
63 | | #endif |
64 | 67.9k | } |
65 | | |
66 | | #ifndef CAPSTONE_DIET |
67 | | static const name_map group_name_maps[] = { |
68 | | { MIPS_GRP_INVALID, NULL }, |
69 | | |
70 | | { MIPS_GRP_JUMP, "jump" }, |
71 | | { MIPS_GRP_CALL, "call" }, |
72 | | { MIPS_GRP_RET, "return" }, |
73 | | { MIPS_GRP_INT, "int" }, |
74 | | { MIPS_GRP_IRET, "iret" }, |
75 | | { MIPS_GRP_PRIVILEGE, "privilege" }, |
76 | | { MIPS_GRP_BRANCH_RELATIVE, "branch_relative" }, |
77 | | |
78 | | // architecture-specific groups |
79 | | #include "MipsGenCSFeatureName.inc" |
80 | | }; |
81 | | #endif |
82 | | |
83 | | const char *Mips_group_name(csh handle, unsigned int id) |
84 | 401k | { |
85 | 401k | #ifndef CAPSTONE_DIET |
86 | 401k | return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); |
87 | | #else |
88 | | return NULL; |
89 | | #endif |
90 | 401k | } |
91 | | |
92 | | const insn_map mips_insns[] = { |
93 | | #include "MipsGenCSMappingInsn.inc" |
94 | | }; |
95 | | |
96 | | void Mips_reg_access(const cs_insn *insn, cs_regs regs_read, |
97 | | uint8_t *regs_read_count, cs_regs regs_write, |
98 | | uint8_t *regs_write_count) |
99 | 0 | { |
100 | 0 | uint8_t i; |
101 | 0 | uint8_t read_count, write_count; |
102 | 0 | cs_mips *mips = &(insn->detail->mips); |
103 | |
|
104 | 0 | read_count = insn->detail->regs_read_count; |
105 | 0 | write_count = insn->detail->regs_write_count; |
106 | | |
107 | | // implicit registers |
108 | 0 | memcpy(regs_read, insn->detail->regs_read, |
109 | 0 | read_count * sizeof(insn->detail->regs_read[0])); |
110 | 0 | memcpy(regs_write, insn->detail->regs_write, |
111 | 0 | write_count * sizeof(insn->detail->regs_write[0])); |
112 | | |
113 | | // explicit registers |
114 | 0 | for (i = 0; i < mips->op_count; i++) { |
115 | 0 | cs_mips_op *op = &(mips->operands[i]); |
116 | 0 | switch ((int)op->type) { |
117 | 0 | case MIPS_OP_REG: |
118 | 0 | if ((op->access & CS_AC_READ) && |
119 | 0 | !arr_exist(regs_read, read_count, op->reg)) { |
120 | 0 | regs_read[read_count] = (uint16_t)op->reg; |
121 | 0 | read_count++; |
122 | 0 | } |
123 | 0 | if ((op->access & CS_AC_WRITE) && |
124 | 0 | !arr_exist(regs_write, write_count, op->reg)) { |
125 | 0 | regs_write[write_count] = (uint16_t)op->reg; |
126 | 0 | write_count++; |
127 | 0 | } |
128 | 0 | break; |
129 | 0 | case MIPS_OP_MEM: |
130 | | // registers appeared in memory references always being read |
131 | 0 | if ((op->mem.base != MIPS_REG_INVALID) && |
132 | 0 | !arr_exist(regs_read, read_count, op->mem.base)) { |
133 | 0 | regs_read[read_count] = (uint16_t)op->mem.base; |
134 | 0 | read_count++; |
135 | 0 | } |
136 | 0 | if ((insn->detail->writeback) && |
137 | 0 | (op->mem.base != MIPS_REG_INVALID) && |
138 | 0 | !arr_exist(regs_write, write_count, op->mem.base)) { |
139 | 0 | regs_write[write_count] = |
140 | 0 | (uint16_t)op->mem.base; |
141 | 0 | write_count++; |
142 | 0 | } |
143 | 0 | default: |
144 | 0 | break; |
145 | 0 | } |
146 | 0 | } |
147 | | |
148 | 0 | *regs_read_count = read_count; |
149 | 0 | *regs_write_count = write_count; |
150 | 0 | } |
151 | | |
152 | | void Mips_set_instr_map_data(MCInst *MI) |
153 | 67.9k | { |
154 | | // Fixes for missing groups. |
155 | 67.9k | if (MCInst_getOpcode(MI) == Mips_JR) { |
156 | 88 | unsigned Reg = MCInst_getOpVal(MI, 0); |
157 | 88 | switch (Reg) { |
158 | 0 | case MIPS_REG_RA: |
159 | 0 | case MIPS_REG_RA_64: |
160 | 0 | add_group(MI, MIPS_GRP_RET); |
161 | 0 | break; |
162 | 88 | } |
163 | 88 | } |
164 | | |
165 | 67.9k | map_cs_id(MI, mips_insns, ARR_SIZE(mips_insns)); |
166 | 67.9k | map_implicit_reads(MI, mips_insns); |
167 | 67.9k | map_implicit_writes(MI, mips_insns); |
168 | 67.9k | map_groups(MI, mips_insns); |
169 | 67.9k | } |
170 | | |
171 | | bool Mips_getInstruction(csh handle, const uint8_t *code, size_t code_len, |
172 | | MCInst *instr, uint16_t *size, uint64_t address, |
173 | | void *info) |
174 | 69.8k | { |
175 | 69.8k | uint64_t size64; |
176 | 69.8k | Mips_init_cs_detail(instr); |
177 | 69.8k | instr->MRI = (MCRegisterInfo *)info; |
178 | 69.8k | map_set_fill_detail_ops(instr, true); |
179 | | |
180 | 69.8k | bool result = Mips_LLVM_getInstruction(instr, &size64, code, code_len, |
181 | 69.8k | address, |
182 | 69.8k | info) != MCDisassembler_Fail; |
183 | 69.8k | if (result) { |
184 | 67.9k | Mips_set_instr_map_data(instr); |
185 | 67.9k | } |
186 | 69.8k | *size = size64; |
187 | 69.8k | return result; |
188 | 69.8k | } |
189 | | |
190 | | void Mips_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) |
191 | 67.9k | { |
192 | 67.9k | MCRegisterInfo *MRI = (MCRegisterInfo *)info; |
193 | 67.9k | MI->MRI = MRI; |
194 | | |
195 | 67.9k | Mips_LLVM_printInst(MI, MI->address, O); |
196 | 67.9k | } |
197 | | |
198 | | static void Mips_setup_op(cs_mips_op *op) |
199 | 698k | { |
200 | 698k | memset(op, 0, sizeof(cs_mips_op)); |
201 | 698k | op->type = MIPS_OP_INVALID; |
202 | 698k | } |
203 | | |
204 | | void Mips_init_cs_detail(MCInst *MI) |
205 | 69.8k | { |
206 | 69.8k | if (detail_is_set(MI)) { |
207 | 69.8k | unsigned int i; |
208 | | |
209 | 69.8k | memset(get_detail(MI), 0, |
210 | 69.8k | offsetof(cs_detail, mips) + sizeof(cs_mips)); |
211 | | |
212 | 767k | for (i = 0; i < ARR_SIZE(Mips_get_detail(MI)->operands); i++) |
213 | 698k | Mips_setup_op(&Mips_get_detail(MI)->operands[i]); |
214 | 69.8k | } |
215 | 69.8k | } |
216 | | |
217 | | static const map_insn_ops insn_operands[] = { |
218 | | #include "MipsGenCSMappingInsnOp.inc" |
219 | | }; |
220 | | |
221 | | static void Mips_set_detail_op_mem_reg(MCInst *MI, unsigned OpNum, mips_reg Reg) |
222 | 16.1k | { |
223 | 16.1k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; |
224 | 16.1k | Mips_get_detail_op(MI, 0)->mem.base = Reg; |
225 | 16.1k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
226 | 16.1k | } |
227 | | |
228 | | static void Mips_set_detail_op_mem_disp(MCInst *MI, unsigned OpNum, int64_t Imm) |
229 | 16.2k | { |
230 | 16.2k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; |
231 | 16.2k | Mips_get_detail_op(MI, 0)->mem.disp = Imm; |
232 | 16.2k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
233 | 16.2k | } |
234 | | |
235 | | static void Mips_set_detail_op_imm(MCInst *MI, unsigned OpNum, int64_t Imm) |
236 | 24.4k | { |
237 | 24.4k | if (!detail_is_set(MI)) |
238 | 0 | return; |
239 | | |
240 | 24.4k | if (doing_mem(MI)) { |
241 | 16.2k | Mips_set_detail_op_mem_disp(MI, OpNum, Imm); |
242 | 16.2k | return; |
243 | 16.2k | } |
244 | | |
245 | 8.28k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_IMM; |
246 | 8.28k | Mips_get_detail_op(MI, 0)->imm = Imm; |
247 | 8.28k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
248 | 8.28k | Mips_inc_op_count(MI); |
249 | 8.28k | } |
250 | | |
251 | | static void Mips_set_detail_op_uimm(MCInst *MI, unsigned OpNum, uint64_t Imm) |
252 | 27.6k | { |
253 | 27.6k | if (!detail_is_set(MI)) |
254 | 0 | return; |
255 | | |
256 | 27.6k | if (doing_mem(MI)) { |
257 | 0 | Mips_set_detail_op_mem_disp(MI, OpNum, Imm); |
258 | 0 | return; |
259 | 0 | } |
260 | | |
261 | 27.6k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_IMM; |
262 | 27.6k | Mips_get_detail_op(MI, 0)->uimm = Imm; |
263 | 27.6k | Mips_get_detail_op(MI, 0)->is_unsigned = true; |
264 | 27.6k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
265 | 27.6k | Mips_inc_op_count(MI); |
266 | 27.6k | } |
267 | | |
268 | | static void Mips_set_detail_op_reg(MCInst *MI, unsigned OpNum, mips_reg Reg, |
269 | | bool is_reglist) |
270 | 117k | { |
271 | 117k | if (!detail_is_set(MI)) |
272 | 0 | return; |
273 | | |
274 | 117k | if (doing_mem(MI)) { |
275 | 16.1k | Mips_set_detail_op_mem_reg(MI, OpNum, Reg); |
276 | 16.1k | return; |
277 | 16.1k | } |
278 | | |
279 | 100k | CS_ASSERT((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG); |
280 | 100k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_REG; |
281 | 100k | Mips_get_detail_op(MI, 0)->reg = Reg; |
282 | 100k | Mips_get_detail_op(MI, 0)->is_reglist = is_reglist; |
283 | 100k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
284 | 100k | Mips_inc_op_count(MI); |
285 | 100k | } |
286 | | |
287 | | static void Mips_set_detail_op_operand(MCInst *MI, unsigned OpNum) |
288 | 140k | { |
289 | 140k | cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM; |
290 | 140k | int64_t value = MCInst_getOpVal(MI, OpNum); |
291 | 140k | if (op_type == CS_OP_IMM) { |
292 | 24.4k | Mips_set_detail_op_imm(MI, OpNum, value); |
293 | 115k | } else if (op_type == CS_OP_REG) { |
294 | 115k | Mips_set_detail_op_reg(MI, OpNum, value, false); |
295 | 115k | } else |
296 | 460 | printf("Operand type %d not handled!\n", op_type); |
297 | 140k | } |
298 | | |
299 | | static void Mips_set_detail_op_branch(MCInst *MI, unsigned OpNum) |
300 | 14.0k | { |
301 | 14.0k | cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM; |
302 | 14.0k | if (op_type == CS_OP_IMM) { |
303 | 13.8k | uint64_t Target = (uint64_t)MCInst_getOpVal(MI, OpNum); |
304 | 13.8k | Mips_set_detail_op_uimm(MI, OpNum, Target + MI->address); |
305 | 13.8k | } else if (op_type == CS_OP_REG) { |
306 | 267 | Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum), |
307 | 267 | false); |
308 | 267 | } else |
309 | 0 | printf("Operand type %d not handled!\n", op_type); |
310 | 14.0k | } |
311 | | |
312 | | static void Mips_set_detail_op_unsigned(MCInst *MI, unsigned OpNum) |
313 | 0 | { |
314 | 0 | Mips_set_detail_op_uimm(MI, OpNum, MCInst_getOpVal(MI, OpNum)); |
315 | 0 | } |
316 | | |
317 | | static void Mips_set_detail_op_unsigned_offset(MCInst *MI, unsigned OpNum, |
318 | | unsigned Bits, uint64_t Offset) |
319 | 13.7k | { |
320 | 13.7k | uint64_t Imm = MCInst_getOpVal(MI, OpNum); |
321 | 13.7k | Imm -= Offset; |
322 | 13.7k | Imm &= (((uint64_t)1) << Bits) - 1; |
323 | 13.7k | Imm += Offset; |
324 | 13.7k | Mips_set_detail_op_uimm(MI, OpNum, Imm); |
325 | 13.7k | } |
326 | | |
327 | | static void Mips_set_detail_op_mem_nanomips(MCInst *MI, unsigned OpNum) |
328 | 0 | { |
329 | 0 | CS_ASSERT(doing_mem(MI)) |
330 | |
|
331 | 0 | MCOperand *Op = MCInst_getOperand(MI, OpNum); |
332 | 0 | Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; |
333 | | // Base is a register, but nanoMips uses the Imm value as register. |
334 | 0 | Mips_get_detail_op(MI, 0)->mem.base = MCOperand_getImm(Op); |
335 | 0 | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
336 | 0 | } |
337 | | |
338 | | static void Mips_set_detail_op_reglist(MCInst *MI, unsigned OpNum, |
339 | | bool isNanoMips) |
340 | 464 | { |
341 | 464 | if (isNanoMips) { |
342 | 0 | for (unsigned i = OpNum; i < MCInst_getNumOperands(MI); i++) { |
343 | 0 | Mips_set_detail_op_reg(MI, i, MCInst_getOpVal(MI, i), |
344 | 0 | true); |
345 | 0 | } |
346 | 0 | return; |
347 | 0 | } |
348 | | // -2 because register List is always first operand of instruction |
349 | | // and it is always followed by memory operand (base + offset). |
350 | 1.91k | for (unsigned i = OpNum, e = MCInst_getNumOperands(MI) - 2; i != e; |
351 | 1.45k | ++i) { |
352 | 1.45k | Mips_set_detail_op_reg(MI, i, MCInst_getOpVal(MI, i), true); |
353 | 1.45k | } |
354 | 464 | } |
355 | | |
356 | | static void Mips_set_detail_op_unsigned_address(MCInst *MI, unsigned OpNum) |
357 | 0 | { |
358 | 0 | uint64_t Target = MI->address + (uint64_t)MCInst_getOpVal(MI, OpNum); |
359 | 0 | Mips_set_detail_op_imm(MI, OpNum, Target); |
360 | 0 | } |
361 | | |
362 | | void Mips_add_cs_detail(MCInst *MI, mips_op_group op_group, va_list args) |
363 | 168k | { |
364 | 168k | if (!detail_is_set(MI) || !map_fill_detail_ops(MI)) |
365 | 0 | return; |
366 | | |
367 | 168k | unsigned OpNum = va_arg(args, unsigned); |
368 | | |
369 | 168k | switch (op_group) { |
370 | 0 | default: |
371 | 0 | printf("Operand group %d not handled!\n", op_group); |
372 | 0 | return; |
373 | 0 | case Mips_OP_GROUP_MemOperand: |
374 | | // this is only used by nanoMips. |
375 | 0 | return Mips_set_detail_op_mem_nanomips(MI, OpNum); |
376 | 12.1k | case Mips_OP_GROUP_BranchOperand: |
377 | | /* fall-thru */ |
378 | 14.0k | case Mips_OP_GROUP_JumpOperand: |
379 | 14.0k | return Mips_set_detail_op_branch(MI, OpNum); |
380 | 140k | case Mips_OP_GROUP_Operand: |
381 | 140k | return Mips_set_detail_op_operand(MI, OpNum); |
382 | 244 | case Mips_OP_GROUP_UImm_1_0: |
383 | 244 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 1, 0); |
384 | 218 | case Mips_OP_GROUP_UImm_2_0: |
385 | 218 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 2, 0); |
386 | 1.11k | case Mips_OP_GROUP_UImm_3_0: |
387 | 1.11k | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 3, 0); |
388 | 0 | case Mips_OP_GROUP_UImm_32_0: |
389 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 32, 0); |
390 | 4.02k | case Mips_OP_GROUP_UImm_16_0: |
391 | 4.02k | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 16, 0); |
392 | 377 | case Mips_OP_GROUP_UImm_8_0: |
393 | 377 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 8, 0); |
394 | 3.61k | case Mips_OP_GROUP_UImm_5_0: |
395 | 3.61k | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 0); |
396 | 278 | case Mips_OP_GROUP_UImm_6_0: |
397 | 278 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 6, 0); |
398 | 850 | case Mips_OP_GROUP_UImm_4_0: |
399 | 850 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 4, 0); |
400 | 0 | case Mips_OP_GROUP_UImm_7_0: |
401 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 7, 0); |
402 | 1.80k | case Mips_OP_GROUP_UImm_10_0: |
403 | 1.80k | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 10, 0); |
404 | 0 | case Mips_OP_GROUP_UImm_6_1: |
405 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 6, 1); |
406 | 321 | case Mips_OP_GROUP_UImm_5_1: |
407 | 321 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 1); |
408 | 0 | case Mips_OP_GROUP_UImm_5_33: |
409 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 33); |
410 | 0 | case Mips_OP_GROUP_UImm_5_32: |
411 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 32); |
412 | 0 | case Mips_OP_GROUP_UImm_6_2: |
413 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 6, 2); |
414 | 535 | case Mips_OP_GROUP_UImm_2_1: |
415 | 535 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 2, 1); |
416 | 83 | case Mips_OP_GROUP_UImm_0_0: |
417 | 83 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 0, 0); |
418 | 0 | case Mips_OP_GROUP_UImm_26_0: |
419 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 26, 0); |
420 | 0 | case Mips_OP_GROUP_UImm_12_0: |
421 | 0 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 12, 0); |
422 | 317 | case Mips_OP_GROUP_UImm_20_0: |
423 | 317 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 20, 0); |
424 | 464 | case Mips_OP_GROUP_RegisterList: |
425 | 464 | return Mips_set_detail_op_reglist(MI, OpNum, false); |
426 | 0 | case Mips_OP_GROUP_NanoMipsRegisterList: |
427 | 0 | return Mips_set_detail_op_reglist(MI, OpNum, true); |
428 | 0 | case Mips_OP_GROUP_PCRel: |
429 | | /* fall-thru */ |
430 | 0 | case Mips_OP_GROUP_Hi20PCRel: |
431 | 0 | return Mips_set_detail_op_unsigned_address(MI, OpNum); |
432 | 0 | case Mips_OP_GROUP_Hi20: |
433 | 0 | return Mips_set_detail_op_unsigned(MI, OpNum); |
434 | 168k | } |
435 | 168k | } |
436 | | |
437 | | void Mips_set_mem_access(MCInst *MI, bool status) |
438 | 32.8k | { |
439 | 32.8k | if (!detail_is_set(MI)) |
440 | 0 | return; |
441 | 32.8k | set_doing_mem(MI, status); |
442 | 32.8k | if (status) { |
443 | 16.4k | if (Mips_get_detail(MI)->op_count > 0 && |
444 | 16.4k | Mips_get_detail_op(MI, -1)->type == MIPS_OP_MEM && |
445 | 16.4k | Mips_get_detail_op(MI, -1)->mem.disp == 0) { |
446 | | // Previous memory operand not done yet. Select it. |
447 | 0 | Mips_dec_op_count(MI); |
448 | 0 | return; |
449 | 0 | } |
450 | | |
451 | | // Init a new one. |
452 | 16.4k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; |
453 | 16.4k | Mips_get_detail_op(MI, 0)->mem.base = MIPS_REG_INVALID; |
454 | 16.4k | Mips_get_detail_op(MI, 0)->mem.disp = 0; |
455 | | |
456 | 16.4k | #ifndef CAPSTONE_DIET |
457 | 16.4k | uint8_t access = |
458 | 16.4k | map_get_op_access(MI, Mips_get_detail(MI)->op_count); |
459 | 16.4k | Mips_get_detail_op(MI, 0)->access = access; |
460 | 16.4k | #endif |
461 | 16.4k | } else { |
462 | | // done, select the next operand slot |
463 | 16.4k | Mips_inc_op_count(MI); |
464 | 16.4k | } |
465 | 32.8k | } |
466 | | |
467 | | #endif |