Home | History | Annotate | Line # | Download | only in opcodes
riscv-dis.c revision 1.3
      1  1.1  matt /* RISC-V disassembler
      2  1.1  matt    Copyright 2011-2014 Free Software Foundation, Inc.
      3  1.1  matt 
      4  1.1  matt    Contributed by Andrew Waterman (waterman (at) cs.berkeley.edu) at UC Berkeley.
      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.1  matt    along with this program; if not, write to the Free Software
     21  1.1  matt    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     22  1.1  matt    MA 02110-1301, USA.  */
     23  1.1  matt 
     24  1.1  matt #include "sysdep.h"
     25  1.1  matt #include "dis-asm.h"
     26  1.1  matt #include "libiberty.h"
     27  1.1  matt #include "opcode/riscv.h"
     28  1.1  matt #include "opintl.h"
     29  1.1  matt #include "elf-bfd.h"
     30  1.1  matt #include "elf/riscv.h"
     31  1.1  matt 
     32  1.1  matt #include <stdint.h>
     33  1.1  matt #include <assert.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.1  matt /* 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.1  matt   if (CONST_STRNEQ (option, "no-aliases"))
     60  1.3  matt     no_aliases = 1;
     61  1.3  matt   else if (CONST_STRNEQ (option, "numeric"))
     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.1  matt 
     67  1.1  matt   /* Invalid option.  */
     68  1.3  matt   fprintf (stderr, _("Unrecognized disassembler option: %s\n"), option);
     69  1.1  matt }
     70  1.1  matt 
     71  1.1  matt static void
     72  1.3  matt parse_riscv_dis_options (const char *opts_in)
     73  1.1  matt {
     74  1.3  matt   char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
     75  1.1  matt 
     76  1.3  matt   set_default_riscv_dis_options ();
     77  1.1  matt 
     78  1.3  matt   for ( ; opt_end != NULL; opt = opt_end + 1)
     79  1.1  matt     {
     80  1.3  matt       if ((opt_end = strchr (opt, ',')) != NULL)
     81  1.3  matt 	*opt_end = 0;
     82  1.3  matt       parse_riscv_dis_option (opt);
     83  1.3  matt     }
     84  1.1  matt 
     85  1.3  matt   free (opts);
     86  1.1  matt }
     87  1.1  matt 
     88  1.1  matt /* Print one argument from an array. */
     89  1.1  matt 
     90  1.1  matt static void
     91  1.1  matt arg_print (struct disassemble_info *info, unsigned long val,
     92  1.1  matt 	   const char* const* array, size_t size)
     93  1.1  matt {
     94  1.1  matt   const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
     95  1.1  matt   (*info->fprintf_func) (info->stream, "%s", s);
     96  1.1  matt }
     97  1.1  matt 
     98  1.1  matt static void
     99  1.1  matt maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
    100  1.1  matt {
    101  1.1  matt   if (pd->hi_addr[base_reg] != (bfd_vma)-1)
    102  1.1  matt     {
    103  1.1  matt       pd->print_addr = pd->hi_addr[base_reg] + offset;
    104  1.1  matt       pd->hi_addr[base_reg] = -1;
    105  1.1  matt     }
    106  1.3  matt   else if (base_reg == X_GP && pd->gp != (bfd_vma)-1)
    107  1.1  matt     pd->print_addr = pd->gp + offset;
    108  1.3  matt   else if (base_reg == X_TP)
    109  1.1  matt     pd->print_addr = offset;
    110  1.1  matt }
    111  1.1  matt 
    112  1.1  matt /* Print insn arguments for 32/64-bit code.  */
    113  1.1  matt 
    114  1.1  matt static void
    115  1.1  matt print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
    116  1.1  matt {
    117  1.1  matt   struct riscv_private_data *pd = info->private_data;
    118  1.1  matt   int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
    119  1.1  matt   int rd = (l >> OP_SH_RD) & OP_MASK_RD;
    120  1.1  matt 
    121  1.1  matt   if (*d != '\0')
    122  1.1  matt     (*info->fprintf_func) (info->stream, "\t");
    123  1.1  matt 
    124  1.1  matt   for (; *d != '\0'; d++)
    125  1.1  matt     {
    126  1.1  matt       switch (*d)
    127  1.1  matt 	{
    128  1.1  matt         /* Xcustom */
    129  1.1  matt         case '^':
    130  1.1  matt           switch (*++d)
    131  1.1  matt             {
    132  1.1  matt             case 'd':
    133  1.1  matt               (*info->fprintf_func) (info->stream, "%d", rd);
    134  1.1  matt               break;
    135  1.1  matt             case 's':
    136  1.1  matt               (*info->fprintf_func) (info->stream, "%d", rs1);
    137  1.1  matt               break;
    138  1.1  matt             case 't':
    139  1.1  matt               (*info->fprintf_func)
    140  1.1  matt                 ( info->stream, "%d", (int)((l >> OP_SH_RS2) & OP_MASK_RS2));
    141  1.1  matt               break;
    142  1.1  matt             case 'j':
    143  1.1  matt               (*info->fprintf_func)
    144  1.1  matt                 ( info->stream, "%d", (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
    145  1.1  matt               break;
    146  1.1  matt             }
    147  1.1  matt           break;
    148  1.1  matt 
    149  1.1  matt         /* Xhwacha */
    150  1.1  matt         case '#':
    151  1.1  matt           switch ( *++d ) {
    152  1.1  matt             case 'g':
    153  1.1  matt               (*info->fprintf_func)
    154  1.1  matt                 ( info->stream, "%d",
    155  1.1  matt                   (int)((l >> OP_SH_IMMNGPR) & OP_MASK_IMMNGPR));
    156  1.1  matt               break;
    157  1.1  matt             case 'f':
    158  1.1  matt               (*info->fprintf_func)
    159  1.1  matt                 ( info->stream, "%d",
    160  1.1  matt                   (int)((l >> OP_SH_IMMNFPR) & OP_MASK_IMMNFPR));
    161  1.1  matt               break;
    162  1.1  matt             case 'p':
    163  1.1  matt               (*info->fprintf_func)
    164  1.1  matt                 ( info->stream, "%d",
    165  1.1  matt                  (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
    166  1.1  matt               break;
    167  1.1  matt             case 'n':
    168  1.1  matt               (*info->fprintf_func)
    169  1.1  matt                 ( info->stream, "%d",
    170  1.1  matt                   (int)(((l >> OP_SH_IMMSEGNELM) & OP_MASK_IMMSEGNELM) + 1));
    171  1.1  matt               break;
    172  1.1  matt             case 'd':
    173  1.1  matt               (*info->fprintf_func)
    174  1.1  matt                 ( info->stream, "%s",
    175  1.3  matt                   riscv_vec_gpr_names[(l >> OP_SH_VRD) & OP_MASK_VRD]);
    176  1.1  matt               break;
    177  1.1  matt             case 's':
    178  1.1  matt               (*info->fprintf_func)
    179  1.1  matt                 ( info->stream, "%s",
    180  1.3  matt                   riscv_vec_gpr_names[(l >> OP_SH_VRS) & OP_MASK_VRS]);
    181  1.1  matt               break;
    182  1.1  matt             case 't':
    183  1.1  matt               (*info->fprintf_func)
    184  1.1  matt                 ( info->stream, "%s",
    185  1.3  matt                   riscv_vec_gpr_names[(l >> OP_SH_VRT) & OP_MASK_VRT]);
    186  1.1  matt               break;
    187  1.1  matt             case 'r':
    188  1.1  matt               (*info->fprintf_func)
    189  1.1  matt                 ( info->stream, "%s",
    190  1.3  matt                   riscv_vec_gpr_names[(l >> OP_SH_VRR) & OP_MASK_VRR]);
    191  1.1  matt               break;
    192  1.1  matt             case 'D':
    193  1.1  matt               (*info->fprintf_func)
    194  1.1  matt                 ( info->stream, "%s",
    195  1.3  matt                   riscv_vec_fpr_names[(l >> OP_SH_VFD) & OP_MASK_VFD]);
    196  1.1  matt               break;
    197  1.1  matt             case 'S':
    198  1.1  matt               (*info->fprintf_func)
    199  1.1  matt                 ( info->stream, "%s",
    200  1.3  matt                   riscv_vec_fpr_names[(l >> OP_SH_VFS) & OP_MASK_VFS]);
    201  1.1  matt               break;
    202  1.1  matt             case 'T':
    203  1.1  matt               (*info->fprintf_func)
    204  1.1  matt                 ( info->stream, "%s",
    205  1.3  matt                   riscv_vec_fpr_names[(l >> OP_SH_VFT) & OP_MASK_VFT]);
    206  1.1  matt               break;
    207  1.1  matt             case 'R':
    208  1.1  matt               (*info->fprintf_func)
    209  1.1  matt                 ( info->stream, "%s",
    210  1.3  matt                   riscv_vec_fpr_names[(l >> OP_SH_VFR) & OP_MASK_VFR]);
    211  1.1  matt               break;
    212  1.1  matt           }
    213  1.1  matt           break;
    214  1.1  matt 
    215  1.1  matt 	case ',':
    216  1.1  matt 	case '(':
    217  1.1  matt 	case ')':
    218  1.1  matt 	case '[':
    219  1.1  matt 	case ']':
    220  1.1  matt 	  (*info->fprintf_func) (info->stream, "%c", *d);
    221  1.1  matt 	  break;
    222  1.1  matt 
    223  1.1  matt 	case '0':
    224  1.1  matt 	  break;
    225  1.1  matt 
    226  1.1  matt 	case 'b':
    227  1.1  matt 	case 's':
    228  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rs1]);
    229  1.1  matt 	  break;
    230  1.1  matt 
    231  1.1  matt 	case 't':
    232  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s",
    233  1.1  matt 				 riscv_gpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
    234  1.1  matt 	  break;
    235  1.1  matt 
    236  1.1  matt 	case 'u':
    237  1.3  matt 	  (*info->fprintf_func) (info->stream, "0x%x", (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
    238  1.1  matt 	  break;
    239  1.1  matt 
    240  1.1  matt 	case 'm':
    241  1.1  matt 	  arg_print(info, (l >> OP_SH_RM) & OP_MASK_RM,
    242  1.1  matt 		    riscv_rm, ARRAY_SIZE(riscv_rm));
    243  1.1  matt 	  break;
    244  1.1  matt 
    245  1.1  matt 	case 'P':
    246  1.1  matt 	  arg_print(info, (l >> OP_SH_PRED) & OP_MASK_PRED,
    247  1.1  matt 	            riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
    248  1.1  matt 	  break;
    249  1.1  matt 
    250  1.1  matt 	case 'Q':
    251  1.1  matt 	  arg_print(info, (l >> OP_SH_SUCC) & OP_MASK_SUCC,
    252  1.1  matt 	            riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
    253  1.1  matt 	  break;
    254  1.1  matt 
    255  1.1  matt 	case 'o':
    256  1.1  matt 	  maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
    257  1.1  matt 	case 'j':
    258  1.2  matt 	  if ((l & MASK_ADDI) == MATCH_ADDI || (l & MASK_JALR) == MATCH_JALR)
    259  1.1  matt 	    maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
    260  1.1  matt 	  (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
    261  1.1  matt 	  break;
    262  1.1  matt 
    263  1.1  matt 	case 'q':
    264  1.1  matt 	  maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
    265  1.1  matt 	  (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
    266  1.1  matt 	  break;
    267  1.1  matt 
    268  1.1  matt 	case 'a':
    269  1.1  matt 	  info->target = EXTRACT_UJTYPE_IMM (l) + pc;
    270  1.1  matt 	  (*info->print_address_func) (info->target, info);
    271  1.1  matt 	  break;
    272  1.1  matt 
    273  1.1  matt 	case 'p':
    274  1.1  matt 	  info->target = EXTRACT_SBTYPE_IMM (l) + pc;
    275  1.1  matt 	  (*info->print_address_func) (info->target, info);
    276  1.1  matt 	  break;
    277  1.1  matt 
    278  1.1  matt 	case 'd':
    279  1.1  matt 	  if ((l & MASK_AUIPC) == MATCH_AUIPC)
    280  1.3  matt 	    pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
    281  1.1  matt 	  else if ((l & MASK_LUI) == MATCH_LUI)
    282  1.3  matt 	    pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
    283  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rd]);
    284  1.1  matt 	  break;
    285  1.1  matt 
    286  1.1  matt 	case 'z':
    287  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[0]);
    288  1.1  matt 	  break;
    289  1.1  matt 
    290  1.1  matt 	case '>':
    291  1.1  matt 	  (*info->fprintf_func) (info->stream, "0x%x",
    292  1.1  matt 				 (unsigned)((l >> OP_SH_SHAMT) & OP_MASK_SHAMT));
    293  1.1  matt 	  break;
    294  1.1  matt 
    295  1.1  matt 	case '<':
    296  1.1  matt 	  (*info->fprintf_func) (info->stream, "0x%x",
    297  1.1  matt 				 (unsigned)((l >> OP_SH_SHAMTW) & OP_MASK_SHAMTW));
    298  1.1  matt 	  break;
    299  1.1  matt 
    300  1.1  matt 	case 'S':
    301  1.1  matt 	case 'U':
    302  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rs1]);
    303  1.1  matt 	  break;
    304  1.1  matt 
    305  1.1  matt 	case 'T':
    306  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s",
    307  1.1  matt 				 riscv_fpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
    308  1.1  matt 	  break;
    309  1.1  matt 
    310  1.1  matt 	case 'D':
    311  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rd]);
    312  1.1  matt 	  break;
    313  1.1  matt 
    314  1.1  matt 	case 'R':
    315  1.1  matt 	  (*info->fprintf_func) (info->stream, "%s",
    316  1.1  matt 				 riscv_fpr_names[(l >> OP_SH_RS3) & OP_MASK_RS3]);
    317  1.1  matt 	  break;
    318  1.1  matt 
    319  1.1  matt 	case 'E':
    320  1.1  matt 	  {
    321  1.3  matt 	    const char* csr_name = NULL;
    322  1.3  matt 	    unsigned int csr = (l >> OP_SH_CSR) & OP_MASK_CSR;
    323  1.3  matt 	    switch (csr)
    324  1.1  matt 	      {
    325  1.1  matt 		#define DECLARE_CSR(name, num) case num: csr_name = #name; break;
    326  1.1  matt 		#include "opcode/riscv-opc.h"
    327  1.1  matt 		#undef DECLARE_CSR
    328  1.1  matt 	      }
    329  1.3  matt 	    if (csr_name)
    330  1.3  matt 	      (*info->fprintf_func) (info->stream, "%s", csr_name);
    331  1.3  matt 	    else
    332  1.3  matt 	      (*info->fprintf_func) (info->stream, "0x%x", csr);
    333  1.1  matt 	    break;
    334  1.1  matt 	  }
    335  1.1  matt 
    336  1.1  matt 	case 'Z':
    337  1.1  matt 	  (*info->fprintf_func) (info->stream, "%d", rs1);
    338  1.1  matt 	  break;
    339  1.1  matt 
    340  1.1  matt 	default:
    341  1.1  matt 	  /* xgettext:c-format */
    342  1.1  matt 	  (*info->fprintf_func) (info->stream,
    343  1.1  matt 				 _("# internal error, undefined modifier (%c)"),
    344  1.1  matt 				 *d);
    345  1.1  matt 	  return;
    346  1.1  matt 	}
    347  1.1  matt     }
    348  1.1  matt }
    349  1.1  matt 
    350  1.1  matt /* Print the RISC-V instruction at address MEMADDR in debugged memory,
    351  1.1  matt    on using INFO.  Returns length of the instruction, in bytes.
    352  1.1  matt    BIGENDIAN must be 1 if this is big-endian code, 0 if
    353  1.1  matt    this is little-endian code.  */
    354  1.1  matt 
    355  1.1  matt static int
    356  1.1  matt riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
    357  1.1  matt {
    358  1.1  matt   const struct riscv_opcode *op;
    359  1.1  matt   static bfd_boolean init = 0;
    360  1.1  matt   static const char *extension = NULL;
    361  1.1  matt   static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
    362  1.1  matt   struct riscv_private_data *pd;
    363  1.1  matt   int insnlen;
    364  1.1  matt 
    365  1.1  matt   /* Build a hash table to shorten the search time.  */
    366  1.1  matt   if (! init)
    367  1.1  matt     {
    368  1.1  matt       unsigned int i;
    369  1.1  matt       unsigned int e_flags = elf_elfheader (info->section->owner)->e_flags;
    370  1.1  matt       extension = riscv_elf_flag_to_name(EF_GET_RISCV_EXT(e_flags));
    371  1.1  matt 
    372  1.1  matt       for (i = 0; i <= OP_MASK_OP; i++)
    373  1.1  matt         for (op = riscv_opcodes; op < &riscv_opcodes[NUMOPCODES]; op++)
    374  1.1  matt           if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
    375  1.1  matt             {
    376  1.1  matt               riscv_hash[i] = op;
    377  1.1  matt               break;
    378  1.1  matt             }
    379  1.1  matt 
    380  1.1  matt       init = 1;
    381  1.1  matt     }
    382  1.1  matt 
    383  1.1  matt   if (info->private_data == NULL)
    384  1.1  matt     {
    385  1.1  matt       int i;
    386  1.1  matt 
    387  1.1  matt       pd = info->private_data = calloc(1, sizeof (struct riscv_private_data));
    388  1.1  matt       pd->gp = -1;
    389  1.1  matt       pd->print_addr = -1;
    390  1.1  matt       for (i = 0; i < (int) ARRAY_SIZE(pd->hi_addr); i++)
    391  1.1  matt 	pd->hi_addr[i] = -1;
    392  1.1  matt 
    393  1.1  matt       for (i = 0; i < info->symtab_size; i++)
    394  1.1  matt 	if (strcmp (bfd_asymbol_name (info->symtab[i]), "_gp") == 0)
    395  1.1  matt 	  pd->gp = bfd_asymbol_value (info->symtab[i]);
    396  1.1  matt     }
    397  1.1  matt   else
    398  1.1  matt     pd = info->private_data;
    399  1.1  matt 
    400  1.1  matt   insnlen = riscv_insn_length (word);
    401  1.1  matt 
    402  1.1  matt   info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
    403  1.1  matt   info->bytes_per_line = 8;
    404  1.1  matt   info->display_endian = info->endian;
    405  1.1  matt   info->insn_info_valid = 1;
    406  1.1  matt   info->branch_delay_insns = 0;
    407  1.1  matt   info->data_size = 0;
    408  1.1  matt   info->insn_type = dis_nonbranch;
    409  1.1  matt   info->target = 0;
    410  1.1  matt   info->target2 = 0;
    411  1.1  matt 
    412  1.1  matt   op = riscv_hash[(word >> OP_SH_OP) & OP_MASK_OP];
    413  1.1  matt   if (op != NULL)
    414  1.1  matt     {
    415  1.1  matt       for (; op < &riscv_opcodes[NUMOPCODES]; op++)
    416  1.1  matt 	{
    417  1.1  matt 	  if ((op->match_func) (op, word)
    418  1.1  matt 	      && !(no_aliases && (op->pinfo & INSN_ALIAS))
    419  1.1  matt 	      && !(op->subset[0] == 'X' && strcmp(op->subset, extension)))
    420  1.1  matt 	    {
    421  1.1  matt 	      (*info->fprintf_func) (info->stream, "%s", op->name);
    422  1.1  matt 	      print_insn_args (op->args, word, memaddr, info);
    423  1.1  matt 	      if (pd->print_addr != (bfd_vma)-1)
    424  1.1  matt 		{
    425  1.1  matt 		  info->target = pd->print_addr;
    426  1.1  matt 		  (*info->fprintf_func) (info->stream, " # ");
    427  1.1  matt 		  (*info->print_address_func) (info->target, info);
    428  1.1  matt 		  pd->print_addr = -1;
    429  1.1  matt 		}
    430  1.1  matt 	      return insnlen;
    431  1.1  matt 	    }
    432  1.1  matt 	}
    433  1.1  matt     }
    434  1.1  matt 
    435  1.1  matt   /* Handle undefined instructions.  */
    436  1.1  matt   info->insn_type = dis_noninsn;
    437  1.1  matt   (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
    438  1.1  matt   return insnlen;
    439  1.1  matt }
    440  1.1  matt 
    441  1.1  matt int
    442  1.1  matt print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
    443  1.1  matt {
    444  1.1  matt   uint16_t i2;
    445  1.1  matt   insn_t insn = 0;
    446  1.1  matt   bfd_vma n;
    447  1.1  matt   int status;
    448  1.1  matt 
    449  1.3  matt   if (info->disassembler_options != NULL)
    450  1.3  matt     {
    451  1.3  matt       parse_riscv_dis_options (info->disassembler_options);
    452  1.3  matt       /* Avoid repeatedly parsing the options.  */
    453  1.3  matt       info->disassembler_options = NULL;
    454  1.3  matt     }
    455  1.3  matt   else if (riscv_gpr_names == NULL)
    456  1.3  matt     set_default_riscv_dis_options ();
    457  1.1  matt 
    458  1.1  matt   /* Instructions are a sequence of 2-byte packets in little-endian order.  */
    459  1.1  matt   for (n = 0; n < sizeof(insn) && n < riscv_insn_length (insn); n += 2)
    460  1.1  matt     {
    461  1.1  matt       status = (*info->read_memory_func) (memaddr + n, (bfd_byte*)&i2, 2, info);
    462  1.1  matt       if (status != 0)
    463  1.1  matt 	{
    464  1.1  matt 	  if (n > 0) /* Don't fail just because we fell off the end. */
    465  1.1  matt 	    break;
    466  1.1  matt 	  (*info->memory_error_func) (status, memaddr, info);
    467  1.1  matt 	  return status;
    468  1.1  matt 	}
    469  1.1  matt 
    470  1.1  matt       i2 = bfd_getl16 (&i2);
    471  1.1  matt       insn |= (insn_t)i2 << (8*n);
    472  1.1  matt     }
    473  1.1  matt 
    474  1.1  matt   return riscv_disassemble_insn (memaddr, insn, info);
    475  1.1  matt }
    476  1.1  matt 
    477  1.1  matt void
    478  1.1  matt print_riscv_disassembler_options (FILE *stream)
    479  1.1  matt {
    480  1.1  matt   fprintf (stream, _("\n\
    481  1.1  matt The following RISC-V-specific disassembler options are supported for use\n\
    482  1.1  matt with the -M switch (multiple options should be separated by commas):\n"));
    483  1.1  matt 
    484  1.1  matt   fprintf (stream, _("\n\
    485  1.3  matt   numeric       Print numeric reigster names, rather than ABI names.\n"));
    486  1.1  matt 
    487  1.1  matt   fprintf (stream, _("\n\
    488  1.3  matt   no-aliases    Disassemble only into canonical instructions, rather\n\
    489  1.3  matt                 than into pseudoinstructions.\n"));
    490  1.1  matt 
    491  1.1  matt   fprintf (stream, _("\n"));
    492  1.1  matt }
    493