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