]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/riscv-dis.c
gdb/doc: don't have .pod targets separate to man page targets
[thirdparty/binutils-gdb.git] / opcodes / riscv-dis.c
CommitLineData
e23eba97 1/* RISC-V disassembler
fd67aa11 2 Copyright (C) 2011-2024 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. */
02a63525
JB
72static const char (*riscv_gpr_names)[NRC];
73static const char (*riscv_fpr_names)[NRC];
e23eba97 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
9132c815
J
218/* Get Zcmp reg_list field. */
219
220static void
221print_reg_list (disassemble_info *info, insn_t l)
222{
223 bool numeric = riscv_gpr_names == riscv_gpr_names_numeric;
224 unsigned reg_list = (int)EXTRACT_OPERAND (REG_LIST, l);
225 unsigned r_start = numeric ? X_S2 : X_S0;
226 info->fprintf_func (info->stream, "%s", riscv_gpr_names[X_RA]);
227
228 if (reg_list == 5)
229 info->fprintf_func (info->stream, ",%s",
230 riscv_gpr_names[X_S0]);
231 else if (reg_list == 6 || (numeric && reg_list > 6))
232 info->fprintf_func (info->stream, ",%s-%s",
233 riscv_gpr_names[X_S0],
234 riscv_gpr_names[X_S1]);
235 if (reg_list == 15)
236 info->fprintf_func (info->stream, ",%s-%s",
237 riscv_gpr_names[r_start],
238 riscv_gpr_names[X_S11]);
239 else if (reg_list == 7 && numeric)
240 info->fprintf_func (info->stream, ",%s",
241 riscv_gpr_names[X_S2]);
242 else if (reg_list > 6)
243 info->fprintf_func (info->stream, ",%s-%s",
244 riscv_gpr_names[r_start],
245 riscv_gpr_names[reg_list + 11]);
246}
247
248/* Get Zcmp sp adjustment immediate. */
249
250static int
251riscv_get_spimm (insn_t l)
252{
253 int spimm = riscv_get_sp_base(l, *riscv_rps_dis.xlen);
254 spimm += EXTRACT_ZCMP_SPIMM (l);
255 if (((l ^ MATCH_CM_PUSH) & MASK_CM_PUSH) == 0)
256 spimm *= -1;
257 return spimm;
258}
259
e23eba97
NC
260/* Print insn arguments for 32/64-bit code. */
261
262static void
437e2ff1 263print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info)
e23eba97
NC
264{
265 struct riscv_private_data *pd = info->private_data;
266 int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
267 int rd = (l >> OP_SH_RD) & OP_MASK_RD;
49d31dc9 268 fprintf_styled_ftype print = info->fprintf_styled_func;
437e2ff1 269 const char *opargStart;
e23eba97 270
437e2ff1 271 if (*oparg != '\0')
49d31dc9 272 print (info->stream, dis_style_text, "\t");
e23eba97 273
437e2ff1 274 for (; *oparg != '\0'; oparg++)
e23eba97 275 {
437e2ff1
NC
276 opargStart = oparg;
277 switch (*oparg)
e23eba97
NC
278 {
279 case 'C': /* RVC */
437e2ff1 280 switch (*++oparg)
e23eba97 281 {
dcd709e0
NC
282 case 's': /* RS1 x8-x15. */
283 case 'w': /* RS1 x8-x15. */
49d31dc9 284 print (info->stream, dis_style_register, "%s",
e23eba97
NC
285 riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
286 break;
dcd709e0
NC
287 case 't': /* RS2 x8-x15. */
288 case 'x': /* RS2 x8-x15. */
49d31dc9 289 print (info->stream, dis_style_register, "%s",
e23eba97
NC
290 riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
291 break;
dcd709e0 292 case 'U': /* RS1, constrained to equal RD. */
49d31dc9
AB
293 print (info->stream, dis_style_register,
294 "%s", riscv_gpr_names[rd]);
e23eba97 295 break;
dcd709e0 296 case 'c': /* RS1, constrained to equal sp. */
49d31dc9
AB
297 print (info->stream, dis_style_register, "%s",
298 riscv_gpr_names[X_SP]);
e23eba97
NC
299 break;
300 case 'V': /* RS2 */
49d31dc9 301 print (info->stream, dis_style_register, "%s",
e23eba97
NC
302 riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
303 break;
f91d48de 304 case 'o':
e23eba97 305 case 'j':
c7dee848
JW
306 if (((l & MASK_C_ADDI) == MATCH_C_ADDI) && rd != 0)
307 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 0);
308 if (info->mach == bfd_mach_riscv64
309 && ((l & MASK_C_ADDIW) == MATCH_C_ADDIW) && rd != 0)
310 maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 1);
49d31dc9
AB
311 print (info->stream, dis_style_immediate, "%d",
312 (int)EXTRACT_CITYPE_IMM (l));
e23eba97
NC
313 break;
314 case 'k':
49d31dc9
AB
315 print (info->stream, dis_style_address_offset, "%d",
316 (int)EXTRACT_CLTYPE_LW_IMM (l));
e23eba97
NC
317 break;
318 case 'l':
49d31dc9
AB
319 print (info->stream, dis_style_address_offset, "%d",
320 (int)EXTRACT_CLTYPE_LD_IMM (l));
e23eba97
NC
321 break;
322 case 'm':
49d31dc9
AB
323 print (info->stream, dis_style_address_offset, "%d",
324 (int)EXTRACT_CITYPE_LWSP_IMM (l));
e23eba97
NC
325 break;
326 case 'n':
49d31dc9
AB
327 print (info->stream, dis_style_address_offset, "%d",
328 (int)EXTRACT_CITYPE_LDSP_IMM (l));
e23eba97
NC
329 break;
330 case 'K':
49d31dc9
AB
331 print (info->stream, dis_style_immediate, "%d",
332 (int)EXTRACT_CIWTYPE_ADDI4SPN_IMM (l));
e23eba97
NC
333 break;
334 case 'L':
49d31dc9
AB
335 print (info->stream, dis_style_immediate, "%d",
336 (int)EXTRACT_CITYPE_ADDI16SP_IMM (l));
e23eba97
NC
337 break;
338 case 'M':
49d31dc9
AB
339 print (info->stream, dis_style_address_offset, "%d",
340 (int)EXTRACT_CSSTYPE_SWSP_IMM (l));
e23eba97
NC
341 break;
342 case 'N':
49d31dc9
AB
343 print (info->stream, dis_style_address_offset, "%d",
344 (int)EXTRACT_CSSTYPE_SDSP_IMM (l));
e23eba97
NC
345 break;
346 case 'p':
5a9f5403 347 info->target = EXTRACT_CBTYPE_IMM (l) + pc;
e23eba97
NC
348 (*info->print_address_func) (info->target, info);
349 break;
350 case 'a':
5a9f5403 351 info->target = EXTRACT_CJTYPE_IMM (l) + pc;
e23eba97
NC
352 (*info->print_address_func) (info->target, info);
353 break;
354 case 'u':
49d31dc9 355 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 356 (unsigned)(EXTRACT_CITYPE_IMM (l) & (RISCV_BIGIMM_REACH-1)));
e23eba97
NC
357 break;
358 case '>':
49d31dc9 359 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 360 (unsigned)EXTRACT_CITYPE_IMM (l) & 0x3f);
e23eba97
NC
361 break;
362 case '<':
49d31dc9 363 print (info->stream, dis_style_immediate, "0x%x",
2cfc7c87 364 (unsigned)EXTRACT_CITYPE_IMM (l) & 0x1f);
e23eba97 365 break;
dcd709e0 366 case 'T': /* Floating-point RS2. */
49d31dc9 367 print (info->stream, dis_style_register, "%s",
e23eba97
NC
368 riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
369 break;
dcd709e0 370 case 'D': /* Floating-point RS2 x8-x15. */
49d31dc9 371 print (info->stream, dis_style_register, "%s",
e23eba97
NC
372 riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
373 break;
374 }
375 break;
376
65e4a99a
NC
377 case 'V': /* RVV */
378 switch (*++oparg)
379 {
380 case 'd':
381 case 'f':
49d31dc9 382 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
383 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
384 break;
385 case 'e':
386 if (!EXTRACT_OPERAND (VWD, l))
49d31dc9
AB
387 print (info->stream, dis_style_register, "%s",
388 riscv_gpr_names[0]);
65e4a99a 389 else
49d31dc9 390 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
391 riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
392 break;
393 case 's':
49d31dc9 394 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
395 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS1, l)]);
396 break;
397 case 't':
398 case 'u': /* VS1 == VS2 already verified at this point. */
399 case 'v': /* VD == VS1 == VS2 already verified at this point. */
49d31dc9 400 print (info->stream, dis_style_register, "%s",
65e4a99a
NC
401 riscv_vecr_names_numeric[EXTRACT_OPERAND (VS2, l)]);
402 break;
403 case '0':
49d31dc9
AB
404 print (info->stream, dis_style_register, "%s",
405 riscv_vecr_names_numeric[0]);
65e4a99a
NC
406 break;
407 case 'b':
408 case 'c':
409 {
410 int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l)
411 : EXTRACT_RVV_VC_IMM (l);
412 unsigned int imm_vlmul = EXTRACT_OPERAND (VLMUL, imm);
413 unsigned int imm_vsew = EXTRACT_OPERAND (VSEW, imm);
414 unsigned int imm_vta = EXTRACT_OPERAND (VTA, imm);
415 unsigned int imm_vma = EXTRACT_OPERAND (VMA, imm);
abfdb09f 416 unsigned int imm_vtype_res = (imm >> 8);
65e4a99a
NC
417
418 if (imm_vsew < ARRAY_SIZE (riscv_vsew)
419 && imm_vlmul < ARRAY_SIZE (riscv_vlmul)
420 && imm_vta < ARRAY_SIZE (riscv_vta)
421 && imm_vma < ARRAY_SIZE (riscv_vma)
ee083a9e
NC
422 && !imm_vtype_res
423 && riscv_vsew[imm_vsew] != NULL
424 && riscv_vlmul[imm_vlmul] != NULL)
49d31dc9
AB
425 print (info->stream, dis_style_text, "%s,%s,%s,%s",
426 riscv_vsew[imm_vsew],
65e4a99a
NC
427 riscv_vlmul[imm_vlmul], riscv_vta[imm_vta],
428 riscv_vma[imm_vma]);
429 else
49d31dc9 430 print (info->stream, dis_style_immediate, "%d", imm);
65e4a99a
NC
431 }
432 break;
433 case 'i':
49d31dc9
AB
434 print (info->stream, dis_style_immediate, "%d",
435 (int)EXTRACT_RVV_VI_IMM (l));
65e4a99a
NC
436 break;
437 case 'j':
49d31dc9
AB
438 print (info->stream, dis_style_immediate, "%d",
439 (int)EXTRACT_RVV_VI_UIMM (l));
65e4a99a
NC
440 break;
441 case 'k':
49d31dc9
AB
442 print (info->stream, dis_style_immediate, "%d",
443 (int)EXTRACT_RVV_OFFSET (l));
65e4a99a 444 break;
c8cb3734
CM
445 case 'l':
446 print (info->stream, dis_style_immediate, "%d",
447 (int)EXTRACT_RVV_VI_UIMM6 (l));
448 break;
65e4a99a 449 case 'm':
f3a80235
TO
450 if (!EXTRACT_OPERAND (VMASK, l))
451 {
452 print (info->stream, dis_style_text, ",");
453 print (info->stream, dis_style_register, "%s",
454 riscv_vecm_names_numeric[0]);
455 }
65e4a99a
NC
456 break;
457 }
458 break;
459
e23eba97
NC
460 case ',':
461 case '(':
462 case ')':
463 case '[':
464 case ']':
9132c815
J
465 case '{':
466 case '}':
49d31dc9 467 print (info->stream, dis_style_text, "%c", *oparg);
e23eba97
NC
468 break;
469
470 case '0':
dcd709e0 471 /* Only print constant 0 if it is the last argument. */
437e2ff1 472 if (!oparg[1])
49d31dc9 473 print (info->stream, dis_style_immediate, "0");
e23eba97
NC
474 break;
475
e23eba97 476 case 's':
35eeb78f 477 if ((l & MASK_JALR) == MATCH_JALR)
48525554 478 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
49d31dc9 479 print (info->stream, dis_style_register, "%s", riscv_gpr_names[rs1]);
e23eba97
NC
480 break;
481
482 case 't':
49d31dc9 483 print (info->stream, dis_style_register, "%s",
e23eba97
NC
484 riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
485 break;
486
487 case 'u':
49d31dc9 488 print (info->stream, dis_style_immediate, "0x%x",
e23eba97
NC
489 (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
490 break;
491
492 case 'm':
493 arg_print (info, EXTRACT_OPERAND (RM, l),
494 riscv_rm, ARRAY_SIZE (riscv_rm));
495 break;
496
497 case 'P':
498 arg_print (info, EXTRACT_OPERAND (PRED, l),
499 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
500 break;
501
502 case 'Q':
503 arg_print (info, EXTRACT_OPERAND (SUCC, l),
504 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
505 break;
506
507 case 'o':
c7dee848 508 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
b52d3cfc 509 /* Fall through. */
e23eba97
NC
510 case 'j':
511 if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0)
512 || (l & MASK_JALR) == MATCH_JALR)
c7dee848
JW
513 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
514 if (info->mach == bfd_mach_riscv64
515 && ((l & MASK_ADDIW) == MATCH_ADDIW) && rs1 != 0)
516 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 1);
49d31dc9
AB
517 print (info->stream, dis_style_immediate, "%d",
518 (int)EXTRACT_ITYPE_IMM (l));
e23eba97
NC
519 break;
520
521 case 'q':
c7dee848 522 maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l), 0);
49d31dc9
AB
523 print (info->stream, dis_style_address_offset, "%d",
524 (int)EXTRACT_STYPE_IMM (l));
e23eba97
NC
525 break;
526
527 case 'a':
5a9f5403 528 info->target = EXTRACT_JTYPE_IMM (l) + pc;
e23eba97
NC
529 (*info->print_address_func) (info->target, info);
530 break;
531
532 case 'p':
5a9f5403 533 info->target = EXTRACT_BTYPE_IMM (l) + pc;
e23eba97
NC
534 (*info->print_address_func) (info->target, info);
535 break;
536
537 case 'd':
538 if ((l & MASK_AUIPC) == MATCH_AUIPC)
539 pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
540 else if ((l & MASK_LUI) == MATCH_LUI)
541 pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
542 else if ((l & MASK_C_LUI) == MATCH_C_LUI)
5a9f5403 543 pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l);
49d31dc9 544 print (info->stream, dis_style_register, "%s", riscv_gpr_names[rd]);
e23eba97
NC
545 break;
546
3d1cafa0 547 case 'y':
9a76ca16 548 print (info->stream, dis_style_immediate, "0x%x",
02a63525 549 EXTRACT_OPERAND (BS, l));
3d1cafa0 550 break;
551
e23eba97 552 case 'z':
49d31dc9 553 print (info->stream, dis_style_register, "%s", riscv_gpr_names[0]);
e23eba97
NC
554 break;
555
556 case '>':
49d31dc9 557 print (info->stream, dis_style_immediate, "0x%x",
02a63525 558 EXTRACT_OPERAND (SHAMT, l));
e23eba97
NC
559 break;
560
561 case '<':
49d31dc9 562 print (info->stream, dis_style_immediate, "0x%x",
02a63525 563 EXTRACT_OPERAND (SHAMTW, l));
e23eba97
NC
564 break;
565
566 case 'S':
567 case 'U':
49d31dc9 568 print (info->stream, dis_style_register, "%s", riscv_fpr_names[rs1]);
e23eba97
NC
569 break;
570
571 case 'T':
49d31dc9
AB
572 print (info->stream, dis_style_register, "%s",
573 riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
e23eba97
NC
574 break;
575
576 case 'D':
49d31dc9 577 print (info->stream, dis_style_register, "%s", riscv_fpr_names[rd]);
e23eba97
NC
578 break;
579
580 case 'R':
49d31dc9
AB
581 print (info->stream, dis_style_register, "%s",
582 riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
e23eba97
NC
583 break;
584
585 case 'E':
586 {
dcd709e0 587 static const char *riscv_csr_hash[4096]; /* Total 2^12 CSRs. */
78933a4a 588 static bool init_csr = false;
e23eba97 589 unsigned int csr = EXTRACT_OPERAND (CSR, l);
8f595e9b
NC
590
591 if (!init_csr)
e23eba97 592 {
8f595e9b
NC
593 unsigned int i;
594 for (i = 0; i < 4096; i++)
595 riscv_csr_hash[i] = NULL;
596
dcd709e0 597 /* Set to the newest privileged version. */
8f595e9b
NC
598 if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
599 default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;
600
08ccfccf
NC
601#define DECLARE_CSR(name, num, class, define_version, abort_version) \
602 if (riscv_csr_hash[num] == NULL \
603 && ((define_version == PRIV_SPEC_CLASS_NONE \
604 && abort_version == PRIV_SPEC_CLASS_NONE) \
605 || (default_priv_spec >= define_version \
606 && default_priv_spec < abort_version))) \
8f595e9b
NC
607 riscv_csr_hash[num] = #name;
608#define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \
609 DECLARE_CSR (name, num, class, define_version, abort_version)
e23eba97
NC
610#include "opcode/riscv-opc.h"
611#undef DECLARE_CSR
612 }
8f595e9b
NC
613
614 if (riscv_csr_hash[csr] != NULL)
6fdd02bb
JM
615 if (riscv_subset_supports (&riscv_rps_dis, "xtheadvector")
616 && (csr == CSR_VSTART
617 || csr == CSR_VXSAT
618 || csr == CSR_VXRM
619 || csr == CSR_VL
620 || csr == CSR_VTYPE
621 || csr == CSR_VLENB))
622 print (info->stream, dis_style_register, "%s",
623 concat ("th.", riscv_csr_hash[csr], NULL));
624 else
625 print (info->stream, dis_style_register, "%s",
626 riscv_csr_hash[csr]);
e23eba97 627 else
9a76ca16 628 print (info->stream, dis_style_immediate, "0x%x", csr);
e23eba97
NC
629 break;
630 }
631
3d1cafa0 632 case 'Y':
9a76ca16 633 print (info->stream, dis_style_immediate, "0x%x",
02a63525 634 EXTRACT_OPERAND (RNUM, l));
3d1cafa0 635 break;
636
e23eba97 637 case 'Z':
9a76ca16 638 print (info->stream, dis_style_immediate, "%d", rs1);
e23eba97
NC
639 break;
640
6de11ff6
NC
641 case 'W': /* Various operands for standard z extensions. */
642 switch (*++oparg)
643 {
644 case 'i':
645 switch (*++oparg)
646 {
647 case 'f':
648 print (info->stream, dis_style_address_offset, "%d",
649 (int) EXTRACT_STYPE_IMM (l));
650 break;
651 default:
652 goto undefined_modifier;
653 }
654 break;
655 case 'f':
656 switch (*++oparg)
657 {
658 case 'v':
659 if (riscv_fli_symval[rs1])
660 print (info->stream, dis_style_text, "%s",
661 riscv_fli_symval[rs1]);
662 else
663 print (info->stream, dis_style_immediate, "%a",
664 riscv_fli_numval[rs1]);
665 break;
666 default:
667 goto undefined_modifier;
668 }
669 break;
670 case 'c': /* Zcb extension 16 bits length instruction fields. */
671 switch (*++oparg)
672 {
673 case 'b':
674 print (info->stream, dis_style_immediate, "%d",
675 (int)EXTRACT_ZCB_BYTE_UIMM (l));
676 break;
677 case 'h':
678 print (info->stream, dis_style_immediate, "%d",
679 (int)EXTRACT_ZCB_HALFWORD_UIMM (l));
680 break;
9132c815
J
681 case 'r':
682 print_reg_list (info, l);
683 break;
684 case 'p':
685 print (info->stream, dis_style_immediate, "%d",
686 riscv_get_spimm (l));
687 break;
6de11ff6
NC
688 default:
689 goto undefined_modifier;
690 }
691 break;
692 default:
693 goto undefined_modifier;
694 }
695 break;
696
697 case 'X': /* Vendor-specific operands. */
698 switch (*++oparg)
699 {
700 case 't': /* Vendor-specific (T-head) operands. */
54bca63b 701 {
6de11ff6
NC
702 size_t n;
703 size_t s;
704 bool sign;
54bca63b
TO
705 switch (*++oparg)
706 {
6a95962e
JM
707 case 'V':
708 ++oparg;
709 if (*oparg != 'c')
710 goto undefined_modifier;
711
712 int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l)
713 : EXTRACT_RVV_VC_IMM (l);
714 unsigned int imm_vediv = EXTRACT_OPERAND (XTHEADVEDIV, imm);
715 unsigned int imm_vlmul = EXTRACT_OPERAND (XTHEADVLMUL, imm);
716 unsigned int imm_vsew = EXTRACT_OPERAND (XTHEADVSEW, imm);
717 unsigned int imm_vtype_res
718 = EXTRACT_OPERAND (XTHEADVTYPE_RES, imm);
719 if (imm_vsew < ARRAY_SIZE (riscv_vsew)
720 && imm_vlmul < ARRAY_SIZE (riscv_th_vlen)
721 && imm_vediv < ARRAY_SIZE (riscv_th_vediv)
722 && ! imm_vtype_res)
723 print (info->stream, dis_style_text, "%s,%s,%s",
724 riscv_vsew[imm_vsew], riscv_th_vlen[imm_vlmul],
725 riscv_th_vediv[imm_vediv]);
726 else
727 print (info->stream, dis_style_immediate, "%d", imm);
728 break;
6de11ff6
NC
729 case 'l': /* Integer immediate, literal. */
730 oparg++;
731 while (*oparg && *oparg != ',')
732 {
733 print (info->stream, dis_style_immediate, "%c", *oparg);
734 oparg++;
735 }
736 oparg--;
54bca63b 737 break;
6de11ff6
NC
738 case 's': /* Integer immediate, 'XsN@S' ... N-bit signed immediate at bit S. */
739 sign = true;
740 goto print_imm;
741 case 'u': /* Integer immediate, 'XuN@S' ... N-bit unsigned immediate at bit S. */
742 sign = false;
743 goto print_imm;
744 print_imm:
745 n = strtol (oparg + 1, (char **)&oparg, 10);
746 if (*oparg != '@')
747 goto undefined_modifier;
748 s = strtol (oparg + 1, (char **)&oparg, 10);
749 oparg--;
750
751 if (!sign)
752 print (info->stream, dis_style_immediate, "%lu",
753 (unsigned long)EXTRACT_U_IMM (n, s, l));
1f3fc45b 754 else
6de11ff6
NC
755 print (info->stream, dis_style_immediate, "%li",
756 (signed long)EXTRACT_S_IMM (n, s, l));
1f3fc45b
CM
757 break;
758 default:
759 goto undefined_modifier;
760 }
54bca63b 761 }
6de11ff6 762 break;
ccb388ca
MB
763 case 'c': /* Vendor-specific (CORE-V) operands. */
764 switch (*++oparg)
765 {
d1bd9787
MB
766 case '2':
767 print (info->stream, dis_style_immediate, "%d",
768 ((int) EXTRACT_CV_IS2_UIMM5 (l)));
769 break;
ccb388ca
MB
770 case '3':
771 print (info->stream, dis_style_immediate, "%d",
772 ((int) EXTRACT_CV_IS3_UIMM5 (l)));
773 break;
774 default:
775 goto undefined_modifier;
776 }
777 break;
248bf6de
NC
778 case 's': /* Vendor-specific (SiFive) operands. */
779 switch (*++oparg)
780 {
781 /* SiFive vector coprocessor interface. */
782 case 'd':
783 print (info->stream, dis_style_register, "0x%x",
784 (unsigned) EXTRACT_OPERAND (RD, l));
785 break;
786 case 't':
787 print (info->stream, dis_style_register, "0x%x",
788 (unsigned) EXTRACT_OPERAND (RS2, l));
789 break;
790 case 'O':
791 switch (*++oparg)
792 {
793 case '2':
794 print (info->stream, dis_style_register, "0x%x",
795 (unsigned) EXTRACT_OPERAND (XSO2, l));
796 break;
797 case '1':
798 print (info->stream, dis_style_register, "0x%x",
799 (unsigned) EXTRACT_OPERAND (XSO1, l));
800 break;
801 }
802 break;
803 }
804 break;
6de11ff6
NC
805 default:
806 goto undefined_modifier;
807 }
8b7419c4 808 break;
1f3fc45b 809
e23eba97 810 default:
8b7419c4 811 undefined_modifier:
e23eba97 812 /* xgettext:c-format */
49d31dc9
AB
813 print (info->stream, dis_style_text,
814 _("# internal error, undefined modifier (%c)"),
437e2ff1 815 *opargStart);
e23eba97
NC
816 return;
817 }
818 }
819}
820
821/* Print the RISC-V instruction at address MEMADDR in debugged memory,
822 on using INFO. Returns length of the instruction, in bytes.
823 BIGENDIAN must be 1 if this is big-endian code, 0 if
824 this is little-endian code. */
825
826static int
97f006bc
TO
827riscv_disassemble_insn (bfd_vma memaddr,
828 insn_t word,
829 const bfd_byte *packet,
830 disassemble_info *info)
e23eba97
NC
831{
832 const struct riscv_opcode *op;
354c1c09 833 static bool init = false;
e23eba97 834 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
26e91972 835 struct riscv_private_data *pd = info->private_data;
0655669b
JB
836 int insnlen, i;
837 bool printed;
e23eba97
NC
838
839#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
840
841 /* Build a hash table to shorten the search time. */
842 if (! init)
843 {
844 for (op = riscv_opcodes; op->name; op++)
845 if (!riscv_hash[OP_HASH_IDX (op->match)])
846 riscv_hash[OP_HASH_IDX (op->match)] = op;
847
354c1c09 848 init = true;
e23eba97
NC
849 }
850
e23eba97
NC
851 insnlen = riscv_insn_length (word);
852
d7560e2d
JW
853 /* RISC-V instructions are always little-endian. */
854 info->endian_code = BFD_ENDIAN_LITTLE;
855
e23eba97
NC
856 info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
857 info->bytes_per_line = 8;
d7560e2d
JW
858 /* We don't support constant pools, so this must be code. */
859 info->display_endian = info->endian_code;
e23eba97
NC
860 info->insn_info_valid = 1;
861 info->branch_delay_insns = 0;
862 info->data_size = 0;
863 info->insn_type = dis_nonbranch;
864 info->target = 0;
865 info->target2 = 0;
866
867 op = riscv_hash[OP_HASH_IDX (word)];
868 if (op != NULL)
869 {
2922d21d
AW
870 /* If XLEN is not known, get its value from the ELF class. */
871 if (info->mach == bfd_mach_riscv64)
872 xlen = 64;
873 else if (info->mach == bfd_mach_riscv32)
874 xlen = 32;
875 else if (info->section != NULL)
e23eba97
NC
876 {
877 Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
878 xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
879 }
880
2b8fd839 881 /* If arch has the Zfinx extension, replace FPR with GPR. */
1469f944 882 if (riscv_subset_supports (&riscv_rps_dis, "zfinx"))
3d5d6bd5 883 riscv_fpr_names = riscv_gpr_names;
40f1a1a4
NC
884 else
885 riscv_fpr_names = riscv_gpr_names == riscv_gpr_names_abi ?
886 riscv_fpr_names_abi : riscv_fpr_names_numeric;
de83e514 887
e23eba97
NC
888 for (; op->name; op++)
889 {
27b33966
JB
890 /* Ignore macro insns. */
891 if (op->pinfo == INSN_MACRO)
892 continue;
e23eba97
NC
893 /* Does the opcode match? */
894 if (! (op->match_func) (op, word))
895 continue;
896 /* Is this a pseudo-instruction and may we print it as such? */
897 if (no_aliases && (op->pinfo & INSN_ALIAS))
898 continue;
899 /* Is this instruction restricted to a certain value of XLEN? */
43135d3b 900 if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
e23eba97 901 continue;
2b8fd839 902 /* Is this instruction supported by the current architecture? */
f786c359
NC
903 if (!riscv_multi_subset_supports (&riscv_rps_dis, op->insn_class))
904 continue;
905
e23eba97 906 /* It's a match. */
49d31dc9
AB
907 (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
908 "%s", op->name);
e23eba97
NC
909 print_insn_args (op->args, word, memaddr, info);
910
911 /* Try to disassemble multi-instruction addressing sequences. */
8fe1be5f 912 if (pd->to_print_addr)
e23eba97
NC
913 {
914 info->target = pd->print_addr;
49d31dc9
AB
915 (*info->fprintf_styled_func)
916 (info->stream, dis_style_comment_start, " # ");
e23eba97 917 (*info->print_address_func) (info->target, info);
8fe1be5f 918 pd->to_print_addr = false;
e23eba97
NC
919 }
920
eb41b248
JW
921 /* Finish filling out insn_info fields. */
922 switch (op->pinfo & INSN_TYPE)
923 {
924 case INSN_BRANCH:
925 info->insn_type = dis_branch;
926 break;
927 case INSN_CONDBRANCH:
928 info->insn_type = dis_condbranch;
929 break;
930 case INSN_JSR:
931 info->insn_type = dis_jsr;
932 break;
933 case INSN_DREF:
934 info->insn_type = dis_dref;
935 break;
936 default:
937 break;
938 }
939
940 if (op->pinfo & INSN_DATA_SIZE)
941 {
942 int size = ((op->pinfo & INSN_DATA_SIZE)
943 >> INSN_DATA_SIZE_SHIFT);
944 info->data_size = 1 << (size - 1);
945 }
946
e23eba97
NC
947 return insnlen;
948 }
949 }
950
0655669b
JB
951 /* We did not find a match, so just print the instruction bits in
952 the shape of an assembler .insn directive. */
e23eba97 953 info->insn_type = dis_noninsn;
0655669b
JB
954 (*info->fprintf_styled_func)
955 (info->stream, dis_style_assembler_directive, ".insn");
956 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
957 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
958 "%d", insnlen);
959 (*info->fprintf_styled_func) (info->stream, dis_style_text, ", ");
960 (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x");
961 for (i = insnlen, printed = false; i >= 2; )
6a7f5766 962 {
0655669b
JB
963 i -= 2;
964 word = bfd_get_bits (packet + i, 16, false);
965 if (!word && !printed)
966 continue;
967
49d31dc9 968 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
0655669b
JB
969 "%04x", (unsigned int) word);
970 printed = true;
6a7f5766 971 }
0655669b 972
e23eba97
NC
973 return insnlen;
974}
975
460e0e6e
PN
976/* If we find the suitable mapping symbol update the STATE.
977 Otherwise, do nothing. */
9b9b1092 978
460e0e6e
PN
979static void
980riscv_update_map_state (int n,
981 enum riscv_seg_mstate *state,
982 struct disassemble_info *info)
9b9b1092
NC
983{
984 const char *name;
985
986 /* If the symbol is in a different section, ignore it. */
987 if (info->section != NULL
988 && info->section != info->symtab[n]->section)
460e0e6e 989 return;
9b9b1092
NC
990
991 name = bfd_asymbol_name(info->symtab[n]);
992 if (strcmp (name, "$x") == 0)
993 *state = MAP_INSN;
994 else if (strcmp (name, "$d") == 0)
995 *state = MAP_DATA;
40f1a1a4
NC
996 else if (strncmp (name, "$xrv", 4) == 0)
997 {
998 *state = MAP_INSN;
999 riscv_release_subset_list (&riscv_subsets);
9326300e
JF
1000
1001 /* ISA mapping string may be numbered, suffixed with '.n'. Do not
1002 consider this as part of the ISA string. */
1003 char *suffix = strchr (name, '.');
1004 if (suffix)
1005 {
1006 int suffix_index = (int)(suffix - name);
1007 char *name_substr = xmalloc (suffix_index + 1);
1008 strncpy (name_substr, name, suffix_index);
1009 name_substr[suffix_index] = '\0';
1010 riscv_parse_subset (&riscv_rps_dis, name_substr + 2);
1011 free (name_substr);
1012 }
1013 else
1014 riscv_parse_subset (&riscv_rps_dis, name + 2);
40f1a1a4 1015 }
460e0e6e
PN
1016}
1017
1018/* Return true if we find the suitable mapping symbol.
1019 Otherwise, return false. */
1020
1021static bool
1022riscv_is_valid_mapping_symbol (int n,
1023 struct disassemble_info *info)
1024{
1025 const char *name;
1026
1027 /* If the symbol is in a different section, ignore it. */
1028 if (info->section != NULL
1029 && info->section != info->symtab[n]->section)
9b9b1092
NC
1030 return false;
1031
460e0e6e 1032 name = bfd_asymbol_name(info->symtab[n]);
2b33b0d9 1033 return riscv_elf_is_mapping_symbols (name);
9b9b1092
NC
1034}
1035
1036/* Check the sorted symbol table (sorted by the symbol value), find the
1037 suitable mapping symbols. */
1038
1039static enum riscv_seg_mstate
1040riscv_search_mapping_symbol (bfd_vma memaddr,
1041 struct disassemble_info *info)
1042{
1043 enum riscv_seg_mstate mstate;
1044 bool from_last_map_symbol;
1045 bool found = false;
1046 int symbol = -1;
1047 int n;
1048
c2f60ac5
KC
1049 /* Return the last map state if the address is still within the range of the
1050 last mapping symbol. */
1051 if (last_map_section == info->section
1052 && (memaddr < last_map_symbol_boundary))
1053 return last_map_state;
1054
1055 last_map_section = info->section;
1056
9b9b1092
NC
1057 /* Decide whether to print the data or instruction by default, in case
1058 we can not find the corresponding mapping symbols. */
1059 mstate = MAP_DATA;
1060 if ((info->section
1061 && info->section->flags & SEC_CODE)
1062 || !info->section)
1063 mstate = MAP_INSN;
1064
1065 if (info->symtab_size == 0
1066 || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour)
1067 return mstate;
1068
1069 /* Reset the last_map_symbol if we start to dump a new section. */
1070 if (memaddr <= 0)
1071 last_map_symbol = -1;
1072
1073 /* If the last stop offset is different from the current one, then
1074 don't use the last_map_symbol to search. We usually reset the
1075 info->stop_offset when handling a new section. */
1076 from_last_map_symbol = (last_map_symbol >= 0
1077 && info->stop_offset == last_stop_offset);
1078
7a7ec56c
JF
1079 /* Start scanning from wherever we finished last time, or the start
1080 of the function. */
1081 n = from_last_map_symbol ? last_map_symbol : info->symtab_pos + 1;
9b9b1092
NC
1082
1083 /* Find the suitable mapping symbol to dump. */
1084 for (; n < info->symtab_size; n++)
1085 {
1086 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1087 /* We have searched all possible symbols in the range. */
1088 if (addr > memaddr)
1089 break;
460e0e6e 1090 if (riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1091 {
1092 symbol = n;
1093 found = true;
1094 /* Do not stop searching, in case there are some mapping
1095 symbols have the same value, but have different names.
1096 Use the last one. */
1097 }
1098 }
1099
1100 /* We can not find the suitable mapping symbol above. Therefore, we
b5c37946 1101 look forwards and try to find it again, but don't go past the start
9b9b1092
NC
1102 of the section. Otherwise a data section without mapping symbols
1103 can pick up a text mapping symbol of a preceeding section. */
1104 if (!found)
1105 {
7a7ec56c 1106 n = from_last_map_symbol ? last_map_symbol : info->symtab_pos;
9b9b1092
NC
1107
1108 for (; n >= 0; n--)
1109 {
1110 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1111 /* We have searched all possible symbols in the range. */
1112 if (addr < (info->section ? info->section->vma : 0))
1113 break;
1114 /* Stop searching once we find the closed mapping symbol. */
460e0e6e 1115 if (riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1116 {
1117 symbol = n;
1118 found = true;
1119 break;
1120 }
1121 }
1122 }
1123
c2f60ac5
KC
1124 if (found)
1125 {
460e0e6e
PN
1126 riscv_update_map_state (symbol, &mstate, info);
1127
c2f60ac5
KC
1128 /* Find the next mapping symbol to determine the boundary of this mapping
1129 symbol. */
1130
1131 bool found_next = false;
1132 /* Try to found next mapping symbol. */
1133 for (n = symbol + 1; n < info->symtab_size; n++)
1134 {
1135 if (info->symtab[symbol]->section != info->symtab[n]->section)
1136 continue;
1137
1138 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1139 const char *sym_name = bfd_asymbol_name(info->symtab[n]);
1140 if (sym_name[0] == '$' && (sym_name[1] == 'x' || sym_name[1] == 'd'))
1141 {
1142 /* The next mapping symbol has been found, and it represents the
1143 boundary of this mapping symbol. */
1144 found_next = true;
1145 last_map_symbol_boundary = addr;
1146 break;
1147 }
1148 }
1149
1150 /* No further mapping symbol has been found, indicating that the boundary
1151 of the current mapping symbol is the end of this section. */
1152 if (!found_next)
1153 last_map_symbol_boundary = info->section->vma + info->section->size;
1154 }
1155
9b9b1092
NC
1156 /* Save the information for next use. */
1157 last_map_symbol = symbol;
1158 last_stop_offset = info->stop_offset;
1159
1160 return mstate;
1161}
1162
1163/* Decide which data size we should print. */
1164
1165static bfd_vma
1166riscv_data_length (bfd_vma memaddr,
1167 disassemble_info *info)
1168{
1169 bfd_vma length;
1170 bool found = false;
1171
1172 length = 4;
1173 if (info->symtab_size != 0
1174 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour
1175 && last_map_symbol >= 0)
1176 {
1177 int n;
1178 enum riscv_seg_mstate m = MAP_NONE;
1179 for (n = last_map_symbol + 1; n < info->symtab_size; n++)
1180 {
1181 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1182 if (addr > memaddr
460e0e6e 1183 && riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1184 {
1185 if (addr - memaddr < length)
1186 length = addr - memaddr;
1187 found = true;
460e0e6e 1188 riscv_update_map_state (n, &m, info);
9b9b1092
NC
1189 break;
1190 }
1191 }
1192 }
1193 if (!found)
1194 {
1195 /* Do not set the length which exceeds the section size. */
1196 bfd_vma offset = info->section->vma + info->section->size;
1197 offset -= memaddr;
1198 length = (offset < length) ? offset : length;
1199 }
1200 length = length == 3 ? 2 : length;
1201 return length;
1202}
1203
1204/* Dump the data contents. */
1205
1206static int
1207riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED,
1208 insn_t data,
97f006bc 1209 const bfd_byte *packet ATTRIBUTE_UNUSED,
9b9b1092
NC
1210 disassemble_info *info)
1211{
1212 info->display_endian = info->endian;
1213
1214 switch (info->bytes_per_chunk)
1215 {
1216 case 1:
1217 info->bytes_per_line = 6;
49d31dc9 1218 (*info->fprintf_styled_func)
f3a80235
TO
1219 (info->stream, dis_style_assembler_directive, ".byte");
1220 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1221 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1222 "0x%02x", (unsigned)data);
9b9b1092
NC
1223 break;
1224 case 2:
1225 info->bytes_per_line = 8;
49d31dc9 1226 (*info->fprintf_styled_func)
f3a80235
TO
1227 (info->stream, dis_style_assembler_directive, ".short");
1228 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1229 (*info->fprintf_styled_func)
e0b004c5 1230 (info->stream, dis_style_immediate, "0x%04x", (unsigned) data);
9b9b1092
NC
1231 break;
1232 case 4:
1233 info->bytes_per_line = 8;
49d31dc9 1234 (*info->fprintf_styled_func)
f3a80235
TO
1235 (info->stream, dis_style_assembler_directive, ".word");
1236 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1237 (*info->fprintf_styled_func)
e0b004c5
TO
1238 (info->stream, dis_style_immediate, "0x%08lx",
1239 (unsigned long) data);
9b9b1092
NC
1240 break;
1241 case 8:
1242 info->bytes_per_line = 8;
49d31dc9 1243 (*info->fprintf_styled_func)
f3a80235
TO
1244 (info->stream, dis_style_assembler_directive, ".dword");
1245 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9
AB
1246 (*info->fprintf_styled_func)
1247 (info->stream, dis_style_immediate, "0x%016llx",
1248 (unsigned long long) data);
9b9b1092
NC
1249 break;
1250 default:
1251 abort ();
1252 }
1253 return info->bytes_per_chunk;
1254}
1255
26e91972
NC
1256static bool
1257riscv_init_disasm_info (struct disassemble_info *info)
1258{
1259 int i;
1260
1261 struct riscv_private_data *pd =
1262 xcalloc (1, sizeof (struct riscv_private_data));
1263 pd->gp = 0;
1264 pd->print_addr = 0;
1265 for (i = 0; i < (int) ARRAY_SIZE (pd->hi_addr); i++)
1266 pd->hi_addr[i] = -1;
1267 pd->to_print_addr = false;
1268 pd->has_gp = false;
1269
1270 for (i = 0; i < info->symtab_size; i++)
1271 {
1272 asymbol *sym = info->symtab[i];
1273 if (strcmp (bfd_asymbol_name (sym), RISCV_GP_SYMBOL) == 0)
1274 {
1275 pd->gp = bfd_asymbol_value (sym);
1276 pd->has_gp = true;
1277 }
1278 }
1279
1280 info->private_data = pd;
1281 return true;
1282}
1283
e23eba97
NC
1284int
1285print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
1286{
73e30e72 1287 bfd_byte packet[RISCV_MAX_INSN_LEN];
e23eba97 1288 insn_t insn = 0;
9b9b1092 1289 bfd_vma dump_size;
e23eba97 1290 int status;
9b9b1092 1291 enum riscv_seg_mstate mstate;
97f006bc
TO
1292 int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *,
1293 struct disassemble_info *);
e23eba97
NC
1294
1295 if (info->disassembler_options != NULL)
1296 {
1297 parse_riscv_dis_options (info->disassembler_options);
1298 /* Avoid repeatedly parsing the options. */
1299 info->disassembler_options = NULL;
1300 }
1301 else if (riscv_gpr_names == NULL)
1302 set_default_riscv_dis_options ();
1303
26e91972
NC
1304 if (info->private_data == NULL && !riscv_init_disasm_info (info))
1305 return -1;
1306
9b9b1092 1307 mstate = riscv_search_mapping_symbol (memaddr, info);
c2f60ac5
KC
1308 /* Save the last mapping state. */
1309 last_map_state = mstate;
9b9b1092
NC
1310
1311 /* Set the size to dump. */
1312 if (mstate == MAP_DATA
1313 && (info->flags & DISASSEMBLE_DATA) == 0)
1314 {
1315 dump_size = riscv_data_length (memaddr, info);
1316 info->bytes_per_chunk = dump_size;
1317 riscv_disassembler = riscv_disassemble_data;
1318 }
1319 else
e23eba97 1320 {
9b9b1092
NC
1321 /* Get the first 2-bytes to check the lenghth of instruction. */
1322 status = (*info->read_memory_func) (memaddr, packet, 2, info);
e23eba97
NC
1323 if (status != 0)
1324 {
e23eba97 1325 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1326 return -1;
e23eba97 1327 }
9b9b1092
NC
1328 insn = (insn_t) bfd_getl16 (packet);
1329 dump_size = riscv_insn_length (insn);
1330 riscv_disassembler = riscv_disassemble_insn;
1331 }
e23eba97 1332
9b9b1092
NC
1333 /* Fetch the instruction to dump. */
1334 status = (*info->read_memory_func) (memaddr, packet, dump_size, info);
1335 if (status != 0)
1336 {
1337 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1338 return -1;
e23eba97 1339 }
9b9b1092 1340 insn = (insn_t) bfd_get_bits (packet, dump_size * 8, false);
e23eba97 1341
97f006bc 1342 return (*riscv_disassembler) (memaddr, insn, packet, info);
e23eba97
NC
1343}
1344
8152e040
NC
1345disassembler_ftype
1346riscv_get_disassembler (bfd *abfd)
1347{
f786c359
NC
1348 const char *default_arch = "rv64gc";
1349
16089f32 1350 if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
8152e040 1351 {
16089f32
TH
1352 const char *sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
1353 if (bfd_get_section_by_name (abfd, sec_name) != NULL)
f786c359 1354 {
16089f32
TH
1355 obj_attribute *attr = elf_known_obj_attributes_proc (abfd);
1356 unsigned int Tag_a = Tag_RISCV_priv_spec;
1357 unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
1358 unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
1359 riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i,
1360 attr[Tag_b].i,
1361 attr[Tag_c].i,
1362 &default_priv_spec);
1363 default_arch = attr[Tag_RISCV_arch].s;
f786c359 1364 }
8152e040 1365 }
f786c359
NC
1366
1367 riscv_release_subset_list (&riscv_subsets);
1368 riscv_parse_subset (&riscv_rps_dis, default_arch);
1369 return print_insn_riscv;
8152e040
NC
1370}
1371
884b49e3
AB
1372/* Prevent use of the fake labels that are generated as part of the DWARF
1373 and for relaxable relocations in the assembler. */
1374
78933a4a 1375bool
884b49e3
AB
1376riscv_symbol_is_valid (asymbol * sym,
1377 struct disassemble_info * info ATTRIBUTE_UNUSED)
1378{
1379 const char * name;
1380
1381 if (sym == NULL)
78933a4a 1382 return false;
884b49e3
AB
1383
1384 name = bfd_asymbol_name (sym);
1385
9b9b1092
NC
1386 return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0
1387 && !riscv_elf_is_mapping_symbols (name));
884b49e3 1388}
3a337a86
AB
1389\f
1390
1391/* Indices into option argument vector for options accepting an argument.
1392 Use RISCV_OPTION_ARG_NONE for options accepting no argument. */
1393
1394typedef enum
1395{
1396 RISCV_OPTION_ARG_NONE = -1,
1397 RISCV_OPTION_ARG_PRIV_SPEC,
1398
1399 RISCV_OPTION_ARG_COUNT
1400} riscv_option_arg_t;
1401
1402/* Valid RISCV disassembler options. */
1403
1404static struct
1405{
1406 const char *name;
1407 const char *description;
1408 riscv_option_arg_t arg;
1409} riscv_options[] =
1410{
1411 { "numeric",
1412 N_("Print numeric register names, rather than ABI names."),
1413 RISCV_OPTION_ARG_NONE },
1414 { "no-aliases",
1415 N_("Disassemble only into canonical instructions."),
1416 RISCV_OPTION_ARG_NONE },
1417 { "priv-spec=",
1418 N_("Print the CSR according to the chosen privilege spec."),
1419 RISCV_OPTION_ARG_PRIV_SPEC }
1420};
1421
1422/* Build the structure representing valid RISCV disassembler options.
1423 This is done dynamically for maintenance ease purpose; a static
1424 initializer would be unreadable. */
1425
1426const disasm_options_and_args_t *
1427disassembler_options_riscv (void)
1428{
1429 static disasm_options_and_args_t *opts_and_args;
1430
1431 if (opts_and_args == NULL)
1432 {
1433 size_t num_options = ARRAY_SIZE (riscv_options);
1434 size_t num_args = RISCV_OPTION_ARG_COUNT;
1435 disasm_option_arg_t *args;
1436 disasm_options_t *opts;
1437 size_t i, priv_spec_count;
1438
1439 args = XNEWVEC (disasm_option_arg_t, num_args + 1);
1440
1441 args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC";
1442 priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_CLASS_NONE - 1;
1443 args[RISCV_OPTION_ARG_PRIV_SPEC].values
1444 = XNEWVEC (const char *, priv_spec_count + 1);
1445 for (i = 0; i < priv_spec_count; i++)
1446 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i]
1447 = riscv_priv_specs[i].name;
1448 /* The array we return must be NULL terminated. */
1449 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] = NULL;
1450
1451 /* The array we return must be NULL terminated. */
1452 args[num_args].name = NULL;
1453 args[num_args].values = NULL;
1454
1455 opts_and_args = XNEW (disasm_options_and_args_t);
1456 opts_and_args->args = args;
1457
1458 opts = &opts_and_args->options;
1459 opts->name = XNEWVEC (const char *, num_options + 1);
1460 opts->description = XNEWVEC (const char *, num_options + 1);
1461 opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
1462 for (i = 0; i < num_options; i++)
1463 {
1464 opts->name[i] = riscv_options[i].name;
1465 opts->description[i] = _(riscv_options[i].description);
1466 if (riscv_options[i].arg != RISCV_OPTION_ARG_NONE)
1467 opts->arg[i] = &args[riscv_options[i].arg];
1468 else
1469 opts->arg[i] = NULL;
1470 }
1471 /* The array we return must be NULL terminated. */
1472 opts->name[i] = NULL;
1473 opts->description[i] = NULL;
1474 opts->arg[i] = NULL;
1475 }
1476
1477 return opts_and_args;
1478}
884b49e3 1479
e23eba97
NC
1480void
1481print_riscv_disassembler_options (FILE *stream)
1482{
3a337a86
AB
1483 const disasm_options_and_args_t *opts_and_args;
1484 const disasm_option_arg_t *args;
1485 const disasm_options_t *opts;
1486 size_t max_len = 0;
1487 size_t i;
1488 size_t j;
1489
1490 opts_and_args = disassembler_options_riscv ();
1491 opts = &opts_and_args->options;
1492 args = opts_and_args->args;
1493
e23eba97 1494 fprintf (stream, _("\n\
3a337a86 1495The following RISC-V specific disassembler options are supported for use\n\
e23eba97 1496with the -M switch (multiple options should be separated by commas):\n"));
3a337a86 1497 fprintf (stream, "\n");
e23eba97 1498
3a337a86
AB
1499 /* Compute the length of the longest option name. */
1500 for (i = 0; opts->name[i] != NULL; i++)
1501 {
1502 size_t len = strlen (opts->name[i]);
8f595e9b 1503
3a337a86
AB
1504 if (opts->arg[i] != NULL)
1505 len += strlen (opts->arg[i]->name);
1506 if (max_len < len)
1507 max_len = len;
1508 }
e23eba97 1509
3a337a86
AB
1510 for (i = 0, max_len++; opts->name[i] != NULL; i++)
1511 {
1512 fprintf (stream, " %s", opts->name[i]);
1513 if (opts->arg[i] != NULL)
1514 fprintf (stream, "%s", opts->arg[i]->name);
1515 if (opts->description[i] != NULL)
1516 {
1517 size_t len = strlen (opts->name[i]);
1518
1519 if (opts->arg != NULL && opts->arg[i] != NULL)
1520 len += strlen (opts->arg[i]->name);
1521 fprintf (stream, "%*c %s", (int) (max_len - len), ' ',
1522 opts->description[i]);
1523 }
1524 fprintf (stream, "\n");
1525 }
1526
1527 for (i = 0; args[i].name != NULL; i++)
1528 {
9869e2e5
TO
1529 if (args[i].values == NULL)
1530 continue;
3a337a86
AB
1531 fprintf (stream, _("\n\
1532 For the options above, the following values are supported for \"%s\":\n "),
1533 args[i].name);
1534 for (j = 0; args[i].values[j] != NULL; j++)
1535 fprintf (stream, " %s", args[i].values[j]);
1536 fprintf (stream, _("\n"));
1537 }
e23eba97
NC
1538
1539 fprintf (stream, _("\n"));
1540}
26e91972
NC
1541
1542void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED)
1543{
1544 riscv_release_subset_list (&riscv_subsets);
1545}