/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 | 3.48k | { |
30 | 3.48k | MCRegisterInfo_InitMCRegisterInfo(MRI, MipsRegDesc, sizeof(MipsRegDesc), |
31 | 3.48k | 0, 0, MipsMCRegisterClasses, |
32 | 3.48k | ARR_SIZE(MipsMCRegisterClasses), 0, 0, |
33 | 3.48k | MipsRegDiffLists, 0, |
34 | 3.48k | MipsSubRegIdxLists, |
35 | 3.48k | ARR_SIZE(MipsSubRegIdxLists), 0); |
36 | 3.48k | } |
37 | | |
38 | | const char *Mips_reg_name(csh handle, unsigned int reg) |
39 | 23.2k | { |
40 | 23.2k | int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax; |
41 | 23.2k | return Mips_LLVM_getRegisterName(reg, |
42 | 23.2k | syntax_opt & CS_OPT_SYNTAX_NOREGNAME); |
43 | 23.2k | } |
44 | | |
45 | | void Mips_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) |
46 | 93.5k | { |
47 | | // Not used by Mips. Information is set after disassembly. |
48 | 93.5k | } |
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 | 93.5k | { |
67 | 93.5k | #ifndef CAPSTONE_DIET |
68 | 93.5k | 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 | 93.5k | if (id >= MIPS_INS_ENDING) |
75 | 0 | return NULL; |
76 | | |
77 | 93.5k | if (id < ARR_SIZE(insn_name_maps)) |
78 | 93.5k | return insn_name_maps[id]; |
79 | | // not found |
80 | 0 | return NULL; |
81 | | #else |
82 | | return NULL; |
83 | | #endif |
84 | 93.5k | } |
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 | 463k | { |
105 | 463k | #ifndef CAPSTONE_DIET |
106 | 463k | return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); |
107 | | #else |
108 | | return NULL; |
109 | | #endif |
110 | 463k | } |
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 | 93.5k | { |
174 | | // Fixes for missing groups. |
175 | 93.5k | if (MCInst_getOpcode(MI) == Mips_JR) { |
176 | 47 | unsigned Reg = MCInst_getOpVal(MI, 0); |
177 | 47 | switch (Reg) { |
178 | 23 | case MIPS_REG_RA: |
179 | 23 | case MIPS_REG_RA_64: |
180 | 23 | add_group(MI, MIPS_GRP_RET); |
181 | 23 | break; |
182 | 47 | } |
183 | 47 | } |
184 | | |
185 | 93.5k | map_cs_id(MI, mips_insns, ARR_SIZE(mips_insns)); |
186 | 93.5k | map_implicit_reads(MI, mips_insns); |
187 | 93.5k | map_implicit_writes(MI, mips_insns); |
188 | 93.5k | map_groups(MI, mips_insns); |
189 | 93.5k | } |
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 | 95.3k | { |
195 | 95.3k | uint64_t size64; |
196 | 95.3k | Mips_init_cs_detail(instr); |
197 | 95.3k | instr->MRI = (MCRegisterInfo *)info; |
198 | 95.3k | map_set_fill_detail_ops(instr, true); |
199 | | |
200 | 95.3k | DecodeStatus Result = Mips_LLVM_getInstruction(instr, &size64, code, code_len, |
201 | 95.3k | address, |
202 | 95.3k | info); |
203 | 95.3k | *size = size64; |
204 | 95.3k | if (Result != MCDisassembler_Fail) { |
205 | 93.5k | Mips_set_instr_map_data(instr); |
206 | 93.5k | } |
207 | 95.3k | if (Result == MCDisassembler_SoftFail) { |
208 | 0 | MCInst_setSoftFail(instr); |
209 | 0 | } |
210 | 95.3k | return Result != MCDisassembler_Fail; |
211 | 95.3k | } |
212 | | |
213 | | void Mips_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) |
214 | 93.5k | { |
215 | 93.5k | MCRegisterInfo *MRI = (MCRegisterInfo *)info; |
216 | 93.5k | MI->MRI = MRI; |
217 | | |
218 | 93.5k | Mips_LLVM_printInst(MI, MI->address, O); |
219 | 93.5k | #ifndef CAPSTONE_DIET |
220 | 93.5k | map_set_alias_id(MI, O, insn_alias_mnem_map, |
221 | 93.5k | ARR_SIZE(insn_alias_mnem_map)); |
222 | 93.5k | #endif |
223 | 93.5k | } |
224 | | |
225 | | static void Mips_setup_op(cs_mips_op *op) |
226 | 953k | { |
227 | 953k | memset(op, 0, sizeof(cs_mips_op)); |
228 | 953k | op->type = MIPS_OP_INVALID; |
229 | 953k | } |
230 | | |
231 | | void Mips_init_cs_detail(MCInst *MI) |
232 | 95.3k | { |
233 | 95.3k | if (detail_is_set(MI)) { |
234 | 95.3k | unsigned int i; |
235 | | |
236 | 95.3k | memset(get_detail(MI), 0, |
237 | 95.3k | offsetof(cs_detail, mips) + sizeof(cs_mips)); |
238 | | |
239 | 1.04M | for (i = 0; i < ARR_SIZE(Mips_get_detail(MI)->operands); i++) |
240 | 953k | Mips_setup_op(&Mips_get_detail(MI)->operands[i]); |
241 | 95.3k | } |
242 | 95.3k | } |
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 | 27.5k | { |
250 | 27.5k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; |
251 | 27.5k | Mips_get_detail_op(MI, 0)->mem.base = Reg; |
252 | 27.5k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
253 | 27.5k | } |
254 | | |
255 | | static void Mips_set_detail_op_mem_disp(MCInst *MI, unsigned OpNum, int64_t Imm) |
256 | 27.8k | { |
257 | 27.8k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; |
258 | 27.8k | Mips_get_detail_op(MI, 0)->mem.disp = Imm; |
259 | 27.8k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
260 | 27.8k | } |
261 | | |
262 | | static void Mips_set_detail_op_imm(MCInst *MI, unsigned OpNum, int64_t Imm) |
263 | 41.2k | { |
264 | 41.2k | if (!detail_is_set(MI)) |
265 | 0 | return; |
266 | | |
267 | 41.2k | if (doing_mem(MI)) { |
268 | 27.8k | Mips_set_detail_op_mem_disp(MI, OpNum, Imm); |
269 | 27.8k | return; |
270 | 27.8k | } |
271 | | |
272 | 13.4k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_IMM; |
273 | 13.4k | Mips_get_detail_op(MI, 0)->imm = Imm; |
274 | 13.4k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
275 | 13.4k | Mips_inc_op_count(MI); |
276 | 13.4k | } |
277 | | |
278 | | static void Mips_set_detail_op_uimm(MCInst *MI, unsigned OpNum, uint64_t Imm) |
279 | 32.5k | { |
280 | 32.5k | if (!detail_is_set(MI)) |
281 | 0 | return; |
282 | | |
283 | 32.5k | if (doing_mem(MI)) { |
284 | 0 | Mips_set_detail_op_mem_disp(MI, OpNum, Imm); |
285 | 0 | return; |
286 | 0 | } |
287 | | |
288 | 32.5k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_IMM; |
289 | 32.5k | Mips_get_detail_op(MI, 0)->uimm = Imm; |
290 | 32.5k | Mips_get_detail_op(MI, 0)->is_unsigned = true; |
291 | 32.5k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
292 | 32.5k | Mips_inc_op_count(MI); |
293 | 32.5k | } |
294 | | |
295 | | static void Mips_set_detail_op_reg(MCInst *MI, unsigned OpNum, mips_reg Reg, |
296 | | bool is_reglist) |
297 | 170k | { |
298 | 170k | if (!detail_is_set(MI)) |
299 | 0 | return; |
300 | | |
301 | 170k | if (doing_mem(MI)) { |
302 | 27.5k | Mips_set_detail_op_mem_reg(MI, OpNum, Reg); |
303 | 27.5k | return; |
304 | 27.5k | } |
305 | | |
306 | 142k | CS_ASSERT((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG); |
307 | 142k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_REG; |
308 | 142k | Mips_get_detail_op(MI, 0)->reg = Reg; |
309 | 142k | Mips_get_detail_op(MI, 0)->is_reglist = is_reglist; |
310 | 142k | Mips_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum); |
311 | 142k | Mips_inc_op_count(MI); |
312 | 142k | } |
313 | | |
314 | | static void Mips_set_detail_op_operand(MCInst *MI, unsigned OpNum) |
315 | 208k | { |
316 | 208k | cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM; |
317 | 208k | int64_t value = MCInst_getOpVal(MI, OpNum); |
318 | 208k | if (op_type == CS_OP_IMM) { |
319 | 41.2k | Mips_set_detail_op_imm(MI, OpNum, value); |
320 | 167k | } else if (op_type == CS_OP_REG) { |
321 | 165k | Mips_set_detail_op_reg(MI, OpNum, value, false); |
322 | 165k | } else |
323 | 1.59k | printf("Operand type %d not handled!\n", op_type); |
324 | 208k | } |
325 | | |
326 | | static void Mips_set_detail_op_jump(MCInst *MI, unsigned OpNum) |
327 | 2.61k | { |
328 | 2.61k | cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM; |
329 | 2.61k | if (op_type == CS_OP_IMM) { |
330 | 2.61k | uint64_t Base = MI->address & ~0x0fffffffull; |
331 | 2.61k | uint64_t Target = Base | (uint64_t)MCInst_getOpVal(MI, OpNum); |
332 | 2.61k | Mips_set_detail_op_uimm(MI, OpNum, Target); |
333 | 2.61k | } 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 | 2.61k | } |
339 | | |
340 | | static void Mips_set_detail_op_branch(MCInst *MI, unsigned OpNum) |
341 | 18.1k | { |
342 | 18.1k | cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM; |
343 | 18.1k | if (op_type == CS_OP_IMM) { |
344 | 17.9k | uint64_t Target = MI->address + MCInst_getOpVal(MI, OpNum); |
345 | 17.9k | Mips_set_detail_op_uimm(MI, OpNum, Target); |
346 | 17.9k | } else if (op_type == CS_OP_REG) { |
347 | 187 | Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum), |
348 | 187 | false); |
349 | 187 | } else |
350 | 0 | printf("Operand type %d not handled!\n", op_type); |
351 | 18.1k | } |
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 | 12.0k | { |
361 | 12.0k | uint64_t Imm = MCInst_getOpVal(MI, OpNum); |
362 | 12.0k | Imm -= Offset; |
363 | 12.0k | Imm &= (((uint64_t)1) << Bits) - 1; |
364 | 12.0k | Imm += Offset; |
365 | 12.0k | Mips_set_detail_op_uimm(MI, OpNum, Imm); |
366 | 12.0k | } |
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 | 1.01k | { |
382 | 1.01k | 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 | 5.08k | for (unsigned i = OpNum, e = MCInst_getNumOperands(MI) - 2; i != e; |
392 | 4.06k | ++i) { |
393 | 4.06k | Mips_set_detail_op_reg(MI, i, MCInst_getOpVal(MI, i), true); |
394 | 4.06k | } |
395 | 1.01k | } |
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 | 242k | { |
405 | 242k | if (!detail_is_set(MI) || !map_fill_detail_ops(MI)) |
406 | 0 | return; |
407 | | |
408 | 242k | unsigned OpNum = va_arg(args, unsigned); |
409 | | |
410 | 242k | 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 | 18.1k | case Mips_OP_GROUP_BranchOperand: |
418 | 18.1k | return Mips_set_detail_op_branch(MI, OpNum); |
419 | 2.61k | case Mips_OP_GROUP_JumpOperand: |
420 | 2.61k | return Mips_set_detail_op_jump(MI, OpNum); |
421 | 208k | case Mips_OP_GROUP_Operand: |
422 | 208k | return Mips_set_detail_op_operand(MI, OpNum); |
423 | 445 | case Mips_OP_GROUP_UImm_1_0: |
424 | 445 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 1, 0); |
425 | 539 | case Mips_OP_GROUP_UImm_2_0: |
426 | 539 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 2, 0); |
427 | 1.21k | case Mips_OP_GROUP_UImm_3_0: |
428 | 1.21k | 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 | 3.33k | case Mips_OP_GROUP_UImm_16_0: |
432 | 3.33k | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 16, 0); |
433 | 256 | case Mips_OP_GROUP_UImm_8_0: |
434 | 256 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 8, 0); |
435 | 2.37k | case Mips_OP_GROUP_UImm_5_0: |
436 | 2.37k | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 5, 0); |
437 | 239 | case Mips_OP_GROUP_UImm_6_0: |
438 | 239 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 6, 0); |
439 | 660 | case Mips_OP_GROUP_UImm_4_0: |
440 | 660 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 4, 0); |
441 | 284 | case Mips_OP_GROUP_UImm_7_0: |
442 | 284 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 7, 0); |
443 | 1.72k | case Mips_OP_GROUP_UImm_10_0: |
444 | 1.72k | 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 | 374 | case Mips_OP_GROUP_UImm_5_1: |
448 | 374 | 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 | 187 | case Mips_OP_GROUP_UImm_2_1: |
456 | 187 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 2, 1); |
457 | 346 | case Mips_OP_GROUP_UImm_0_0: |
458 | 346 | 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 | 96 | case Mips_OP_GROUP_UImm_20_0: |
464 | 96 | return Mips_set_detail_op_unsigned_offset(MI, OpNum, 20, 0); |
465 | 1.01k | case Mips_OP_GROUP_RegisterList: |
466 | 1.01k | 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 | 242k | } |
476 | 242k | } |
477 | | |
478 | | void Mips_set_mem_access(MCInst *MI, bool status) |
479 | 56.9k | { |
480 | 56.9k | if (!detail_is_set(MI)) |
481 | 0 | return; |
482 | 56.9k | set_doing_mem(MI, status); |
483 | 56.9k | if (status) { |
484 | 28.4k | if (Mips_get_detail(MI)->op_count > 0 && |
485 | 28.4k | Mips_get_detail_op(MI, -1)->type == MIPS_OP_MEM && |
486 | 28.4k | 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 | 28.4k | Mips_get_detail_op(MI, 0)->type = MIPS_OP_MEM; |
494 | 28.4k | Mips_get_detail_op(MI, 0)->mem.base = MIPS_REG_INVALID; |
495 | 28.4k | Mips_get_detail_op(MI, 0)->mem.disp = 0; |
496 | | |
497 | 28.4k | #ifndef CAPSTONE_DIET |
498 | 28.4k | uint8_t access = |
499 | 28.4k | map_get_op_access(MI, Mips_get_detail(MI)->op_count); |
500 | 28.4k | Mips_get_detail_op(MI, 0)->access = access; |
501 | 28.4k | #endif |
502 | 28.4k | } else { |
503 | | // done, select the next operand slot |
504 | 28.4k | Mips_inc_op_count(MI); |
505 | 28.4k | } |
506 | 56.9k | } |
507 | | |
508 | | #endif |