Home | History | Annotate | Download | only in opcodes
      1 /* xtensa-dis.c.  Disassembly functions for Xtensa.
      2    Copyright (C) 2003-2016 Free Software Foundation, Inc.
      3    Contributed by Bob Wilson at Tensilica, Inc. (bwilson (at) tensilica.com)
      4 
      5    This file is part of the GNU opcodes library.
      6 
      7    This library is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3, or (at your option)
     10    any later version.
     11 
     12    It is distributed in the hope that it will be useful, but WITHOUT
     13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15    License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this file; see the file COPYING.  If not, write to the
     19    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 #include "sysdep.h"
     23 #include <stdlib.h>
     24 #include <stdio.h>
     25 #include <sys/types.h>
     26 #include <string.h>
     27 #include "xtensa-isa.h"
     28 #include "ansidecl.h"
     29 #include "libiberty.h"
     30 #include "dis-asm.h"
     31 
     32 #include <setjmp.h>
     33 
     34 extern xtensa_isa xtensa_default_isa;
     35 
     36 #ifndef MAX
     37 #define MAX(a,b) (a > b ? a : b)
     38 #endif
     39 
     40 int show_raw_fields;
     41 
     42 struct dis_private
     43 {
     44   bfd_byte *byte_buf;
     45   OPCODES_SIGJMP_BUF bailout;
     46 };
     47 
     48 
     49 static int
     50 fetch_data (struct disassemble_info *info, bfd_vma memaddr)
     51 {
     52   int length, status = 0;
     53   struct dis_private *priv = (struct dis_private *) info->private_data;
     54   int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
     55 
     56   /* Read the maximum instruction size, padding with zeros if we go past
     57      the end of the text section.  This code will automatically adjust
     58      length when we hit the end of the buffer.  */
     59 
     60   memset (priv->byte_buf, 0, insn_size);
     61   for (length = insn_size; length > 0; length--)
     62     {
     63       status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
     64 					  info);
     65       if (status == 0)
     66 	return length;
     67     }
     68   (*info->memory_error_func) (status, memaddr, info);
     69   OPCODES_SIGLONGJMP (priv->bailout, 1);
     70   /*NOTREACHED*/
     71 }
     72 
     73 
     74 static void
     75 print_xtensa_operand (bfd_vma memaddr,
     76 		      struct disassemble_info *info,
     77 		      xtensa_opcode opc,
     78 		      int opnd,
     79 		      unsigned operand_val)
     80 {
     81   xtensa_isa isa = xtensa_default_isa;
     82   int signed_operand_val;
     83 
     84   if (show_raw_fields)
     85     {
     86       if (operand_val < 0xa)
     87 	(*info->fprintf_func) (info->stream, "%u", operand_val);
     88       else
     89 	(*info->fprintf_func) (info->stream, "0x%x", operand_val);
     90       return;
     91     }
     92 
     93   (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
     94   signed_operand_val = (int) operand_val;
     95 
     96   if (xtensa_operand_is_register (isa, opc, opnd) == 0)
     97     {
     98       if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
     99 	{
    100 	  (void) xtensa_operand_undo_reloc (isa, opc, opnd,
    101 					    &operand_val, memaddr);
    102 	  info->target = operand_val;
    103 	  (*info->print_address_func) (info->target, info);
    104 	}
    105       else
    106 	{
    107 	  if ((signed_operand_val > -256) && (signed_operand_val < 256))
    108 	    (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
    109 	  else
    110 	    (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
    111 	}
    112     }
    113   else
    114     {
    115       int i = 1;
    116       xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
    117       (*info->fprintf_func) (info->stream, "%s%u",
    118 			     xtensa_regfile_shortname (isa, opnd_rf),
    119 			     operand_val);
    120       while (i < xtensa_operand_num_regs (isa, opc, opnd))
    121 	{
    122 	  operand_val++;
    123 	  (*info->fprintf_func) (info->stream, ":%s%u",
    124 				 xtensa_regfile_shortname (isa, opnd_rf),
    125 				 operand_val);
    126 	  i++;
    127 	}
    128     }
    129 }
    130 
    131 
    132 /* Print the Xtensa instruction at address MEMADDR on info->stream.
    133    Returns length of the instruction in bytes.  */
    134 
    135 int
    136 print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
    137 {
    138   unsigned operand_val;
    139   int bytes_fetched, size, maxsize, i, n, noperands, nslots;
    140   xtensa_isa isa;
    141   xtensa_opcode opc;
    142   xtensa_format fmt;
    143   struct dis_private priv;
    144   static bfd_byte *byte_buf = NULL;
    145   static xtensa_insnbuf insn_buffer = NULL;
    146   static xtensa_insnbuf slot_buffer = NULL;
    147   int first, first_slot, valid_insn;
    148 
    149   if (!xtensa_default_isa)
    150     xtensa_default_isa = xtensa_isa_init (0, 0);
    151 
    152   info->target = 0;
    153   maxsize = xtensa_isa_maxlength (xtensa_default_isa);
    154 
    155   /* Set bytes_per_line to control the amount of whitespace between the hex
    156      values and the opcode.  For Xtensa, we always print one "chunk" and we
    157      vary bytes_per_chunk to determine how many bytes to print.  (objdump
    158      would apparently prefer that we set bytes_per_chunk to 1 and vary
    159      bytes_per_line but that makes it hard to fit 64-bit instructions on
    160      an 80-column screen.)  The value of bytes_per_line here is not exactly
    161      right, because objdump adds an extra space for each chunk so that the
    162      amount of whitespace depends on the chunk size.  Oh well, it's good
    163      enough....  Note that we set the minimum size to 4 to accomodate
    164      literal pools.  */
    165   info->bytes_per_line = MAX (maxsize, 4);
    166 
    167   /* Allocate buffers the first time through.  */
    168   if (!insn_buffer)
    169     {
    170       insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
    171       slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
    172       byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
    173     }
    174 
    175   priv.byte_buf = byte_buf;
    176 
    177   info->private_data = (void *) &priv;
    178   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
    179       /* Error return.  */
    180       return -1;
    181 
    182   /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
    183   isa = xtensa_default_isa;
    184   size = 0;
    185   nslots = 0;
    186 
    187   /* Fetch the maximum size instruction.  */
    188   bytes_fetched = fetch_data (info, memaddr);
    189 
    190   /* Copy the bytes into the decode buffer.  */
    191   memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
    192 			   sizeof (xtensa_insnbuf_word)));
    193   xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched);
    194 
    195   fmt = xtensa_format_decode (isa, insn_buffer);
    196   if (fmt == XTENSA_UNDEFINED
    197       || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched))
    198     valid_insn = 0;
    199   else
    200     {
    201       /* Make sure all the opcodes are valid.  */
    202       valid_insn = 1;
    203       nslots = xtensa_format_num_slots (isa, fmt);
    204       for (n = 0; n < nslots; n++)
    205 	{
    206 	  xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
    207 	  if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
    208 	      == XTENSA_UNDEFINED)
    209 	    {
    210 	      valid_insn = 0;
    211 	      break;
    212 	    }
    213 	}
    214     }
    215 
    216   if (!valid_insn)
    217     {
    218       (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
    219       return 1;
    220     }
    221 
    222   if (nslots > 1)
    223     (*info->fprintf_func) (info->stream, "{ ");
    224 
    225   first_slot = 1;
    226   for (n = 0; n < nslots; n++)
    227     {
    228       if (first_slot)
    229 	first_slot = 0;
    230       else
    231 	(*info->fprintf_func) (info->stream, "; ");
    232 
    233       xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
    234       opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
    235       (*info->fprintf_func) (info->stream, "%s",
    236 			     xtensa_opcode_name (isa, opc));
    237 
    238       /* Print the operands (if any).  */
    239       noperands = xtensa_opcode_num_operands (isa, opc);
    240       first = 1;
    241       for (i = 0; i < noperands; i++)
    242 	{
    243 	  if (xtensa_operand_is_visible (isa, opc, i) == 0)
    244 	    continue;
    245 	  if (first)
    246 	    {
    247 	      (*info->fprintf_func) (info->stream, "\t");
    248 	      first = 0;
    249 	    }
    250 	  else
    251 	    (*info->fprintf_func) (info->stream, ", ");
    252 	  (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
    253 					   slot_buffer, &operand_val);
    254 
    255 	  print_xtensa_operand (memaddr, info, opc, i, operand_val);
    256 	}
    257     }
    258 
    259   if (nslots > 1)
    260     (*info->fprintf_func) (info->stream, " }");
    261 
    262   info->bytes_per_chunk = size;
    263   info->display_endian = info->endian;
    264 
    265   return size;
    266 }
    267 
    268