riscv-dis.c revision 1.1.1.3 1 1.1 christos /* RISC-V disassembler
2 1.1.1.3 christos Copyright (C) 2011-2020 Free Software Foundation, Inc.
3 1.1 christos
4 1.1.1.2 christos Contributed by Andrew Waterman (andrew (at) sifive.com).
5 1.1 christos Based on MIPS target.
6 1.1 christos
7 1.1 christos This file is part of the GNU opcodes library.
8 1.1 christos
9 1.1 christos This library is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 3, or (at your option)
12 1.1 christos any later version.
13 1.1 christos
14 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
15 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 1.1 christos License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1.1.2 christos along with this program; see the file COPYING3. If not,
21 1.1.1.2 christos see <http://www.gnu.org/licenses/>. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1.1.2 christos #include "disassemble.h"
25 1.1 christos #include "libiberty.h"
26 1.1 christos #include "opcode/riscv.h"
27 1.1 christos #include "opintl.h"
28 1.1 christos #include "elf-bfd.h"
29 1.1 christos #include "elf/riscv.h"
30 1.1 christos
31 1.1.1.3 christos #include "bfd_stdint.h"
32 1.1.1.2 christos #include <ctype.h>
33 1.1 christos
34 1.1 christos struct riscv_private_data
35 1.1 christos {
36 1.1 christos bfd_vma gp;
37 1.1 christos bfd_vma print_addr;
38 1.1 christos bfd_vma hi_addr[OP_MASK_RD + 1];
39 1.1 christos };
40 1.1 christos
41 1.1 christos static const char * const *riscv_gpr_names;
42 1.1 christos static const char * const *riscv_fpr_names;
43 1.1 christos
44 1.1.1.2 christos /* Other options. */
45 1.1 christos static int no_aliases; /* If set disassemble as most general inst. */
46 1.1 christos
47 1.1 christos static void
48 1.1 christos set_default_riscv_dis_options (void)
49 1.1 christos {
50 1.1 christos riscv_gpr_names = riscv_gpr_names_abi;
51 1.1 christos riscv_fpr_names = riscv_fpr_names_abi;
52 1.1 christos no_aliases = 0;
53 1.1 christos }
54 1.1 christos
55 1.1 christos static void
56 1.1 christos parse_riscv_dis_option (const char *option)
57 1.1 christos {
58 1.1.1.2 christos if (strcmp (option, "no-aliases") == 0)
59 1.1 christos no_aliases = 1;
60 1.1.1.2 christos else if (strcmp (option, "numeric") == 0)
61 1.1 christos {
62 1.1 christos riscv_gpr_names = riscv_gpr_names_numeric;
63 1.1 christos riscv_fpr_names = riscv_fpr_names_numeric;
64 1.1 christos }
65 1.1.1.2 christos else
66 1.1.1.2 christos {
67 1.1.1.2 christos /* xgettext:c-format */
68 1.1.1.2 christos opcodes_error_handler (_("unrecognized disassembler option: %s"), option);
69 1.1.1.2 christos }
70 1.1 christos }
71 1.1 christos
72 1.1 christos static void
73 1.1 christos parse_riscv_dis_options (const char *opts_in)
74 1.1 christos {
75 1.1 christos char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
76 1.1 christos
77 1.1 christos set_default_riscv_dis_options ();
78 1.1 christos
79 1.1 christos for ( ; opt_end != NULL; opt = opt_end + 1)
80 1.1 christos {
81 1.1 christos if ((opt_end = strchr (opt, ',')) != NULL)
82 1.1 christos *opt_end = 0;
83 1.1 christos parse_riscv_dis_option (opt);
84 1.1 christos }
85 1.1 christos
86 1.1 christos free (opts);
87 1.1 christos }
88 1.1 christos
89 1.1.1.2 christos /* Print one argument from an array. */
90 1.1 christos
91 1.1 christos static void
92 1.1 christos arg_print (struct disassemble_info *info, unsigned long val,
93 1.1 christos const char* const* array, size_t size)
94 1.1 christos {
95 1.1 christos const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
96 1.1 christos (*info->fprintf_func) (info->stream, "%s", s);
97 1.1 christos }
98 1.1 christos
99 1.1 christos static void
100 1.1 christos maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
101 1.1 christos {
102 1.1 christos if (pd->hi_addr[base_reg] != (bfd_vma)-1)
103 1.1 christos {
104 1.1.1.2 christos pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset;
105 1.1 christos pd->hi_addr[base_reg] = -1;
106 1.1 christos }
107 1.1 christos else if (base_reg == X_GP && pd->gp != (bfd_vma)-1)
108 1.1 christos pd->print_addr = pd->gp + offset;
109 1.1.1.2 christos else if (base_reg == X_TP || base_reg == 0)
110 1.1 christos pd->print_addr = offset;
111 1.1 christos }
112 1.1 christos
113 1.1 christos /* Print insn arguments for 32/64-bit code. */
114 1.1 christos
115 1.1 christos static void
116 1.1 christos print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
117 1.1 christos {
118 1.1 christos struct riscv_private_data *pd = info->private_data;
119 1.1 christos int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
120 1.1 christos int rd = (l >> OP_SH_RD) & OP_MASK_RD;
121 1.1.1.2 christos fprintf_ftype print = info->fprintf_func;
122 1.1 christos
123 1.1 christos if (*d != '\0')
124 1.1.1.2 christos print (info->stream, "\t");
125 1.1 christos
126 1.1 christos for (; *d != '\0'; d++)
127 1.1 christos {
128 1.1 christos switch (*d)
129 1.1 christos {
130 1.1.1.2 christos case 'C': /* RVC */
131 1.1.1.2 christos switch (*++d)
132 1.1.1.2 christos {
133 1.1.1.2 christos case 's': /* RS1 x8-x15 */
134 1.1.1.2 christos case 'w': /* RS1 x8-x15 */
135 1.1.1.2 christos print (info->stream, "%s",
136 1.1.1.2 christos riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
137 1.1.1.2 christos break;
138 1.1.1.2 christos case 't': /* RS2 x8-x15 */
139 1.1.1.2 christos case 'x': /* RS2 x8-x15 */
140 1.1.1.2 christos print (info->stream, "%s",
141 1.1.1.2 christos riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
142 1.1.1.2 christos break;
143 1.1.1.2 christos case 'U': /* RS1, constrained to equal RD */
144 1.1.1.2 christos print (info->stream, "%s", riscv_gpr_names[rd]);
145 1.1.1.2 christos break;
146 1.1.1.2 christos case 'c': /* RS1, constrained to equal sp */
147 1.1.1.2 christos print (info->stream, "%s", riscv_gpr_names[X_SP]);
148 1.1.1.2 christos break;
149 1.1.1.2 christos case 'V': /* RS2 */
150 1.1.1.2 christos print (info->stream, "%s",
151 1.1.1.2 christos riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
152 1.1.1.2 christos break;
153 1.1.1.2 christos case 'i':
154 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_SIMM3 (l));
155 1.1.1.2 christos break;
156 1.1.1.2 christos case 'o':
157 1.1.1.2 christos case 'j':
158 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_IMM (l));
159 1.1.1.2 christos break;
160 1.1.1.2 christos case 'k':
161 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_LW_IMM (l));
162 1.1.1.2 christos break;
163 1.1.1.2 christos case 'l':
164 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_LD_IMM (l));
165 1.1.1.2 christos break;
166 1.1.1.2 christos case 'm':
167 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_LWSP_IMM (l));
168 1.1.1.2 christos break;
169 1.1.1.2 christos case 'n':
170 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
171 1.1.1.2 christos break;
172 1.1.1.2 christos case 'K':
173 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
174 1.1.1.2 christos break;
175 1.1.1.2 christos case 'L':
176 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
177 1.1.1.2 christos break;
178 1.1.1.2 christos case 'M':
179 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
180 1.1.1.2 christos break;
181 1.1.1.2 christos case 'N':
182 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
183 1.1.1.2 christos break;
184 1.1.1.2 christos case 'p':
185 1.1.1.2 christos info->target = EXTRACT_RVC_B_IMM (l) + pc;
186 1.1.1.2 christos (*info->print_address_func) (info->target, info);
187 1.1.1.2 christos break;
188 1.1.1.2 christos case 'a':
189 1.1.1.2 christos info->target = EXTRACT_RVC_J_IMM (l) + pc;
190 1.1.1.2 christos (*info->print_address_func) (info->target, info);
191 1.1.1.2 christos break;
192 1.1.1.2 christos case 'u':
193 1.1.1.2 christos print (info->stream, "0x%x",
194 1.1.1.2 christos (int)(EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
195 1.1.1.2 christos break;
196 1.1.1.2 christos case '>':
197 1.1.1.2 christos print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x3f);
198 1.1.1.2 christos break;
199 1.1.1.2 christos case '<':
200 1.1.1.2 christos print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x1f);
201 1.1.1.2 christos break;
202 1.1.1.2 christos case 'T': /* floating-point RS2 */
203 1.1.1.2 christos print (info->stream, "%s",
204 1.1.1.2 christos riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
205 1.1.1.2 christos break;
206 1.1.1.2 christos case 'D': /* floating-point RS2 x8-x15 */
207 1.1.1.2 christos print (info->stream, "%s",
208 1.1.1.2 christos riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
209 1.1.1.2 christos break;
210 1.1.1.2 christos }
211 1.1.1.2 christos break;
212 1.1 christos
213 1.1 christos case ',':
214 1.1 christos case '(':
215 1.1 christos case ')':
216 1.1 christos case '[':
217 1.1 christos case ']':
218 1.1.1.2 christos print (info->stream, "%c", *d);
219 1.1 christos break;
220 1.1 christos
221 1.1 christos case '0':
222 1.1.1.2 christos /* Only print constant 0 if it is the last argument */
223 1.1.1.2 christos if (!d[1])
224 1.1.1.2 christos print (info->stream, "0");
225 1.1 christos break;
226 1.1 christos
227 1.1 christos case 'b':
228 1.1 christos case 's':
229 1.1.1.2 christos if ((l & MASK_JALR) == MATCH_JALR)
230 1.1.1.2 christos maybe_print_address (pd, rs1, 0);
231 1.1.1.2 christos print (info->stream, "%s", riscv_gpr_names[rs1]);
232 1.1 christos break;
233 1.1 christos
234 1.1 christos case 't':
235 1.1.1.2 christos print (info->stream, "%s",
236 1.1.1.2 christos riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
237 1.1 christos break;
238 1.1 christos
239 1.1 christos case 'u':
240 1.1.1.2 christos print (info->stream, "0x%x",
241 1.1.1.2 christos (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
242 1.1 christos break;
243 1.1 christos
244 1.1 christos case 'm':
245 1.1.1.2 christos arg_print (info, EXTRACT_OPERAND (RM, l),
246 1.1.1.2 christos riscv_rm, ARRAY_SIZE (riscv_rm));
247 1.1 christos break;
248 1.1 christos
249 1.1 christos case 'P':
250 1.1.1.2 christos arg_print (info, EXTRACT_OPERAND (PRED, l),
251 1.1.1.2 christos riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
252 1.1 christos break;
253 1.1 christos
254 1.1 christos case 'Q':
255 1.1.1.2 christos arg_print (info, EXTRACT_OPERAND (SUCC, l),
256 1.1.1.2 christos riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
257 1.1 christos break;
258 1.1 christos
259 1.1 christos case 'o':
260 1.1 christos maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
261 1.1.1.2 christos /* Fall through. */
262 1.1 christos case 'j':
263 1.1.1.2 christos if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0)
264 1.1.1.2 christos || (l & MASK_JALR) == MATCH_JALR)
265 1.1 christos maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
266 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
267 1.1 christos break;
268 1.1 christos
269 1.1 christos case 'q':
270 1.1 christos maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
271 1.1.1.2 christos print (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
272 1.1 christos break;
273 1.1 christos
274 1.1 christos case 'a':
275 1.1 christos info->target = EXTRACT_UJTYPE_IMM (l) + pc;
276 1.1 christos (*info->print_address_func) (info->target, info);
277 1.1 christos break;
278 1.1 christos
279 1.1 christos case 'p':
280 1.1 christos info->target = EXTRACT_SBTYPE_IMM (l) + pc;
281 1.1 christos (*info->print_address_func) (info->target, info);
282 1.1 christos break;
283 1.1 christos
284 1.1 christos case 'd':
285 1.1 christos if ((l & MASK_AUIPC) == MATCH_AUIPC)
286 1.1 christos pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
287 1.1 christos else if ((l & MASK_LUI) == MATCH_LUI)
288 1.1 christos pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
289 1.1.1.2 christos else if ((l & MASK_C_LUI) == MATCH_C_LUI)
290 1.1.1.2 christos pd->hi_addr[rd] = EXTRACT_RVC_LUI_IMM (l);
291 1.1.1.2 christos print (info->stream, "%s", riscv_gpr_names[rd]);
292 1.1 christos break;
293 1.1 christos
294 1.1 christos case 'z':
295 1.1.1.2 christos print (info->stream, "%s", riscv_gpr_names[0]);
296 1.1 christos break;
297 1.1 christos
298 1.1 christos case '>':
299 1.1.1.2 christos print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMT, l));
300 1.1 christos break;
301 1.1 christos
302 1.1 christos case '<':
303 1.1.1.2 christos print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMTW, l));
304 1.1 christos break;
305 1.1 christos
306 1.1 christos case 'S':
307 1.1 christos case 'U':
308 1.1.1.2 christos print (info->stream, "%s", riscv_fpr_names[rs1]);
309 1.1 christos break;
310 1.1 christos
311 1.1 christos case 'T':
312 1.1.1.2 christos print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
313 1.1 christos break;
314 1.1 christos
315 1.1 christos case 'D':
316 1.1.1.2 christos print (info->stream, "%s", riscv_fpr_names[rd]);
317 1.1 christos break;
318 1.1 christos
319 1.1 christos case 'R':
320 1.1.1.2 christos print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
321 1.1 christos break;
322 1.1 christos
323 1.1 christos case 'E':
324 1.1 christos {
325 1.1 christos const char* csr_name = NULL;
326 1.1.1.2 christos unsigned int csr = EXTRACT_OPERAND (CSR, l);
327 1.1 christos switch (csr)
328 1.1 christos {
329 1.1.1.2 christos #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
330 1.1.1.2 christos #include "opcode/riscv-opc.h"
331 1.1.1.2 christos #undef DECLARE_CSR
332 1.1 christos }
333 1.1 christos if (csr_name)
334 1.1.1.2 christos print (info->stream, "%s", csr_name);
335 1.1 christos else
336 1.1.1.2 christos print (info->stream, "0x%x", csr);
337 1.1 christos break;
338 1.1 christos }
339 1.1 christos
340 1.1 christos case 'Z':
341 1.1.1.2 christos print (info->stream, "%d", rs1);
342 1.1 christos break;
343 1.1 christos
344 1.1 christos default:
345 1.1 christos /* xgettext:c-format */
346 1.1.1.2 christos print (info->stream, _("# internal error, undefined modifier (%c)"),
347 1.1.1.2 christos *d);
348 1.1 christos return;
349 1.1 christos }
350 1.1 christos }
351 1.1 christos }
352 1.1 christos
353 1.1 christos /* Print the RISC-V instruction at address MEMADDR in debugged memory,
354 1.1 christos on using INFO. Returns length of the instruction, in bytes.
355 1.1 christos BIGENDIAN must be 1 if this is big-endian code, 0 if
356 1.1 christos this is little-endian code. */
357 1.1 christos
358 1.1 christos static int
359 1.1 christos riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
360 1.1 christos {
361 1.1 christos const struct riscv_opcode *op;
362 1.1 christos static bfd_boolean init = 0;
363 1.1 christos static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
364 1.1 christos struct riscv_private_data *pd;
365 1.1 christos int insnlen;
366 1.1 christos
367 1.1.1.2 christos #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
368 1.1.1.2 christos
369 1.1 christos /* Build a hash table to shorten the search time. */
370 1.1 christos if (! init)
371 1.1 christos {
372 1.1.1.2 christos for (op = riscv_opcodes; op->name; op++)
373 1.1.1.2 christos if (!riscv_hash[OP_HASH_IDX (op->match)])
374 1.1.1.2 christos riscv_hash[OP_HASH_IDX (op->match)] = op;
375 1.1 christos
376 1.1 christos init = 1;
377 1.1 christos }
378 1.1 christos
379 1.1 christos if (info->private_data == NULL)
380 1.1 christos {
381 1.1 christos int i;
382 1.1 christos
383 1.1.1.2 christos pd = info->private_data = xcalloc (1, sizeof (struct riscv_private_data));
384 1.1 christos pd->gp = -1;
385 1.1 christos pd->print_addr = -1;
386 1.1.1.2 christos for (i = 0; i < (int)ARRAY_SIZE (pd->hi_addr); i++)
387 1.1 christos pd->hi_addr[i] = -1;
388 1.1 christos
389 1.1 christos for (i = 0; i < info->symtab_size; i++)
390 1.1.1.2 christos if (strcmp (bfd_asymbol_name (info->symtab[i]), RISCV_GP_SYMBOL) == 0)
391 1.1 christos pd->gp = bfd_asymbol_value (info->symtab[i]);
392 1.1 christos }
393 1.1 christos else
394 1.1 christos pd = info->private_data;
395 1.1 christos
396 1.1 christos insnlen = riscv_insn_length (word);
397 1.1 christos
398 1.1.1.3 christos /* RISC-V instructions are always little-endian. */
399 1.1.1.3 christos info->endian_code = BFD_ENDIAN_LITTLE;
400 1.1.1.3 christos
401 1.1 christos info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
402 1.1 christos info->bytes_per_line = 8;
403 1.1.1.3 christos /* We don't support constant pools, so this must be code. */
404 1.1.1.3 christos info->display_endian = info->endian_code;
405 1.1 christos info->insn_info_valid = 1;
406 1.1 christos info->branch_delay_insns = 0;
407 1.1 christos info->data_size = 0;
408 1.1 christos info->insn_type = dis_nonbranch;
409 1.1 christos info->target = 0;
410 1.1 christos info->target2 = 0;
411 1.1 christos
412 1.1.1.2 christos op = riscv_hash[OP_HASH_IDX (word)];
413 1.1 christos if (op != NULL)
414 1.1 christos {
415 1.1.1.3 christos unsigned xlen = 0;
416 1.1.1.2 christos
417 1.1.1.2 christos /* If XLEN is not known, get its value from the ELF class. */
418 1.1.1.2 christos if (info->mach == bfd_mach_riscv64)
419 1.1.1.2 christos xlen = 64;
420 1.1.1.2 christos else if (info->mach == bfd_mach_riscv32)
421 1.1.1.2 christos xlen = 32;
422 1.1.1.2 christos else if (info->section != NULL)
423 1.1 christos {
424 1.1.1.2 christos Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
425 1.1.1.2 christos xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
426 1.1.1.2 christos }
427 1.1.1.2 christos
428 1.1.1.2 christos for (; op->name; op++)
429 1.1.1.2 christos {
430 1.1.1.2 christos /* Does the opcode match? */
431 1.1.1.2 christos if (! (op->match_func) (op, word))
432 1.1.1.2 christos continue;
433 1.1.1.2 christos /* Is this a pseudo-instruction and may we print it as such? */
434 1.1.1.2 christos if (no_aliases && (op->pinfo & INSN_ALIAS))
435 1.1.1.2 christos continue;
436 1.1.1.2 christos /* Is this instruction restricted to a certain value of XLEN? */
437 1.1.1.3 christos if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
438 1.1.1.2 christos continue;
439 1.1.1.2 christos
440 1.1.1.2 christos /* It's a match. */
441 1.1.1.2 christos (*info->fprintf_func) (info->stream, "%s", op->name);
442 1.1.1.2 christos print_insn_args (op->args, word, memaddr, info);
443 1.1.1.2 christos
444 1.1.1.2 christos /* Try to disassemble multi-instruction addressing sequences. */
445 1.1.1.2 christos if (pd->print_addr != (bfd_vma)-1)
446 1.1 christos {
447 1.1.1.2 christos info->target = pd->print_addr;
448 1.1.1.2 christos (*info->fprintf_func) (info->stream, " # ");
449 1.1.1.2 christos (*info->print_address_func) (info->target, info);
450 1.1.1.2 christos pd->print_addr = -1;
451 1.1 christos }
452 1.1.1.2 christos
453 1.1.1.3 christos /* Finish filling out insn_info fields. */
454 1.1.1.3 christos switch (op->pinfo & INSN_TYPE)
455 1.1.1.3 christos {
456 1.1.1.3 christos case INSN_BRANCH:
457 1.1.1.3 christos info->insn_type = dis_branch;
458 1.1.1.3 christos break;
459 1.1.1.3 christos case INSN_CONDBRANCH:
460 1.1.1.3 christos info->insn_type = dis_condbranch;
461 1.1.1.3 christos break;
462 1.1.1.3 christos case INSN_JSR:
463 1.1.1.3 christos info->insn_type = dis_jsr;
464 1.1.1.3 christos break;
465 1.1.1.3 christos case INSN_DREF:
466 1.1.1.3 christos info->insn_type = dis_dref;
467 1.1.1.3 christos break;
468 1.1.1.3 christos default:
469 1.1.1.3 christos break;
470 1.1.1.3 christos }
471 1.1.1.3 christos
472 1.1.1.3 christos if (op->pinfo & INSN_DATA_SIZE)
473 1.1.1.3 christos {
474 1.1.1.3 christos int size = ((op->pinfo & INSN_DATA_SIZE)
475 1.1.1.3 christos >> INSN_DATA_SIZE_SHIFT);
476 1.1.1.3 christos info->data_size = 1 << (size - 1);
477 1.1.1.3 christos }
478 1.1.1.3 christos
479 1.1.1.2 christos return insnlen;
480 1.1 christos }
481 1.1 christos }
482 1.1 christos
483 1.1.1.2 christos /* We did not find a match, so just print the instruction bits. */
484 1.1 christos info->insn_type = dis_noninsn;
485 1.1 christos (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
486 1.1 christos return insnlen;
487 1.1 christos }
488 1.1 christos
489 1.1 christos int
490 1.1 christos print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
491 1.1 christos {
492 1.1.1.2 christos bfd_byte packet[2];
493 1.1 christos insn_t insn = 0;
494 1.1 christos bfd_vma n;
495 1.1 christos int status;
496 1.1 christos
497 1.1 christos if (info->disassembler_options != NULL)
498 1.1 christos {
499 1.1 christos parse_riscv_dis_options (info->disassembler_options);
500 1.1 christos /* Avoid repeatedly parsing the options. */
501 1.1 christos info->disassembler_options = NULL;
502 1.1 christos }
503 1.1 christos else if (riscv_gpr_names == NULL)
504 1.1 christos set_default_riscv_dis_options ();
505 1.1 christos
506 1.1 christos /* Instructions are a sequence of 2-byte packets in little-endian order. */
507 1.1.1.2 christos for (n = 0; n < sizeof (insn) && n < riscv_insn_length (insn); n += 2)
508 1.1 christos {
509 1.1.1.2 christos status = (*info->read_memory_func) (memaddr + n, packet, 2, info);
510 1.1 christos if (status != 0)
511 1.1 christos {
512 1.1.1.2 christos /* Don't fail just because we fell off the end. */
513 1.1.1.2 christos if (n > 0)
514 1.1 christos break;
515 1.1 christos (*info->memory_error_func) (status, memaddr, info);
516 1.1 christos return status;
517 1.1 christos }
518 1.1 christos
519 1.1.1.2 christos insn |= ((insn_t) bfd_getl16 (packet)) << (8 * n);
520 1.1 christos }
521 1.1 christos
522 1.1 christos return riscv_disassemble_insn (memaddr, insn, info);
523 1.1 christos }
524 1.1 christos
525 1.1.1.3 christos /* Prevent use of the fake labels that are generated as part of the DWARF
526 1.1.1.3 christos and for relaxable relocations in the assembler. */
527 1.1.1.3 christos
528 1.1.1.3 christos bfd_boolean
529 1.1.1.3 christos riscv_symbol_is_valid (asymbol * sym,
530 1.1.1.3 christos struct disassemble_info * info ATTRIBUTE_UNUSED)
531 1.1.1.3 christos {
532 1.1.1.3 christos const char * name;
533 1.1.1.3 christos
534 1.1.1.3 christos if (sym == NULL)
535 1.1.1.3 christos return FALSE;
536 1.1.1.3 christos
537 1.1.1.3 christos name = bfd_asymbol_name (sym);
538 1.1.1.3 christos
539 1.1.1.3 christos return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0);
540 1.1.1.3 christos }
541 1.1.1.3 christos
542 1.1 christos void
543 1.1 christos print_riscv_disassembler_options (FILE *stream)
544 1.1 christos {
545 1.1 christos fprintf (stream, _("\n\
546 1.1 christos The following RISC-V-specific disassembler options are supported for use\n\
547 1.1 christos with the -M switch (multiple options should be separated by commas):\n"));
548 1.1 christos
549 1.1 christos fprintf (stream, _("\n\
550 1.1.1.2 christos numeric Print numeric register names, rather than ABI names.\n"));
551 1.1 christos
552 1.1 christos fprintf (stream, _("\n\
553 1.1 christos no-aliases Disassemble only into canonical instructions, rather\n\
554 1.1 christos than into pseudoinstructions.\n"));
555 1.1 christos
556 1.1 christos fprintf (stream, _("\n"));
557 1.1 christos }
558