]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/riscv-dis.c
LoongArch: Fix ld test failures caused by using instruction aliases
[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
1079 /* Start scanning at the start of the function, or wherever
1080 we finished last time. */
1081 n = info->symtab_pos + 1;
1082 if (from_last_map_symbol && n >= last_map_symbol)
1083 n = last_map_symbol;
1084
1085 /* Find the suitable mapping symbol to dump. */
1086 for (; n < info->symtab_size; n++)
1087 {
1088 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1089 /* We have searched all possible symbols in the range. */
1090 if (addr > memaddr)
1091 break;
460e0e6e 1092 if (riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1093 {
1094 symbol = n;
1095 found = true;
1096 /* Do not stop searching, in case there are some mapping
1097 symbols have the same value, but have different names.
1098 Use the last one. */
1099 }
1100 }
1101
1102 /* We can not find the suitable mapping symbol above. Therefore, we
b5c37946 1103 look forwards and try to find it again, but don't go past the start
9b9b1092
NC
1104 of the section. Otherwise a data section without mapping symbols
1105 can pick up a text mapping symbol of a preceeding section. */
1106 if (!found)
1107 {
1108 n = info->symtab_pos;
1109 if (from_last_map_symbol && n >= last_map_symbol)
1110 n = last_map_symbol;
1111
1112 for (; n >= 0; n--)
1113 {
1114 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1115 /* We have searched all possible symbols in the range. */
1116 if (addr < (info->section ? info->section->vma : 0))
1117 break;
1118 /* Stop searching once we find the closed mapping symbol. */
460e0e6e 1119 if (riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1120 {
1121 symbol = n;
1122 found = true;
1123 break;
1124 }
1125 }
1126 }
1127
c2f60ac5
KC
1128 if (found)
1129 {
460e0e6e
PN
1130 riscv_update_map_state (symbol, &mstate, info);
1131
c2f60ac5
KC
1132 /* Find the next mapping symbol to determine the boundary of this mapping
1133 symbol. */
1134
1135 bool found_next = false;
1136 /* Try to found next mapping symbol. */
1137 for (n = symbol + 1; n < info->symtab_size; n++)
1138 {
1139 if (info->symtab[symbol]->section != info->symtab[n]->section)
1140 continue;
1141
1142 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1143 const char *sym_name = bfd_asymbol_name(info->symtab[n]);
1144 if (sym_name[0] == '$' && (sym_name[1] == 'x' || sym_name[1] == 'd'))
1145 {
1146 /* The next mapping symbol has been found, and it represents the
1147 boundary of this mapping symbol. */
1148 found_next = true;
1149 last_map_symbol_boundary = addr;
1150 break;
1151 }
1152 }
1153
1154 /* No further mapping symbol has been found, indicating that the boundary
1155 of the current mapping symbol is the end of this section. */
1156 if (!found_next)
1157 last_map_symbol_boundary = info->section->vma + info->section->size;
1158 }
1159
9b9b1092
NC
1160 /* Save the information for next use. */
1161 last_map_symbol = symbol;
1162 last_stop_offset = info->stop_offset;
1163
1164 return mstate;
1165}
1166
1167/* Decide which data size we should print. */
1168
1169static bfd_vma
1170riscv_data_length (bfd_vma memaddr,
1171 disassemble_info *info)
1172{
1173 bfd_vma length;
1174 bool found = false;
1175
1176 length = 4;
1177 if (info->symtab_size != 0
1178 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour
1179 && last_map_symbol >= 0)
1180 {
1181 int n;
1182 enum riscv_seg_mstate m = MAP_NONE;
1183 for (n = last_map_symbol + 1; n < info->symtab_size; n++)
1184 {
1185 bfd_vma addr = bfd_asymbol_value (info->symtab[n]);
1186 if (addr > memaddr
460e0e6e 1187 && riscv_is_valid_mapping_symbol (n, info))
9b9b1092
NC
1188 {
1189 if (addr - memaddr < length)
1190 length = addr - memaddr;
1191 found = true;
460e0e6e 1192 riscv_update_map_state (n, &m, info);
9b9b1092
NC
1193 break;
1194 }
1195 }
1196 }
1197 if (!found)
1198 {
1199 /* Do not set the length which exceeds the section size. */
1200 bfd_vma offset = info->section->vma + info->section->size;
1201 offset -= memaddr;
1202 length = (offset < length) ? offset : length;
1203 }
1204 length = length == 3 ? 2 : length;
1205 return length;
1206}
1207
1208/* Dump the data contents. */
1209
1210static int
1211riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED,
1212 insn_t data,
97f006bc 1213 const bfd_byte *packet ATTRIBUTE_UNUSED,
9b9b1092
NC
1214 disassemble_info *info)
1215{
1216 info->display_endian = info->endian;
1217
1218 switch (info->bytes_per_chunk)
1219 {
1220 case 1:
1221 info->bytes_per_line = 6;
49d31dc9 1222 (*info->fprintf_styled_func)
f3a80235
TO
1223 (info->stream, dis_style_assembler_directive, ".byte");
1224 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1225 (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1226 "0x%02x", (unsigned)data);
9b9b1092
NC
1227 break;
1228 case 2:
1229 info->bytes_per_line = 8;
49d31dc9 1230 (*info->fprintf_styled_func)
f3a80235
TO
1231 (info->stream, dis_style_assembler_directive, ".short");
1232 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1233 (*info->fprintf_styled_func)
e0b004c5 1234 (info->stream, dis_style_immediate, "0x%04x", (unsigned) data);
9b9b1092
NC
1235 break;
1236 case 4:
1237 info->bytes_per_line = 8;
49d31dc9 1238 (*info->fprintf_styled_func)
f3a80235
TO
1239 (info->stream, dis_style_assembler_directive, ".word");
1240 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9 1241 (*info->fprintf_styled_func)
e0b004c5
TO
1242 (info->stream, dis_style_immediate, "0x%08lx",
1243 (unsigned long) data);
9b9b1092
NC
1244 break;
1245 case 8:
1246 info->bytes_per_line = 8;
49d31dc9 1247 (*info->fprintf_styled_func)
f3a80235
TO
1248 (info->stream, dis_style_assembler_directive, ".dword");
1249 (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
49d31dc9
AB
1250 (*info->fprintf_styled_func)
1251 (info->stream, dis_style_immediate, "0x%016llx",
1252 (unsigned long long) data);
9b9b1092
NC
1253 break;
1254 default:
1255 abort ();
1256 }
1257 return info->bytes_per_chunk;
1258}
1259
26e91972
NC
1260static bool
1261riscv_init_disasm_info (struct disassemble_info *info)
1262{
1263 int i;
1264
1265 struct riscv_private_data *pd =
1266 xcalloc (1, sizeof (struct riscv_private_data));
1267 pd->gp = 0;
1268 pd->print_addr = 0;
1269 for (i = 0; i < (int) ARRAY_SIZE (pd->hi_addr); i++)
1270 pd->hi_addr[i] = -1;
1271 pd->to_print_addr = false;
1272 pd->has_gp = false;
1273
1274 for (i = 0; i < info->symtab_size; i++)
1275 {
1276 asymbol *sym = info->symtab[i];
1277 if (strcmp (bfd_asymbol_name (sym), RISCV_GP_SYMBOL) == 0)
1278 {
1279 pd->gp = bfd_asymbol_value (sym);
1280 pd->has_gp = true;
1281 }
1282 }
1283
1284 info->private_data = pd;
1285 return true;
1286}
1287
e23eba97
NC
1288int
1289print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
1290{
73e30e72 1291 bfd_byte packet[RISCV_MAX_INSN_LEN];
e23eba97 1292 insn_t insn = 0;
9b9b1092 1293 bfd_vma dump_size;
e23eba97 1294 int status;
9b9b1092 1295 enum riscv_seg_mstate mstate;
97f006bc
TO
1296 int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *,
1297 struct disassemble_info *);
e23eba97
NC
1298
1299 if (info->disassembler_options != NULL)
1300 {
1301 parse_riscv_dis_options (info->disassembler_options);
1302 /* Avoid repeatedly parsing the options. */
1303 info->disassembler_options = NULL;
1304 }
1305 else if (riscv_gpr_names == NULL)
1306 set_default_riscv_dis_options ();
1307
26e91972
NC
1308 if (info->private_data == NULL && !riscv_init_disasm_info (info))
1309 return -1;
1310
9b9b1092 1311 mstate = riscv_search_mapping_symbol (memaddr, info);
c2f60ac5
KC
1312 /* Save the last mapping state. */
1313 last_map_state = mstate;
9b9b1092
NC
1314
1315 /* Set the size to dump. */
1316 if (mstate == MAP_DATA
1317 && (info->flags & DISASSEMBLE_DATA) == 0)
1318 {
1319 dump_size = riscv_data_length (memaddr, info);
1320 info->bytes_per_chunk = dump_size;
1321 riscv_disassembler = riscv_disassemble_data;
1322 }
1323 else
e23eba97 1324 {
9b9b1092
NC
1325 /* Get the first 2-bytes to check the lenghth of instruction. */
1326 status = (*info->read_memory_func) (memaddr, packet, 2, info);
e23eba97
NC
1327 if (status != 0)
1328 {
e23eba97 1329 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1330 return -1;
e23eba97 1331 }
9b9b1092
NC
1332 insn = (insn_t) bfd_getl16 (packet);
1333 dump_size = riscv_insn_length (insn);
1334 riscv_disassembler = riscv_disassemble_insn;
1335 }
e23eba97 1336
9b9b1092
NC
1337 /* Fetch the instruction to dump. */
1338 status = (*info->read_memory_func) (memaddr, packet, dump_size, info);
1339 if (status != 0)
1340 {
1341 (*info->memory_error_func) (status, memaddr, info);
e43d8768 1342 return -1;
e23eba97 1343 }
9b9b1092 1344 insn = (insn_t) bfd_get_bits (packet, dump_size * 8, false);
e23eba97 1345
97f006bc 1346 return (*riscv_disassembler) (memaddr, insn, packet, info);
e23eba97
NC
1347}
1348
8152e040
NC
1349disassembler_ftype
1350riscv_get_disassembler (bfd *abfd)
1351{
f786c359
NC
1352 const char *default_arch = "rv64gc";
1353
16089f32 1354 if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
8152e040 1355 {
16089f32
TH
1356 const char *sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
1357 if (bfd_get_section_by_name (abfd, sec_name) != NULL)
f786c359 1358 {
16089f32
TH
1359 obj_attribute *attr = elf_known_obj_attributes_proc (abfd);
1360 unsigned int Tag_a = Tag_RISCV_priv_spec;
1361 unsigned int Tag_b = Tag_RISCV_priv_spec_minor;
1362 unsigned int Tag_c = Tag_RISCV_priv_spec_revision;
1363 riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i,
1364 attr[Tag_b].i,
1365 attr[Tag_c].i,
1366 &default_priv_spec);
1367 default_arch = attr[Tag_RISCV_arch].s;
f786c359 1368 }
8152e040 1369 }
f786c359
NC
1370
1371 riscv_release_subset_list (&riscv_subsets);
1372 riscv_parse_subset (&riscv_rps_dis, default_arch);
1373 return print_insn_riscv;
8152e040
NC
1374}
1375
884b49e3
AB
1376/* Prevent use of the fake labels that are generated as part of the DWARF
1377 and for relaxable relocations in the assembler. */
1378
78933a4a 1379bool
884b49e3
AB
1380riscv_symbol_is_valid (asymbol * sym,
1381 struct disassemble_info * info ATTRIBUTE_UNUSED)
1382{
1383 const char * name;
1384
1385 if (sym == NULL)
78933a4a 1386 return false;
884b49e3
AB
1387
1388 name = bfd_asymbol_name (sym);
1389
9b9b1092
NC
1390 return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0
1391 && !riscv_elf_is_mapping_symbols (name));
884b49e3 1392}
3a337a86
AB
1393\f
1394
1395/* Indices into option argument vector for options accepting an argument.
1396 Use RISCV_OPTION_ARG_NONE for options accepting no argument. */
1397
1398typedef enum
1399{
1400 RISCV_OPTION_ARG_NONE = -1,
1401 RISCV_OPTION_ARG_PRIV_SPEC,
1402
1403 RISCV_OPTION_ARG_COUNT
1404} riscv_option_arg_t;
1405
1406/* Valid RISCV disassembler options. */
1407
1408static struct
1409{
1410 const char *name;
1411 const char *description;
1412 riscv_option_arg_t arg;
1413} riscv_options[] =
1414{
1415 { "numeric",
1416 N_("Print numeric register names, rather than ABI names."),
1417 RISCV_OPTION_ARG_NONE },
1418 { "no-aliases",
1419 N_("Disassemble only into canonical instructions."),
1420 RISCV_OPTION_ARG_NONE },
1421 { "priv-spec=",
1422 N_("Print the CSR according to the chosen privilege spec."),
1423 RISCV_OPTION_ARG_PRIV_SPEC }
1424};
1425
1426/* Build the structure representing valid RISCV disassembler options.
1427 This is done dynamically for maintenance ease purpose; a static
1428 initializer would be unreadable. */
1429
1430const disasm_options_and_args_t *
1431disassembler_options_riscv (void)
1432{
1433 static disasm_options_and_args_t *opts_and_args;
1434
1435 if (opts_and_args == NULL)
1436 {
1437 size_t num_options = ARRAY_SIZE (riscv_options);
1438 size_t num_args = RISCV_OPTION_ARG_COUNT;
1439 disasm_option_arg_t *args;
1440 disasm_options_t *opts;
1441 size_t i, priv_spec_count;
1442
1443 args = XNEWVEC (disasm_option_arg_t, num_args + 1);
1444
1445 args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC";
1446 priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_CLASS_NONE - 1;
1447 args[RISCV_OPTION_ARG_PRIV_SPEC].values
1448 = XNEWVEC (const char *, priv_spec_count + 1);
1449 for (i = 0; i < priv_spec_count; i++)
1450 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i]
1451 = riscv_priv_specs[i].name;
1452 /* The array we return must be NULL terminated. */
1453 args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] = NULL;
1454
1455 /* The array we return must be NULL terminated. */
1456 args[num_args].name = NULL;
1457 args[num_args].values = NULL;
1458
1459 opts_and_args = XNEW (disasm_options_and_args_t);
1460 opts_and_args->args = args;
1461
1462 opts = &opts_and_args->options;
1463 opts->name = XNEWVEC (const char *, num_options + 1);
1464 opts->description = XNEWVEC (const char *, num_options + 1);
1465 opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
1466 for (i = 0; i < num_options; i++)
1467 {
1468 opts->name[i] = riscv_options[i].name;
1469 opts->description[i] = _(riscv_options[i].description);
1470 if (riscv_options[i].arg != RISCV_OPTION_ARG_NONE)
1471 opts->arg[i] = &args[riscv_options[i].arg];
1472 else
1473 opts->arg[i] = NULL;
1474 }
1475 /* The array we return must be NULL terminated. */
1476 opts->name[i] = NULL;
1477 opts->description[i] = NULL;
1478 opts->arg[i] = NULL;
1479 }
1480
1481 return opts_and_args;
1482}
884b49e3 1483
e23eba97
NC
1484void
1485print_riscv_disassembler_options (FILE *stream)
1486{
3a337a86
AB
1487 const disasm_options_and_args_t *opts_and_args;
1488 const disasm_option_arg_t *args;
1489 const disasm_options_t *opts;
1490 size_t max_len = 0;
1491 size_t i;
1492 size_t j;
1493
1494 opts_and_args = disassembler_options_riscv ();
1495 opts = &opts_and_args->options;
1496 args = opts_and_args->args;
1497
e23eba97 1498 fprintf (stream, _("\n\
3a337a86 1499The following RISC-V specific disassembler options are supported for use\n\
e23eba97 1500with the -M switch (multiple options should be separated by commas):\n"));
3a337a86 1501 fprintf (stream, "\n");
e23eba97 1502
3a337a86
AB
1503 /* Compute the length of the longest option name. */
1504 for (i = 0; opts->name[i] != NULL; i++)
1505 {
1506 size_t len = strlen (opts->name[i]);
8f595e9b 1507
3a337a86
AB
1508 if (opts->arg[i] != NULL)
1509 len += strlen (opts->arg[i]->name);
1510 if (max_len < len)
1511 max_len = len;
1512 }
e23eba97 1513
3a337a86
AB
1514 for (i = 0, max_len++; opts->name[i] != NULL; i++)
1515 {
1516 fprintf (stream, " %s", opts->name[i]);
1517 if (opts->arg[i] != NULL)
1518 fprintf (stream, "%s", opts->arg[i]->name);
1519 if (opts->description[i] != NULL)
1520 {
1521 size_t len = strlen (opts->name[i]);
1522
1523 if (opts->arg != NULL && opts->arg[i] != NULL)
1524 len += strlen (opts->arg[i]->name);
1525 fprintf (stream, "%*c %s", (int) (max_len - len), ' ',
1526 opts->description[i]);
1527 }
1528 fprintf (stream, "\n");
1529 }
1530
1531 for (i = 0; args[i].name != NULL; i++)
1532 {
9869e2e5
TO
1533 if (args[i].values == NULL)
1534 continue;
3a337a86
AB
1535 fprintf (stream, _("\n\
1536 For the options above, the following values are supported for \"%s\":\n "),
1537 args[i].name);
1538 for (j = 0; args[i].values[j] != NULL; j++)
1539 fprintf (stream, " %s", args[i].values[j]);
1540 fprintf (stream, _("\n"));
1541 }
e23eba97
NC
1542
1543 fprintf (stream, _("\n"));
1544}
26e91972
NC
1545
1546void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED)
1547{
1548 riscv_release_subset_list (&riscv_subsets);
1549}