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