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