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