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