Back to index

cell-binutils  2.17cvs20070401
xtensa-dis.c
Go to the documentation of this file.
00001 /* xtensa-dis.c.  Disassembly functions for Xtensa.
00002    Copyright 2003, 2004 Free Software Foundation, Inc.
00003    Contributed by Bob Wilson at Tensilica, Inc. (bwilson@tensilica.com)
00004 
00005    This file is part of GDB, GAS, and the GNU binutils.
00006 
00007    GDB, GAS, and the GNU binutils are free software; you can redistribute
00008    them and/or modify them under the terms of the GNU General Public
00009    License as published by the Free Software Foundation; either version 2,
00010    or (at your option) any later version.
00011 
00012    GDB, GAS, and the GNU binutils are distributed in the hope that they
00013    will be useful, but WITHOUT ANY WARRANTY; without even the implied
00014    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
00015    the GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License along
00018    with this file; see the file COPYING.  If not, write to the Free
00019    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
00020    USA.  */
00021 
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <sys/types.h>
00025 #include <string.h>
00026 #include "xtensa-isa.h"
00027 #include "ansidecl.h"
00028 #include "libiberty.h"
00029 #include "sysdep.h"
00030 #include "dis-asm.h"
00031 
00032 #include <setjmp.h>
00033 
00034 extern xtensa_isa xtensa_default_isa;
00035 
00036 #ifndef MAX
00037 #define MAX(a,b) (a > b ? a : b)
00038 #endif
00039 
00040 int show_raw_fields;
00041 
00042 struct dis_private
00043 {
00044   bfd_byte *byte_buf;
00045   jmp_buf bailout;
00046 };
00047 
00048 
00049 static int
00050 fetch_data (struct disassemble_info *info, bfd_vma memaddr)
00051 {
00052   int length, status = 0;
00053   struct dis_private *priv = (struct dis_private *) info->private_data;
00054   int insn_size = xtensa_isa_maxlength (xtensa_default_isa);
00055 
00056   /* Read the maximum instruction size, padding with zeros if we go past
00057      the end of the text section.  This code will automatically adjust
00058      length when we hit the end of the buffer.  */
00059 
00060   memset (priv->byte_buf, 0, insn_size);
00061   for (length = insn_size; length > 0; length--)
00062     {
00063       status = (*info->read_memory_func) (memaddr, priv->byte_buf, length,
00064                                      info);
00065       if (status == 0)
00066        return length;
00067     }
00068   (*info->memory_error_func) (status, memaddr, info);
00069   longjmp (priv->bailout, 1);
00070   /*NOTREACHED*/
00071 }
00072 
00073 
00074 static void
00075 print_xtensa_operand (bfd_vma memaddr,
00076                     struct disassemble_info *info,
00077                     xtensa_opcode opc,
00078                     int opnd,
00079                     unsigned operand_val)
00080 {
00081   xtensa_isa isa = xtensa_default_isa;
00082   int signed_operand_val;
00083     
00084   if (show_raw_fields)
00085     {
00086       if (operand_val < 0xa)
00087        (*info->fprintf_func) (info->stream, "%u", operand_val);
00088       else
00089        (*info->fprintf_func) (info->stream, "0x%x", operand_val);
00090       return;
00091     }
00092 
00093   (void) xtensa_operand_decode (isa, opc, opnd, &operand_val);
00094   signed_operand_val = (int) operand_val;
00095 
00096   if (xtensa_operand_is_register (isa, opc, opnd) == 0)
00097     {
00098       if (xtensa_operand_is_PCrelative (isa, opc, opnd) == 1)
00099        {
00100          (void) xtensa_operand_undo_reloc (isa, opc, opnd,
00101                                        &operand_val, memaddr);
00102          info->target = operand_val;
00103          (*info->print_address_func) (info->target, info);
00104        }
00105       else
00106        {
00107          if ((signed_operand_val > -256) && (signed_operand_val < 256))
00108            (*info->fprintf_func) (info->stream, "%d", signed_operand_val);
00109          else
00110            (*info->fprintf_func) (info->stream, "0x%x", signed_operand_val);
00111        }
00112     }
00113   else
00114     {
00115       int i = 1;
00116       xtensa_regfile opnd_rf = xtensa_operand_regfile (isa, opc, opnd);
00117       (*info->fprintf_func) (info->stream, "%s%u",
00118                           xtensa_regfile_shortname (isa, opnd_rf),
00119                           operand_val);
00120       while (i < xtensa_operand_num_regs (isa, opc, opnd))
00121        {
00122          operand_val++;
00123          (*info->fprintf_func) (info->stream, ":%s%u",
00124                              xtensa_regfile_shortname (isa, opnd_rf),
00125                              operand_val);
00126          i++;
00127        } 
00128     }
00129 }
00130 
00131 
00132 /* Print the Xtensa instruction at address MEMADDR on info->stream.
00133    Returns length of the instruction in bytes.  */
00134 
00135 int
00136 print_insn_xtensa (bfd_vma memaddr, struct disassemble_info *info)
00137 {
00138   unsigned operand_val;
00139   int bytes_fetched, size, maxsize, i, n, noperands, nslots;
00140   xtensa_isa isa;
00141   xtensa_opcode opc;
00142   xtensa_format fmt;
00143   struct dis_private priv;
00144   static bfd_byte *byte_buf = NULL;
00145   static xtensa_insnbuf insn_buffer = NULL;
00146   static xtensa_insnbuf slot_buffer = NULL;
00147   int first, first_slot, valid_insn;
00148 
00149   if (!xtensa_default_isa)
00150     xtensa_default_isa = xtensa_isa_init (0, 0);
00151 
00152   info->target = 0;
00153   maxsize = xtensa_isa_maxlength (xtensa_default_isa);
00154 
00155   /* Set bytes_per_line to control the amount of whitespace between the hex
00156      values and the opcode.  For Xtensa, we always print one "chunk" and we
00157      vary bytes_per_chunk to determine how many bytes to print.  (objdump
00158      would apparently prefer that we set bytes_per_chunk to 1 and vary
00159      bytes_per_line but that makes it hard to fit 64-bit instructions on
00160      an 80-column screen.)  The value of bytes_per_line here is not exactly
00161      right, because objdump adds an extra space for each chunk so that the
00162      amount of whitespace depends on the chunk size.  Oh well, it's good
00163      enough....  Note that we set the minimum size to 4 to accomodate
00164      literal pools.  */
00165   info->bytes_per_line = MAX (maxsize, 4);
00166 
00167   /* Allocate buffers the first time through.  */
00168   if (!insn_buffer)
00169     {
00170       insn_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
00171       slot_buffer = xtensa_insnbuf_alloc (xtensa_default_isa);
00172       byte_buf = (bfd_byte *) xmalloc (MAX (maxsize, 4));
00173     }
00174 
00175   priv.byte_buf = byte_buf;
00176 
00177   info->private_data = (void *) &priv;
00178   if (setjmp (priv.bailout) != 0)
00179       /* Error return.  */
00180       return -1;
00181 
00182   /* Don't set "isa" before the setjmp to keep the compiler from griping.  */
00183   isa = xtensa_default_isa;
00184   size = 0;
00185   nslots = 0;
00186 
00187   /* Fetch the maximum size instruction.  */
00188   bytes_fetched = fetch_data (info, memaddr);
00189 
00190   /* Copy the bytes into the decode buffer.  */
00191   memset (insn_buffer, 0, (xtensa_insnbuf_size (isa) *
00192                         sizeof (xtensa_insnbuf_word)));
00193   xtensa_insnbuf_from_chars (isa, insn_buffer, priv.byte_buf, bytes_fetched);
00194 
00195   fmt = xtensa_format_decode (isa, insn_buffer);
00196   if (fmt == XTENSA_UNDEFINED
00197       || ((size = xtensa_format_length (isa, fmt)) > bytes_fetched))
00198     valid_insn = 0;
00199   else
00200     {
00201       /* Make sure all the opcodes are valid.  */
00202       valid_insn = 1;
00203       nslots = xtensa_format_num_slots (isa, fmt);
00204       for (n = 0; n < nslots; n++)
00205        {
00206          xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
00207          if (xtensa_opcode_decode (isa, fmt, n, slot_buffer)
00208              == XTENSA_UNDEFINED)
00209            {
00210              valid_insn = 0;
00211              break;
00212            }
00213        }
00214     }
00215 
00216   if (!valid_insn)
00217     {
00218       (*info->fprintf_func) (info->stream, ".byte %#02x", priv.byte_buf[0]);
00219       return 1;
00220     }
00221 
00222   if (nslots > 1)
00223     (*info->fprintf_func) (info->stream, "{ ");
00224 
00225   first_slot = 1;
00226   for (n = 0; n < nslots; n++)
00227     {
00228       if (first_slot)
00229        first_slot = 0;
00230       else
00231        (*info->fprintf_func) (info->stream, "; ");
00232 
00233       xtensa_format_get_slot (isa, fmt, n, insn_buffer, slot_buffer);
00234       opc = xtensa_opcode_decode (isa, fmt, n, slot_buffer);
00235       (*info->fprintf_func) (info->stream, "%s",
00236                           xtensa_opcode_name (isa, opc));
00237 
00238       /* Print the operands (if any).  */
00239       noperands = xtensa_opcode_num_operands (isa, opc);
00240       first = 1;
00241       for (i = 0; i < noperands; i++)
00242        {
00243          if (xtensa_operand_is_visible (isa, opc, i) == 0)
00244            continue;
00245          if (first)
00246            {
00247              (*info->fprintf_func) (info->stream, "\t");
00248              first = 0;
00249            }
00250          else
00251            (*info->fprintf_func) (info->stream, ", ");
00252          (void) xtensa_operand_get_field (isa, opc, i, fmt, n,
00253                                       slot_buffer, &operand_val);
00254 
00255          print_xtensa_operand (memaddr, info, opc, i, operand_val);
00256        }
00257     }
00258 
00259   if (nslots > 1)
00260     (*info->fprintf_func) (info->stream, " }");
00261 
00262   info->bytes_per_chunk = size;
00263   info->display_endian = info->endian;
00264 
00265   return size;
00266 }
00267