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