/src/capstonenext/arch/RISCV/RISCVMapping.c
Line | Count | Source |
1 | | #include "capstone/cs_operand.h" |
2 | | #include "capstone/riscv.h" |
3 | | #include <stdint.h> |
4 | | #include <float.h> |
5 | | #include <math.h> |
6 | | #ifdef CAPSTONE_HAS_RISCV |
7 | | |
8 | | #include <string.h> |
9 | | |
10 | | #include "../../Mapping.h" |
11 | | #include "../../cs_simple_types.h" |
12 | | #include "../../utils.h" |
13 | | |
14 | | #include "RISCVBaseInfo.h" |
15 | | #include "RISCVMapping.h" |
16 | | |
17 | | #define GET_INSTRINFO_ENUM |
18 | | #include "RISCVGenInstrInfo.inc" |
19 | | |
20 | | #define GET_REGINFO_ENUM |
21 | | #define GET_REGINFO_MC_DESC |
22 | | #include "RISCVGenRegisterInfo.inc" |
23 | | |
24 | | #include "RISCVInstPrinter.h" |
25 | | |
26 | | const char *RISCV_reg_name(csh handle, unsigned int reg) |
27 | 24.8k | { |
28 | 24.8k | int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax; |
29 | | |
30 | 24.8k | if (syntax_opt & CS_OPT_SYNTAX_NOREGNAME) { |
31 | 0 | return RISCV_LLVM_getRegisterName(reg, RISCV_NoRegAltName); |
32 | 0 | } |
33 | 24.8k | return RISCV_LLVM_getRegisterName(reg, RISCV_ABIRegAltName); |
34 | 24.8k | } |
35 | | |
36 | | static const insn_map insns[] = { |
37 | | #include "RISCVGenCSMappingInsn.inc" |
38 | | }; |
39 | | |
40 | | const insn_map *RISCV_insns = insns; |
41 | | const unsigned int RISCV_insn_count = ARR_SIZE(insns); |
42 | | |
43 | | #ifndef CAPSTONE_DIET |
44 | | static const map_insn_ops insn_operands[] = { |
45 | | #include "RISCVGenCSMappingInsnOp.inc" |
46 | | }; |
47 | | |
48 | | static const name_map insn_alias_mnem_map[] = { |
49 | | #include "RISCVGenCSAliasMnemMap.inc" |
50 | | }; |
51 | | #endif |
52 | | |
53 | | void RISCV_add_cs_detail_0(MCInst *MI, riscv_op_group opgroup, unsigned OpNum) |
54 | 229k | { |
55 | 229k | if (!detail_is_set(MI)) |
56 | 0 | return; |
57 | | // Rounding mode: store in detail, not as a regular operand. |
58 | 229k | if (opgroup == RISCV_OP_GROUP_FRMArg || |
59 | 226k | opgroup == RISCV_OP_GROUP_FRMArgLegacy) { |
60 | 3.45k | unsigned frm = (unsigned)MCInst_getOperand(MI, OpNum)->ImmVal; |
61 | 3.45k | riscv_rounding_mode rm; |
62 | 3.45k | switch (frm) { |
63 | 564 | case RISCVFPRndMode_RNE: |
64 | 564 | rm = RISCV_RM_RNE; |
65 | 564 | break; |
66 | 838 | case RISCVFPRndMode_RTZ: |
67 | 838 | rm = RISCV_RM_RTZ; |
68 | 838 | break; |
69 | 717 | case RISCVFPRndMode_RDN: |
70 | 717 | rm = RISCV_RM_RDN; |
71 | 717 | break; |
72 | 335 | case RISCVFPRndMode_RUP: |
73 | 335 | rm = RISCV_RM_RUP; |
74 | 335 | break; |
75 | 680 | case RISCVFPRndMode_RMM: |
76 | 680 | rm = RISCV_RM_RMM; |
77 | 680 | break; |
78 | 318 | case RISCVFPRndMode_DYN: |
79 | 318 | rm = RISCV_RM_DYN; |
80 | 318 | break; |
81 | 0 | default: |
82 | 0 | rm = RISCV_RM_INVALID; |
83 | 0 | break; |
84 | 3.45k | } |
85 | 3.45k | RISCV_get_detail(MI)->rounding_mode = rm; |
86 | 3.45k | return; |
87 | 3.45k | } |
88 | | |
89 | | // unmasked instructions, the mask register is not real |
90 | 225k | if (opgroup == RISCV_OP_GROUP_VMaskReg) { |
91 | 5.56k | MCOperand *mask = MCInst_getOperand(MI, OpNum); |
92 | 5.56k | if (MCOperand_isReg(mask) && |
93 | 5.56k | MCOperand_getReg(mask) == RISCV_NoRegister) |
94 | 2.65k | return; |
95 | 5.56k | } |
96 | | |
97 | 223k | if (opgroup == RISCV_OP_GROUP_FPImmOperand) { |
98 | 627 | unsigned Imm = (unsigned)MCInst_getOperand(MI, OpNum)->ImmVal; |
99 | 627 | cs_riscv_op *op = RISCV_get_detail_op_at(MI, OpNum); |
100 | 627 | op->type = RISCV_OP_FP; |
101 | 627 | op->access = (cs_ac_type)map_get_op_access(MI, OpNum); |
102 | 627 | switch (Imm) { |
103 | 188 | case 1: // min |
104 | 188 | switch (MI->Opcode) { |
105 | 155 | case RISCV_FLI_S: |
106 | 155 | op->dimm = (double)FLT_MIN; |
107 | 155 | break; |
108 | 0 | case RISCV_FLI_D: |
109 | 0 | op->dimm = (double)DBL_MIN; |
110 | 0 | break; |
111 | 33 | case RISCV_FLI_H: |
112 | 33 | op->dimm = 6.103515625e-05; |
113 | 33 | break; |
114 | 0 | default: |
115 | 0 | op->dimm = 0.0; |
116 | 0 | break; |
117 | 188 | } |
118 | 188 | break; |
119 | 188 | case 30: // inf |
120 | 121 | op->dimm = INFINITY; |
121 | 121 | break; |
122 | 75 | case 31: // nan |
123 | 75 | op->dimm = NAN; |
124 | 75 | break; |
125 | 243 | default: |
126 | 243 | op->dimm = (double)getFPImm(Imm); |
127 | 243 | break; |
128 | 627 | } |
129 | 627 | RISCV_inc_op_count(MI); |
130 | 627 | return; |
131 | 627 | } |
132 | 222k | cs_riscv_op *op = RISCV_get_detail_op_at(MI, OpNum); |
133 | 222k | op->type = (riscv_op_type)map_get_op_type(MI, OpNum); |
134 | 222k | op->access = (cs_ac_type)map_get_op_access(MI, OpNum); |
135 | 222k | switch (map_get_op_type(MI, OpNum)) { |
136 | 134k | case CS_OP_REG: |
137 | 134k | op->reg = MCInst_getOperand(MI, OpNum)->RegVal; |
138 | 134k | break; |
139 | 0 | case CS_OP_MEM: |
140 | 0 | op->mem.base = 0; |
141 | 0 | op->mem.disp = MCInst_getOperand(MI, OpNum)->ImmVal; |
142 | 0 | break; |
143 | 47.1k | case CS_OP_IMM: { |
144 | 47.1k | uint64_t val = MCInst_getOperand(MI, OpNum)->ImmVal; |
145 | 47.1k | if (opgroup != RISCV_OP_GROUP_CSRSystemRegister) { |
146 | 44.9k | op->imm = val; |
147 | 44.9k | if (opgroup == RISCV_OP_GROUP_BranchOperand) { |
148 | 6.85k | op->imm += MI->address; |
149 | 6.85k | } |
150 | 44.9k | } else /* system register read-write */ { |
151 | 2.22k | op->type = RISCV_OP_CSR; |
152 | 2.22k | op->csr = val; |
153 | | // CSR instruction always read-writes the system operand |
154 | 2.22k | op->access = CS_AC_READ_WRITE; |
155 | 2.22k | } |
156 | 47.1k | break; |
157 | 0 | } |
158 | 21.8k | case CS_OP_MEM_REG: |
159 | 21.8k | op->type = (riscv_op_type)CS_OP_MEM; |
160 | 21.8k | op->mem.base = MCInst_getOperand(MI, OpNum)->RegVal; |
161 | 21.8k | break; |
162 | 19.1k | case CS_OP_MEM_IMM: |
163 | | // fill in the disp in the last operand |
164 | 19.1k | op = RISCV_get_detail_op_at(MI, OpNum - 1); |
165 | 19.1k | op->type = (riscv_op_type)CS_OP_MEM; |
166 | 19.1k | op->mem.disp = MCInst_getOperand(MI, OpNum)->ImmVal; |
167 | 19.1k | RISCV_dec_op_count( |
168 | 19.1k | MI); // don't increase the count, cancel the coming increment |
169 | 19.1k | break; |
170 | 198 | case CS_OP_INVALID: |
171 | 198 | break; |
172 | 0 | default: { |
173 | 0 | CS_ASSERT(0 && "unhandled operand type"); |
174 | 0 | } |
175 | 222k | } |
176 | 222k | RISCV_inc_op_count(MI); |
177 | 222k | } |
178 | | |
179 | | static inline void RISCV_add_adhoc_groups(MCInst *MI); |
180 | | |
181 | | void RISCV_add_groups(MCInst *MI) |
182 | 91.8k | { |
183 | 91.8k | if (!detail_is_set(MI)) |
184 | 0 | return; |
185 | | |
186 | 91.8k | get_detail(MI)->groups_count = 0; |
187 | | |
188 | 91.8k | #ifndef CAPSTONE_DIET |
189 | 91.8k | int i = 0; |
190 | 205k | while (insns[MI->Opcode].groups[i] != 0) { |
191 | 113k | add_group(MI, insns[MI->Opcode].groups[i]); |
192 | 113k | i++; |
193 | 113k | } |
194 | 91.8k | #endif |
195 | | |
196 | 91.8k | RISCV_add_adhoc_groups(MI); |
197 | 91.8k | } |
198 | | |
199 | | enum { |
200 | | #define GET_ENUM_VALUES_RISCVOpcode |
201 | | #include "RISCVGenCSSystemOperandsEnum.inc" |
202 | | }; |
203 | | |
204 | | static inline void RISCV_add_privileged_group(MCInst *MI) |
205 | 91.8k | { |
206 | 91.8k | const uint8_t *bytes = MI->flat_insn->bytes; |
207 | 91.8k | uint8_t opcode = bytes[0] & 0x80; |
208 | | // no privileged instruction has a major opcode other than SYSTEM |
209 | 91.8k | if (opcode != RISCV_RISCVOPCODE_SYSTEM) { |
210 | 91.8k | return; |
211 | 91.8k | } |
212 | 0 | uint8_t func3 = (bytes[1] >> 4) & 0x7; |
213 | | // no privileged instruction has a minor opcode other than PRIV or PRIVM |
214 | 0 | if (func3 != 0 && func3 != 0x4) { |
215 | 0 | return; |
216 | 0 | } |
217 | 0 | uint16_t func12 = readBytes16(MI, &(bytes[2])) >> 4; |
218 | | // ecall and ebreak has SYSTEM and PRIV but aren't privileged |
219 | 0 | if (func12 == 0 || func12 == 1) { |
220 | 0 | return; |
221 | 0 | } |
222 | 0 | uint8_t func6 = func12 >> 6; |
223 | | // a subspace under extension-defined custom SYSTEM instructions that is not privileged |
224 | 0 | if (func6 == 0x23 || func6 == 0x33) { |
225 | 0 | return; |
226 | 0 | } |
227 | 0 | add_group(MI, RISCV_GRP_PRIVILEGE); |
228 | 0 | } |
229 | | |
230 | | static inline void RISCV_add_interrupt_group(MCInst *MI) |
231 | 91.8k | { |
232 | 91.8k | if (MI->Opcode == RISCV_ECALL || MI->Opcode == RISCV_EBREAK) { |
233 | 141 | add_group(MI, RISCV_GRP_INT); |
234 | 141 | } |
235 | 91.8k | } |
236 | | |
237 | | static inline void RISCV_add_interrupt_ret_group(MCInst *MI) |
238 | 91.8k | { |
239 | 91.8k | if (MI->Opcode == RISCV_MRET || MI->Opcode == RISCV_SRET) { |
240 | 95 | add_group(MI, RISCV_GRP_IRET); |
241 | 95 | } |
242 | 91.8k | } |
243 | | |
244 | | // calls are implemented in RISCV as plain jumps that happen to set a link register containing the return address |
245 | | // but this link register could be given as the null register x0, discarding the return address and making them jumps |
246 | | static inline void RISCV_add_call_group(MCInst *MI) |
247 | 91.8k | { |
248 | 91.8k | if (MI->Opcode == RISCV_JAL || MI->Opcode == RISCV_JALR) { |
249 | 1.89k | cs_riscv_op *op = RISCV_get_detail_op_at(MI, 0); |
250 | 1.89k | if ((op->type == (riscv_op_type)CS_OP_REG) && |
251 | 1.18k | op->reg != RISCV_REG_X0 && (op->access & CS_AC_WRITE)) { |
252 | 1.18k | add_group(MI, RISCV_GRP_CALL); |
253 | 1.18k | } |
254 | 1.89k | if (MI->Opcode == RISCV_JAL) { |
255 | 408 | add_group(MI, RISCV_GRP_BRANCH_RELATIVE); |
256 | 408 | } |
257 | 1.89k | } |
258 | 91.8k | } |
259 | | |
260 | | // returns are implemented in RISCV as a plain indirect jump that happen to reference the return address register ra == x1 |
261 | | static inline void RISCV_add_ret_group(MCInst *MI) |
262 | 91.8k | { |
263 | 91.8k | if (MI->Opcode == RISCV_C_JR) { |
264 | | // indirect jumps whose source is ra |
265 | 2.55k | cs_riscv_op *op = RISCV_get_detail_op_at(MI, 0); |
266 | 2.55k | if ((op->type == (riscv_op_type)CS_OP_REG) && |
267 | 0 | op->reg == RISCV_REG_X1) { |
268 | 0 | add_group(MI, RISCV_GRP_RET); |
269 | 2.55k | } else { |
270 | 2.55k | add_group(MI, RISCV_GRP_JUMP); |
271 | 2.55k | } |
272 | 2.55k | } |
273 | 91.8k | if (MI->Opcode == RISCV_JALR) { |
274 | | // indirect jumps whose source is ra |
275 | 1.48k | cs_riscv_op *dstreg = RISCV_get_detail_op_at(MI, 0); |
276 | 1.48k | cs_riscv_op *op = RISCV_get_detail_op_at(MI, 1); |
277 | 1.48k | cs_riscv_op *op2 = RISCV_get_detail_op_at(MI, 2); |
278 | 1.48k | if ((op->type == (riscv_op_type)CS_OP_REG) && |
279 | 1.15k | op->reg == RISCV_REG_X1 && |
280 | 693 | op2->type == (riscv_op_type)CS_OP_IMM && op2->imm == 0 && |
281 | 0 | dstreg->type == (riscv_op_type)CS_OP_REG && |
282 | 0 | dstreg->reg == RISCV_REG_X0) { |
283 | 0 | add_group(MI, RISCV_GRP_RET); |
284 | 1.48k | } else { |
285 | 1.48k | if (!((dstreg->type == (riscv_op_type)CS_OP_REG) && |
286 | 803 | dstreg->reg != RISCV_REG_X0 && |
287 | 803 | (dstreg->access & CS_AC_WRITE))) { |
288 | 681 | add_group(MI, RISCV_GRP_JUMP); |
289 | 681 | } |
290 | 1.48k | } |
291 | 1.48k | } |
292 | 91.8k | } |
293 | | |
294 | | static inline void RISCV_add_adhoc_groups(MCInst *MI) |
295 | 91.8k | { |
296 | 91.8k | RISCV_add_privileged_group(MI); |
297 | 91.8k | RISCV_add_interrupt_group(MI); |
298 | 91.8k | RISCV_add_interrupt_ret_group(MI); |
299 | 91.8k | RISCV_add_call_group(MI); |
300 | 91.8k | RISCV_add_ret_group(MI); |
301 | 91.8k | } |
302 | | |
303 | | // memset all stalled values in the detail struct to 0 before disassembling any next instruction |
304 | | void RISCV_init_cs_detail(MCInst *MI) |
305 | 93.1k | { |
306 | 93.1k | if (detail_is_set(MI)) |
307 | 93.1k | memset(get_detail(MI), 0, |
308 | 93.1k | offsetof(cs_detail, riscv) + sizeof(cs_riscv)); |
309 | 93.1k | } |
310 | | |
311 | | // for weird reasons some instructions end up with valid operands that are |
312 | | // interspersed with invalid operands, i.e. the operands array is an "island" |
313 | | // of valid operands with invalid gaps between them, this function will compactify |
314 | | // all the valid operands and pad the rest of the array to invalid |
315 | | void RISCV_compact_operands(MCInst *MI) |
316 | 91.8k | { |
317 | 91.8k | if (!detail_is_set(MI)) |
318 | 0 | return; |
319 | 91.8k | cs_riscv_op *ops = RISCV_get_detail(MI)->operands; |
320 | 91.8k | unsigned int write_pos = 0; |
321 | | |
322 | | // Move valid elements to front |
323 | 826k | for (unsigned int read_pos = 0; read_pos < NUM_RISCV_OPS; read_pos++) { |
324 | 735k | if (ops[read_pos].type != (riscv_op_type)CS_OP_INVALID) { |
325 | 223k | if (write_pos != read_pos) { |
326 | 26.2k | ops[write_pos] = ops[read_pos]; |
327 | 26.2k | } |
328 | 223k | write_pos++; |
329 | 223k | } |
330 | 735k | } |
331 | | // fill the rest, if any, with invalid |
332 | 91.8k | memset((void *)(&ops[write_pos]), CS_OP_INVALID, |
333 | 91.8k | (NUM_RISCV_OPS - write_pos) * sizeof(cs_riscv_op)); |
334 | 91.8k | } |
335 | | |
336 | | // given internal insn id, return public instruction info |
337 | | void RISCV_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) |
338 | 91.8k | { |
339 | 91.8k | insn_map const *insn_map = NULL; |
340 | | |
341 | 91.8k | if ((insn_map = lookup_insn_map(h, id))) { |
342 | 91.8k | insn->id = insn_map->mapid; |
343 | | |
344 | 91.8k | if (h->detail_opt) { |
345 | 91.8k | #ifndef CAPSTONE_DIET |
346 | 91.8k | memcpy(insn->detail->regs_read, insn_map->regs_use, |
347 | 91.8k | sizeof(insn_map->regs_use)); |
348 | 91.8k | insn->detail->regs_read_count = |
349 | 91.8k | (uint8_t)count_positive(insn_map->regs_use); |
350 | | |
351 | 91.8k | memcpy(insn->detail->regs_write, insn_map->regs_mod, |
352 | 91.8k | sizeof(insn_map->regs_mod)); |
353 | 91.8k | insn->detail->regs_write_count = |
354 | 91.8k | (uint8_t)count_positive(insn_map->regs_mod); |
355 | | |
356 | 91.8k | memcpy(insn->detail->groups, insn_map->groups, |
357 | 91.8k | sizeof(insn_map->groups)); |
358 | 91.8k | insn->detail->groups_count = |
359 | 91.8k | (uint8_t)count_positive8(insn_map->groups); |
360 | | |
361 | 91.8k | if (insn_map->branch || insn_map->indirect_branch) { |
362 | | // this insn also belongs to JUMP group. add JUMP group |
363 | 4.95k | insn->detail |
364 | 4.95k | ->groups[insn->detail->groups_count] = |
365 | 4.95k | RISCV_GRP_JUMP; |
366 | 4.95k | insn->detail->groups_count++; |
367 | 4.95k | } |
368 | 91.8k | #endif |
369 | 91.8k | } |
370 | 91.8k | } |
371 | 91.8k | } |
372 | | |
373 | | static const char *const insn_name_maps[] = { |
374 | | #include "RISCVGenCSMappingInsnName.inc" |
375 | | }; |
376 | | |
377 | | // called from RISCV_LLVM_printInstruction() to avoid exporting |
378 | | // insn_alias_mnem_map and its size via extern declarations |
379 | | void RISCV_set_alias_id(MCInst *MI, SStream *O) |
380 | 91.8k | { |
381 | 91.8k | #ifndef CAPSTONE_DIET |
382 | 91.8k | map_set_alias_id(MI, O, insn_alias_mnem_map, |
383 | 91.8k | ARR_SIZE(insn_alias_mnem_map)); |
384 | 91.8k | #endif |
385 | 91.8k | } |
386 | | |
387 | | const char *RISCV_insn_name(csh handle, unsigned int id) |
388 | 91.8k | { |
389 | 91.8k | #ifndef CAPSTONE_DIET |
390 | 91.8k | if (id < RISCV_INS_ENDING) |
391 | 91.8k | return insn_name_maps[id]; |
392 | | |
393 | 0 | if (id > RISCV_INS_ALIAS_BEGIN && id < RISCV_INS_ALIAS_END) |
394 | 0 | return insn_alias_mnem_map[id - RISCV_INS_ALIAS_BEGIN - 1].name; |
395 | 0 | #endif |
396 | 0 | return NULL; |
397 | 0 | } |
398 | | |
399 | | #ifndef CAPSTONE_DIET |
400 | | static const name_map group_name_maps[] = { |
401 | | // generic groups |
402 | | { RISCV_GRP_INVALID, NULL }, |
403 | | { RISCV_GRP_JUMP, "jump" }, |
404 | | { RISCV_GRP_CALL, "call" }, |
405 | | { RISCV_GRP_RET, "ret" }, |
406 | | { RISCV_GRP_INT, "int" }, |
407 | | { RISCV_GRP_IRET, "iret" }, |
408 | | { RISCV_GRP_PRIVILEGE, "privileged" }, |
409 | | { RISCV_GRP_BRANCH_RELATIVE, "branch_relative" }, |
410 | | |
411 | | // architecture specific |
412 | | #include "RISCVGenCSFeatureName.inc" |
413 | | |
414 | | { RISCV_GRP_ENDING, NULL } |
415 | | }; |
416 | | #endif |
417 | | |
418 | | const char *RISCV_group_name(csh handle, unsigned int id) |
419 | 118k | { |
420 | 118k | #ifndef CAPSTONE_DIET |
421 | | // verify group id |
422 | | // if past the end |
423 | 118k | if (id >= RISCV_GRP_ENDING || |
424 | | // or in the encoding gap between generic groups and arch-specific groups |
425 | 118k | (id > RISCV_GRP_BRANCH_RELATIVE && id < RISCV_FEATURE_HASSTDEXTI)) |
426 | 0 | return NULL; |
427 | 118k | return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); |
428 | | #else |
429 | | return NULL; |
430 | | #endif |
431 | 118k | } |
432 | | |
433 | | // map instruction name to public instruction ID |
434 | | riscv_insn RISCV_map_insn(const char *name) |
435 | 0 | { |
436 | 0 | unsigned int i; |
437 | 0 | for (i = 1; i < ARR_SIZE(insn_name_maps); i++) { |
438 | 0 | if (!strcmp(name, insn_name_maps[i])) |
439 | 0 | return i; |
440 | 0 | } |
441 | 0 | #ifndef CAPSTONE_DIET |
442 | 0 | for (i = 0; i < ARR_SIZE(insn_alias_mnem_map); i++) { |
443 | 0 | if (!strcmp(name, insn_alias_mnem_map[i].name)) |
444 | 0 | return insn_alias_mnem_map[i].id; |
445 | 0 | } |
446 | 0 | #endif |
447 | 0 | return RISCV_INS_INVALID; |
448 | 0 | } |
449 | | |
450 | | void RISCV_reg_access(const cs_insn *insn, cs_regs regs_read, |
451 | | uint8_t *regs_read_count, cs_regs regs_write, |
452 | | uint8_t *regs_write_count) |
453 | 0 | { |
454 | 0 | const cs_riscv *riscv = &(insn->detail->riscv); |
455 | 0 | uint8_t read_count = 0; |
456 | 0 | uint8_t write_count = 0; |
457 | |
|
458 | 0 | for (int j = 0; j < riscv->op_count; j++) { |
459 | 0 | const cs_riscv_op *op = &riscv->operands[j]; |
460 | |
|
461 | 0 | if (op->type == RISCV_OP_REG) { |
462 | 0 | if ((op->access & CS_AC_WRITE) && |
463 | 0 | !arr_exist(regs_write, write_count, op->reg)) { |
464 | 0 | regs_write[write_count++] = (uint16_t)op->reg; |
465 | 0 | } |
466 | 0 | if ((op->access & CS_AC_READ) && |
467 | 0 | !arr_exist(regs_read, read_count, op->reg)) { |
468 | 0 | regs_read[read_count++] = (uint16_t)op->reg; |
469 | 0 | } |
470 | 0 | } else if (op->type == RISCV_OP_MEM) { |
471 | 0 | if (op->mem.base != RISCV_REG_INVALID && |
472 | 0 | !arr_exist(regs_read, read_count, op->mem.base)) { |
473 | 0 | regs_read[read_count++] = |
474 | 0 | (uint16_t)op->mem.base; |
475 | 0 | } |
476 | 0 | } |
477 | 0 | } |
478 | |
|
479 | 0 | *regs_read_count = read_count; |
480 | 0 | *regs_write_count = write_count; |
481 | 0 | } |
482 | | |
483 | | void RISCV_init(MCRegisterInfo *MRI) |
484 | 1.63k | { |
485 | 1.63k | MCRegisterInfo_InitMCRegisterInfo(MRI, RISCVRegDesc, RISCV_REG_ENDING, |
486 | 1.63k | 0, 0, RISCVMCRegisterClasses, |
487 | 1.63k | ARR_SIZE(RISCVMCRegisterClasses), 0, |
488 | 1.63k | 0, RISCVRegDiffLists, 0, |
489 | 1.63k | RISCVSubRegIdxLists, |
490 | 1.63k | ARR_SIZE(RISCVSubRegIdxLists), 0); |
491 | 1.63k | } |
492 | | |
493 | | #endif |