]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/riscv-dis.c
gas: introduce .errif and .warnif
[thirdparty/binutils-gdb.git] / opcodes / riscv-dis.c
CommitLineData
e23eba97 1/* RISC-V disassembler
e8e7cf2a 2 Copyright (C) 2011-2025 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
5ccd3193
AB
35/* The RISC-V disassembler produces styled output using
36 disassemble_info::fprintf_styled_func. This define prevents use of
37 disassemble_info::fprintf_func which is for unstyled output. */
38#define fprintf_func please_use_fprintf_styled_func_instead
39
0d1f4362
MP
40/* The earliest privilege spec supported by disassembler. */
41#define PRIV_SPEC_EARLIEST PRIV_SPEC_CLASS_1P10
42
e23eba97
NC
43struct riscv_private_data
44{
45 bfd_vma gp;
46 bfd_vma print_addr;
47 bfd_vma hi_addr[OP_MASK_RD + 1];
8fe1be5f
TO
48 bool to_print_addr;
49 bool has_gp;
3f61a38b
NC
50 /* Current XLEN for the disassembler. */
51 unsigned xlen;
52 /* Default ISA specification version. */
53 enum riscv_spec_class default_isa_spec;
54 /* Default privileged specification. */
55 enum riscv_spec_class default_priv_spec;
56 /* Used for architecture parser. */
57 riscv_parse_subset_t riscv_rps_dis;
ade87b8e
AO
58 /* Default architecture string for the object file. It will be changed once
59 elf architecture attribute exits. This is used for mapping symbol $x. */
60 const char* default_arch;
3f61a38b
NC
61 /* Used for mapping symbols. */
62 int last_map_symbol;
63 bfd_vma last_stop_offset;
64 bfd_vma last_map_symbol_boundary;
65 enum riscv_seg_mstate last_map_state;
66 asection *last_map_section;
67 /* Register names as used by the disassembler. */
68 const char (*riscv_gpr_names)[NRC];
69 const char (*riscv_fpr_names)[NRC];
70 /* If set, disassemble as most general instruction. */
71 bool no_aliases;
88891208 72 /* If set, disassemble without checking architecture string, just like what
3f61a38b
NC
73 we did at the beginning. */
74 bool all_ext;
e23eba97
NC
75};
76
2b8fd839
TO
77/* Set default RISC-V disassembler options. */
78
e23eba97 79static void
3f61a38b 80set_default_riscv_dis_options (struct disassemble_info *info)
e23eba97 81{
3f61a38b
NC
82 struct riscv_private_data *pd = info->private_data;
83 pd->riscv_gpr_names = riscv_gpr_names_abi;
84 pd->riscv_fpr_names = riscv_fpr_names_abi;
85 pd->no_aliases = false;
88891208 86 pd->all_ext = false;
e23eba97
NC
87}
88
2b8fd839
TO
89/* Parse RISC-V disassembler option (without arguments). */
90
78933a4a 91static bool
3f61a38b
NC
92parse_riscv_dis_option_without_args (const char *option,
93 struct disassemble_info *info)
e23eba97 94{
3f61a38b 95 struct riscv_private_data *pd = info->private_data;
e23eba97 96 if (strcmp (option, "no-aliases") == 0)
3f61a38b 97 pd->no_aliases = true;
e23eba97
NC
98 else if (strcmp (option, "numeric") == 0)
99 {
3f61a38b
NC
100 pd->riscv_gpr_names = riscv_gpr_names_numeric;
101 pd->riscv_fpr_names = riscv_fpr_names_numeric;
e23eba97 102 }
004a5bfc 103 else if (strcmp (option, "max") == 0)
3f61a38b 104 pd->all_ext = true;
8f595e9b 105 else
78933a4a
AM
106 return false;
107 return true;
8f595e9b
NC
108}
109
2b8fd839
TO
110/* Parse RISC-V disassembler option (possibly with arguments). */
111
8f595e9b 112static void
3f61a38b 113parse_riscv_dis_option (const char *option, struct disassemble_info *info)
8f595e9b
NC
114{
115 char *equal, *value;
116
3f61a38b 117 if (parse_riscv_dis_option_without_args (option, info))
8f595e9b
NC
118 return;
119
120 equal = strchr (option, '=');
121 if (equal == NULL)
122 {
123 /* The option without '=' should be defined above. */
124 opcodes_error_handler (_("unrecognized disassembler option: %s"), option);
125 return;
126 }
127 if (equal == option
128 || *(equal + 1) == '\0')
129 {
130 /* Invalid options with '=', no option name before '=',
131 and no value after '='. */
132 opcodes_error_handler (_("unrecognized disassembler option with '=': %s"),
133 option);
134 return;
135 }
136
137 *equal = '\0';
138 value = equal + 1;
139 if (strcmp (option, "priv-spec") == 0)
140 {
3f61a38b 141 struct riscv_private_data *pd = info->private_data;
3d73d29e
NC
142 enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE;
143 const char *name = NULL;
144
145 RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec);
0d1f4362 146 if (priv_spec < PRIV_SPEC_EARLIEST)
b800637e 147 opcodes_error_handler (_("unknown privileged spec set by %s=%s"),
8152e040 148 option, value);
3f61a38b
NC
149 else if (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE)
150 pd->default_priv_spec = priv_spec;
151 else if (pd->default_priv_spec != priv_spec)
3d73d29e 152 {
3f61a38b 153 RISCV_GET_PRIV_SPEC_NAME (name, pd->default_priv_spec);
3d73d29e
NC
154 opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, "
155 "the elf privilege attribute is %s"),
156 option, value, name);
157 }
8f595e9b 158 }
e23eba97
NC
159 else
160 {
a6743a54
AM
161 /* xgettext:c-format */
162 opcodes_error_handler (_("unrecognized disassembler option: %s"), option);
e23eba97
NC
163 }
164}
165
2b8fd839
TO
166/* Parse RISC-V disassembler options. */
167
e23eba97 168static void
3f61a38b 169parse_riscv_dis_options (const char *opts_in, struct disassemble_info *info)
e23eba97
NC
170{
171 char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
172
3f61a38b 173 set_default_riscv_dis_options (info);
e23eba97
NC
174
175 for ( ; opt_end != NULL; opt = opt_end + 1)
176 {
177 if ((opt_end = strchr (opt, ',')) != NULL)
178 *opt_end = 0;
3f61a38b 179 parse_riscv_dis_option (opt, info);
e23eba97
NC
180 }
181
182 free (opts);
183}
184
185/* Print one argument from an array. */
186
187static void
188arg_print (struct disassemble_info *info, unsigned long val,
189 const char* const* array, size_t size)
190{
191 const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
49d31dc9 192 (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s", s);
e23eba97
NC
193}
194
2b8fd839
TO
195/* If we need to print an address, set its value and state. */
196
e23eba97 197static void
c7dee848
JW
198maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset,
199 int wide)
e23eba97
NC
200{
201 if (pd->hi_addr[base_reg] != (bfd_vma)-1)
202 {
35fd2b2b 203 pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset;
e23eba97
NC
204 pd->hi_addr[base_reg] = -1;
205 }
8fe1be5f 206 else if (base_reg == X_GP && pd->has_gp)
e23eba97
NC
207 pd->print_addr = pd->gp + offset;
208 else if (base_reg == X_TP || base_reg == 0)
209 pd->print_addr = offset;
48525554
TO
210 else
211 return; /* Don't print the address. */
8fe1be5f 212 pd->to_print_addr = true;
c7dee848
JW
213
214 /* Sign-extend a 32-bit value to a 64-bit value. */
215 if (wide)
216 pd->print_addr = (bfd_vma)(int32_t) pd->print_addr;
48525554
TO
217
218 /* Fit into a 32-bit value on RV32. */
3f61a38b 219 if (pd->xlen == 32)
48525554 220 pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr;
e23eba97
NC
221}
222
9132c815
J
223/* Get Zcmp reg_list field. */
224
225static void
226print_reg_list (disassemble_info *info, insn_t l)
227{
3f61a38b
NC
228 struct riscv_private_data *pd = info->private_data;
229 bool numeric = pd->riscv_gpr_names == riscv_gpr_names_numeric;
9132c815
J
230 unsigned reg_list = (int)EXTRACT_OPERAND (REG_LIST, l);
231 unsigned r_start = numeric ? X_S2 : X_S0;
47277edc 232 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 233 "%s", pd->riscv_gpr_names[X_RA]);
9132c815
J
234
235 if (reg_list == 5)
47277edc
AB
236 {
237 info->fprintf_styled_func (info->stream, dis_style_text, ",");
238 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 239 "%s", pd->riscv_gpr_names[X_S0]);
47277edc 240 }
9132c815 241 else if (reg_list == 6 || (numeric && reg_list > 6))
47277edc
AB
242 {
243 info->fprintf_styled_func (info->stream, dis_style_text, ",");
244 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 245 "%s", pd->riscv_gpr_names[X_S0]);
47277edc
AB
246 info->fprintf_styled_func (info->stream, dis_style_text, "-");
247 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 248 "%s", pd->riscv_gpr_names[X_S1]);
47277edc
AB
249 }
250
9132c815 251 if (reg_list == 15)
47277edc
AB
252 {
253 info->fprintf_styled_func (info->stream, dis_style_text, ",");
254 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 255 "%s", pd->riscv_gpr_names[r_start]);
47277edc
AB
256 info->fprintf_styled_func (info->stream, dis_style_text, "-");
257 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 258 "%s", pd->riscv_gpr_names[X_S11]);
47277edc 259 }
9132c815 260 else if (reg_list == 7 && numeric)
47277edc
AB
261 {
262 info->fprintf_styled_func (info->stream, dis_style_text, ",");
263 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 264 "%s", pd->riscv_gpr_names[X_S2]);
47277edc 265 }
9132c815 266 else if (reg_list > 6)
47277edc
AB
267 {
268 info->fprintf_styled_func (info->stream, dis_style_text, ",");
269 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 270 "%s", pd->riscv_gpr_names[r_start]);
47277edc
AB
271 info->fprintf_styled_func (info->stream, dis_style_text, "-");
272 info->fprintf_styled_func (info->stream, dis_style_register,
3f61a38b 273 "%s", pd->riscv_gpr_names[reg_list + 11]);
47277edc 274 }
9132c815
J
275}
276
277/* Get Zcmp sp adjustment immediate. */
278
279static int
3f61a38b 280riscv_get_spimm (insn_t l, int xlen)
9132c815 281{
3f61a38b 282 int spimm = riscv_get_sp_base(l, xlen);
9132c815
J
283 spimm += EXTRACT_ZCMP_SPIMM (l);
284 if (((l ^ MATCH_CM_PUSH) & MASK_CM_PUSH) == 0)
285 spimm *= -1;
286 return spimm;
287}
288
ca2590d7
J
289/* Get s-register regno by using sreg number.
290 e.g. the regno of s0 is 8, so
291 riscv_zcmp_get_sregno (0) equals 8. */
292
293static unsigned
294riscv_zcmp_get_sregno (unsigned sreg_idx)
295{
296 return sreg_idx > 1 ?
297 sreg_idx + 16 : sreg_idx + 8;
298}
299
e23eba97
NC
300/* Print insn arguments for 32/64-bit code. */
301
302static void
437e2ff1 303print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info)
e23eba97
NC
304{
305 struct riscv_private_data *pd = info->private_data;
306 int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
307 int rd = (l >> OP_SH_RD) & OP_MASK_RD;
49d31dc9 308 fprintf_styled_ftype print = info->fprintf_styled_func;
437e2ff1 309 const char *opargStart;
e23eba97 310
437e2ff1 311 if (*oparg != '\0')
49d31dc9 312 print (info->stream, dis_style_text, "\t");
e23eba97 313
437e2ff1 314 for (; *oparg != '\0'; oparg++)
e23eba97 315 {
437e2ff1
NC
316 opargStart = oparg;
317 switch (*oparg)
e23eba97
NC
318 {
319 case 'C': /* RVC */
437e2ff1 320 switch (*++oparg)
e23eba97 321 {
dcd709e0
NC
322 case 's': /* RS1 x8-x15. */
323 case 'w': /* RS1 x8-x15. */
49d31dc9 324 print (info->stream, dis_style_register, "%s",
3f61a38b 325 pd->riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
e23eba97 326 break;
dcd709e0
NC
327 case 't': /* RS2 x8-x15. */
328 case 'x': /* RS2 x8-x15. */
49d31dc9 329 print (info->stream, dis_style_register, "%s",
3f61a38b 330 pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
e23eba97 331 break;
dcd709e0 332 case 'U': /* RS1, constrained to equal RD. */
49d31dc9 333 print (info->stream, dis_style_register,
3f61a38b 334 "%s", pd->riscv_gpr_names[rd]);
e23eba97 335 break;
dcd709e0 336 case 'c': /* RS1, constrained to equal sp. */
49d31dc9 337 print (info->stream, dis_style_register, "%s",
3f61a38b 338 pd->riscv_gpr_names[X_SP]);
e23eba97
NC
339 break;
340 case 'V': /* RS2 */
49d31dc9 341 print (info->stream, dis_style_register, "%s",
3f61a38b 342 pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
e23eba97 343 break;
f91d48de 344 case 'o':
e23eba97 345 case 'j':
c7dee848
JW
346 if (((l & MASK_C_ADDI) == MATCH_C_ADDI) && rd != 0)
347 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 0);
348 if (info->mach == bfd_mach_riscv64
349 && ((l & MASK_C_ADDIW) == MATCH_C_ADDIW) && rd != 0)
350 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 1);
49d31dc9
AB
351 print (info->stream, dis_style_immediate, "%d",
352 (int)EXTRACT_CITYPE_IMM (l));
e23eba97
NC
353 break;
354 case 'k':
49d31dc9
AB
355 print (info->stream, dis_style_address_offset, "%d",
356 (int)EXTRACT_CLTYPE_LW_IMM (l));
e23eba97
NC
357 break;
358 case 'l':
49d31dc9
AB
359 print (info->stream, dis_style_address_offset, "%d",
360 (int)EXTRACT_CLTYPE_LD_IMM (l));
e23eba97
NC
361 break;
362 case 'm':
49d31dc9
AB
363 print (info->stream, dis_style_address_offset, "%d",
364 (int)EXTRACT_CITYPE_LWSP_IMM (l));
e23eba97
NC
365 break;
366 case 'n':
49d31dc9
AB
367 print (info->stream, dis_style_address_offset, "%d",
368 (int)EXTRACT_CITYPE_LDSP_IMM (l));
e23eba97
NC
369 break;
370 case 'K':
49d31dc9
AB
371 print (info->stream, dis_style_immediate, "%d",
372 (int)EXTRACT_CIWTYPE_ADDI4SPN_IMM (l));
e23eba97
NC
373 break;
374 case 'L':
49d31dc9
AB
375 print (info->stream, dis_style_immediate, "%d",
376 (int)EXTRACT_CITYPE_ADDI16SP_IMM (l));
e23eba97
NC
377 break;
378 case 'M':
49d31dc9
AB
379 print (info->stream, dis_style_address_offset, "%d",
380 (int)EXTRACT_CSSTYPE_SWSP_IMM (l));
e23eba97
NC
381 break;
382 case 'N':
49d31dc9
AB
383 print (info->stream, dis_style_address_offset, "%d",
384 (int)EXTRACT_CSSTYPE_SDSP_IMM (l));
e23eba97
NC
385 break;
386 case 'p':
5a9f5403 387 info->target = EXTRACT_CBTYPE_IMM (l) + pc;
e23eba97
NC
388 (*info->print_address_func) (info->target, info);
389 break;
390 case 'a':
5a9f5403 391 info->target = EXTRACT_CJTYPE_IMM (l) + pc;
e23eba97
NC
392 (*info->print_address_func) (info->target, info);
393 break;
394 case 'u':
49d31dc9 395 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 396 (unsigned)(EXTRACT_CITYPE_IMM (l) & (RISCV_BIGIMM_REACH-1)));
e23eba97
NC
397 break;
398 case '>':
49d31dc9 399 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 400 (unsigned)EXTRACT_CITYPE_IMM (l) & 0x3f);
e23eba97
NC
401 break;
402 case '<':
49d31dc9 403 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 404 (unsigned)EXTRACT_CITYPE_IMM (l) & 0x1f);
e23eba97 405 break;
dcd709e0 406 case 'T': /* Floating-point RS2. */
49d31dc9 407 print (info->stream, dis_style_register, "%s",
3f61a38b 408 pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
e23eba97 409 break;
dcd709e0 410 case 'D': /* Floating-point RS2 x8-x15. */
49d31dc9 411 print (info->stream, dis_style_register, "%s",
3f61a38b 412 pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
e23eba97
NC
413 break;
414 }
415 break;
416
65e4a99a
NC
417 case 'V': /* RVV */
418 switch (*++oparg)
419 {
420 case 'd':
421 case 'f':
49d31dc9 422 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
423 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
424 break;
425 case 'e':
426 if (!EXTRACT_OPERAND (VWD, l))
49d31dc9 427 print (info->stream, dis_style_register, "%s",
3f61a38b 428 pd->riscv_gpr_names[0]);
65e4a99a 429 else
49d31dc9 430 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
431 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
432 break;
433 case 's':
49d31dc9 434 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
435 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS1, l)]);
436 break;
437 case 't':
438 case 'u': /* VS1 == VS2 already verified at this point. */
439 case 'v': /* VD == VS1 == VS2 already verified at this point. */
49d31dc9 440 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
441 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS2, l)]);
442 break;
443 case '0':
49d31dc9
AB
444 print (info->stream, dis_style_register, "%s",
445 riscv_vecr_names_numeric[0]);
65e4a99a
NC
446 break;
447 case 'b':
448 case 'c':
449 {
450 int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l)
451 : EXTRACT_RVV_VC_IMM (l);
452 unsigned int imm_vlmul = EXTRACT_OPERAND (VLMUL, imm);
453 unsigned int imm_vsew = EXTRACT_OPERAND (VSEW, imm);
454 unsigned int imm_vta = EXTRACT_OPERAND (VTA, imm);
455 unsigned int imm_vma = EXTRACT_OPERAND (VMA, imm);
abfdb09f 456 unsigned int imm_vtype_res = (imm >> 8);
65e4a99a
NC
457
458 if (imm_vsew < ARRAY_SIZE (riscv_vsew)
459 && imm_vlmul < ARRAY_SIZE (riscv_vlmul)
460 && imm_vta < ARRAY_SIZE (riscv_vta)
461 && imm_vma < ARRAY_SIZE (riscv_vma)
ee083a9e
NC
462 && !imm_vtype_res
463 && riscv_vsew[imm_vsew] != NULL
464 && riscv_vlmul[imm_vlmul] != NULL)
49d31dc9
AB
465 print (info->stream, dis_style_text, "%s,%s,%s,%s",
466 riscv_vsew[imm_vsew],
65e4a99a
NC
467 riscv_vlmul[imm_vlmul], riscv_vta[imm_vta],
468 riscv_vma[imm_vma]);
469 else
49d31dc9 470 print (info->stream, dis_style_immediate, "%d", imm);
65e4a99a
NC
471 }
472 break;
473 case 'i':
49d31dc9
AB
474 print (info->stream, dis_style_immediate, "%d",
475 (int)EXTRACT_RVV_VI_IMM (l));
65e4a99a
NC
476 break;
477 case 'j':
49d31dc9
AB
478 print (info->stream, dis_style_immediate, "%d",
479 (int)EXTRACT_RVV_VI_UIMM (l));
65e4a99a
NC
480 break;
481 case 'k':
49d31dc9
AB
482 print (info->stream, dis_style_immediate, "%d",
483 (int)EXTRACT_RVV_OFFSET (l));
65e4a99a 484 break;
c8cb3734
CM
485 case 'l':
486 print (info->stream, dis_style_immediate, "%d",
487 (int)EXTRACT_RVV_VI_UIMM6 (l));
488 break;
65e4a99a 489 case 'm':
f3a80235
TO
490 if (!EXTRACT_OPERAND (VMASK, l))
491 {
492 print (info->stream, dis_style_text, ",");
493 print (info->stream, dis_style_register, "%s",
494 riscv_vecm_names_numeric[0]);
495 }
65e4a99a
NC
496 break;
497 }
498 break;
499
e23eba97
NC
500 case ',':
501 case '(':
502 case ')':
503 case '[':
504 case ']':
9132c815
J
505 case '{':
506 case '}':
49d31dc9 507 print (info->stream, dis_style_text, "%c", *oparg);
e23eba97
NC
508 break;
509
510 case '0':
dcd709e0 511 /* Only print constant 0 if it is the last argument. */
437e2ff1 512 if (!oparg[1])
49d31dc9 513 print (info->stream, dis_style_immediate, "0");
e23eba97
NC
514 break;
515
617ead3c
CF
516 case 'r':
517 print (info->stream, dis_style_register, "%s",
518 pd->riscv_gpr_names[EXTRACT_OPERAND (RS3, l)]);
519 break;
520
e23eba97 521 case 's':
35eeb78f 522 if ((l & MASK_JALR) == MATCH_JALR)
48525554 523 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
3f61a38b
NC
524 print (info->stream, dis_style_register, "%s",
525 pd->riscv_gpr_names[rs1]);
e23eba97
NC
526 break;
527
528 case 't':
49d31dc9 529 print (info->stream, dis_style_register, "%s",
3f61a38b 530 pd->riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
e23eba97
NC
531 break;
532
533 case 'u':
49d31dc9 534 print (info->stream, dis_style_immediate, "0x%x",
e23eba97
NC
535 (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
536 break;
537
538 case 'm':
539 arg_print (info, EXTRACT_OPERAND (RM, l),
540 riscv_rm, ARRAY_SIZE (riscv_rm));
541 break;
542
543 case 'P':
544 arg_print (info, EXTRACT_OPERAND (PRED, l),
545 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
546 break;
547
548 case 'Q':
549 arg_print (info, EXTRACT_OPERAND (SUCC, l),
550 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
551 break;
552
553 case 'o':
c7dee848 554 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
b52d3cfc 555 /* Fall through. */
e23eba97
NC
556 case 'j':
557 if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0)
558 || (l & MASK_JALR) == MATCH_JALR)
c7dee848
JW
559 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
560 if (info->mach == bfd_mach_riscv64
561 && ((l & MASK_ADDIW) == MATCH_ADDIW) && rs1 != 0)
562 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 1);
49d31dc9
AB
563 print (info->stream, dis_style_immediate, "%d",
564 (int)EXTRACT_ITYPE_IMM (l));
e23eba97
NC
565 break;
566
567 case 'q':
c7dee848 568 maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l), 0);
49d31dc9
AB
569 print (info->stream, dis_style_address_offset, "%d",
570 (int)EXTRACT_STYPE_IMM (l));
e23eba97
NC
571 break;
572
573 case 'a':
5a9f5403 574 info->target = EXTRACT_JTYPE_IMM (l) + pc;
e23eba97
NC
575 (*info->print_address_func) (info->target, info);
576 break;
577
578 case 'p':
5a9f5403 579 info->target = EXTRACT_BTYPE_IMM (l) + pc;
e23eba97
NC
580 (*info->print_address_func) (info->target, info);
581 break;
582
583 case 'd':
584 if ((l & MASK_AUIPC) == MATCH_AUIPC)
585 pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
586 else if ((l & MASK_LUI) == MATCH_LUI)
587 pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
588 else if ((l & MASK_C_LUI) == MATCH_C_LUI)
5a9f5403 589 pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l);
3f61a38b
NC
590 print (info->stream, dis_style_register, "%s",
591 pd->riscv_gpr_names[rd]);
e23eba97
NC
592 break;
593
3d1cafa0 594 case 'y':
9a76ca16 595 print (info->stream, dis_style_immediate, "0x%x",
02a63525 596 EXTRACT_OPERAND (BS, l));
3d1cafa0 597 break;
598
e23eba97 599 case 'z':
3f61a38b
NC
600 print (info->stream, dis_style_register, "%s",
601 pd->riscv_gpr_names[0]);
e23eba97
NC
602 break;
603
604 case '>':
49d31dc9 605 print (info->stream, dis_style_immediate, "0x%x",
02a63525 606 EXTRACT_OPERAND (SHAMT, l));
e23eba97
NC
607 break;
608
609 case '<':
49d31dc9 610 print (info->stream, dis_style_immediate, "0x%x",
02a63525 611 EXTRACT_OPERAND (SHAMTW, l));
e23eba97
NC
612 break;
613
614 case 'S':
615 case 'U':
3f61a38b
NC
616 print (info->stream, dis_style_register, "%s",
617 pd->riscv_fpr_names[rs1]);
e23eba97
NC
618 break;
619
620 case 'T':
49d31dc9 621 print (info->stream, dis_style_register, "%s",
3f61a38b 622 pd->riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
e23eba97
NC
623 break;
624
625 case 'D':
3f61a38b
NC
626 print (info->stream, dis_style_register, "%s",
627 pd->riscv_fpr_names[rd]);
e23eba97
NC
628 break;
629
630 case 'R':
49d31dc9 631 print (info->stream, dis_style_register, "%s",
3f61a38b 632 pd->riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
e23eba97
NC
633 break;
634
635 case 'E':
636 {
dcd709e0 637 static const char *riscv_csr_hash[4096]; /* Total 2^12 CSRs. */
78933a4a 638 static bool init_csr = false;
e23eba97 639 unsigned int csr = EXTRACT_OPERAND (CSR, l);
8f595e9b
NC
640
641 if (!init_csr)
e23eba97 642 {
8f595e9b
NC
643 unsigned int i;
644 for (i = 0; i < 4096; i++)
645 riscv_csr_hash[i] = NULL;
646
dcd709e0 647 /* Set to the newest privileged version. */
3f61a38b
NC
648 if (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE)
649 pd->default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;
8f595e9b 650
08ccfccf
NC
651#define DECLARE_CSR(name, num, class, define_version, abort_version) \
652 if (riscv_csr_hash[num] == NULL \
653 && ((define_version == PRIV_SPEC_CLASS_NONE \
654 && abort_version == PRIV_SPEC_CLASS_NONE) \
3f61a38b
NC
655 || (pd->default_priv_spec >= define_version \
656 && pd->default_priv_spec < abort_version))) \
8f595e9b
NC
657 riscv_csr_hash[num] = #name;
658#define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \
659 DECLARE_CSR (name, num, class, define_version, abort_version)
e23eba97
NC
660#include "opcode/riscv-opc.h"
661#undef DECLARE_CSR
662 }
8f595e9b
NC
663
664 if (riscv_csr_hash[csr] != NULL)
3f61a38b 665 if (riscv_subset_supports (&pd->riscv_rps_dis, "xtheadvector")
6fdd02bb
JM
666 && (csr == CSR_VSTART
667 || csr == CSR_VXSAT
668 || csr == CSR_VXRM
669 || csr == CSR_VL
670 || csr == CSR_VTYPE
671 || csr == CSR_VLENB))
672 print (info->stream, dis_style_register, "%s",
673 concat ("th.", riscv_csr_hash[csr], NULL));
674 else
675 print (info->stream, dis_style_register, "%s",
676 riscv_csr_hash[csr]);
e23eba97 677 else
9a76ca16 678 print (info->stream, dis_style_immediate, "0x%x", csr);
e23eba97
NC
679 break;
680 }
681
3d1cafa0 682 case 'Y':
9a76ca16 683 print (info->stream, dis_style_immediate, "0x%x",
02a63525 684 EXTRACT_OPERAND (RNUM, l));
3d1cafa0 685 break;
686
e23eba97 687 case 'Z':
9a76ca16 688 print (info->stream, dis_style_immediate, "%d", rs1);
e23eba97
NC
689 break;
690
6de11ff6
NC
691 case 'W': /* Various operands for standard z extensions. */
692 switch (*++oparg)
693 {
694 case 'i':
695 switch (*++oparg)
696 {
697 case 'f':
698 print (info->stream, dis_style_address_offset, "%d",
699 (int) EXTRACT_STYPE_IMM (l));
700 break;
701 default:
702 goto undefined_modifier;
703 }
704 break;
705 case 'f':
706 switch (*++oparg)
707 {
708 case 'v':
709 if (riscv_fli_symval[rs1])
710 print (info->stream, dis_style_text, "%s",
711 riscv_fli_symval[rs1]);
712 else
713 print (info->stream, dis_style_immediate, "%a",
714 riscv_fli_numval[rs1]);
715 break;
716 default:
717 goto undefined_modifier;
718 }
719 break;
720 case 'c': /* Zcb extension 16 bits length instruction fields. */
721 switch (*++oparg)
722 {
ca2590d7
J
723 case '1':
724 print (info->stream, dis_style_register, "%s",
3f61a38b 725 pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG1, l))]);
ca2590d7
J
726 break;
727 case '2':
728 print (info->stream, dis_style_register, "%s",
3f61a38b 729 pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG2, l))]);
ca2590d7 730 break;
6de11ff6
NC
731 case 'b':
732 print (info->stream, dis_style_immediate, "%d",
733 (int)EXTRACT_ZCB_BYTE_UIMM (l));
734 break;
735 case 'h':
736 print (info->stream, dis_style_immediate, "%d",
737 (int)EXTRACT_ZCB_HALFWORD_UIMM (l));
738 break;
9132c815
J
739 case 'r':
740 print_reg_list (info, l);
741 break;
742 case 'p':
743 print (info->stream, dis_style_immediate, "%d",
3f61a38b 744 riscv_get_spimm (l, pd->xlen));
9132c815 745 break;
00ef37e8
J
746 case 'i':
747 case 'I':
748 print (info->stream, dis_style_address_offset,
62065166 749 "%" PRIu64, EXTRACT_ZCMT_INDEX (l));
00ef37e8 750 break;
6de11ff6
NC
751 default:
752 goto undefined_modifier;
753 }
754 break;
755 default:
756 goto undefined_modifier;
757 }
758 break;
759
760 case 'X': /* Vendor-specific operands. */
761 switch (*++oparg)
762 {
763 case 't': /* Vendor-specific (T-head) operands. */
54bca63b 764 {
6de11ff6
NC
765 size_t n;
766 size_t s;
767 bool sign;
54bca63b
TO
768 switch (*++oparg)
769 {
6a95962e
JM
770 case 'V':
771 ++oparg;
772 if (*oparg != 'c')
773 goto undefined_modifier;
774
775 int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l)
776 : EXTRACT_RVV_VC_IMM (l);
777 unsigned int imm_vediv = EXTRACT_OPERAND (XTHEADVEDIV, imm);
778 unsigned int imm_vlmul = EXTRACT_OPERAND (XTHEADVLMUL, imm);
779 unsigned int imm_vsew = EXTRACT_OPERAND (XTHEADVSEW, imm);
780 unsigned int imm_vtype_res
781 = EXTRACT_OPERAND (XTHEADVTYPE_RES, imm);
782 if (imm_vsew < ARRAY_SIZE (riscv_vsew)
783 && imm_vlmul < ARRAY_SIZE (riscv_th_vlen)
784 && imm_vediv < ARRAY_SIZE (riscv_th_vediv)
785 && ! imm_vtype_res)
786 print (info->stream, dis_style_text, "%s,%s,%s",
787 riscv_vsew[imm_vsew], riscv_th_vlen[imm_vlmul],
788 riscv_th_vediv[imm_vediv]);
789 else
790 print (info->stream, dis_style_immediate, "%d", imm);
791 break;
6de11ff6
NC
792 case 'l': /* Integer immediate, literal. */
793 oparg++;
794 while (*oparg && *oparg != ',')
795 {
796 print (info->stream, dis_style_immediate, "%c", *oparg);
797 oparg++;
798 }
799 oparg--;
54bca63b 800 break;
6de11ff6
NC
801 case 's': /* Integer immediate, 'XsN@S' ... N-bit signed immediate at bit S. */
802 sign = true;
803 goto print_imm;
804 case 'u': /* Integer immediate, 'XuN@S' ... N-bit unsigned immediate at bit S. */
805 sign = false;
806 goto print_imm;
807 print_imm:
808 n = strtol (oparg + 1, (char **)&oparg, 10);
809 if (*oparg != '@')
810 goto undefined_modifier;
811 s = strtol (oparg + 1, (char **)&oparg, 10);
812 oparg--;
813
814 if (!sign)
815 print (info->stream, dis_style_immediate, "%lu",
816 (unsigned long)EXTRACT_U_IMM (n, s, l));
1f3fc45b 817 else
6de11ff6
NC
818 print (info->stream, dis_style_immediate, "%li",
819 (signed long)EXTRACT_S_IMM (n, s, l));
1f3fc45b
CM
820 break;
821 default:
822 goto undefined_modifier;
823 }
54bca63b 824 }
6de11ff6 825 break;
ccb388ca
MB
826 case 'c': /* Vendor-specific (CORE-V) operands. */
827 switch (*++oparg)
828 {
d1bd9787
MB
829 case '2':
830 print (info->stream, dis_style_immediate, "%d",
831 ((int) EXTRACT_CV_IS2_UIMM5 (l)));
832 break;
ccb388ca
MB
833 case '3':
834 print (info->stream, dis_style_immediate, "%d",
835 ((int) EXTRACT_CV_IS3_UIMM5 (l)));
836 break;
b0f266f3
MB
837 case '4':
838 print (info->stream, dis_style_immediate, "%d",
839 ((int) EXTRACT_CV_BI_IMM5 (l)));
840 break;
a6ecb18b
MB
841 case '5':
842 print (info->stream, dis_style_immediate, "%d",
843 ((int) EXTRACT_CV_SIMD_IMM6 (l)));
844 break;
2f1739a3
MB
845 case '6':
846 print (info->stream, dis_style_immediate, "%d",
847 ((int) EXTRACT_CV_BITMANIP_UIMM5 (l)));
848 break;
849 case '7':
850 print (info->stream, dis_style_immediate, "%d",
851 ((int) EXTRACT_CV_BITMANIP_UIMM2 (l)));
852 break;
a6ecb18b
MB
853 case '8':
854 print (info->stream, dis_style_immediate, "%d",
855 ((int) EXTRACT_CV_SIMD_UIMM6 (l)));
856 ++oparg;
857 break;
ccb388ca
MB
858 default:
859 goto undefined_modifier;
860 }
861 break;
248bf6de
NC
862 case 's': /* Vendor-specific (SiFive) operands. */
863 switch (*++oparg)
864 {
865 /* SiFive vector coprocessor interface. */
866 case 'd':
867 print (info->stream, dis_style_register, "0x%x",
868 (unsigned) EXTRACT_OPERAND (RD, l));
869 break;
870 case 't':
871 print (info->stream, dis_style_register, "0x%x",
872 (unsigned) EXTRACT_OPERAND (RS2, l));
873 break;
874 case 'O':
875 switch (*++oparg)
876 {
877 case '2':
878 print (info->stream, dis_style_register, "0x%x",
879 (unsigned) EXTRACT_OPERAND (XSO2, l));
880 break;
881 case '1':
882 print (info->stream, dis_style_register, "0x%x",
883 (unsigned) EXTRACT_OPERAND (XSO1, l));
884 break;
885 }
886 break;
887 }
888 break;
617ead3c
CF
889 case 'm': /* Vendor-specific (MIPS) operands. */
890 switch (*++oparg)
891 {
892 case '@':
893 print (info->stream, dis_style_register, "0x%x",
894 (unsigned) EXTRACT_OPERAND (MIPS_HINT, l));
895 break;
896 case '#':
897 print (info->stream, dis_style_register, "0x%x",
898 (unsigned) EXTRACT_OPERAND (MIPS_IMM9, l));
899 break;
900 case '$':
901 print (info->stream, dis_style_immediate, "%d",
902 (unsigned)EXTRACT_MIPS_LDP_IMM (l));
903 break;
904 case '%':
905 print (info->stream, dis_style_immediate, "%d",
906 (unsigned)EXTRACT_MIPS_LWP_IMM (l));
907 break;
908 case '^':
909 print (info->stream, dis_style_immediate, "%d",
910 (unsigned)EXTRACT_MIPS_SDP_IMM (l));
911 break;
912 case '&':
913 print (info->stream, dis_style_immediate, "%d",
914 (unsigned)EXTRACT_MIPS_SWP_IMM (l));
915 break;
916 default:
917 goto undefined_modifier;
918 }
919 break;
6de11ff6
NC
920 default:
921 goto undefined_modifier;
922 }
8b7419c4 923 break;
1f3fc45b 924
e23eba97 925 default:
8b7419c4 926 undefined_modifier:
e23eba97 927 /* xgettext:c-format */
49d31dc9
AB
928 print (info->stream, dis_style_text,
929 _("# internal error, undefined modifier (%c)"),
437e2ff1 930 *opargStart);
e23eba97
NC
931 return;
932 }
933 }
934}
935
936/* Print the RISC-V instruction at address MEMADDR in debugged memory,
937 on using INFO. Returns length of the instruction, in bytes.
938 BIGENDIAN must be 1 if this is big-endian code, 0 if
939 this is little-endian code. */
940
941static int
97f006bc
TO
942riscv_disassemble_insn (bfd_vma memaddr,
943 insn_t word,
944 const bfd_byte *packet,
945 disassemble_info *info)
e23eba97
NC
946{
947 const struct riscv_opcode *op;
354c1c09 948 static bool init = false;
e23eba97 949 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
26e91972 950 struct riscv_private_data *pd = info->private_data;
0655669b
JB
951 int insnlen, i;
952 bool printed;
e23eba97
NC
953
954#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
955
956 /* Build a hash table to shorten the search time. */
957 if (! init)
958 {
959 for (op = riscv_opcodes; op->name; op++)
960 if (!riscv_hash[OP_HASH_IDX (op->match)])
961 riscv_hash[OP_HASH_IDX (op->match)] = op;
962
354c1c09 963 init = true;
e23eba97
NC
964 }
965
e23eba97
NC
966 insnlen = riscv_insn_length (word);
967
d7560e2d
JW
968 /* RISC-V instructions are always little-endian. */
969 info->endian_code = BFD_ENDIAN_LITTLE;
970
e23eba97
NC
971 info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
972 info->bytes_per_line = 8;
d7560e2d
JW
973 /* We don't support constant pools, so this must be code. */
974 info->display_endian = info->endian_code;
e23eba97
NC
975 info->insn_info_valid = 1;
976 info->branch_delay_insns = 0;
977 info->data_size = 0;
978 info->insn_type = dis_nonbranch;
979 info->target = 0;
980 info->target2 = 0;
981
982 op = riscv_hash[OP_HASH_IDX (word)];
983 if (op != NULL)
984 {
2922d21d
AW
985 /* If XLEN is not known, get its value from the ELF class. */
986 if (info->mach == bfd_mach_riscv64)
3f61a38b 987 pd->xlen = 64;
2922d21d 988 else if (info->mach == bfd_mach_riscv32)
3f61a38b 989 pd->xlen = 32;
2922d21d 990 else if (info->section != NULL)
e23eba97
NC
991 {
992 Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
3f61a38b 993 pd->xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
e23eba97
NC
994 }
995
2b8fd839 996 /* If arch has the Zfinx extension, replace FPR with GPR. */
3f61a38b
NC
997 if (riscv_subset_supports (&pd->riscv_rps_dis, "zfinx"))
998 pd->riscv_fpr_names = pd->riscv_gpr_names;
40f1a1a4 999 else
3f61a38b
NC
1000 pd->riscv_fpr_names = pd->riscv_gpr_names == riscv_gpr_names_abi ?
1001 riscv_fpr_names_abi : riscv_fpr_names_numeric;
de83e514 1002
e23eba97
NC
1003 for (; op->name; op++)
1004 {
27b33966
JB
1005 /* Ignore macro insns. */
1006 if (op->pinfo == INSN_MACRO)
1007 continue;
e23eba97
NC
1008 /* Does the opcode match? */
1009 if (! (op->match_func) (op, word))
1010 continue;
1011 /* Is this a pseudo-instruction and may we print it as such? */
3f61a38b 1012 if (pd->no_aliases && (op->pinfo & INSN_ALIAS))
e23eba97
NC
1013 continue;
1014 /* Is this instruction restricted to a certain value of XLEN? */
3f61a38b
NC
1015 if ((op->xlen_requirement != 0)
1016 && (op->xlen_requirement != pd->xlen))
e23eba97 1017 continue;
2b8fd839 1018 /* Is this instruction supported by the current architecture? */
3f61a38b
NC
1019 if (!pd->all_ext
1020 && !riscv_multi_subset_supports (&pd->riscv_rps_dis,
1021 op->insn_class))
f786c359
NC
1022 continue;
1023
e23eba97 1024 /* It's a match. */
49d31dc9
AB
1025 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1026 "%s", op->name);
e23eba97
NC
1027 print_insn_args (op->args, word, memaddr, info);
1028
1029 /* Try to disassemble multi-instruction addressing sequences. */
8fe1be5f 1030 if (pd->to_print_addr)
e23eba97
NC
1031 {
1032 info->target = pd->print_addr;
49d31dc9
AB
1033 (*info->fprintf_styled_func)
1034 (info->stream, dis_style_comment_start, " # ");
e23eba97 1035 (*info->print_address_func) (info->target, info);
8fe1be5f 1036 pd->to_print_addr = false;
e23eba97
NC
1037 }
1038
eb41b248
JW
1039 /* Finish filling out insn_info fields. */
1040 switch (op->pinfo & INSN_TYPE)
1041 {
1042 case INSN_BRANCH:
1043 info->insn_type = dis_branch;
1044 break;
1045 case INSN_CONDBRANCH:
1046 info->insn_type = dis_condbranch;
1047 break;
1048 case INSN_JSR:
1049 info->insn_type = dis_jsr;
1050 break;
1051 case INSN_DREF:
1052 info->insn_type = dis_dref;
1053 break;
1054 default:
1055 break;
1056 }
1057
1058 if (op->pinfo & INSN_DATA_SIZE)
1059 {
1060 int size = ((op->pinfo & INSN_DATA_SIZE)
1061 >> INSN_DATA_SIZE_SHIFT);
1062 info->data_size = 1 << (size - 1);
1063 }
1064
e23eba97
NC
1065 return insnlen;
1066 }
1067 }
1068
0655669b
JB
1069 /* We did not find a match, so just print the instruction bits in
1070 the shape of an assembler .insn directive. */
e23eba97 1071 info->insn_type = dis_noninsn;
0655669b
JB
1072 (*info->fprintf_styled_func)
1073 (info->stream, dis_style_assembler_directive, ".insn");
1074 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1075 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1076 "%d", insnlen);
1077 (*info->fprintf_styled_func) (info->stream, dis_style_text, ", ");
1078 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x");
1079 for (i = insnlen, printed = false; i >= 2; )
6a7f5766 1080 {
0655669b
JB
1081 i -= 2;
1082 word = bfd_get_bits (packet + i, 16, false);
784e2ef5 1083 if (!word && !printed && i)
0655669b
JB
1084 continue;
1085
49d31dc9 1086 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
0655669b
JB
1087 "%04x", (unsigned int) word);
1088 printed = true;
6a7f5766 1089 }
0655669b 1090
e23eba97
NC
1091 return insnlen;
1092}
1093
e4c9f0e6
NC
1094/* Decide if we need to parse the architecture string again, also record the
1095 string into the current subset list. */
1096
1097static void
1098riscv_dis_parse_subset (struct disassemble_info *info, const char *arch_new)
1099{
1100 struct riscv_private_data *pd = info->private_data;
1101 const char *arch_subset_list = pd->riscv_rps_dis.subset_list->arch_str;
1102 if (arch_subset_list == NULL || strcmp (arch_subset_list, arch_new) != 0)
1103 {
1104 riscv_release_subset_list (pd->riscv_rps_dis.subset_list);
1105 riscv_parse_subset (&pd->riscv_rps_dis, arch_new);
1106 riscv_arch_str (pd->xlen, pd->riscv_rps_dis.subset_list,
1107 true/* update */);
1108 }
1109}
1110
460e0e6e
PN
1111/* If we find the suitable mapping symbol update the STATE.
1112 Otherwise, do nothing. */
9b9b1092 1113
460e0e6e
PN
1114static void
1115riscv_update_map_state (int n,
1116 enum riscv_seg_mstate *state,
1117 struct disassemble_info *info)
9b9b1092 1118{
3f61a38b 1119 struct riscv_private_data *pd = info->private_data;
9b9b1092
NC
1120 const char *name;
1121
1122 /* If the symbol is in a different section, ignore it. */
1123 if (info->section != NULL
1124 && info->section != info->symtab[n]->section)
460e0e6e 1125 return;
9b9b1092
NC
1126
1127 name = bfd_asymbol_name(info->symtab[n]);
ade87b8e 1128 if (strcmp (name, "$d") == 0)
9b9b1092 1129 *state = MAP_DATA;
ade87b8e
AO
1130 else if (strcmp (name, "$x") == 0)
1131 {
1132 *state = MAP_INSN;
e4c9f0e6 1133 riscv_dis_parse_subset (info, pd->default_arch);
ade87b8e 1134 }
40f1a1a4
NC
1135 else if (strncmp (name, "$xrv", 4) == 0)
1136 {
1137 *state = MAP_INSN;
9326300e
JF
1138
1139 /* ISA mapping string may be numbered, suffixed with '.n'. Do not
1140 consider this as part of the ISA string. */
1141 char *suffix = strchr (name, '.');
1142 if (suffix)
1143 {
1144 int suffix_index = (int)(suffix - name);
1145 char *name_substr = xmalloc (suffix_index + 1);
1146 strncpy (name_substr, name, suffix_index);
1147 name_substr[suffix_index] = '\0';
e4c9f0e6 1148 riscv_dis_parse_subset (info, name_substr + 2);
9326300e
JF
1149 free (name_substr);
1150 }
1151 else
e4c9f0e6 1152 riscv_dis_parse_subset (info, name + 2);
40f1a1a4 1153 }
460e0e6e
PN
1154}
1155
1156/* Return true if we find the suitable mapping symbol.
1157 Otherwise, return false. */
1158
1159static bool
1160riscv_is_valid_mapping_symbol (int n,
1161 struct disassemble_info *info)
1162{
1163 const char *name;
1164
1165 /* If the symbol is in a different section, ignore it. */
1166 if (info->section != NULL
1167 && info->section != info->symtab[n]->section)
9b9b1092
NC
1168 return false;
1169
460e0e6e 1170 name = bfd_asymbol_name(info->symtab[n]);
2b33b0d9 1171 return riscv_elf_is_mapping_symbols (name);
9b9b1092
NC
1172}
1173
1174/* Check the sorted symbol table (sorted by the symbol value), find the
1175 suitable mapping symbols. */
1176
1177static enum riscv_seg_mstate
1178riscv_search_mapping_symbol (bfd_vma memaddr,
1179 struct disassemble_info *info)
1180{
3f61a38b 1181 struct riscv_private_data *pd = info->private_data;
9b9b1092
NC
1182 enum riscv_seg_mstate mstate;
1183 bool from_last_map_symbol;
1184 bool found = false;
1185 int symbol = -1;
1186 int n;
1187
c2f60ac5
KC
1188 /* Return the last map state if the address is still within the range of the
1189 last mapping symbol. */
3f61a38b
NC
1190 if (pd->last_map_section == info->section
1191 && (memaddr < pd->last_map_symbol_boundary))
1192 return pd->last_map_state;
c2f60ac5 1193
3f61a38b 1194 pd->last_map_section = info->section;
c2f60ac5 1195
9b9b1092
NC
1196 /* Decide whether to print the data or instruction by default, in case
1197 we can not find the corresponding mapping symbols. */
1198 mstate = MAP_DATA;
1199 if ((info->section
1200 && info->section->flags & SEC_CODE)
1201 || !info->section)
1202 mstate = MAP_INSN;
1203
1204 if (info->symtab_size == 0
1205 || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour)
1206 return mstate;
1207
1208 /* Reset the last_map_symbol if we start to dump a new section. */
1209 if (memaddr <= 0)
3f61a38b 1210 pd->last_map_symbol = -1;
9b9b1092
NC
1211
1212 /* If the last stop offset is different from the current one, then
1213 don't use the last_map_symbol to search. We usually reset the
1214 info->stop_offset when handling a new section. */
3f61a38b
NC
1215 from_last_map_symbol = (pd->last_map_symbol >= 0
1216 && info->stop_offset == pd->last_stop_offset);
9b9b1092 1217
7a7ec56c
JF
1218 /* Start scanning from wherever we finished last time, or the start
1219 of the function. */
3f61a38b 1220 n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos + 1;
9b9b1092
NC
1221
1222 /* Find the suitable mapping symbol to dump. */
1223 for (; n < info->symtab_size; n++)
1224 {
1225 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1226 /* We have searched all possible symbols in the range. */
1227 if (addr > memaddr)
1228 break;
460e0e6e 1229 if (riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1230 {
1231 symbol = n;
1232 found = true;
1233 /* Do not stop searching, in case there are some mapping
1234 symbols have the same value, but have different names.
1235 Use the last one. */
1236 }
1237 }
1238
1239 /* We can not find the suitable mapping symbol above. Therefore, we
b5c37946 1240 look forwards and try to find it again, but don't go past the start
9b9b1092
NC
1241 of the section. Otherwise a data section without mapping symbols
1242 can pick up a text mapping symbol of a preceeding section. */
1243 if (!found)
1244 {
3f61a38b 1245 n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos;
9b9b1092
NC
1246
1247 for (; n >= 0; n--)
1248 {
1249 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1250 /* We have searched all possible symbols in the range. */
1251 if (addr < (info->section ? info->section->vma : 0))
1252 break;
1253 /* Stop searching once we find the closed mapping symbol. */
460e0e6e 1254 if (riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1255 {
1256 symbol = n;
1257 found = true;
1258 break;
1259 }
1260 }
1261 }
1262
c2f60ac5
KC
1263 if (found)
1264 {
460e0e6e
PN
1265 riscv_update_map_state (symbol, &mstate, info);
1266
c2f60ac5
KC
1267 /* Find the next mapping symbol to determine the boundary of this mapping
1268 symbol. */
1269
1270 bool found_next = false;
1271 /* Try to found next mapping symbol. */
1272 for (n = symbol + 1; n < info->symtab_size; n++)
1273 {
1274 if (info->symtab[symbol]->section != info->symtab[n]->section)
1275 continue;
1276
1277 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1278 const char *sym_name = bfd_asymbol_name(info->symtab[n]);
1279 if (sym_name[0] == '$' && (sym_name[1] == 'x' || sym_name[1] == 'd'))
1280 {
1281 /* The next mapping symbol has been found, and it represents the
1282 boundary of this mapping symbol. */
1283 found_next = true;
3f61a38b 1284 pd->last_map_symbol_boundary = addr;
c2f60ac5
KC
1285 break;
1286 }
1287 }
1288
1289 /* No further mapping symbol has been found, indicating that the boundary
1290 of the current mapping symbol is the end of this section. */
1291 if (!found_next)
3f61a38b
NC
1292 pd->last_map_symbol_boundary = info->section->vma
1293 + info->section->size;
c2f60ac5
KC
1294 }
1295
9b9b1092 1296 /* Save the information for next use. */
3f61a38b
NC
1297 pd->last_map_symbol = symbol;
1298 pd->last_stop_offset = info->stop_offset;
9b9b1092
NC
1299
1300 return mstate;
1301}
1302
1303/* Decide which data size we should print. */
1304
1305static bfd_vma
1306riscv_data_length (bfd_vma memaddr,
1307 disassemble_info *info)
1308{
3f61a38b 1309 struct riscv_private_data *pd = info->private_data;
9b9b1092
NC
1310 bfd_vma length;
1311 bool found = false;
1312
1313 length = 4;
1314 if (info->symtab_size != 0
1315 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour
3f61a38b 1316 && pd->last_map_symbol >= 0)
9b9b1092
NC
1317 {
1318 int n;
1319 enum riscv_seg_mstate m = MAP_NONE;
3f61a38b 1320 for (n = pd->last_map_symbol + 1; n < info->symtab_size; n++)
9b9b1092
NC
1321 {
1322 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1323 if (addr > memaddr
460e0e6e 1324 && riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1325 {
1326 if (addr - memaddr < length)
1327 length = addr - memaddr;
1328 found = true;
460e0e6e 1329 riscv_update_map_state (n, &m, info);
9b9b1092
NC
1330 break;
1331 }
1332 }
1333 }
1334 if (!found)
1335 {
1336 /* Do not set the length which exceeds the section size. */
1337 bfd_vma offset = info->section->vma + info->section->size;
1338 offset -= memaddr;
1339 length = (offset < length) ? offset : length;
1340 }
1341 length = length == 3 ? 2 : length;
1342 return length;
1343}
1344
1345/* Dump the data contents. */
1346
1347static int
1348riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED,
1349 insn_t data,
97f006bc 1350 const bfd_byte *packet ATTRIBUTE_UNUSED,
9b9b1092
NC
1351 disassemble_info *info)
1352{
1353 info->display_endian = info->endian;
227a52fb 1354 int i;
9b9b1092
NC
1355
1356 switch (info->bytes_per_chunk)
1357 {
1358 case 1:
1359 info->bytes_per_line = 6;
49d31dc9 1360 (*info->fprintf_styled_func)
f3a80235
TO
1361 (info->stream, dis_style_assembler_directive, ".byte");
1362 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1363 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1364 "0x%02x", (unsigned)data);
9b9b1092
NC
1365 break;
1366 case 2:
1367 info->bytes_per_line = 8;
49d31dc9 1368 (*info->fprintf_styled_func)
f3a80235
TO
1369 (info->stream, dis_style_assembler_directive, ".short");
1370 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1371 (*info->fprintf_styled_func)
e0b004c5 1372 (info->stream, dis_style_immediate, "0x%04x", (unsigned) data);
9b9b1092
NC
1373 break;
1374 case 4:
1375 info->bytes_per_line = 8;
49d31dc9 1376 (*info->fprintf_styled_func)
f3a80235
TO
1377 (info->stream, dis_style_assembler_directive, ".word");
1378 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1379 (*info->fprintf_styled_func)
e0b004c5
TO
1380 (info->stream, dis_style_immediate, "0x%08lx",
1381 (unsigned long) data);
9b9b1092
NC
1382 break;
1383 case 8:
1384 info->bytes_per_line = 8;
49d31dc9 1385 (*info->fprintf_styled_func)
f3a80235
TO
1386 (info->stream, dis_style_assembler_directive, ".dword");
1387 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9
AB
1388 (*info->fprintf_styled_func)
1389 (info->stream, dis_style_immediate, "0x%016llx",
1390 (unsigned long long) data);
9b9b1092
NC
1391 break;
1392 default:
227a52fb
CJ
1393 /* Arbitrary data so just print the bits in the shape of an .<N>byte
1394 directive. */
1395 info->bytes_per_line = info->bytes_per_chunk;
1396 (*info->fprintf_styled_func)
1397 (info->stream, dis_style_assembler_directive, ".%dbyte", info->bytes_per_chunk);
1398 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1399 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x");
1400 for (i = info->bytes_per_line; i > 0;)
1401 {
1402 i--;
1403 data = bfd_get_bits (packet + i, 8, false);
1404 (*info->fprintf_styled_func)
1405 (info->stream, dis_style_immediate, "%02x",
1406 (unsigned) data);
1407 }
1408 break;
9b9b1092
NC
1409 }
1410 return info->bytes_per_chunk;
1411}
1412
26e91972
NC
1413static bool
1414riscv_init_disasm_info (struct disassemble_info *info)
1415{
1416 int i;
26e91972
NC
1417 struct riscv_private_data *pd =
1418 xcalloc (1, sizeof (struct riscv_private_data));
1419 pd->gp = 0;
1420 pd->print_addr = 0;
1421 for (i = 0; i < (int) ARRAY_SIZE (pd->hi_addr); i++)
1422 pd->hi_addr[i] = -1;
1423 pd->to_print_addr = false;
26e91972 1424
3f61a38b 1425 pd->has_gp = false;
26e91972
NC
1426 for (i = 0; i < info->symtab_size; i++)
1427 {
1428 asymbol *sym = info->symtab[i];
1429 if (strcmp (bfd_asymbol_name (sym), RISCV_GP_SYMBOL) == 0)
1430 {
1431 pd->gp = bfd_asymbol_value (sym);
1432 pd->has_gp = true;
1433 }
1434 }
1435
3f61a38b
NC
1436 pd->xlen = 0;
1437 pd->default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1;
1438 pd->default_priv_spec = PRIV_SPEC_CLASS_NONE;
1439
1440 pd->riscv_rps_dis.subset_list = xcalloc (1, sizeof (riscv_parse_subset_t));
1441 pd->riscv_rps_dis.error_handler = opcodes_error_handler;
1442 pd->riscv_rps_dis.xlen = &pd->xlen;
1443 pd->riscv_rps_dis.isa_spec = &pd->default_isa_spec;
1444 pd->riscv_rps_dis.check_unknown_prefixed_ext = false;
ade87b8e 1445 pd->default_arch = "rv64gc";
3f61a38b
NC
1446 if (info->section != NULL)
1447 {
1448 bfd *abfd = info->section->owner;
1449 if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1450 {
1451 const char *sec_name =
1452 get_elf_backend_data (abfd)->obj_attrs_section;
1453 if (bfd_get_section_by_name (abfd, sec_name) != NULL)
1454 {
1455 obj_attribute *attr = elf_known_obj_attributes_proc (abfd);
1456 unsigned int Tag_a = Tag_RISCV_priv_spec;
1457 unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
1458 unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
1459 riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i,
1460 attr[Tag_b].i,
1461 attr[Tag_c].i,
1462 &pd->default_priv_spec);
ade87b8e 1463 pd->default_arch = attr[Tag_RISCV_arch].s;
3f61a38b
NC
1464 }
1465 }
1466 }
3f61a38b
NC
1467
1468 pd->last_map_symbol = -1;
1469 pd->last_stop_offset = 0;
1470 pd->last_map_symbol_boundary = 0;
1471 pd->last_map_state = MAP_NONE;
1472 pd->last_map_section = NULL;
1473 pd->riscv_gpr_names = NULL;
1474 pd->riscv_fpr_names = NULL;
1475 pd->no_aliases = false;
1476 pd->all_ext = false;
1477
26e91972 1478 info->private_data = pd;
e4c9f0e6 1479 riscv_dis_parse_subset (info, pd->default_arch);
26e91972
NC
1480 return true;
1481}
1482
6a04e823
CJ
1483/* Fetch an instruction. If only a partial instruction is able to be fetched,
1484 return the number of accessible bytes. */
1485
1486static bfd_vma
1487fetch_insn (bfd_vma memaddr,
1488 bfd_byte *packet,
1489 bfd_vma dump_size,
1490 struct disassemble_info *info,
1491 volatile int *status)
1492{
1493 do
1494 {
1495 *status = (*info->read_memory_func) (memaddr, packet, dump_size, info);
1496 }
1497 while (*status != 0 && dump_size-- > 1);
1498
1499 return dump_size;
1500}
1501
e23eba97
NC
1502int
1503print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
1504{
73e30e72 1505 bfd_byte packet[RISCV_MAX_INSN_LEN];
e23eba97 1506 insn_t insn = 0;
6a04e823 1507 bfd_vma dump_size, bytes_fetched;
e23eba97 1508 int status;
9b9b1092 1509 enum riscv_seg_mstate mstate;
97f006bc
TO
1510 int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *,
1511 struct disassemble_info *);
e23eba97 1512
3f61a38b
NC
1513 if (info->private_data == NULL && !riscv_init_disasm_info (info))
1514 return -1;
1515
e23eba97
NC
1516 if (info->disassembler_options != NULL)
1517 {
3f61a38b 1518 parse_riscv_dis_options (info->disassembler_options, info);
e23eba97
NC
1519 /* Avoid repeatedly parsing the options. */
1520 info->disassembler_options = NULL;
1521 }
3f61a38b
NC
1522 else if (((struct riscv_private_data *) info->private_data)->riscv_gpr_names == NULL)
1523 set_default_riscv_dis_options (info);
26e91972 1524
9b9b1092 1525 mstate = riscv_search_mapping_symbol (memaddr, info);
c2f60ac5 1526 /* Save the last mapping state. */
3f61a38b 1527 ((struct riscv_private_data *) info->private_data)->last_map_state = mstate;
9b9b1092
NC
1528
1529 /* Set the size to dump. */
1530 if (mstate == MAP_DATA
1531 && (info->flags & DISASSEMBLE_DATA) == 0)
1532 {
1533 dump_size = riscv_data_length (memaddr, info);
1534 info->bytes_per_chunk = dump_size;
1535 riscv_disassembler = riscv_disassemble_data;
1536 }
1537 else
e23eba97 1538 {
9b9b1092 1539 /* Get the first 2-bytes to check the lenghth of instruction. */
6a04e823 1540 bytes_fetched = fetch_insn (memaddr, packet, 2, info, &status);
e23eba97
NC
1541 if (status != 0)
1542 {
e23eba97 1543 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1544 return -1;
e23eba97 1545 }
6a04e823
CJ
1546 else if (bytes_fetched != 2)
1547 {
1548 /* Only the first byte was able to be read. Dump the partial
1549 instruction. */
1550 dump_size = bytes_fetched;
1551 info->bytes_per_chunk = dump_size;
1552 riscv_disassembler = riscv_disassemble_data;
1553 goto print;
1554 }
9b9b1092
NC
1555 insn = (insn_t) bfd_getl16 (packet);
1556 dump_size = riscv_insn_length (insn);
1557 riscv_disassembler = riscv_disassemble_insn;
1558 }
e23eba97 1559
6a04e823
CJ
1560 bytes_fetched = fetch_insn (memaddr, packet, dump_size, info, &status);
1561
9b9b1092
NC
1562 if (status != 0)
1563 {
1564 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1565 return -1;
e23eba97 1566 }
6a04e823
CJ
1567 else if (bytes_fetched != dump_size)
1568 {
1569 dump_size = bytes_fetched;
1570 info->bytes_per_chunk = dump_size;
1571 riscv_disassembler = riscv_disassemble_data;
1572 }
1573
1574 print:
1575
9b9b1092 1576 insn = (insn_t) bfd_get_bits (packet, dump_size * 8, false);
e23eba97 1577
97f006bc 1578 return (*riscv_disassembler) (memaddr, insn, packet, info);
e23eba97
NC
1579}
1580
884b49e3
AB
1581/* Prevent use of the fake labels that are generated as part of the DWARF
1582 and for relaxable relocations in the assembler. */
1583
78933a4a 1584bool
884b49e3
AB
1585riscv_symbol_is_valid (asymbol * sym,
1586 struct disassemble_info * info ATTRIBUTE_UNUSED)
1587{
1588 const char * name;
1589
1590 if (sym == NULL)
78933a4a 1591 return false;
884b49e3
AB
1592
1593 name = bfd_asymbol_name (sym);
1594
9b9b1092
NC
1595 return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0
1596 && !riscv_elf_is_mapping_symbols (name));
884b49e3 1597}
3a337a86
AB
1598\f
1599
1600/* Indices into option argument vector for options accepting an argument.
1601 Use RISCV_OPTION_ARG_NONE for options accepting no argument. */
1602
1603typedef enum
1604{
1605 RISCV_OPTION_ARG_NONE = -1,
1606 RISCV_OPTION_ARG_PRIV_SPEC,
1607
1608 RISCV_OPTION_ARG_COUNT
1609} riscv_option_arg_t;
1610
1611/* Valid RISCV disassembler options. */
1612
1613static struct
1614{
1615 const char *name;
1616 const char *description;
1617 riscv_option_arg_t arg;
1618} riscv_options[] =
1619{
88891208
MP
1620 { "max",
1621 N_("Disassemble without checking architecture string."),
1622 RISCV_OPTION_ARG_NONE },
3a337a86
AB
1623 { "numeric",
1624 N_("Print numeric register names, rather than ABI names."),
1625 RISCV_OPTION_ARG_NONE },
1626 { "no-aliases",
1627 N_("Disassemble only into canonical instructions."),
1628 RISCV_OPTION_ARG_NONE },
1629 { "priv-spec=",
1630 N_("Print the CSR according to the chosen privilege spec."),
1631 RISCV_OPTION_ARG_PRIV_SPEC }
1632};
1633
1634/* Build the structure representing valid RISCV disassembler options.
1635 This is done dynamically for maintenance ease purpose; a static
1636 initializer would be unreadable. */
1637
1638const disasm_options_and_args_t *
1639disassembler_options_riscv (void)
1640{
1641 static disasm_options_and_args_t *opts_and_args;
1642
1643 if (opts_and_args == NULL)
1644 {
1645 size_t num_options = ARRAY_SIZE (riscv_options);
1646 size_t num_args = RISCV_OPTION_ARG_COUNT;
1647 disasm_option_arg_t *args;
1648 disasm_options_t *opts;
1649 size_t i, priv_spec_count;
1650
1651 args = XNEWVEC (disasm_option_arg_t, num_args + 1);
1652
1653 args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC";
0d1f4362 1654 priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_EARLIEST;
3a337a86
AB
1655 args[RISCV_OPTION_ARG_PRIV_SPEC].values
1656 = XNEWVEC (const char *, priv_spec_count + 1);
1657 for (i = 0; i < priv_spec_count; i++)
1658 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i]
0d1f4362 1659 = riscv_priv_specs[PRIV_SPEC_EARLIEST - PRIV_SPEC_CLASS_NONE - 1 + i].name;
3a337a86
AB
1660 /* The array we return must be NULL terminated. */
1661 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] = NULL;
1662
1663 /* The array we return must be NULL terminated. */
1664 args[num_args].name = NULL;
1665 args[num_args].values = NULL;
1666
1667 opts_and_args = XNEW (disasm_options_and_args_t);
1668 opts_and_args->args = args;
1669
1670 opts = &opts_and_args->options;
1671 opts->name = XNEWVEC (const char *, num_options + 1);
1672 opts->description = XNEWVEC (const char *, num_options + 1);
1673 opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
1674 for (i = 0; i < num_options; i++)
1675 {
1676 opts->name[i] = riscv_options[i].name;
1677 opts->description[i] = _(riscv_options[i].description);
1678 if (riscv_options[i].arg != RISCV_OPTION_ARG_NONE)
1679 opts->arg[i] = &args[riscv_options[i].arg];
1680 else
1681 opts->arg[i] = NULL;
1682 }
1683 /* The array we return must be NULL terminated. */
1684 opts->name[i] = NULL;
1685 opts->description[i] = NULL;
1686 opts->arg[i] = NULL;
1687 }
1688
1689 return opts_and_args;
1690}
884b49e3 1691
e23eba97
NC
1692void
1693print_riscv_disassembler_options (FILE *stream)
1694{
3a337a86
AB
1695 const disasm_options_and_args_t *opts_and_args;
1696 const disasm_option_arg_t *args;
1697 const disasm_options_t *opts;
1698 size_t max_len = 0;
1699 size_t i;
1700 size_t j;
1701
1702 opts_and_args = disassembler_options_riscv ();
1703 opts = &opts_and_args->options;
1704 args = opts_and_args->args;
1705
e23eba97 1706 fprintf (stream, _("\n\
3a337a86 1707The following RISC-V specific disassembler options are supported for use\n\
e23eba97 1708with the -M switch (multiple options should be separated by commas):\n"));
3a337a86 1709 fprintf (stream, "\n");
e23eba97 1710
3a337a86
AB
1711 /* Compute the length of the longest option name. */
1712 for (i = 0; opts->name[i] != NULL; i++)
1713 {
1714 size_t len = strlen (opts->name[i]);
8f595e9b 1715
3a337a86
AB
1716 if (opts->arg[i] != NULL)
1717 len += strlen (opts->arg[i]->name);
1718 if (max_len < len)
1719 max_len = len;
1720 }
e23eba97 1721
3a337a86
AB
1722 for (i = 0, max_len++; opts->name[i] != NULL; i++)
1723 {
1724 fprintf (stream, " %s", opts->name[i]);
1725 if (opts->arg[i] != NULL)
1726 fprintf (stream, "%s", opts->arg[i]->name);
1727 if (opts->description[i] != NULL)
1728 {
1729 size_t len = strlen (opts->name[i]);
1730
1731 if (opts->arg != NULL && opts->arg[i] != NULL)
1732 len += strlen (opts->arg[i]->name);
1733 fprintf (stream, "%*c %s", (int) (max_len - len), ' ',
1734 opts->description[i]);
1735 }
1736 fprintf (stream, "\n");
1737 }
1738
1739 for (i = 0; args[i].name != NULL; i++)
1740 {
9869e2e5
TO
1741 if (args[i].values == NULL)
1742 continue;
3a337a86
AB
1743 fprintf (stream, _("\n\
1744 For the options above, the following values are supported for \"%s\":\n "),
1745 args[i].name);
1746 for (j = 0; args[i].values[j] != NULL; j++)
1747 fprintf (stream, " %s", args[i].values[j]);
1748 fprintf (stream, _("\n"));
1749 }
e23eba97
NC
1750
1751 fprintf (stream, _("\n"));
1752}
26e91972
NC
1753
1754void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED)
1755{
3f61a38b
NC
1756 struct riscv_private_data *pd = info->private_data;
1757 if (pd)
3a69ff93
AM
1758 {
1759 riscv_release_subset_list (pd->riscv_rps_dis.subset_list);
1760 free (pd->riscv_rps_dis.subset_list);
1761 }
26e91972 1762}