Home | History | Annotate | Line # | Download | only in opcodes
riscv-dis.c revision 1.4
      1  1.1      matt /* RISC-V disassembler
      2  1.4  christos    Copyright (C) 2011-2018 Free Software Foundation, Inc.
      3  1.1      matt 
      4  1.4  christos    Contributed by Andrew Waterman (andrew (at) sifive.com).
      5  1.1      matt    Based on MIPS target.
      6  1.1      matt 
      7  1.1      matt    This file is part of the GNU opcodes library.
      8  1.1      matt 
      9  1.1      matt    This library is free software; you can redistribute it and/or modify
     10  1.1      matt    it under the terms of the GNU General Public License as published by
     11  1.1      matt    the Free Software Foundation; either version 3, or (at your option)
     12  1.1      matt    any later version.
     13  1.1      matt 
     14  1.1      matt    It is distributed in the hope that it will be useful, but WITHOUT
     15  1.1      matt    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     16  1.1      matt    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     17  1.1      matt    License for more details.
     18  1.1      matt 
     19  1.1      matt    You should have received a copy of the GNU General Public License
     20  1.4  christos    along with this program; see the file COPYING3. If not,
     21  1.4  christos    see <http://www.gnu.org/licenses/>.  */
     22  1.1      matt 
     23  1.1      matt #include "sysdep.h"
     24  1.4  christos #include "disassemble.h"
     25  1.1      matt #include "libiberty.h"
     26  1.1      matt #include "opcode/riscv.h"
     27  1.1      matt #include "opintl.h"
     28  1.1      matt #include "elf-bfd.h"
     29  1.1      matt #include "elf/riscv.h"
     30  1.1      matt 
     31  1.1      matt #include <stdint.h>
     32  1.4  christos 
     33  1.4  christos #include <ctype.h>
     34  1.1      matt 
     35  1.1      matt struct riscv_private_data
     36  1.1      matt {
     37  1.1      matt   bfd_vma gp;
     38  1.1      matt   bfd_vma print_addr;
     39  1.1      matt   bfd_vma hi_addr[OP_MASK_RD + 1];
     40  1.1      matt };
     41  1.1      matt 
     42  1.1      matt static const char * const *riscv_gpr_names;
     43  1.1      matt static const char * const *riscv_fpr_names;
     44  1.1      matt 
     45  1.4  christos /* Other options.  */
     46  1.1      matt static int no_aliases;	/* If set disassemble as most general inst.  */
     47  1.1      matt 
     48  1.1      matt static void
     49  1.3      matt set_default_riscv_dis_options (void)
     50  1.1      matt {
     51  1.1      matt   riscv_gpr_names = riscv_gpr_names_abi;
     52  1.1      matt   riscv_fpr_names = riscv_fpr_names_abi;
     53  1.1      matt   no_aliases = 0;
     54  1.1      matt }
     55  1.1      matt 
     56  1.1      matt static void
     57  1.3      matt parse_riscv_dis_option (const char *option)
     58  1.1      matt {
     59  1.4  christos   if (strcmp (option, "no-aliases") == 0)
     60  1.3      matt     no_aliases = 1;
     61  1.4  christos   else if (strcmp (option, "numeric") == 0)
     62  1.1      matt     {
     63  1.3      matt       riscv_gpr_names = riscv_gpr_names_numeric;
     64  1.3      matt       riscv_fpr_names = riscv_fpr_names_numeric;
     65  1.1      matt     }
     66  1.4  christos   else
     67  1.4  christos     {
     68  1.4  christos       /* Invalid option.  */
     69  1.4  christos       fprintf (stderr, _("Unrecognized disassembler option: %s\n"), option);
     70  1.4  christos     }
     71  1.1      matt }
     72  1.1      matt 
     73  1.1      matt static void
     74  1.3      matt parse_riscv_dis_options (const char *opts_in)
     75  1.1      matt {
     76  1.3      matt   char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
     77  1.1      matt 
     78  1.3      matt   set_default_riscv_dis_options ();
     79  1.1      matt 
     80  1.3      matt   for ( ; opt_end != NULL; opt = opt_end + 1)
     81  1.1      matt     {
     82  1.3      matt       if ((opt_end = strchr (opt, ',')) != NULL)
     83  1.3      matt 	*opt_end = 0;
     84  1.3      matt       parse_riscv_dis_option (opt);
     85  1.3      matt     }
     86  1.1      matt 
     87  1.3      matt   free (opts);
     88  1.1      matt }
     89  1.1      matt 
     90  1.4  christos /* Print one argument from an array.  */
     91  1.1      matt 
     92  1.1      matt static void
     93  1.1      matt arg_print (struct disassemble_info *info, unsigned long val,
     94  1.1      matt 	   const char* const* array, size_t size)
     95  1.1      matt {
     96  1.1      matt   const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
     97  1.1      matt   (*info->fprintf_func) (info->stream, "%s", s);
     98  1.1      matt }
     99  1.1      matt 
    100  1.1      matt static void
    101  1.1      matt maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
    102  1.1      matt {
    103  1.1      matt   if (pd->hi_addr[base_reg] != (bfd_vma)-1)
    104  1.1      matt     {
    105  1.4  christos       pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset;
    106  1.1      matt       pd->hi_addr[base_reg] = -1;
    107  1.1      matt     }
    108  1.3      matt   else if (base_reg == X_GP && pd->gp != (bfd_vma)-1)
    109  1.1      matt     pd->print_addr = pd->gp + offset;
    110  1.4  christos   else if (base_reg == X_TP || base_reg == 0)
    111  1.1      matt     pd->print_addr = offset;
    112  1.1      matt }
    113  1.1      matt 
    114  1.1      matt /* Print insn arguments for 32/64-bit code.  */
    115  1.1      matt 
    116  1.1      matt static void
    117  1.1      matt print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
    118  1.1      matt {
    119  1.1      matt   struct riscv_private_data *pd = info->private_data;
    120  1.1      matt   int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
    121  1.1      matt   int rd = (l >> OP_SH_RD) & OP_MASK_RD;
    122  1.4  christos   fprintf_ftype print = info->fprintf_func;
    123  1.1      matt 
    124  1.1      matt   if (*d != '\0')
    125  1.4  christos     print (info->stream, "\t");
    126  1.1      matt 
    127  1.1      matt   for (; *d != '\0'; d++)
    128  1.1      matt     {
    129  1.1      matt       switch (*d)
    130  1.1      matt 	{
    131  1.4  christos 	case 'C': /* RVC */
    132  1.4  christos 	  switch (*++d)
    133  1.4  christos 	    {
    134  1.4  christos 	    case 's': /* RS1 x8-x15 */
    135  1.4  christos 	    case 'w': /* RS1 x8-x15 */
    136  1.4  christos 	      print (info->stream, "%s",
    137  1.4  christos 		     riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
    138  1.4  christos 	      break;
    139  1.4  christos 	    case 't': /* RS2 x8-x15 */
    140  1.4  christos 	    case 'x': /* RS2 x8-x15 */
    141  1.4  christos 	      print (info->stream, "%s",
    142  1.4  christos 		     riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
    143  1.4  christos 	      break;
    144  1.4  christos 	    case 'U': /* RS1, constrained to equal RD */
    145  1.4  christos 	      print (info->stream, "%s", riscv_gpr_names[rd]);
    146  1.4  christos 	      break;
    147  1.4  christos 	    case 'c': /* RS1, constrained to equal sp */
    148  1.4  christos 	      print (info->stream, "%s", riscv_gpr_names[X_SP]);
    149  1.4  christos 	      break;
    150  1.4  christos 	    case 'V': /* RS2 */
    151  1.4  christos 	      print (info->stream, "%s",
    152  1.4  christos 		     riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
    153  1.4  christos 	      break;
    154  1.4  christos 	    case 'i':
    155  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_SIMM3 (l));
    156  1.4  christos 	      break;
    157  1.4  christos 	    case 'o':
    158  1.4  christos 	    case 'j':
    159  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_IMM (l));
    160  1.4  christos 	      break;
    161  1.4  christos 	    case 'k':
    162  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_LW_IMM (l));
    163  1.4  christos 	      break;
    164  1.4  christos 	    case 'l':
    165  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_LD_IMM (l));
    166  1.4  christos 	      break;
    167  1.4  christos 	    case 'm':
    168  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_LWSP_IMM (l));
    169  1.4  christos 	      break;
    170  1.4  christos 	    case 'n':
    171  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
    172  1.4  christos 	      break;
    173  1.4  christos 	    case 'K':
    174  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
    175  1.4  christos 	      break;
    176  1.4  christos 	    case 'L':
    177  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
    178  1.4  christos 	      break;
    179  1.4  christos 	    case 'M':
    180  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
    181  1.4  christos 	      break;
    182  1.4  christos 	    case 'N':
    183  1.4  christos 	      print (info->stream, "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
    184  1.4  christos 	      break;
    185  1.4  christos 	    case 'p':
    186  1.4  christos 	      info->target = EXTRACT_RVC_B_IMM (l) + pc;
    187  1.4  christos 	      (*info->print_address_func) (info->target, info);
    188  1.4  christos 	      break;
    189  1.4  christos 	    case 'a':
    190  1.4  christos 	      info->target = EXTRACT_RVC_J_IMM (l) + pc;
    191  1.4  christos 	      (*info->print_address_func) (info->target, info);
    192  1.4  christos 	      break;
    193  1.4  christos 	    case 'u':
    194  1.4  christos 	      print (info->stream, "0x%x",
    195  1.4  christos 		     (int)(EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
    196  1.4  christos 	      break;
    197  1.4  christos 	    case '>':
    198  1.4  christos 	      print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x3f);
    199  1.4  christos 	      break;
    200  1.4  christos 	    case '<':
    201  1.4  christos 	      print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x1f);
    202  1.4  christos 	      break;
    203  1.4  christos 	    case 'T': /* floating-point RS2 */
    204  1.4  christos 	      print (info->stream, "%s",
    205  1.4  christos 		     riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
    206  1.4  christos 	      break;
    207  1.4  christos 	    case 'D': /* floating-point RS2 x8-x15 */
    208  1.4  christos 	      print (info->stream, "%s",
    209  1.4  christos 		     riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
    210  1.4  christos 	      break;
    211  1.4  christos 	    }
    212  1.4  christos 	  break;
    213  1.1      matt 
    214  1.1      matt 	case ',':
    215  1.1      matt 	case '(':
    216  1.1      matt 	case ')':
    217  1.1      matt 	case '[':
    218  1.1      matt 	case ']':
    219  1.4  christos 	  print (info->stream, "%c", *d);
    220  1.1      matt 	  break;
    221  1.1      matt 
    222  1.1      matt 	case '0':
    223  1.4  christos 	  /* Only print constant 0 if it is the last argument */
    224  1.4  christos 	  if (!d[1])
    225  1.4  christos 	    print (info->stream, "0");
    226  1.1      matt 	  break;
    227  1.1      matt 
    228  1.1      matt 	case 'b':
    229  1.1      matt 	case 's':
    230  1.4  christos 	  if ((l & MASK_JALR) == MATCH_JALR)
    231  1.4  christos 	    maybe_print_address (pd, rs1, 0);
    232  1.4  christos 	  print (info->stream, "%s", riscv_gpr_names[rs1]);
    233  1.1      matt 	  break;
    234  1.1      matt 
    235  1.1      matt 	case 't':
    236  1.4  christos 	  print (info->stream, "%s",
    237  1.4  christos 		 riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
    238  1.1      matt 	  break;
    239  1.1      matt 
    240  1.1      matt 	case 'u':
    241  1.4  christos 	  print (info->stream, "0x%x",
    242  1.4  christos 		 (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
    243  1.1      matt 	  break;
    244  1.1      matt 
    245  1.1      matt 	case 'm':
    246  1.4  christos 	  arg_print (info, EXTRACT_OPERAND (RM, l),
    247  1.4  christos 		     riscv_rm, ARRAY_SIZE (riscv_rm));
    248  1.1      matt 	  break;
    249  1.1      matt 
    250  1.1      matt 	case 'P':
    251  1.4  christos 	  arg_print (info, EXTRACT_OPERAND (PRED, l),
    252  1.4  christos 		     riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
    253  1.1      matt 	  break;
    254  1.1      matt 
    255  1.1      matt 	case 'Q':
    256  1.4  christos 	  arg_print (info, EXTRACT_OPERAND (SUCC, l),
    257  1.4  christos 		     riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
    258  1.1      matt 	  break;
    259  1.1      matt 
    260  1.1      matt 	case 'o':
    261  1.1      matt 	  maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
    262  1.4  christos 	  /* Fall through.  */
    263  1.1      matt 	case 'j':
    264  1.4  christos 	  if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0)
    265  1.4  christos 	      || (l & MASK_JALR) == MATCH_JALR)
    266  1.1      matt 	    maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
    267  1.4  christos 	  print (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
    268  1.1      matt 	  break;
    269  1.1      matt 
    270  1.1      matt 	case 'q':
    271  1.1      matt 	  maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
    272  1.4  christos 	  print (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
    273  1.1      matt 	  break;
    274  1.1      matt 
    275  1.1      matt 	case 'a':
    276  1.1      matt 	  info->target = EXTRACT_UJTYPE_IMM (l) + pc;
    277  1.1      matt 	  (*info->print_address_func) (info->target, info);
    278  1.1      matt 	  break;
    279  1.1      matt 
    280  1.1      matt 	case 'p':
    281  1.1      matt 	  info->target = EXTRACT_SBTYPE_IMM (l) + pc;
    282  1.1      matt 	  (*info->print_address_func) (info->target, info);
    283  1.1      matt 	  break;
    284  1.1      matt 
    285  1.1      matt 	case 'd':
    286  1.1      matt 	  if ((l & MASK_AUIPC) == MATCH_AUIPC)
    287  1.3      matt 	    pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
    288  1.1      matt 	  else if ((l & MASK_LUI) == MATCH_LUI)
    289  1.3      matt 	    pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
    290  1.4  christos 	  else if ((l & MASK_C_LUI) == MATCH_C_LUI)
    291  1.4  christos 	    pd->hi_addr[rd] = EXTRACT_RVC_LUI_IMM (l);
    292  1.4  christos 	  print (info->stream, "%s", riscv_gpr_names[rd]);
    293  1.1      matt 	  break;
    294  1.1      matt 
    295  1.1      matt 	case 'z':
    296  1.4  christos 	  print (info->stream, "%s", riscv_gpr_names[0]);
    297  1.1      matt 	  break;
    298  1.1      matt 
    299  1.1      matt 	case '>':
    300  1.4  christos 	  print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMT, l));
    301  1.1      matt 	  break;
    302  1.1      matt 
    303  1.1      matt 	case '<':
    304  1.4  christos 	  print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMTW, l));
    305  1.1      matt 	  break;
    306  1.1      matt 
    307  1.1      matt 	case 'S':
    308  1.1      matt 	case 'U':
    309  1.4  christos 	  print (info->stream, "%s", riscv_fpr_names[rs1]);
    310  1.1      matt 	  break;
    311  1.1      matt 
    312  1.1      matt 	case 'T':
    313  1.4  christos 	  print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
    314  1.1      matt 	  break;
    315  1.1      matt 
    316  1.1      matt 	case 'D':
    317  1.4  christos 	  print (info->stream, "%s", riscv_fpr_names[rd]);
    318  1.1      matt 	  break;
    319  1.1      matt 
    320  1.1      matt 	case 'R':
    321  1.4  christos 	  print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
    322  1.1      matt 	  break;
    323  1.1      matt 
    324  1.1      matt 	case 'E':
    325  1.1      matt 	  {
    326  1.3      matt 	    const char* csr_name = NULL;
    327  1.4  christos 	    unsigned int csr = EXTRACT_OPERAND (CSR, l);
    328  1.3      matt 	    switch (csr)
    329  1.1      matt 	      {
    330  1.4  christos #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
    331  1.4  christos #include "opcode/riscv-opc.h"
    332  1.4  christos #undef DECLARE_CSR
    333  1.1      matt 	      }
    334  1.3      matt 	    if (csr_name)
    335  1.4  christos 	      print (info->stream, "%s", csr_name);
    336  1.3      matt 	    else
    337  1.4  christos 	      print (info->stream, "0x%x", csr);
    338  1.1      matt 	    break;
    339  1.1      matt 	  }
    340  1.1      matt 
    341  1.1      matt 	case 'Z':
    342  1.4  christos 	  print (info->stream, "%d", rs1);
    343  1.1      matt 	  break;
    344  1.1      matt 
    345  1.1      matt 	default:
    346  1.1      matt 	  /* xgettext:c-format */
    347  1.4  christos 	  print (info->stream, _("# internal error, undefined modifier (%c)"),
    348  1.4  christos 		 *d);
    349  1.1      matt 	  return;
    350  1.1      matt 	}
    351  1.1      matt     }
    352  1.1      matt }
    353  1.1      matt 
    354  1.1      matt /* Print the RISC-V instruction at address MEMADDR in debugged memory,
    355  1.1      matt    on using INFO.  Returns length of the instruction, in bytes.
    356  1.1      matt    BIGENDIAN must be 1 if this is big-endian code, 0 if
    357  1.1      matt    this is little-endian code.  */
    358  1.1      matt 
    359  1.1      matt static int
    360  1.1      matt riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
    361  1.1      matt {
    362  1.1      matt   const struct riscv_opcode *op;
    363  1.1      matt   static bfd_boolean init = 0;
    364  1.1      matt   static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
    365  1.1      matt   struct riscv_private_data *pd;
    366  1.1      matt   int insnlen;
    367  1.1      matt 
    368  1.4  christos #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
    369  1.4  christos 
    370  1.1      matt   /* Build a hash table to shorten the search time.  */
    371  1.1      matt   if (! init)
    372  1.1      matt     {
    373  1.4  christos       for (op = riscv_opcodes; op->name; op++)
    374  1.4  christos 	if (!riscv_hash[OP_HASH_IDX (op->match)])
    375  1.4  christos 	  riscv_hash[OP_HASH_IDX (op->match)] = op;
    376  1.1      matt 
    377  1.1      matt       init = 1;
    378  1.1      matt     }
    379  1.1      matt 
    380  1.1      matt   if (info->private_data == NULL)
    381  1.1      matt     {
    382  1.1      matt       int i;
    383  1.1      matt 
    384  1.4  christos       pd = info->private_data = xcalloc (1, sizeof (struct riscv_private_data));
    385  1.1      matt       pd->gp = -1;
    386  1.1      matt       pd->print_addr = -1;
    387  1.4  christos       for (i = 0; i < (int)ARRAY_SIZE (pd->hi_addr); i++)
    388  1.1      matt 	pd->hi_addr[i] = -1;
    389  1.1      matt 
    390  1.1      matt       for (i = 0; i < info->symtab_size; i++)
    391  1.4  christos 	if (strcmp (bfd_asymbol_name (info->symtab[i]), RISCV_GP_SYMBOL) == 0)
    392  1.1      matt 	  pd->gp = bfd_asymbol_value (info->symtab[i]);
    393  1.1      matt     }
    394  1.1      matt   else
    395  1.1      matt     pd = info->private_data;
    396  1.1      matt 
    397  1.1      matt   insnlen = riscv_insn_length (word);
    398  1.1      matt 
    399  1.1      matt   info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
    400  1.1      matt   info->bytes_per_line = 8;
    401  1.1      matt   info->display_endian = info->endian;
    402  1.1      matt   info->insn_info_valid = 1;
    403  1.1      matt   info->branch_delay_insns = 0;
    404  1.1      matt   info->data_size = 0;
    405  1.1      matt   info->insn_type = dis_nonbranch;
    406  1.1      matt   info->target = 0;
    407  1.1      matt   info->target2 = 0;
    408  1.1      matt 
    409  1.4  christos   op = riscv_hash[OP_HASH_IDX (word)];
    410  1.1      matt   if (op != NULL)
    411  1.1      matt     {
    412  1.4  christos       int xlen = 0;
    413  1.4  christos 
    414  1.4  christos       /* If XLEN is not known, get its value from the ELF class.  */
    415  1.4  christos       if (info->mach == bfd_mach_riscv64)
    416  1.4  christos 	xlen = 64;
    417  1.4  christos       else if (info->mach == bfd_mach_riscv32)
    418  1.4  christos 	xlen = 32;
    419  1.4  christos       else if (info->section != NULL)
    420  1.1      matt 	{
    421  1.4  christos 	  Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
    422  1.4  christos 	  xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
    423  1.4  christos 	}
    424  1.4  christos 
    425  1.4  christos       for (; op->name; op++)
    426  1.4  christos 	{
    427  1.4  christos 	  /* Does the opcode match?  */
    428  1.4  christos 	  if (! (op->match_func) (op, word))
    429  1.4  christos 	    continue;
    430  1.4  christos 	  /* Is this a pseudo-instruction and may we print it as such?  */
    431  1.4  christos 	  if (no_aliases && (op->pinfo & INSN_ALIAS))
    432  1.4  christos 	    continue;
    433  1.4  christos 	  /* Is this instruction restricted to a certain value of XLEN?  */
    434  1.4  christos 	  if (isdigit (op->subset[0]) && atoi (op->subset) != xlen)
    435  1.4  christos 	    continue;
    436  1.4  christos 
    437  1.4  christos 	  /* It's a match.  */
    438  1.4  christos 	  (*info->fprintf_func) (info->stream, "%s", op->name);
    439  1.4  christos 	  print_insn_args (op->args, word, memaddr, info);
    440  1.4  christos 
    441  1.4  christos 	  /* Try to disassemble multi-instruction addressing sequences.  */
    442  1.4  christos 	  if (pd->print_addr != (bfd_vma)-1)
    443  1.1      matt 	    {
    444  1.4  christos 	      info->target = pd->print_addr;
    445  1.4  christos 	      (*info->fprintf_func) (info->stream, " # ");
    446  1.4  christos 	      (*info->print_address_func) (info->target, info);
    447  1.4  christos 	      pd->print_addr = -1;
    448  1.1      matt 	    }
    449  1.4  christos 
    450  1.4  christos 	  return insnlen;
    451  1.1      matt 	}
    452  1.1      matt     }
    453  1.1      matt 
    454  1.4  christos   /* We did not find a match, so just print the instruction bits.  */
    455  1.1      matt   info->insn_type = dis_noninsn;
    456  1.1      matt   (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
    457  1.1      matt   return insnlen;
    458  1.1      matt }
    459  1.1      matt 
    460  1.1      matt int
    461  1.1      matt print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
    462  1.1      matt {
    463  1.4  christos   bfd_byte packet[2];
    464  1.1      matt   insn_t insn = 0;
    465  1.1      matt   bfd_vma n;
    466  1.1      matt   int status;
    467  1.1      matt 
    468  1.3      matt   if (info->disassembler_options != NULL)
    469  1.3      matt     {
    470  1.3      matt       parse_riscv_dis_options (info->disassembler_options);
    471  1.3      matt       /* Avoid repeatedly parsing the options.  */
    472  1.3      matt       info->disassembler_options = NULL;
    473  1.3      matt     }
    474  1.3      matt   else if (riscv_gpr_names == NULL)
    475  1.3      matt     set_default_riscv_dis_options ();
    476  1.1      matt 
    477  1.1      matt   /* Instructions are a sequence of 2-byte packets in little-endian order.  */
    478  1.4  christos   for (n = 0; n < sizeof (insn) && n < riscv_insn_length (insn); n += 2)
    479  1.1      matt     {
    480  1.4  christos       status = (*info->read_memory_func) (memaddr + n, packet, 2, info);
    481  1.1      matt       if (status != 0)
    482  1.1      matt 	{
    483  1.4  christos 	  /* Don't fail just because we fell off the end.  */
    484  1.4  christos 	  if (n > 0)
    485  1.1      matt 	    break;
    486  1.1      matt 	  (*info->memory_error_func) (status, memaddr, info);
    487  1.1      matt 	  return status;
    488  1.1      matt 	}
    489  1.1      matt 
    490  1.4  christos       insn |= ((insn_t) bfd_getl16 (packet)) << (8 * n);
    491  1.1      matt     }
    492  1.1      matt 
    493  1.1      matt   return riscv_disassemble_insn (memaddr, insn, info);
    494  1.1      matt }
    495  1.1      matt 
    496  1.1      matt void
    497  1.1      matt print_riscv_disassembler_options (FILE *stream)
    498  1.1      matt {
    499  1.1      matt   fprintf (stream, _("\n\
    500  1.1      matt The following RISC-V-specific disassembler options are supported for use\n\
    501  1.1      matt with the -M switch (multiple options should be separated by commas):\n"));
    502  1.1      matt 
    503  1.1      matt   fprintf (stream, _("\n\
    504  1.4  christos   numeric       Print numeric register names, rather than ABI names.\n"));
    505  1.1      matt 
    506  1.1      matt   fprintf (stream, _("\n\
    507  1.3      matt   no-aliases    Disassemble only into canonical instructions, rather\n\
    508  1.3      matt                 than into pseudoinstructions.\n"));
    509  1.1      matt 
    510  1.1      matt   fprintf (stream, _("\n"));
    511  1.1      matt }
    512