Home | History | Annotate | Line # | Download | only in opcodes
riscv-dis.c revision 1.2
      1 /* RISC-V disassembler
      2    Copyright 2011-2014 Free Software Foundation, Inc.
      3 
      4    Contributed by Andrew Waterman (waterman (at) cs.berkeley.edu) at UC Berkeley.
      5    Based on MIPS target.
      6 
      7    This file is part of the GNU opcodes library.
      8 
      9    This library is free software; you can redistribute it and/or modify
     10    it under the terms of the GNU General Public License as published by
     11    the Free Software Foundation; either version 3, or (at your option)
     12    any later version.
     13 
     14    It is distributed in the hope that it will be useful, but WITHOUT
     15    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     16    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     17    License for more details.
     18 
     19    You should have received a copy of the GNU General Public License
     20    along with this program; if not, write to the Free Software
     21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     22    MA 02110-1301, USA.  */
     23 
     24 #include "sysdep.h"
     25 #include "dis-asm.h"
     26 #include "libiberty.h"
     27 #include "opcode/riscv.h"
     28 #include "opintl.h"
     29 #include "elf-bfd.h"
     30 #include "elf/riscv.h"
     31 
     32 #include <stdint.h>
     33 #include <assert.h>
     34 
     35 /* FIXME: These should be shared with gdb somehow.  */
     36 
     37 static const char * const riscv_gpr_names_numeric[32] =
     38 {
     39   "x0",   "x1",   "x2",   "x3",   "x4",   "x5",   "x6",   "x7",
     40   "x8",   "x9",   "x10",  "x11",  "x12",  "x13",  "x14",  "x15",
     41   "x16",  "x17",  "x18",  "x19",  "x20",  "x21",  "x22",  "x23",
     42   "x24",  "x25",  "x26",  "x27",  "x28",  "x29",  "x30",  "x31"
     43 };
     44 
     45 static const char * const riscv_gpr_names_abi[32] = {
     46   "zero", "ra", "s0", "s1",  "s2",  "s3",  "s4",  "s5",
     47   "s6",   "s7", "s8", "s9", "s10", "s11",  "sp",  "tp",
     48   "v0",   "v1", "a0", "a1",  "a2",  "a3",  "a4",  "a5",
     49   "a6",   "a7", "t0", "t1",  "t2",  "t3",  "t4",  "gp"
     50 };
     51 
     52 
     53 static const char * const riscv_fpr_names_numeric[32] =
     54 {
     55   "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
     56   "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
     57   "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
     58   "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31"
     59 };
     60 
     61 static const char * const riscv_fpr_names_abi[32] = {
     62   "fs0", "fs1",  "fs2",  "fs3",  "fs4",  "fs5",  "fs6",  "fs7",
     63   "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15",
     64   "fv0", "fv1", "fa0",   "fa1",  "fa2",  "fa3",  "fa4",  "fa5",
     65   "fa6", "fa7", "ft0",   "ft1",  "ft2",  "ft3",  "ft4",  "ft5"
     66 };
     67 
     68 static const char * const riscv_vgr_reg_names_riscv[32] =
     69 {
     70   "vx0",  "vx1",  "vx2",  "vx3",  "vx4",  "vx5",  "vx6",  "vx7",
     71   "vx8",  "vx9",  "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
     72   "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
     73   "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
     74 };
     75 
     76 static const char * const riscv_vfp_reg_names_riscv[32] =
     77 {
     78   "vf0",  "vf1",  "vf2",  "vf3",  "vf4",  "vf5",  "vf6",  "vf7",
     79   "vf8",  "vf9",  "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
     80   "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
     81   "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
     82 };
     83 
     84 struct riscv_abi_choice
     85 {
     86   const char * name;
     87   const char * const *gpr_names;
     88   const char * const *fpr_names;
     89 };
     90 
     91 struct riscv_abi_choice riscv_abi_choices[] =
     92 {
     93   { "numeric", riscv_gpr_names_numeric, riscv_fpr_names_numeric },
     94   { "32", riscv_gpr_names_abi, riscv_fpr_names_abi },
     95   { "64", riscv_gpr_names_abi, riscv_fpr_names_abi },
     96 };
     97 
     98 struct riscv_arch_choice
     99 {
    100   const char *name;
    101   int bfd_mach_valid;
    102   unsigned long bfd_mach;
    103 };
    104 
    105 const struct riscv_arch_choice riscv_arch_choices[] =
    106 {
    107   { "numeric",	0, 0 },
    108   { "rv32",	1, bfd_mach_riscv32 },
    109   { "rv64",	1, bfd_mach_riscv64 },
    110 };
    111 
    112 struct riscv_private_data
    113 {
    114   bfd_vma gp;
    115   bfd_vma print_addr;
    116   bfd_vma hi_addr[OP_MASK_RD + 1];
    117 };
    118 
    119 /* ISA and processor type to disassemble for, and register names to use.
    120    set_default_riscv_dis_options and parse_riscv_dis_options fill in these
    121    values.  */
    122 static const char * const *riscv_gpr_names;
    123 static const char * const *riscv_fpr_names;
    124 
    125 /* Other options */
    126 static int no_aliases;	/* If set disassemble as most general inst.  */
    127 
    128 static const struct riscv_abi_choice *
    130 choose_abi_by_name (const char *name, unsigned int namelen)
    131 {
    132   const struct riscv_abi_choice *c;
    133   unsigned int i;
    134 
    135   for (i = 0, c = NULL; i < ARRAY_SIZE (riscv_abi_choices) && c == NULL; i++)
    136     if (strncmp (riscv_abi_choices[i].name, name, namelen) == 0
    137 	&& strlen (riscv_abi_choices[i].name) == namelen)
    138       c = &riscv_abi_choices[i];
    139 
    140   return c;
    141 }
    142 
    143 static void
    144 set_default_riscv_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED)
    145 {
    146   riscv_gpr_names = riscv_gpr_names_abi;
    147   riscv_fpr_names = riscv_fpr_names_abi;
    148   no_aliases = 0;
    149 }
    150 
    151 static void
    152 parse_riscv_dis_option (const char *option, unsigned int len)
    153 {
    154   unsigned int i, optionlen, vallen;
    155   const char *val;
    156   const struct riscv_abi_choice *chosen_abi;
    157 
    158   /* Try to match options that are simple flags */
    159   if (CONST_STRNEQ (option, "no-aliases"))
    160     {
    161       no_aliases = 1;
    162       return;
    163     }
    164 
    165   /* Look for the = that delimits the end of the option name.  */
    166   for (i = 0; i < len; i++)
    167     if (option[i] == '=')
    168       break;
    169 
    170   if (i == 0)		/* Invalid option: no name before '='.  */
    171     return;
    172   if (i == len)		/* Invalid option: no '='.  */
    173     return;
    174   if (i == (len - 1))	/* Invalid option: no value after '='.  */
    175     return;
    176 
    177   optionlen = i;
    178   val = option + (optionlen + 1);
    179   vallen = len - (optionlen + 1);
    180 
    181   if (strncmp ("gpr-names", option, optionlen) == 0
    182       && strlen ("gpr-names") == optionlen)
    183     {
    184       chosen_abi = choose_abi_by_name (val, vallen);
    185       if (chosen_abi != NULL)
    186 	riscv_gpr_names = chosen_abi->gpr_names;
    187       return;
    188     }
    189 
    190   if (strncmp ("fpr-names", option, optionlen) == 0
    191       && strlen ("fpr-names") == optionlen)
    192     {
    193       chosen_abi = choose_abi_by_name (val, vallen);
    194       if (chosen_abi != NULL)
    195 	riscv_fpr_names = chosen_abi->fpr_names;
    196       return;
    197     }
    198 
    199   /* Invalid option.  */
    200 }
    201 
    202 static void
    203 parse_riscv_dis_options (const char *options)
    204 {
    205   const char *option_end;
    206 
    207   if (options == NULL)
    208     return;
    209 
    210   while (*options != '\0')
    211     {
    212       /* Skip empty options.  */
    213       if (*options == ',')
    214 	{
    215 	  options++;
    216 	  continue;
    217 	}
    218 
    219       /* We know that *options is neither NUL or a comma.  */
    220       option_end = options + 1;
    221       while (*option_end != ',' && *option_end != '\0')
    222 	option_end++;
    223 
    224       parse_riscv_dis_option (options, option_end - options);
    225 
    226       /* Go on to the next one.  If option_end points to a comma, it
    227 	 will be skipped above.  */
    228       options = option_end;
    229     }
    230 }
    231 
    232 /* Print one argument from an array. */
    233 
    234 static void
    235 arg_print (struct disassemble_info *info, unsigned long val,
    236 	   const char* const* array, size_t size)
    237 {
    238   const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
    239   (*info->fprintf_func) (info->stream, "%s", s);
    240 }
    241 
    242 static void
    243 maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
    244 {
    245   if (pd->hi_addr[base_reg] != (bfd_vma)-1)
    246     {
    247       pd->print_addr = pd->hi_addr[base_reg] + offset;
    248       pd->hi_addr[base_reg] = -1;
    249     }
    250   else if (base_reg == GP_REG && pd->gp != (bfd_vma)-1)
    251     pd->print_addr = pd->gp + offset;
    252   else if (base_reg == TP_REG)
    253     pd->print_addr = offset;
    254 }
    255 
    256 /* Print insn arguments for 32/64-bit code.  */
    257 
    258 static void
    259 print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
    260 {
    261   struct riscv_private_data *pd = info->private_data;
    262   int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
    263   int rd = (l >> OP_SH_RD) & OP_MASK_RD;
    264 
    265   if (*d != '\0')
    266     (*info->fprintf_func) (info->stream, "\t");
    267 
    268   for (; *d != '\0'; d++)
    269     {
    270       switch (*d)
    271 	{
    272         /* Xcustom */
    273         case '^':
    274           switch (*++d)
    275             {
    276             case 'd':
    277               (*info->fprintf_func) (info->stream, "%d", rd);
    278               break;
    279             case 's':
    280               (*info->fprintf_func) (info->stream, "%d", rs1);
    281               break;
    282             case 't':
    283               (*info->fprintf_func)
    284                 ( info->stream, "%d", (int)((l >> OP_SH_RS2) & OP_MASK_RS2));
    285               break;
    286             case 'j':
    287               (*info->fprintf_func)
    288                 ( info->stream, "%d", (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
    289               break;
    290             }
    291           break;
    292 
    293         /* Xhwacha */
    294         case '#':
    295           switch ( *++d ) {
    296             case 'g':
    297               (*info->fprintf_func)
    298                 ( info->stream, "%d",
    299                   (int)((l >> OP_SH_IMMNGPR) & OP_MASK_IMMNGPR));
    300               break;
    301             case 'f':
    302               (*info->fprintf_func)
    303                 ( info->stream, "%d",
    304                   (int)((l >> OP_SH_IMMNFPR) & OP_MASK_IMMNFPR));
    305               break;
    306             case 'p':
    307               (*info->fprintf_func)
    308                 ( info->stream, "%d",
    309                  (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
    310               break;
    311             case 'n':
    312               (*info->fprintf_func)
    313                 ( info->stream, "%d",
    314                   (int)(((l >> OP_SH_IMMSEGNELM) & OP_MASK_IMMSEGNELM) + 1));
    315               break;
    316             case 'd':
    317               (*info->fprintf_func)
    318                 ( info->stream, "%s",
    319                   riscv_vgr_reg_names_riscv[(l >> OP_SH_VRD) & OP_MASK_VRD]);
    320               break;
    321             case 's':
    322               (*info->fprintf_func)
    323                 ( info->stream, "%s",
    324                   riscv_vgr_reg_names_riscv[(l >> OP_SH_VRS) & OP_MASK_VRS]);
    325               break;
    326             case 't':
    327               (*info->fprintf_func)
    328                 ( info->stream, "%s",
    329                   riscv_vgr_reg_names_riscv[(l >> OP_SH_VRT) & OP_MASK_VRT]);
    330               break;
    331             case 'r':
    332               (*info->fprintf_func)
    333                 ( info->stream, "%s",
    334                   riscv_vgr_reg_names_riscv[(l >> OP_SH_VRR) & OP_MASK_VRR]);
    335               break;
    336             case 'D':
    337               (*info->fprintf_func)
    338                 ( info->stream, "%s",
    339                   riscv_vfp_reg_names_riscv[(l >> OP_SH_VFD) & OP_MASK_VFD]);
    340               break;
    341             case 'S':
    342               (*info->fprintf_func)
    343                 ( info->stream, "%s",
    344                   riscv_vfp_reg_names_riscv[(l >> OP_SH_VFS) & OP_MASK_VFS]);
    345               break;
    346             case 'T':
    347               (*info->fprintf_func)
    348                 ( info->stream, "%s",
    349                   riscv_vfp_reg_names_riscv[(l >> OP_SH_VFT) & OP_MASK_VFT]);
    350               break;
    351             case 'R':
    352               (*info->fprintf_func)
    353                 ( info->stream, "%s",
    354                   riscv_vfp_reg_names_riscv[(l >> OP_SH_VFR) & OP_MASK_VFR]);
    355               break;
    356           }
    357           break;
    358 
    359 	case ',':
    360 	case '(':
    361 	case ')':
    362 	case '[':
    363 	case ']':
    364 	  (*info->fprintf_func) (info->stream, "%c", *d);
    365 	  break;
    366 
    367 	case '0':
    368 	  break;
    369 
    370 	case 'b':
    371 	case 's':
    372 	  (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rs1]);
    373 	  break;
    374 
    375 	case 't':
    376 	  (*info->fprintf_func) (info->stream, "%s",
    377 				 riscv_gpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
    378 	  break;
    379 
    380 	case 'u':
    381 	  (*info->fprintf_func) (info->stream, "0x%x", (unsigned)EXTRACT_UTYPE_IMM (l) << RISCV_IMM_BITS >> RISCV_IMM_BITS);
    382 	  break;
    383 
    384 	case 'm':
    385 	  arg_print(info, (l >> OP_SH_RM) & OP_MASK_RM,
    386 		    riscv_rm, ARRAY_SIZE(riscv_rm));
    387 	  break;
    388 
    389 	case 'P':
    390 	  arg_print(info, (l >> OP_SH_PRED) & OP_MASK_PRED,
    391 	            riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
    392 	  break;
    393 
    394 	case 'Q':
    395 	  arg_print(info, (l >> OP_SH_SUCC) & OP_MASK_SUCC,
    396 	            riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
    397 	  break;
    398 
    399 	case 'o':
    400 	  maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
    401 	case 'j':
    402 	  if ((l & MASK_ADDI) == MATCH_ADDI || (l & MASK_JALR) == MATCH_JALR)
    403 	    maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
    404 	  (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
    405 	  break;
    406 
    407 	case 'q':
    408 	  maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
    409 	  (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
    410 	  break;
    411 
    412 	case 'a':
    413 	  info->target = EXTRACT_UJTYPE_IMM (l) + pc;
    414 	  (*info->print_address_func) (info->target, info);
    415 	  break;
    416 
    417 	case 'p':
    418 	  info->target = EXTRACT_SBTYPE_IMM (l) + pc;
    419 	  (*info->print_address_func) (info->target, info);
    420 	  break;
    421 
    422 	case 'd':
    423 	  if ((l & MASK_AUIPC) == MATCH_AUIPC)
    424 	    pd->hi_addr[rd] = pc + (EXTRACT_UTYPE_IMM (l) << RISCV_IMM_BITS);
    425 	  else if ((l & MASK_LUI) == MATCH_LUI)
    426 	    pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l) << RISCV_IMM_BITS;
    427 	  (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rd]);
    428 	  break;
    429 
    430 	case 'z':
    431 	  (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[0]);
    432 	  break;
    433 
    434 	case '>':
    435 	  (*info->fprintf_func) (info->stream, "0x%x",
    436 				 (unsigned)((l >> OP_SH_SHAMT) & OP_MASK_SHAMT));
    437 	  break;
    438 
    439 	case '<':
    440 	  (*info->fprintf_func) (info->stream, "0x%x",
    441 				 (unsigned)((l >> OP_SH_SHAMTW) & OP_MASK_SHAMTW));
    442 	  break;
    443 
    444 	case 'S':
    445 	case 'U':
    446 	  (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rs1]);
    447 	  break;
    448 
    449 	case 'T':
    450 	  (*info->fprintf_func) (info->stream, "%s",
    451 				 riscv_fpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
    452 	  break;
    453 
    454 	case 'D':
    455 	  (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rd]);
    456 	  break;
    457 
    458 	case 'R':
    459 	  (*info->fprintf_func) (info->stream, "%s",
    460 				 riscv_fpr_names[(l >> OP_SH_RS3) & OP_MASK_RS3]);
    461 	  break;
    462 
    463 	case 'E':
    464 	  {
    465 	    const char* csr_name = "unknown";
    466 	    switch ((l >> OP_SH_CSR) & OP_MASK_CSR)
    467 	      {
    468 		#define DECLARE_CSR(name, num) case num: csr_name = #name; break;
    469 		#include "opcode/riscv-opc.h"
    470 		#undef DECLARE_CSR
    471 	      }
    472 	    (*info->fprintf_func) (info->stream, "%s", csr_name);
    473 	    break;
    474 	  }
    475 
    476 	case 'Z':
    477 	  (*info->fprintf_func) (info->stream, "%d", rs1);
    478 	  break;
    479 
    480 	default:
    481 	  /* xgettext:c-format */
    482 	  (*info->fprintf_func) (info->stream,
    483 				 _("# internal error, undefined modifier (%c)"),
    484 				 *d);
    485 	  return;
    486 	}
    487     }
    488 }
    489 
    490 #if 0
    491 static unsigned long
    492 riscv_rvc_uncompress(unsigned long rvc_insn)
    493 {
    494   #define IS_INSN(x, op) (((x) & MASK_##op) == MATCH_##op)
    495   #define EXTRACT_OPERAND(x, op) (((x) >> OP_SH_##op) & OP_MASK_##op)
    496 
    497   int crd = EXTRACT_OPERAND(rvc_insn, CRD);
    498   int crs1 = EXTRACT_OPERAND(rvc_insn, CRS1);
    499   int crs2 = EXTRACT_OPERAND(rvc_insn, CRS2);
    500   int crds = EXTRACT_OPERAND(rvc_insn, CRDS);
    501   int crs1s = EXTRACT_OPERAND(rvc_insn, CRS1S);
    502   int crs2s = EXTRACT_OPERAND(rvc_insn, CRS2S);
    503   int crs2bs = EXTRACT_OPERAND(rvc_insn, CRS2BS);
    504 
    505   int cimm6 = EXTRACT_OPERAND(rvc_insn, CIMM6);
    506   int imm6 = ((int32_t)cimm6 << 26 >> 26) & (RISCV_IMM_REACH-1);
    507   int imm6x4 = (((int32_t)cimm6 << 26 >> 26)*4) & (RISCV_IMM_REACH-1);
    508   int imm6x4lo = imm6x4 & ((1<<RISCV_IMMLO_BITS)-1);
    509   int imm6x4hi = (imm6x4 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
    510   int imm6x8 = (((int32_t)cimm6 << 26 >> 26)*8) & (RISCV_IMM_REACH-1);
    511   int imm6x8lo = imm6x8 & ((1<<RISCV_IMMLO_BITS)-1);
    512   int imm6x8hi = (imm6x8 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
    513 
    514   int cimm5 = EXTRACT_OPERAND(rvc_insn, CIMM5);
    515   int imm5 = ((int32_t)cimm5 << 27 >> 27) & (RISCV_IMM_REACH-1);
    516   int imm5lo = imm5 & ((1<<RISCV_IMMLO_BITS)-1);
    517   int imm5hi = (imm5 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
    518   int imm5x4 = (((int32_t)cimm5 << 27 >> 27)*4) & (RISCV_IMM_REACH-1);
    519   int imm5x4lo = imm5x4 & ((1<<RISCV_IMMLO_BITS)-1);
    520   int imm5x4hi = (imm5x4 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
    521   int imm5x8 = (((int32_t)cimm5 << 27 >> 27)*8) & (RISCV_IMM_REACH-1);
    522   int imm5x8lo = imm5x8 & ((1<<RISCV_IMMLO_BITS)-1);
    523   int imm5x8hi = (imm5x8 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
    524 
    525   int cimm10 = EXTRACT_OPERAND(rvc_insn, CIMM10);
    526   int jt10 = ((int32_t)cimm10 << 22 >> 22) & ((1<<RISCV_JUMP_BITS)-1);
    527 
    528   if(IS_INSN(rvc_insn, C_ADDI))
    529   {
    530     if(crd == 0)
    531     {
    532       if(imm6 & 0x20)
    533         return MATCH_JALR | (LINK_REG << OP_SH_RD) | (crs1 << OP_SH_RS1);
    534       else
    535         return MATCH_JALR | (crs1 << OP_SH_RS1);
    536     }
    537     return MATCH_ADDI | (crd << OP_SH_RD) | (crd << OP_SH_RS1) |
    538            (imm6 << OP_SH_IMMEDIATE);
    539   }
    540   if(IS_INSN(rvc_insn, C_ADDIW))
    541     return MATCH_ADDIW | (crd << OP_SH_RD) | (crd << OP_SH_RS1) | (imm6 << OP_SH_IMMEDIATE);
    542   if(IS_INSN(rvc_insn, C_LI))
    543     return MATCH_ADDI | (crd << OP_SH_RD) | (imm6 << OP_SH_IMMEDIATE);
    544   if(IS_INSN(rvc_insn, C_MOVE))
    545     return MATCH_ADDI | (crd << OP_SH_RD) | (crs1 << OP_SH_RS1);
    546   if(IS_INSN(rvc_insn, C_SLLI))
    547     return MATCH_SLLI | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
    548   if(IS_INSN(rvc_insn, C_SLLI32))
    549     return MATCH_SLLI | ((cimm5+32) << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
    550   if(IS_INSN(rvc_insn, C_SRLI))
    551     return MATCH_SRLI | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
    552   if(IS_INSN(rvc_insn, C_SRLI32))
    553     return MATCH_SRLI | ((cimm5+32) << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
    554   if(IS_INSN(rvc_insn, C_SRAI))
    555     return MATCH_SRAI | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
    556   if(IS_INSN(rvc_insn, C_SRAI32))
    557     return MATCH_SRAI | ((cimm5+32) << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
    558   if(IS_INSN(rvc_insn, C_SLLIW))
    559     return MATCH_SLLIW | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
    560   if(IS_INSN(rvc_insn, C_ADD))
    561     return MATCH_ADD | (crd << OP_SH_RD) | (crs1 << OP_SH_RS1) | (crd << OP_SH_RS2);
    562   if(IS_INSN(rvc_insn, C_SUB))
    563     return MATCH_SUB | (crd << OP_SH_RD) | (crs1 << OP_SH_RS1) | (crd << OP_SH_RS2);
    564   if(IS_INSN(rvc_insn, C_ADD3))
    565     return MATCH_ADD | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
    566   if(IS_INSN(rvc_insn, C_SUB3))
    567     return MATCH_SUB | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
    568   if(IS_INSN(rvc_insn, C_AND3))
    569     return MATCH_AND | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
    570   if(IS_INSN(rvc_insn, C_OR3))
    571     return MATCH_OR | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
    572   if(IS_INSN(rvc_insn, C_J))
    573     return MATCH_JAL | (jt10 << OP_SH_TARGET);
    574   if(IS_INSN(rvc_insn, C_BEQ))
    575     return MATCH_BEQ | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5lo << OP_SH_IMMLO) | (imm5hi << OP_SH_IMMHI);
    576   if(IS_INSN(rvc_insn, C_BNE))
    577     return MATCH_BNE | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5lo << OP_SH_IMMLO) | (imm5hi << OP_SH_IMMHI);
    578   if(IS_INSN(rvc_insn, C_LDSP))
    579     return MATCH_LD | (30 << OP_SH_RS1) | (crd << OP_SH_RD) | (imm6x8 << OP_SH_IMMEDIATE);
    580   if(IS_INSN(rvc_insn, C_LWSP))
    581     return MATCH_LW | (30 << OP_SH_RS1) | (crd << OP_SH_RD) | (imm6x4 << OP_SH_IMMEDIATE);
    582   if(IS_INSN(rvc_insn, C_SDSP))
    583     return MATCH_SD | (30 << OP_SH_RS1) | (crs2 << OP_SH_RS2) | (imm6x8lo << OP_SH_IMMLO) | (imm6x8hi << OP_SH_IMMHI);
    584   if(IS_INSN(rvc_insn, C_SWSP))
    585     return MATCH_SW | (30 << OP_SH_RS1) | (crs2 << OP_SH_RS2) | (imm6x4lo << OP_SH_IMMLO) | (imm6x4hi << OP_SH_IMMHI);
    586   if(IS_INSN(rvc_insn, C_LD))
    587     return MATCH_LD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x8 << OP_SH_IMMEDIATE);
    588   if(IS_INSN(rvc_insn, C_LW))
    589     return MATCH_LW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x4 << OP_SH_IMMEDIATE);
    590   if(IS_INSN(rvc_insn, C_SD))
    591     return MATCH_SD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x8lo << OP_SH_IMMLO) | (imm5x8hi << OP_SH_IMMHI);
    592   if(IS_INSN(rvc_insn, C_SW))
    593     return MATCH_SW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x4lo << OP_SH_IMMLO) | (imm5x4hi << OP_SH_IMMHI);
    594   if(IS_INSN(rvc_insn, C_LD0))
    595     return MATCH_LD | (crs1 << OP_SH_RS1) | (crd << OP_SH_RD);
    596   if(IS_INSN(rvc_insn, C_LW0))
    597     return MATCH_LW | (crs1 << OP_SH_RS1) | (crd << OP_SH_RD);
    598   if(IS_INSN(rvc_insn, C_FLD))
    599     return MATCH_FLD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x8 << OP_SH_IMMEDIATE);
    600   if(IS_INSN(rvc_insn, C_FLW))
    601     return MATCH_FLW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x4 << OP_SH_IMMEDIATE);
    602   if(IS_INSN(rvc_insn, C_FSD))
    603     return MATCH_FSD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x8lo << OP_SH_IMMLO) | (imm5x8hi << OP_SH_IMMHI);
    604   if(IS_INSN(rvc_insn, C_FSW))
    605     return MATCH_FSW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x4lo << OP_SH_IMMLO) | (imm5x4hi << OP_SH_IMMHI);
    606 
    607   return rvc_insn;
    608 }
    609 #endif
    610 
    611 /* Print the RISC-V instruction at address MEMADDR in debugged memory,
    612    on using INFO.  Returns length of the instruction, in bytes.
    613    BIGENDIAN must be 1 if this is big-endian code, 0 if
    614    this is little-endian code.  */
    615 
    616 static int
    617 riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
    618 {
    619   const struct riscv_opcode *op;
    620   static bfd_boolean init = 0;
    621   static const char *extension = NULL;
    622   static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
    623   struct riscv_private_data *pd;
    624   int insnlen;
    625 
    626   /* Build a hash table to shorten the search time.  */
    627   if (! init)
    628     {
    629       unsigned int i;
    630       unsigned int e_flags = elf_elfheader (info->section->owner)->e_flags;
    631       extension = riscv_elf_flag_to_name(EF_GET_RISCV_EXT(e_flags));
    632 
    633       for (i = 0; i <= OP_MASK_OP; i++)
    634         for (op = riscv_opcodes; op < &riscv_opcodes[NUMOPCODES]; op++)
    635           if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
    636             {
    637               riscv_hash[i] = op;
    638               break;
    639             }
    640 
    641       init = 1;
    642     }
    643 
    644   if (info->private_data == NULL)
    645     {
    646       int i;
    647 
    648       pd = info->private_data = calloc(1, sizeof (struct riscv_private_data));
    649       pd->gp = -1;
    650       pd->print_addr = -1;
    651       for (i = 0; i < (int) ARRAY_SIZE(pd->hi_addr); i++)
    652 	pd->hi_addr[i] = -1;
    653 
    654       for (i = 0; i < info->symtab_size; i++)
    655 	if (strcmp (bfd_asymbol_name (info->symtab[i]), "_gp") == 0)
    656 	  pd->gp = bfd_asymbol_value (info->symtab[i]);
    657     }
    658   else
    659     pd = info->private_data;
    660 
    661   insnlen = riscv_insn_length (word);
    662 
    663 #if 0
    664   if (insnlen == 2)
    665     word = riscv_rvc_uncompress(word);
    666 #endif
    667 
    668   info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
    669   info->bytes_per_line = 8;
    670   info->display_endian = info->endian;
    671   info->insn_info_valid = 1;
    672   info->branch_delay_insns = 0;
    673   info->data_size = 0;
    674   info->insn_type = dis_nonbranch;
    675   info->target = 0;
    676   info->target2 = 0;
    677 
    678   op = riscv_hash[(word >> OP_SH_OP) & OP_MASK_OP];
    679   if (op != NULL)
    680     {
    681       for (; op < &riscv_opcodes[NUMOPCODES]; op++)
    682 	{
    683 	  if ((op->match_func) (op, word)
    684 	      && !(no_aliases && (op->pinfo & INSN_ALIAS))
    685 	      && !(op->subset[0] == 'X' && strcmp(op->subset, extension)))
    686 	    {
    687 	      (*info->fprintf_func) (info->stream, "%s", op->name);
    688 	      print_insn_args (op->args, word, memaddr, info);
    689 	      if (pd->print_addr != (bfd_vma)-1)
    690 		{
    691 		  info->target = pd->print_addr;
    692 		  (*info->fprintf_func) (info->stream, " # ");
    693 		  (*info->print_address_func) (info->target, info);
    694 		  pd->print_addr = -1;
    695 		}
    696 	      return insnlen;
    697 	    }
    698 	}
    699     }
    700 
    701   /* Handle undefined instructions.  */
    702   info->insn_type = dis_noninsn;
    703   (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
    704   return insnlen;
    705 }
    706 
    707 int
    708 print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
    709 {
    710   uint16_t i2;
    711   insn_t insn = 0;
    712   bfd_vma n;
    713   int status;
    714 
    715   set_default_riscv_dis_options (info);
    716   parse_riscv_dis_options (info->disassembler_options);
    717 
    718   /* Instructions are a sequence of 2-byte packets in little-endian order.  */
    719   for (n = 0; n < sizeof(insn) && n < riscv_insn_length (insn); n += 2)
    720     {
    721       status = (*info->read_memory_func) (memaddr + n, (bfd_byte*)&i2, 2, info);
    722       if (status != 0)
    723 	{
    724 	  if (n > 0) /* Don't fail just because we fell off the end. */
    725 	    break;
    726 	  (*info->memory_error_func) (status, memaddr, info);
    727 	  return status;
    728 	}
    729 
    730       i2 = bfd_getl16 (&i2);
    731       insn |= (insn_t)i2 << (8*n);
    732     }
    733 
    734   return riscv_disassemble_insn (memaddr, insn, info);
    735 }
    736 
    737 void
    738 print_riscv_disassembler_options (FILE *stream)
    739 {
    740   unsigned int i;
    741 
    742   fprintf (stream, _("\n\
    743 The following RISC-V-specific disassembler options are supported for use\n\
    744 with the -M switch (multiple options should be separated by commas):\n"));
    745 
    746   fprintf (stream, _("\n\
    747   gpr-names=ABI            Print GPR names according to  specified ABI.\n\
    748                            Default: based on binary being disassembled.\n"));
    749 
    750   fprintf (stream, _("\n\
    751   fpr-names=ABI            Print FPR names according to specified ABI.\n\
    752                            Default: numeric.\n"));
    753 
    754   fprintf (stream, _("\n\
    755   For the options above, the following values are supported for \"ABI\":\n\
    756    "));
    757   for (i = 0; i < ARRAY_SIZE (riscv_abi_choices); i++)
    758     fprintf (stream, " %s", riscv_abi_choices[i].name);
    759   fprintf (stream, _("\n"));
    760 
    761   fprintf (stream, _("\n"));
    762 }
    763