Back to index

cell-binutils  2.17cvs20070401
ppc-dis.c
Go to the documentation of this file.
00001 /* ppc-dis.c -- Disassemble PowerPC instructions
00002    Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
00003    Free Software Foundation, Inc.
00004    Written by Ian Lance Taylor, Cygnus Support
00005 
00006 This file is part of GDB, GAS, and the GNU binutils.
00007 
00008 GDB, GAS, and the GNU binutils are free software; you can redistribute
00009 them and/or modify them under the terms of the GNU General Public
00010 License as published by the Free Software Foundation; either version
00011 2, or (at your option) any later version.
00012 
00013 GDB, GAS, and the GNU binutils are distributed in the hope that they
00014 will be useful, but WITHOUT ANY WARRANTY; without even the implied
00015 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
00016 the GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this file; see the file COPYING.  If not, write to the Free
00020 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 #include <stdio.h>
00023 #include "sysdep.h"
00024 #include "dis-asm.h"
00025 #include "opcode/ppc.h"
00026 
00027 /* This file provides several disassembler functions, all of which use
00028    the disassembler interface defined in dis-asm.h.  Several functions
00029    are provided because this file handles disassembly for the PowerPC
00030    in both big and little endian mode and also for the POWER (RS/6000)
00031    chip.  */
00032 
00033 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int);
00034 
00035 /* Determine which set of machines to disassemble for.  PPC403/601 or
00036    BookE.  For convenience, also disassemble instructions supported
00037    by the AltiVec vector unit.  */
00038 
00039 static int
00040 powerpc_dialect (struct disassemble_info *info)
00041 {
00042   int dialect = PPC_OPCODE_PPC;
00043 
00044   if (BFD_DEFAULT_TARGET_SIZE == 64)
00045     dialect |= PPC_OPCODE_64;
00046 
00047   if (info->disassembler_options
00048       && strstr (info->disassembler_options, "booke") != NULL)
00049     dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
00050   else if ((info->mach == bfd_mach_ppc_e500)
00051           || (info->disassembler_options
00052               && strstr (info->disassembler_options, "e500") != NULL))
00053     dialect |= (PPC_OPCODE_BOOKE
00054               | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
00055               | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
00056               | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
00057               | PPC_OPCODE_RFMCI);
00058   else if (info->disassembler_options
00059           && strstr (info->disassembler_options, "efs") != NULL)
00060     dialect |= PPC_OPCODE_EFS;
00061   else if (info->disassembler_options
00062           && strstr (info->disassembler_options, "e300") != NULL)
00063     dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON;
00064   else if (info->disassembler_options
00065           && strstr (info->disassembler_options, "440") != NULL)
00066     dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_32
00067       | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI;
00068   else
00069     dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
00070               | PPC_OPCODE_COMMON | PPC_OPCODE_ALTIVEC);
00071 
00072   if (info->disassembler_options
00073       && strstr (info->disassembler_options, "power4") != NULL)
00074     dialect |= PPC_OPCODE_POWER4;
00075 
00076   if (info->disassembler_options
00077       && strstr (info->disassembler_options, "power5") != NULL)
00078     dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5;
00079 
00080   if (info->disassembler_options
00081       && strstr (info->disassembler_options, "cell") != NULL)
00082     dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC;
00083 
00084   if (info->disassembler_options
00085       && strstr (info->disassembler_options, "power6") != NULL)
00086     dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC;
00087 
00088   if (info->disassembler_options
00089       && strstr (info->disassembler_options, "any") != NULL)
00090     dialect |= PPC_OPCODE_ANY;
00091 
00092   if (info->disassembler_options)
00093     {
00094       if (strstr (info->disassembler_options, "32") != NULL)
00095        dialect &= ~PPC_OPCODE_64;
00096       else if (strstr (info->disassembler_options, "64") != NULL)
00097        dialect |= PPC_OPCODE_64;
00098     }
00099 
00100   info->private_data = (char *) 0 + dialect;
00101   return dialect;
00102 }
00103 
00104 /* Print a big endian PowerPC instruction.  */
00105 
00106 int
00107 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
00108 {
00109   int dialect = (char *) info->private_data - (char *) 0;
00110   return print_insn_powerpc (memaddr, info, 1, dialect);
00111 }
00112 
00113 /* Print a little endian PowerPC instruction.  */
00114 
00115 int
00116 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
00117 {
00118   int dialect = (char *) info->private_data - (char *) 0;
00119   return print_insn_powerpc (memaddr, info, 0, dialect);
00120 }
00121 
00122 /* Print a POWER (RS/6000) instruction.  */
00123 
00124 int
00125 print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
00126 {
00127   return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
00128 }
00129 
00130 /* Print a PowerPC or POWER instruction.  */
00131 
00132 static int
00133 print_insn_powerpc (bfd_vma memaddr,
00134                   struct disassemble_info *info,
00135                   int bigendian,
00136                   int dialect)
00137 {
00138   bfd_byte buffer[4];
00139   int status;
00140   unsigned long insn;
00141   const struct powerpc_opcode *opcode;
00142   const struct powerpc_opcode *opcode_end;
00143   unsigned long op;
00144 
00145   if (dialect == 0)
00146     dialect = powerpc_dialect (info);
00147 
00148   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
00149   if (status != 0)
00150     {
00151       (*info->memory_error_func) (status, memaddr, info);
00152       return -1;
00153     }
00154 
00155   if (bigendian)
00156     insn = bfd_getb32 (buffer);
00157   else
00158     insn = bfd_getl32 (buffer);
00159 
00160   /* Get the major opcode of the instruction.  */
00161   op = PPC_OP (insn);
00162 
00163   /* Find the first match in the opcode table.  We could speed this up
00164      a bit by doing a binary search on the major opcode.  */
00165   opcode_end = powerpc_opcodes + powerpc_num_opcodes;
00166  again:
00167   for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
00168     {
00169       unsigned long table_op;
00170       const unsigned char *opindex;
00171       const struct powerpc_operand *operand;
00172       int invalid;
00173       int need_comma;
00174       int need_paren;
00175 
00176       table_op = PPC_OP (opcode->opcode);
00177       if (op < table_op)
00178        break;
00179       if (op > table_op)
00180        continue;
00181 
00182       if ((insn & opcode->mask) != opcode->opcode
00183          || (opcode->flags & dialect) == 0)
00184        continue;
00185 
00186       /* Make two passes over the operands.  First see if any of them
00187         have extraction functions, and, if they do, make sure the
00188         instruction is valid.  */
00189       invalid = 0;
00190       for (opindex = opcode->operands; *opindex != 0; opindex++)
00191        {
00192          operand = powerpc_operands + *opindex;
00193          if (operand->extract)
00194            (*operand->extract) (insn, dialect, &invalid);
00195        }
00196       if (invalid)
00197        continue;
00198 
00199       /* The instruction is valid.  */
00200       if (opcode->operands[0] != 0)
00201        (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
00202       else
00203        (*info->fprintf_func) (info->stream, "%s", opcode->name);
00204 
00205       /* Now extract and print the operands.  */
00206       need_comma = 0;
00207       need_paren = 0;
00208       for (opindex = opcode->operands; *opindex != 0; opindex++)
00209        {
00210          long value;
00211 
00212          operand = powerpc_operands + *opindex;
00213 
00214          /* Operands that are marked FAKE are simply ignored.  We
00215             already made sure that the extract function considered
00216             the instruction to be valid.  */
00217          if ((operand->flags & PPC_OPERAND_FAKE) != 0)
00218            continue;
00219 
00220          /* Extract the value from the instruction.  */
00221          if (operand->extract)
00222            value = (*operand->extract) (insn, dialect, &invalid);
00223          else
00224            {
00225              value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
00226              if ((operand->flags & PPC_OPERAND_SIGNED) != 0
00227                 && (value & (1 << (operand->bits - 1))) != 0)
00228               value -= 1 << operand->bits;
00229            }
00230 
00231          /* If the operand is optional, and the value is zero, don't
00232             print anything.  */
00233          if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
00234              && (operand->flags & PPC_OPERAND_NEXT) == 0
00235              && value == 0)
00236            continue;
00237 
00238          if (need_comma)
00239            {
00240              (*info->fprintf_func) (info->stream, ",");
00241              need_comma = 0;
00242            }
00243 
00244          /* Print the operand as directed by the flags.  */
00245          if ((operand->flags & PPC_OPERAND_GPR) != 0
00246              || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
00247            (*info->fprintf_func) (info->stream, "r%ld", value);
00248          else if ((operand->flags & PPC_OPERAND_FPR) != 0)
00249            (*info->fprintf_func) (info->stream, "f%ld", value);
00250          else if ((operand->flags & PPC_OPERAND_VR) != 0)
00251            (*info->fprintf_func) (info->stream, "v%ld", value);
00252          else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
00253            (*info->print_address_func) (memaddr + value, info);
00254          else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
00255            (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
00256          else if ((operand->flags & PPC_OPERAND_CR) == 0
00257                  || (dialect & PPC_OPCODE_PPC) == 0)
00258            (*info->fprintf_func) (info->stream, "%ld", value);
00259          else
00260            {
00261              if (operand->bits == 3)
00262               (*info->fprintf_func) (info->stream, "cr%ld", value);
00263              else
00264               {
00265                 static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
00266                 int cr;
00267                 int cc;
00268 
00269                 cr = value >> 2;
00270                 if (cr != 0)
00271                   (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
00272                 cc = value & 3;
00273                 (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
00274               }
00275            }
00276 
00277          if (need_paren)
00278            {
00279              (*info->fprintf_func) (info->stream, ")");
00280              need_paren = 0;
00281            }
00282 
00283          if ((operand->flags & PPC_OPERAND_PARENS) == 0)
00284            need_comma = 1;
00285          else
00286            {
00287              (*info->fprintf_func) (info->stream, "(");
00288              need_paren = 1;
00289            }
00290        }
00291 
00292       /* We have found and printed an instruction; return.  */
00293       return 4;
00294     }
00295 
00296   if ((dialect & PPC_OPCODE_ANY) != 0)
00297     {
00298       dialect = ~PPC_OPCODE_ANY;
00299       goto again;
00300     }
00301 
00302   /* We could not find a match.  */
00303   (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
00304 
00305   return 4;
00306 }
00307 
00308 void
00309 print_ppc_disassembler_options (FILE *stream)
00310 {
00311   fprintf (stream, "\n\
00312 The following PPC specific disassembler options are supported for use with\n\
00313 the -M switch:\n");
00314 
00315   fprintf (stream, "  booke|booke32|booke64    Disassemble the BookE instructions\n");
00316   fprintf (stream, "  e300                     Disassemble the e300 instructions\n");
00317   fprintf (stream, "  e500|e500x2              Disassemble the e500 instructions\n");
00318   fprintf (stream, "  440                      Disassemble the 440 instructions\n");
00319   fprintf (stream, "  efs                      Disassemble the EFS instructions\n");
00320   fprintf (stream, "  power4                   Disassemble the Power4 instructions\n");
00321   fprintf (stream, "  power5                   Disassemble the Power5 instructions\n");
00322   fprintf (stream, "  power6                   Disassemble the Power6 instructions\n");
00323   fprintf (stream, "  32                       Do not disassemble 64-bit instructions\n");
00324   fprintf (stream, "  64                       Allow disassembly of 64-bit instructions\n");
00325 }