]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/riscv-dis.c
Revert "2.41 Release sources"
[thirdparty/binutils-gdb.git] / opcodes / riscv-dis.c
CommitLineData
e23eba97 1/* RISC-V disassembler
d87bef3a 2 Copyright (C) 2011-2023 Free Software Foundation, Inc.
e23eba97
NC
3
4 Contributed by Andrew Waterman (andrew@sifive.com).
5 Based on MIPS target.
6
7 This file is part of the GNU opcodes library.
8
9 This library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 It is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
22
23#include "sysdep.h"
88c1242d 24#include "disassemble.h"
e23eba97
NC
25#include "libiberty.h"
26#include "opcode/riscv.h"
27#include "opintl.h"
28#include "elf-bfd.h"
29#include "elf/riscv.h"
f786c359 30#include "elfxx-riscv.h"
e23eba97 31
3dfb1b6d 32#include <stdint.h>
e23eba97
NC
33#include <ctype.h>
34
2b8fd839 35/* Current XLEN for the disassembler. */
3009ffe0 36static unsigned xlen = 0;
2b8fd839
TO
37
38/* Default ISA specification version (constant as of now). */
f786c359 39static enum riscv_spec_class default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1;
8f595e9b 40
2b8fd839
TO
41/* Default privileged specification
42 (as specified by the ELF attributes or the `priv-spec' option). */
43static enum riscv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE;
f786c359
NC
44
45static riscv_subset_list_t riscv_subsets;
46static riscv_parse_subset_t riscv_rps_dis =
47{
48 &riscv_subsets, /* subset_list. */
49 opcodes_error_handler,/* error_handler. */
50 &xlen, /* xlen. */
51 &default_isa_spec, /* isa_spec. */
52 false, /* check_unknown_prefixed_ext. */
53};
54
e23eba97
NC
55struct riscv_private_data
56{
57 bfd_vma gp;
58 bfd_vma print_addr;
59 bfd_vma hi_addr[OP_MASK_RD + 1];
8fe1be5f
TO
60 bool to_print_addr;
61 bool has_gp;
e23eba97
NC
62};
63
9b9b1092
NC
64/* Used for mapping symbols. */
65static int last_map_symbol = -1;
66static bfd_vma last_stop_offset = 0;
c2f60ac5
KC
67static bfd_vma last_map_symbol_boundary = 0;
68static enum riscv_seg_mstate last_map_state = MAP_NONE;
69static asection *last_map_section = NULL;
9b9b1092 70
2b8fd839 71/* Register names as used by the disassembler. */
e23eba97
NC
72static const char * const *riscv_gpr_names;
73static const char * const *riscv_fpr_names;
74
dcd709e0 75/* If set, disassemble as most general instruction. */
354c1c09 76static bool no_aliases = false;
e23eba97 77
2b8fd839
TO
78
79/* Set default RISC-V disassembler options. */
80
e23eba97
NC
81static void
82set_default_riscv_dis_options (void)
83{
84 riscv_gpr_names = riscv_gpr_names_abi;
85 riscv_fpr_names = riscv_fpr_names_abi;
354c1c09 86 no_aliases = false;
e23eba97
NC
87}
88
2b8fd839
TO
89/* Parse RISC-V disassembler option (without arguments). */
90
78933a4a 91static bool
8f595e9b 92parse_riscv_dis_option_without_args (const char *option)
e23eba97
NC
93{
94 if (strcmp (option, "no-aliases") == 0)
354c1c09 95 no_aliases = true;
e23eba97
NC
96 else if (strcmp (option, "numeric") == 0)
97 {
98 riscv_gpr_names = riscv_gpr_names_numeric;
99 riscv_fpr_names = riscv_fpr_names_numeric;
100 }
8f595e9b 101 else
78933a4a
AM
102 return false;
103 return true;
8f595e9b
NC
104}
105
2b8fd839
TO
106/* Parse RISC-V disassembler option (possibly with arguments). */
107
8f595e9b
NC
108static void
109parse_riscv_dis_option (const char *option)
110{
111 char *equal, *value;
112
113 if (parse_riscv_dis_option_without_args (option))
114 return;
115
116 equal = strchr (option, '=');
117 if (equal == NULL)
118 {
119 /* The option without '=' should be defined above. */
120 opcodes_error_handler (_("unrecognized disassembler option: %s"), option);
121 return;
122 }
123 if (equal == option
124 || *(equal + 1) == '\0')
125 {
126 /* Invalid options with '=', no option name before '=',
127 and no value after '='. */
128 opcodes_error_handler (_("unrecognized disassembler option with '=': %s"),
129 option);
130 return;
131 }
132
133 *equal = '\0';
134 value = equal + 1;
135 if (strcmp (option, "priv-spec") == 0)
136 {
3d73d29e
NC
137 enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE;
138 const char *name = NULL;
139
140 RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec);
141 if (priv_spec == PRIV_SPEC_CLASS_NONE)
b800637e 142 opcodes_error_handler (_("unknown privileged spec set by %s=%s"),
8152e040
NC
143 option, value);
144 else if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
145 default_priv_spec = priv_spec;
146 else if (default_priv_spec != priv_spec)
3d73d29e
NC
147 {
148 RISCV_GET_PRIV_SPEC_NAME (name, default_priv_spec);
149 opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, "
150 "the elf privilege attribute is %s"),
151 option, value, name);
152 }
8f595e9b 153 }
e23eba97
NC
154 else
155 {
a6743a54
AM
156 /* xgettext:c-format */
157 opcodes_error_handler (_("unrecognized disassembler option: %s"), option);
e23eba97
NC
158 }
159}
160
2b8fd839
TO
161/* Parse RISC-V disassembler options. */
162
e23eba97
NC
163static void
164parse_riscv_dis_options (const char *opts_in)
165{
166 char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
167
168 set_default_riscv_dis_options ();
169
170 for ( ; opt_end != NULL; opt = opt_end + 1)
171 {
172 if ((opt_end = strchr (opt, ',')) != NULL)
173 *opt_end = 0;
174 parse_riscv_dis_option (opt);
175 }
176
177 free (opts);
178}
179
180/* Print one argument from an array. */
181
182static void
183arg_print (struct disassemble_info *info, unsigned long val,
184 const char* const* array, size_t size)
185{
186 const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
49d31dc9 187 (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s", s);
e23eba97
NC
188}
189
2b8fd839
TO
190/* If we need to print an address, set its value and state. */
191
e23eba97 192static void
c7dee848
JW
193maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset,
194 int wide)
e23eba97
NC
195{
196 if (pd->hi_addr[base_reg] != (bfd_vma)-1)
197 {
35fd2b2b 198 pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset;
e23eba97
NC
199 pd->hi_addr[base_reg] = -1;
200 }
8fe1be5f 201 else if (base_reg == X_GP && pd->has_gp)
e23eba97
NC
202 pd->print_addr = pd->gp + offset;
203 else if (base_reg == X_TP || base_reg == 0)
204 pd->print_addr = offset;
48525554
TO
205 else
206 return; /* Don't print the address. */
8fe1be5f 207 pd->to_print_addr = true;
c7dee848
JW
208
209 /* Sign-extend a 32-bit value to a 64-bit value. */
210 if (wide)
211 pd->print_addr = (bfd_vma)(int32_t) pd->print_addr;
48525554
TO
212
213 /* Fit into a 32-bit value on RV32. */
214 if (xlen == 32)
215 pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr;
e23eba97
NC
216}
217
218/* Print insn arguments for 32/64-bit code. */
219
220static void
437e2ff1 221print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info)
e23eba97
NC
222{
223 struct riscv_private_data *pd = info->private_data;
224 int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
225 int rd = (l >> OP_SH_RD) & OP_MASK_RD;
49d31dc9 226 fprintf_styled_ftype print = info->fprintf_styled_func;
437e2ff1 227 const char *opargStart;
e23eba97 228
437e2ff1 229 if (*oparg != '\0')
49d31dc9 230 print (info->stream, dis_style_text, "\t");
e23eba97 231
437e2ff1 232 for (; *oparg != '\0'; oparg++)
e23eba97 233 {
437e2ff1
NC
234 opargStart = oparg;
235 switch (*oparg)
e23eba97
NC
236 {
237 case 'C': /* RVC */
437e2ff1 238 switch (*++oparg)
e23eba97 239 {
dcd709e0
NC
240 case 's': /* RS1 x8-x15. */
241 case 'w': /* RS1 x8-x15. */
49d31dc9 242 print (info->stream, dis_style_register, "%s",
e23eba97
NC
243 riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
244 break;
dcd709e0
NC
245 case 't': /* RS2 x8-x15. */
246 case 'x': /* RS2 x8-x15. */
49d31dc9 247 print (info->stream, dis_style_register, "%s",
e23eba97
NC
248 riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
249 break;
dcd709e0 250 case 'U': /* RS1, constrained to equal RD. */
49d31dc9
AB
251 print (info->stream, dis_style_register,
252 "%s", riscv_gpr_names[rd]);
e23eba97 253 break;
dcd709e0 254 case 'c': /* RS1, constrained to equal sp. */
49d31dc9
AB
255 print (info->stream, dis_style_register, "%s",
256 riscv_gpr_names[X_SP]);
e23eba97
NC
257 break;
258 case 'V': /* RS2 */
49d31dc9 259 print (info->stream, dis_style_register, "%s",
e23eba97
NC
260 riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
261 break;
f91d48de 262 case 'o':
e23eba97 263 case 'j':
c7dee848
JW
264 if (((l & MASK_C_ADDI) == MATCH_C_ADDI) && rd != 0)
265 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 0);
266 if (info->mach == bfd_mach_riscv64
267 && ((l & MASK_C_ADDIW) == MATCH_C_ADDIW) && rd != 0)
268 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 1);
49d31dc9
AB
269 print (info->stream, dis_style_immediate, "%d",
270 (int)EXTRACT_CITYPE_IMM (l));
e23eba97
NC
271 break;
272 case 'k':
49d31dc9
AB
273 print (info->stream, dis_style_address_offset, "%d",
274 (int)EXTRACT_CLTYPE_LW_IMM (l));
e23eba97
NC
275 break;
276 case 'l':
49d31dc9
AB
277 print (info->stream, dis_style_address_offset, "%d",
278 (int)EXTRACT_CLTYPE_LD_IMM (l));
e23eba97
NC
279 break;
280 case 'm':
49d31dc9
AB
281 print (info->stream, dis_style_address_offset, "%d",
282 (int)EXTRACT_CITYPE_LWSP_IMM (l));
e23eba97
NC
283 break;
284 case 'n':
49d31dc9
AB
285 print (info->stream, dis_style_address_offset, "%d",
286 (int)EXTRACT_CITYPE_LDSP_IMM (l));
e23eba97
NC
287 break;
288 case 'K':
49d31dc9
AB
289 print (info->stream, dis_style_immediate, "%d",
290 (int)EXTRACT_CIWTYPE_ADDI4SPN_IMM (l));
e23eba97
NC
291 break;
292 case 'L':
49d31dc9
AB
293 print (info->stream, dis_style_immediate, "%d",
294 (int)EXTRACT_CITYPE_ADDI16SP_IMM (l));
e23eba97
NC
295 break;
296 case 'M':
49d31dc9
AB
297 print (info->stream, dis_style_address_offset, "%d",
298 (int)EXTRACT_CSSTYPE_SWSP_IMM (l));
e23eba97
NC
299 break;
300 case 'N':
49d31dc9
AB
301 print (info->stream, dis_style_address_offset, "%d",
302 (int)EXTRACT_CSSTYPE_SDSP_IMM (l));
e23eba97
NC
303 break;
304 case 'p':
5a9f5403 305 info->target = EXTRACT_CBTYPE_IMM (l) + pc;
e23eba97
NC
306 (*info->print_address_func) (info->target, info);
307 break;
308 case 'a':
5a9f5403 309 info->target = EXTRACT_CJTYPE_IMM (l) + pc;
e23eba97
NC
310 (*info->print_address_func) (info->target, info);
311 break;
312 case 'u':
49d31dc9 313 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 314 (unsigned)(EXTRACT_CITYPE_IMM (l) & (RISCV_BIGIMM_REACH-1)));
e23eba97
NC
315 break;
316 case '>':
49d31dc9 317 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 318 (unsigned)EXTRACT_CITYPE_IMM (l) & 0x3f);
e23eba97
NC
319 break;
320 case '<':
49d31dc9 321 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 322 (unsigned)EXTRACT_CITYPE_IMM (l) & 0x1f);
e23eba97 323 break;
dcd709e0 324 case 'T': /* Floating-point RS2. */
49d31dc9 325 print (info->stream, dis_style_register, "%s",
e23eba97
NC
326 riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
327 break;
dcd709e0 328 case 'D': /* Floating-point RS2 x8-x15. */
49d31dc9 329 print (info->stream, dis_style_register, "%s",
e23eba97
NC
330 riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
331 break;
332 }
333 break;
334
65e4a99a
NC
335 case 'V': /* RVV */
336 switch (*++oparg)
337 {
338 case 'd':
339 case 'f':
49d31dc9 340 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
341 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
342 break;
343 case 'e':
344 if (!EXTRACT_OPERAND (VWD, l))
49d31dc9
AB
345 print (info->stream, dis_style_register, "%s",
346 riscv_gpr_names[0]);
65e4a99a 347 else
49d31dc9 348 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
349 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
350 break;
351 case 's':
49d31dc9 352 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
353 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS1, l)]);
354 break;
355 case 't':
356 case 'u': /* VS1 == VS2 already verified at this point. */
357 case 'v': /* VD == VS1 == VS2 already verified at this point. */
49d31dc9 358 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
359 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS2, l)]);
360 break;
361 case '0':
49d31dc9
AB
362 print (info->stream, dis_style_register, "%s",
363 riscv_vecr_names_numeric[0]);
65e4a99a
NC
364 break;
365 case 'b':
366 case 'c':
367 {
368 int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l)
369 : EXTRACT_RVV_VC_IMM (l);
370 unsigned int imm_vlmul = EXTRACT_OPERAND (VLMUL, imm);
371 unsigned int imm_vsew = EXTRACT_OPERAND (VSEW, imm);
372 unsigned int imm_vta = EXTRACT_OPERAND (VTA, imm);
373 unsigned int imm_vma = EXTRACT_OPERAND (VMA, imm);
abfdb09f 374 unsigned int imm_vtype_res = (imm >> 8);
65e4a99a
NC
375
376 if (imm_vsew < ARRAY_SIZE (riscv_vsew)
377 && imm_vlmul < ARRAY_SIZE (riscv_vlmul)
378 && imm_vta < ARRAY_SIZE (riscv_vta)
379 && imm_vma < ARRAY_SIZE (riscv_vma)
ee083a9e
NC
380 && !imm_vtype_res
381 && riscv_vsew[imm_vsew] != NULL
382 && riscv_vlmul[imm_vlmul] != NULL)
49d31dc9
AB
383 print (info->stream, dis_style_text, "%s,%s,%s,%s",
384 riscv_vsew[imm_vsew],
65e4a99a
NC
385 riscv_vlmul[imm_vlmul], riscv_vta[imm_vta],
386 riscv_vma[imm_vma]);
387 else
49d31dc9 388 print (info->stream, dis_style_immediate, "%d", imm);
65e4a99a
NC
389 }
390 break;
391 case 'i':
49d31dc9
AB
392 print (info->stream, dis_style_immediate, "%d",
393 (int)EXTRACT_RVV_VI_IMM (l));
65e4a99a
NC
394 break;
395 case 'j':
49d31dc9
AB
396 print (info->stream, dis_style_immediate, "%d",
397 (int)EXTRACT_RVV_VI_UIMM (l));
65e4a99a
NC
398 break;
399 case 'k':
49d31dc9
AB
400 print (info->stream, dis_style_immediate, "%d",
401 (int)EXTRACT_RVV_OFFSET (l));
65e4a99a 402 break;
c8cb3734
CM
403 case 'l':
404 print (info->stream, dis_style_immediate, "%d",
405 (int)EXTRACT_RVV_VI_UIMM6 (l));
406 break;
65e4a99a 407 case 'm':
f3a80235
TO
408 if (!EXTRACT_OPERAND (VMASK, l))
409 {
410 print (info->stream, dis_style_text, ",");
411 print (info->stream, dis_style_register, "%s",
412 riscv_vecm_names_numeric[0]);
413 }
65e4a99a
NC
414 break;
415 }
416 break;
417
e23eba97
NC
418 case ',':
419 case '(':
420 case ')':
421 case '[':
422 case ']':
49d31dc9 423 print (info->stream, dis_style_text, "%c", *oparg);
e23eba97
NC
424 break;
425
426 case '0':
dcd709e0 427 /* Only print constant 0 if it is the last argument. */
437e2ff1 428 if (!oparg[1])
49d31dc9 429 print (info->stream, dis_style_immediate, "0");
e23eba97
NC
430 break;
431
e23eba97 432 case 's':
35eeb78f 433 if ((l & MASK_JALR) == MATCH_JALR)
48525554 434 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
49d31dc9 435 print (info->stream, dis_style_register, "%s", riscv_gpr_names[rs1]);
e23eba97
NC
436 break;
437
438 case 't':
49d31dc9 439 print (info->stream, dis_style_register, "%s",
e23eba97
NC
440 riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
441 break;
442
443 case 'u':
49d31dc9 444 print (info->stream, dis_style_immediate, "0x%x",
e23eba97
NC
445 (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
446 break;
447
448 case 'm':
449 arg_print (info, EXTRACT_OPERAND (RM, l),
450 riscv_rm, ARRAY_SIZE (riscv_rm));
451 break;
452
453 case 'P':
454 arg_print (info, EXTRACT_OPERAND (PRED, l),
455 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
456 break;
457
458 case 'Q':
459 arg_print (info, EXTRACT_OPERAND (SUCC, l),
460 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
461 break;
462
463 case 'o':
c7dee848 464 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
b52d3cfc 465 /* Fall through. */
e23eba97
NC
466 case 'j':
467 if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0)
468 || (l & MASK_JALR) == MATCH_JALR)
c7dee848
JW
469 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
470 if (info->mach == bfd_mach_riscv64
471 && ((l & MASK_ADDIW) == MATCH_ADDIW) && rs1 != 0)
472 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 1);
49d31dc9
AB
473 print (info->stream, dis_style_immediate, "%d",
474 (int)EXTRACT_ITYPE_IMM (l));
e23eba97
NC
475 break;
476
477 case 'q':
c7dee848 478 maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l), 0);
49d31dc9
AB
479 print (info->stream, dis_style_address_offset, "%d",
480 (int)EXTRACT_STYPE_IMM (l));
e23eba97
NC
481 break;
482
483 case 'a':
5a9f5403 484 info->target = EXTRACT_JTYPE_IMM (l) + pc;
e23eba97
NC
485 (*info->print_address_func) (info->target, info);
486 break;
487
488 case 'p':
5a9f5403 489 info->target = EXTRACT_BTYPE_IMM (l) + pc;
e23eba97
NC
490 (*info->print_address_func) (info->target, info);
491 break;
492
493 case 'd':
494 if ((l & MASK_AUIPC) == MATCH_AUIPC)
495 pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
496 else if ((l & MASK_LUI) == MATCH_LUI)
497 pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
498 else if ((l & MASK_C_LUI) == MATCH_C_LUI)
5a9f5403 499 pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l);
49d31dc9 500 print (info->stream, dis_style_register, "%s", riscv_gpr_names[rd]);
e23eba97
NC
501 break;
502
3d1cafa0 503 case 'y':
9a76ca16 504 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 505 (unsigned)EXTRACT_OPERAND (BS, l));
3d1cafa0 506 break;
507
e23eba97 508 case 'z':
49d31dc9 509 print (info->stream, dis_style_register, "%s", riscv_gpr_names[0]);
e23eba97
NC
510 break;
511
512 case '>':
49d31dc9 513 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 514 (unsigned)EXTRACT_OPERAND (SHAMT, l));
e23eba97
NC
515 break;
516
517 case '<':
49d31dc9 518 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 519 (unsigned)EXTRACT_OPERAND (SHAMTW, l));
e23eba97
NC
520 break;
521
522 case 'S':
523 case 'U':
49d31dc9 524 print (info->stream, dis_style_register, "%s", riscv_fpr_names[rs1]);
e23eba97
NC
525 break;
526
527 case 'T':
49d31dc9
AB
528 print (info->stream, dis_style_register, "%s",
529 riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
e23eba97
NC
530 break;
531
532 case 'D':
49d31dc9 533 print (info->stream, dis_style_register, "%s", riscv_fpr_names[rd]);
e23eba97
NC
534 break;
535
536 case 'R':
49d31dc9
AB
537 print (info->stream, dis_style_register, "%s",
538 riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
e23eba97
NC
539 break;
540
541 case 'E':
542 {
dcd709e0 543 static const char *riscv_csr_hash[4096]; /* Total 2^12 CSRs. */
78933a4a 544 static bool init_csr = false;
e23eba97 545 unsigned int csr = EXTRACT_OPERAND (CSR, l);
8f595e9b
NC
546
547 if (!init_csr)
e23eba97 548 {
8f595e9b
NC
549 unsigned int i;
550 for (i = 0; i < 4096; i++)
551 riscv_csr_hash[i] = NULL;
552
dcd709e0 553 /* Set to the newest privileged version. */
8f595e9b
NC
554 if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
555 default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;
556
08ccfccf
NC
557#define DECLARE_CSR(name, num, class, define_version, abort_version) \
558 if (riscv_csr_hash[num] == NULL \
559 && ((define_version == PRIV_SPEC_CLASS_NONE \
560 && abort_version == PRIV_SPEC_CLASS_NONE) \
561 || (default_priv_spec >= define_version \
562 && default_priv_spec < abort_version))) \
8f595e9b
NC
563 riscv_csr_hash[num] = #name;
564#define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \
565 DECLARE_CSR (name, num, class, define_version, abort_version)
e23eba97
NC
566#include "opcode/riscv-opc.h"
567#undef DECLARE_CSR
568 }
8f595e9b
NC
569
570 if (riscv_csr_hash[csr] != NULL)
e840e61c
AB
571 print (info->stream, dis_style_register, "%s",
572 riscv_csr_hash[csr]);
e23eba97 573 else
9a76ca16 574 print (info->stream, dis_style_immediate, "0x%x", csr);
e23eba97
NC
575 break;
576 }
577
3d1cafa0 578 case 'Y':
9a76ca16 579 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 580 (unsigned) EXTRACT_OPERAND (RNUM, l));
3d1cafa0 581 break;
582
e23eba97 583 case 'Z':
9a76ca16 584 print (info->stream, dis_style_immediate, "%d", rs1);
e23eba97
NC
585 break;
586
54bca63b
TO
587 case 'W': /* Various operands. */
588 {
589 switch (*++oparg)
590 {
591 case 'i':
592 switch (*++oparg)
593 {
594 case 'f':
595 print (info->stream, dis_style_address_offset, "%d",
596 (int) EXTRACT_STYPE_IMM (l));
597 break;
598 default:
599 goto undefined_modifier;
600 }
601 break;
1f3fc45b
CM
602 case 'f':
603 switch (*++oparg)
604 {
605 case 'v':
606 if (riscv_fli_symval[rs1])
607 print (info->stream, dis_style_text, "%s",
608 riscv_fli_symval[rs1]);
609 else
610 print (info->stream, dis_style_immediate, "%a",
611 riscv_fli_numval[rs1]);
612 break;
613 default:
614 goto undefined_modifier;
615 }
616 break;
b5c37946
SJ
617 case 'c': /* Zcb extension 16 bits length instruction fields. */
618 switch (*++oparg)
619 {
620 case 'b':
621 print (info->stream, dis_style_immediate, "%d",
622 (int)EXTRACT_ZCB_BYTE_UIMM (l));
623 break;
624 case 'h':
625 print (info->stream, dis_style_immediate, "%d",
626 (int)EXTRACT_ZCB_HALFWORD_UIMM (l));
627 break;
628 default: break;
629 }
630 break;
54bca63b
TO
631 default:
632 goto undefined_modifier;
633 }
634 }
635 break;
636
8b7419c4
CM
637 case 'X': /* Integer immediate. */
638 {
639 size_t n;
640 size_t s;
641 bool sign;
642
643 switch (*++oparg)
644 {
25236d63
CM
645 case 'l': /* Literal. */
646 oparg++;
647 while (*oparg && *oparg != ',')
648 {
a13886e2 649 print (info->stream, dis_style_immediate, "%c", *oparg);
25236d63
CM
650 oparg++;
651 }
652 oparg--;
653 break;
8b7419c4
CM
654 case 's': /* 'XsN@S' ... N-bit signed immediate at bit S. */
655 sign = true;
656 goto print_imm;
657 case 'u': /* 'XuN@S' ... N-bit unsigned immediate at bit S. */
658 sign = false;
659 goto print_imm;
660 print_imm:
b0423163 661 n = strtol (oparg + 1, (char **)&oparg, 10);
8b7419c4
CM
662 if (*oparg != '@')
663 goto undefined_modifier;
b0423163 664 s = strtol (oparg + 1, (char **)&oparg, 10);
8b7419c4
CM
665 oparg--;
666
667 if (!sign)
15543290
TO
668 print (info->stream, dis_style_immediate, "%lu",
669 (unsigned long)EXTRACT_U_IMM (n, s, l));
8b7419c4 670 else
15543290
TO
671 print (info->stream, dis_style_immediate, "%li",
672 (signed long)EXTRACT_S_IMM (n, s, l));
8b7419c4
CM
673 break;
674 default:
675 goto undefined_modifier;
676 }
677 }
678 break;
1f3fc45b 679
e23eba97 680 default:
8b7419c4 681 undefined_modifier:
e23eba97 682 /* xgettext:c-format */
49d31dc9
AB
683 print (info->stream, dis_style_text,
684 _("# internal error, undefined modifier (%c)"),
437e2ff1 685 *opargStart);
e23eba97
NC
686 return;
687 }
688 }
689}
690
691/* Print the RISC-V instruction at address MEMADDR in debugged memory,
692 on using INFO. Returns length of the instruction, in bytes.
693 BIGENDIAN must be 1 if this is big-endian code, 0 if
694 this is little-endian code. */
695
696static int
97f006bc
TO
697riscv_disassemble_insn (bfd_vma memaddr,
698 insn_t word,
699 const bfd_byte *packet,
700 disassemble_info *info)
e23eba97
NC
701{
702 const struct riscv_opcode *op;
354c1c09 703 static bool init = false;
e23eba97 704 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
26e91972 705 struct riscv_private_data *pd = info->private_data;
0655669b
JB
706 int insnlen, i;
707 bool printed;
e23eba97
NC
708
709#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
710
711 /* Build a hash table to shorten the search time. */
712 if (! init)
713 {
714 for (op = riscv_opcodes; op->name; op++)
715 if (!riscv_hash[OP_HASH_IDX (op->match)])
716 riscv_hash[OP_HASH_IDX (op->match)] = op;
717
354c1c09 718 init = true;
e23eba97
NC
719 }
720
e23eba97
NC
721 insnlen = riscv_insn_length (word);
722
d7560e2d
JW
723 /* RISC-V instructions are always little-endian. */
724 info->endian_code = BFD_ENDIAN_LITTLE;
725
e23eba97
NC
726 info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
727 info->bytes_per_line = 8;
d7560e2d
JW
728 /* We don't support constant pools, so this must be code. */
729 info->display_endian = info->endian_code;
e23eba97
NC
730 info->insn_info_valid = 1;
731 info->branch_delay_insns = 0;
732 info->data_size = 0;
733 info->insn_type = dis_nonbranch;
734 info->target = 0;
735 info->target2 = 0;
736
737 op = riscv_hash[OP_HASH_IDX (word)];
738 if (op != NULL)
739 {
2922d21d
AW
740 /* If XLEN is not known, get its value from the ELF class. */
741 if (info->mach == bfd_mach_riscv64)
742 xlen = 64;
743 else if (info->mach == bfd_mach_riscv32)
744 xlen = 32;
745 else if (info->section != NULL)
e23eba97
NC
746 {
747 Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
748 xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
749 }
750
2b8fd839 751 /* If arch has the Zfinx extension, replace FPR with GPR. */
1469f944 752 if (riscv_subset_supports (&riscv_rps_dis, "zfinx"))
3d5d6bd5 753 riscv_fpr_names = riscv_gpr_names;
40f1a1a4
NC
754 else
755 riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi ?
756 riscv_fpr_names_abi : riscv_fpr_names_numeric;
de83e514 757
e23eba97
NC
758 for (; op->name; op++)
759 {
760 /* Does the opcode match? */
761 if (! (op->match_func) (op, word))
762 continue;
763 /* Is this a pseudo-instruction and may we print it as such? */
764 if (no_aliases && (op->pinfo & INSN_ALIAS))
765 continue;
766 /* Is this instruction restricted to a certain value of XLEN? */
43135d3b 767 if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
e23eba97 768 continue;
2b8fd839 769 /* Is this instruction supported by the current architecture? */
f786c359
NC
770 if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class))
771 continue;
772
e23eba97 773 /* It's a match. */
49d31dc9
AB
774 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
775 "%s", op->name);
e23eba97
NC
776 print_insn_args (op->args, word, memaddr, info);
777
778 /* Try to disassemble multi-instruction addressing sequences. */
8fe1be5f 779 if (pd->to_print_addr)
e23eba97
NC
780 {
781 info->target = pd->print_addr;
49d31dc9
AB
782 (*info->fprintf_styled_func)
783 (info->stream, dis_style_comment_start, " # ");
e23eba97 784 (*info->print_address_func) (info->target, info);
8fe1be5f 785 pd->to_print_addr = false;
e23eba97
NC
786 }
787
eb41b248
JW
788 /* Finish filling out insn_info fields. */
789 switch (op->pinfo & INSN_TYPE)
790 {
791 case INSN_BRANCH:
792 info->insn_type = dis_branch;
793 break;
794 case INSN_CONDBRANCH:
795 info->insn_type = dis_condbranch;
796 break;
797 case INSN_JSR:
798 info->insn_type = dis_jsr;
799 break;
800 case INSN_DREF:
801 info->insn_type = dis_dref;
802 break;
803 default:
804 break;
805 }
806
807 if (op->pinfo & INSN_DATA_SIZE)
808 {
809 int size = ((op->pinfo & INSN_DATA_SIZE)
810 >> INSN_DATA_SIZE_SHIFT);
811 info->data_size = 1 << (size - 1);
812 }
813
e23eba97
NC
814 return insnlen;
815 }
816 }
817
0655669b
JB
818 /* We did not find a match, so just print the instruction bits in
819 the shape of an assembler .insn directive. */
e23eba97 820 info->insn_type = dis_noninsn;
0655669b
JB
821 (*info->fprintf_styled_func)
822 (info->stream, dis_style_assembler_directive, ".insn");
823 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
824 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
825 "%d", insnlen);
826 (*info->fprintf_styled_func) (info->stream, dis_style_text, ", ");
827 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x");
828 for (i = insnlen, printed = false; i >= 2; )
6a7f5766 829 {
0655669b
JB
830 i -= 2;
831 word = bfd_get_bits (packet + i, 16, false);
832 if (!word && !printed)
833 continue;
834
49d31dc9 835 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
0655669b
JB
836 "%04x", (unsigned int) word);
837 printed = true;
6a7f5766 838 }
0655669b 839
e23eba97
NC
840 return insnlen;
841}
842
9b9b1092
NC
843/* Return true if we find the suitable mapping symbol,
844 and also update the STATE. Otherwise, return false. */
845
846static bool
847riscv_get_map_state (int n,
848 enum riscv_seg_mstate *state,
849 struct disassemble_info *info)
850{
851 const char *name;
852
853 /* If the symbol is in a different section, ignore it. */
854 if (info->section != NULL
855 && info->section != info->symtab[n]->section)
856 return false;
857
858 name = bfd_asymbol_name(info->symtab[n]);
859 if (strcmp (name, "$x") == 0)
860 *state = MAP_INSN;
861 else if (strcmp (name, "$d") == 0)
862 *state = MAP_DATA;
40f1a1a4
NC
863 else if (strncmp (name, "$xrv", 4) == 0)
864 {
865 *state = MAP_INSN;
866 riscv_release_subset_list (&riscv_subsets);
867 riscv_parse_subset (&riscv_rps_dis, name + 2);
868 }
9b9b1092
NC
869 else
870 return false;
871
872 return true;
873}
874
875/* Check the sorted symbol table (sorted by the symbol value), find the
876 suitable mapping symbols. */
877
878static enum riscv_seg_mstate
879riscv_search_mapping_symbol (bfd_vma memaddr,
880 struct disassemble_info *info)
881{
882 enum riscv_seg_mstate mstate;
883 bool from_last_map_symbol;
884 bool found = false;
885 int symbol = -1;
886 int n;
887
c2f60ac5
KC
888 /* Return the last map state if the address is still within the range of the
889 last mapping symbol. */
890 if (last_map_section == info->section
891 && (memaddr < last_map_symbol_boundary))
892 return last_map_state;
893
894 last_map_section = info->section;
895
9b9b1092
NC
896 /* Decide whether to print the data or instruction by default, in case
897 we can not find the corresponding mapping symbols. */
898 mstate = MAP_DATA;
899 if ((info->section
900 && info->section->flags & SEC_CODE)
901 || !info->section)
902 mstate = MAP_INSN;
903
904 if (info->symtab_size == 0
905 || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour)
906 return mstate;
907
908 /* Reset the last_map_symbol if we start to dump a new section. */
909 if (memaddr <= 0)
910 last_map_symbol = -1;
911
912 /* If the last stop offset is different from the current one, then
913 don't use the last_map_symbol to search. We usually reset the
914 info->stop_offset when handling a new section. */
915 from_last_map_symbol = (last_map_symbol >= 0
916 && info->stop_offset == last_stop_offset);
917
918 /* Start scanning at the start of the function, or wherever
919 we finished last time. */
920 n = info->symtab_pos + 1;
921 if (from_last_map_symbol && n >= last_map_symbol)
922 n = last_map_symbol;
923
924 /* Find the suitable mapping symbol to dump. */
925 for (; n < info->symtab_size; n++)
926 {
927 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
928 /* We have searched all possible symbols in the range. */
929 if (addr > memaddr)
930 break;
931 if (riscv_get_map_state (n, &mstate, info))
932 {
933 symbol = n;
934 found = true;
935 /* Do not stop searching, in case there are some mapping
936 symbols have the same value, but have different names.
937 Use the last one. */
938 }
939 }
940
941 /* We can not find the suitable mapping symbol above. Therefore, we
b5c37946 942 look forwards and try to find it again, but don't go past the start
9b9b1092
NC
943 of the section. Otherwise a data section without mapping symbols
944 can pick up a text mapping symbol of a preceeding section. */
945 if (!found)
946 {
947 n = info->symtab_pos;
948 if (from_last_map_symbol && n >= last_map_symbol)
949 n = last_map_symbol;
950
951 for (; n >= 0; n--)
952 {
953 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
954 /* We have searched all possible symbols in the range. */
955 if (addr < (info->section ? info->section->vma : 0))
956 break;
957 /* Stop searching once we find the closed mapping symbol. */
958 if (riscv_get_map_state (n, &mstate, info))
959 {
960 symbol = n;
961 found = true;
962 break;
963 }
964 }
965 }
966
c2f60ac5
KC
967 if (found)
968 {
969 /* Find the next mapping symbol to determine the boundary of this mapping
970 symbol. */
971
972 bool found_next = false;
973 /* Try to found next mapping symbol. */
974 for (n = symbol + 1; n < info->symtab_size; n++)
975 {
976 if (info->symtab[symbol]->section != info->symtab[n]->section)
977 continue;
978
979 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
980 const char *sym_name = bfd_asymbol_name(info->symtab[n]);
981 if (sym_name[0] == '$' && (sym_name[1] == 'x' || sym_name[1] == 'd'))
982 {
983 /* The next mapping symbol has been found, and it represents the
984 boundary of this mapping symbol. */
985 found_next = true;
986 last_map_symbol_boundary = addr;
987 break;
988 }
989 }
990
991 /* No further mapping symbol has been found, indicating that the boundary
992 of the current mapping symbol is the end of this section. */
993 if (!found_next)
994 last_map_symbol_boundary = info->section->vma + info->section->size;
995 }
996
9b9b1092
NC
997 /* Save the information for next use. */
998 last_map_symbol = symbol;
999 last_stop_offset = info->stop_offset;
1000
1001 return mstate;
1002}
1003
1004/* Decide which data size we should print. */
1005
1006static bfd_vma
1007riscv_data_length (bfd_vma memaddr,
1008 disassemble_info *info)
1009{
1010 bfd_vma length;
1011 bool found = false;
1012
1013 length = 4;
1014 if (info->symtab_size != 0
1015 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour
1016 && last_map_symbol >= 0)
1017 {
1018 int n;
1019 enum riscv_seg_mstate m = MAP_NONE;
1020 for (n = last_map_symbol + 1; n < info->symtab_size; n++)
1021 {
1022 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1023 if (addr > memaddr
1024 && riscv_get_map_state (n, &m, info))
1025 {
1026 if (addr - memaddr < length)
1027 length = addr - memaddr;
1028 found = true;
1029 break;
1030 }
1031 }
1032 }
1033 if (!found)
1034 {
1035 /* Do not set the length which exceeds the section size. */
1036 bfd_vma offset = info->section->vma + info->section->size;
1037 offset -= memaddr;
1038 length = (offset < length) ? offset : length;
1039 }
1040 length = length == 3 ? 2 : length;
1041 return length;
1042}
1043
1044/* Dump the data contents. */
1045
1046static int
1047riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED,
1048 insn_t data,
97f006bc 1049 const bfd_byte *packet ATTRIBUTE_UNUSED,
9b9b1092
NC
1050 disassemble_info *info)
1051{
1052 info->display_endian = info->endian;
1053
1054 switch (info->bytes_per_chunk)
1055 {
1056 case 1:
1057 info->bytes_per_line = 6;
49d31dc9 1058 (*info->fprintf_styled_func)
f3a80235
TO
1059 (info->stream, dis_style_assembler_directive, ".byte");
1060 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1061 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1062 "0x%02x", (unsigned)data);
9b9b1092
NC
1063 break;
1064 case 2:
1065 info->bytes_per_line = 8;
49d31dc9 1066 (*info->fprintf_styled_func)
f3a80235
TO
1067 (info->stream, dis_style_assembler_directive, ".short");
1068 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1069 (*info->fprintf_styled_func)
e0b004c5 1070 (info->stream, dis_style_immediate, "0x%04x", (unsigned) data);
9b9b1092
NC
1071 break;
1072 case 4:
1073 info->bytes_per_line = 8;
49d31dc9 1074 (*info->fprintf_styled_func)
f3a80235
TO
1075 (info->stream, dis_style_assembler_directive, ".word");
1076 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1077 (*info->fprintf_styled_func)
e0b004c5
TO
1078 (info->stream, dis_style_immediate, "0x%08lx",
1079 (unsigned long) data);
9b9b1092
NC
1080 break;
1081 case 8:
1082 info->bytes_per_line = 8;
49d31dc9 1083 (*info->fprintf_styled_func)
f3a80235
TO
1084 (info->stream, dis_style_assembler_directive, ".dword");
1085 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9
AB
1086 (*info->fprintf_styled_func)
1087 (info->stream, dis_style_immediate, "0x%016llx",
1088 (unsigned long long) data);
9b9b1092
NC
1089 break;
1090 default:
1091 abort ();
1092 }
1093 return info->bytes_per_chunk;
1094}
1095
26e91972
NC
1096static bool
1097riscv_init_disasm_info (struct disassemble_info *info)
1098{
1099 int i;
1100
1101 struct riscv_private_data *pd =
1102 xcalloc (1, sizeof (struct riscv_private_data));
1103 pd->gp = 0;
1104 pd->print_addr = 0;
1105 for (i = 0; i < (int) ARRAY_SIZE (pd->hi_addr); i++)
1106 pd->hi_addr[i] = -1;
1107 pd->to_print_addr = false;
1108 pd->has_gp = false;
1109
1110 for (i = 0; i < info->symtab_size; i++)
1111 {
1112 asymbol *sym = info->symtab[i];
1113 if (strcmp (bfd_asymbol_name (sym), RISCV_GP_SYMBOL) == 0)
1114 {
1115 pd->gp = bfd_asymbol_value (sym);
1116 pd->has_gp = true;
1117 }
1118 }
1119
1120 info->private_data = pd;
1121 return true;
1122}
1123
e23eba97
NC
1124int
1125print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
1126{
73e30e72 1127 bfd_byte packet[RISCV_MAX_INSN_LEN];
e23eba97 1128 insn_t insn = 0;
9b9b1092 1129 bfd_vma dump_size;
e23eba97 1130 int status;
9b9b1092 1131 enum riscv_seg_mstate mstate;
97f006bc
TO
1132 int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *,
1133 struct disassemble_info *);
e23eba97
NC
1134
1135 if (info->disassembler_options != NULL)
1136 {
1137 parse_riscv_dis_options (info->disassembler_options);
1138 /* Avoid repeatedly parsing the options. */
1139 info->disassembler_options = NULL;
1140 }
1141 else if (riscv_gpr_names == NULL)
1142 set_default_riscv_dis_options ();
1143
26e91972
NC
1144 if (info->private_data == NULL && !riscv_init_disasm_info (info))
1145 return -1;
1146
9b9b1092 1147 mstate = riscv_search_mapping_symbol (memaddr, info);
c2f60ac5
KC
1148 /* Save the last mapping state. */
1149 last_map_state = mstate;
9b9b1092
NC
1150
1151 /* Set the size to dump. */
1152 if (mstate == MAP_DATA
1153 && (info->flags & DISASSEMBLE_DATA) == 0)
1154 {
1155 dump_size = riscv_data_length (memaddr, info);
1156 info->bytes_per_chunk = dump_size;
1157 riscv_disassembler = riscv_disassemble_data;
1158 }
1159 else
e23eba97 1160 {
9b9b1092
NC
1161 /* Get the first 2-bytes to check the lenghth of instruction. */
1162 status = (*info->read_memory_func) (memaddr, packet, 2, info);
e23eba97
NC
1163 if (status != 0)
1164 {
e23eba97 1165 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1166 return -1;
e23eba97 1167 }
9b9b1092
NC
1168 insn = (insn_t) bfd_getl16 (packet);
1169 dump_size = riscv_insn_length (insn);
1170 riscv_disassembler = riscv_disassemble_insn;
1171 }
e23eba97 1172
9b9b1092
NC
1173 /* Fetch the instruction to dump. */
1174 status = (*info->read_memory_func) (memaddr, packet, dump_size, info);
1175 if (status != 0)
1176 {
1177 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1178 return -1;
e23eba97 1179 }
9b9b1092 1180 insn = (insn_t) bfd_get_bits (packet, dump_size * 8, false);
e23eba97 1181
97f006bc 1182 return (*riscv_disassembler) (memaddr, insn, packet, info);
e23eba97
NC
1183}
1184
8152e040
NC
1185disassembler_ftype
1186riscv_get_disassembler (bfd *abfd)
1187{
f786c359
NC
1188 const char *default_arch = "rv64gc";
1189
16089f32 1190 if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
8152e040 1191 {
16089f32
TH
1192 const char *sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
1193 if (bfd_get_section_by_name (abfd, sec_name) != NULL)
f786c359 1194 {
16089f32
TH
1195 obj_attribute *attr = elf_known_obj_attributes_proc (abfd);
1196 unsigned int Tag_a = Tag_RISCV_priv_spec;
1197 unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
1198 unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
1199 riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i,
1200 attr[Tag_b].i,
1201 attr[Tag_c].i,
1202 &default_priv_spec);
1203 default_arch = attr[Tag_RISCV_arch].s;
f786c359 1204 }
8152e040 1205 }
f786c359
NC
1206
1207 riscv_release_subset_list (&riscv_subsets);
1208 riscv_parse_subset (&riscv_rps_dis, default_arch);
1209 return print_insn_riscv;
8152e040
NC
1210}
1211
884b49e3
AB
1212/* Prevent use of the fake labels that are generated as part of the DWARF
1213 and for relaxable relocations in the assembler. */
1214
78933a4a 1215bool
884b49e3
AB
1216riscv_symbol_is_valid (asymbol * sym,
1217 struct disassemble_info * info ATTRIBUTE_UNUSED)
1218{
1219 const char * name;
1220
1221 if (sym == NULL)
78933a4a 1222 return false;
884b49e3
AB
1223
1224 name = bfd_asymbol_name (sym);
1225
9b9b1092
NC
1226 return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0
1227 && !riscv_elf_is_mapping_symbols (name));
884b49e3 1228}
3a337a86
AB
1229\f
1230
1231/* Indices into option argument vector for options accepting an argument.
1232 Use RISCV_OPTION_ARG_NONE for options accepting no argument. */
1233
1234typedef enum
1235{
1236 RISCV_OPTION_ARG_NONE = -1,
1237 RISCV_OPTION_ARG_PRIV_SPEC,
1238
1239 RISCV_OPTION_ARG_COUNT
1240} riscv_option_arg_t;
1241
1242/* Valid RISCV disassembler options. */
1243
1244static struct
1245{
1246 const char *name;
1247 const char *description;
1248 riscv_option_arg_t arg;
1249} riscv_options[] =
1250{
1251 { "numeric",
1252 N_("Print numeric register names, rather than ABI names."),
1253 RISCV_OPTION_ARG_NONE },
1254 { "no-aliases",
1255 N_("Disassemble only into canonical instructions."),
1256 RISCV_OPTION_ARG_NONE },
1257 { "priv-spec=",
1258 N_("Print the CSR according to the chosen privilege spec."),
1259 RISCV_OPTION_ARG_PRIV_SPEC }
1260};
1261
1262/* Build the structure representing valid RISCV disassembler options.
1263 This is done dynamically for maintenance ease purpose; a static
1264 initializer would be unreadable. */
1265
1266const disasm_options_and_args_t *
1267disassembler_options_riscv (void)
1268{
1269 static disasm_options_and_args_t *opts_and_args;
1270
1271 if (opts_and_args == NULL)
1272 {
1273 size_t num_options = ARRAY_SIZE (riscv_options);
1274 size_t num_args = RISCV_OPTION_ARG_COUNT;
1275 disasm_option_arg_t *args;
1276 disasm_options_t *opts;
1277 size_t i, priv_spec_count;
1278
1279 args = XNEWVEC (disasm_option_arg_t, num_args + 1);
1280
1281 args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC";
1282 priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_CLASS_NONE - 1;
1283 args[RISCV_OPTION_ARG_PRIV_SPEC].values
1284 = XNEWVEC (const char *, priv_spec_count + 1);
1285 for (i = 0; i < priv_spec_count; i++)
1286 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i]
1287 = riscv_priv_specs[i].name;
1288 /* The array we return must be NULL terminated. */
1289 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] = NULL;
1290
1291 /* The array we return must be NULL terminated. */
1292 args[num_args].name = NULL;
1293 args[num_args].values = NULL;
1294
1295 opts_and_args = XNEW (disasm_options_and_args_t);
1296 opts_and_args->args = args;
1297
1298 opts = &opts_and_args->options;
1299 opts->name = XNEWVEC (const char *, num_options + 1);
1300 opts->description = XNEWVEC (const char *, num_options + 1);
1301 opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
1302 for (i = 0; i < num_options; i++)
1303 {
1304 opts->name[i] = riscv_options[i].name;
1305 opts->description[i] = _(riscv_options[i].description);
1306 if (riscv_options[i].arg != RISCV_OPTION_ARG_NONE)
1307 opts->arg[i] = &args[riscv_options[i].arg];
1308 else
1309 opts->arg[i] = NULL;
1310 }
1311 /* The array we return must be NULL terminated. */
1312 opts->name[i] = NULL;
1313 opts->description[i] = NULL;
1314 opts->arg[i] = NULL;
1315 }
1316
1317 return opts_and_args;
1318}
884b49e3 1319
e23eba97
NC
1320void
1321print_riscv_disassembler_options (FILE *stream)
1322{
3a337a86
AB
1323 const disasm_options_and_args_t *opts_and_args;
1324 const disasm_option_arg_t *args;
1325 const disasm_options_t *opts;
1326 size_t max_len = 0;
1327 size_t i;
1328 size_t j;
1329
1330 opts_and_args = disassembler_options_riscv ();
1331 opts = &opts_and_args->options;
1332 args = opts_and_args->args;
1333
e23eba97 1334 fprintf (stream, _("\n\
3a337a86 1335The following RISC-V specific disassembler options are supported for use\n\
e23eba97 1336with the -M switch (multiple options should be separated by commas):\n"));
3a337a86 1337 fprintf (stream, "\n");
e23eba97 1338
3a337a86
AB
1339 /* Compute the length of the longest option name. */
1340 for (i = 0; opts->name[i] != NULL; i++)
1341 {
1342 size_t len = strlen (opts->name[i]);
8f595e9b 1343
3a337a86
AB
1344 if (opts->arg[i] != NULL)
1345 len += strlen (opts->arg[i]->name);
1346 if (max_len < len)
1347 max_len = len;
1348 }
e23eba97 1349
3a337a86
AB
1350 for (i = 0, max_len++; opts->name[i] != NULL; i++)
1351 {
1352 fprintf (stream, " %s", opts->name[i]);
1353 if (opts->arg[i] != NULL)
1354 fprintf (stream, "%s", opts->arg[i]->name);
1355 if (opts->description[i] != NULL)
1356 {
1357 size_t len = strlen (opts->name[i]);
1358
1359 if (opts->arg != NULL && opts->arg[i] != NULL)
1360 len += strlen (opts->arg[i]->name);
1361 fprintf (stream, "%*c %s", (int) (max_len - len), ' ',
1362 opts->description[i]);
1363 }
1364 fprintf (stream, "\n");
1365 }
1366
1367 for (i = 0; args[i].name != NULL; i++)
1368 {
9869e2e5
TO
1369 if (args[i].values == NULL)
1370 continue;
3a337a86
AB
1371 fprintf (stream, _("\n\
1372 For the options above, the following values are supported for \"%s\":\n "),
1373 args[i].name);
1374 for (j = 0; args[i].values[j] != NULL; j++)
1375 fprintf (stream, " %s", args[i].values[j]);
1376 fprintf (stream, _("\n"));
1377 }
e23eba97
NC
1378
1379 fprintf (stream, _("\n"));
1380}
26e91972
NC
1381
1382void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED)
1383{
1384 riscv_release_subset_list (&riscv_subsets);
1385}