opcodes/
[deliverable/binutils-gdb.git] / opcodes / ppc-dis.c
index e5bae64c2834c1cce34bc411cc288ee4ed79670c..88c4fe7773858d3734fca60f4297f0e404b148a4 100644 (file)
@@ -1,6 +1,6 @@
 /* ppc-dis.c -- Disassemble PowerPC instructions
-   Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+   2008 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support
 
    This file is part of the GNU opcodes library.
    are provided because this file handles disassembly for the PowerPC
    in both big and little endian mode and also for the POWER (RS/6000)
    chip.  */
+static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
+                              ppc_cpu_t);
 
-static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int);
+struct dis_private
+{
+  /* Stash the result of parsing disassembler_options here.  */
+  ppc_cpu_t dialect;
+};
+
+#define POWERPC_DIALECT(INFO) \
+  (((struct dis_private *) ((INFO)->private_data))->dialect)
 
 /* Determine which set of machines to disassemble for.  PPC403/601 or
    BookE.  For convenience, also disassemble instructions supported
    by the AltiVec vector unit.  */
 
 static int
-powerpc_dialect (struct disassemble_info *info)
+powerpc_init_dialect (struct disassemble_info *info)
 {
-  int dialect = PPC_OPCODE_PPC;
+  ppc_cpu_t dialect = PPC_OPCODE_PPC;
+  struct dis_private *priv = calloc (sizeof (*priv), 1);
+
+  if (priv == NULL)
+    return FALSE;
 
   if (BFD_DEFAULT_TARGET_SIZE == 64)
     dialect |= PPC_OPCODE_64;
@@ -50,7 +63,7 @@ powerpc_dialect (struct disassemble_info *info)
     dialect |= PPC_OPCODE_PPCPS;
   else if (info->disassembler_options
       && strstr (info->disassembler_options, "booke") != NULL)
-    dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
+    dialect |= PPC_OPCODE_BOOKE;
   else if ((info->mach == bfd_mach_ppc_e500mc)
           || (info->disassembler_options
               && strstr (info->disassembler_options, "e500mc") != NULL))
@@ -72,7 +85,8 @@ powerpc_dialect (struct disassemble_info *info)
           && strstr (info->disassembler_options, "e300") != NULL)
     dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON;
   else if (info->disassembler_options
-          && strstr (info->disassembler_options, "440") != NULL)
+          && (strstr (info->disassembler_options, "440") != NULL
+              || strstr (info->disassembler_options, "464") != NULL))
     dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_32
       | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI;
   else
@@ -93,7 +107,17 @@ powerpc_dialect (struct disassemble_info *info)
 
   if (info->disassembler_options
       && strstr (info->disassembler_options, "power6") != NULL)
-    dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC;
+    dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
+              | PPC_OPCODE_ALTIVEC;
+
+  if (info->disassembler_options
+      && strstr (info->disassembler_options, "power7") != NULL)
+    dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
+              | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX;
+
+  if (info->disassembler_options
+      && strstr (info->disassembler_options, "vsx") != NULL)
+    dialect |= PPC_OPCODE_VSX;
 
   if (info->disassembler_options
       && strstr (info->disassembler_options, "any") != NULL)
@@ -107,8 +131,10 @@ powerpc_dialect (struct disassemble_info *info)
        dialect |= PPC_OPCODE_64;
     }
 
-  info->private_data = (char *) 0 + dialect;
-  return dialect;
+  info->private_data = priv;
+  POWERPC_DIALECT(info) = dialect;
+
+  return TRUE;
 }
 
 /* Print a big endian PowerPC instruction.  */
@@ -116,8 +142,9 @@ powerpc_dialect (struct disassemble_info *info)
 int
 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
 {
-  int dialect = (char *) info->private_data - (char *) 0;
-  return print_insn_powerpc (memaddr, info, 1, dialect);
+  if (info->private_data == NULL && !powerpc_init_dialect (info))
+    return -1;
+  return print_insn_powerpc (memaddr, info, 1, POWERPC_DIALECT(info));
 }
 
 /* Print a little endian PowerPC instruction.  */
@@ -125,8 +152,9 @@ print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
 int
 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
 {
-  int dialect = (char *) info->private_data - (char *) 0;
-  return print_insn_powerpc (memaddr, info, 0, dialect);
+  if (info->private_data == NULL && !powerpc_init_dialect (info))
+    return -1;
+  return print_insn_powerpc (memaddr, info, 0, POWERPC_DIALECT(info));
 }
 
 /* Print a POWER (RS/6000) instruction.  */
@@ -141,7 +169,7 @@ print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
 
 static long
 operand_value_powerpc (const struct powerpc_operand *operand,
-                      unsigned long insn, int dialect)
+                      unsigned long insn, ppc_cpu_t dialect)
 {
   long value;
   int invalid;
@@ -171,7 +199,7 @@ operand_value_powerpc (const struct powerpc_operand *operand,
 
 static int
 skip_optional_operands (const unsigned char *opindex,
-                       unsigned long insn, int dialect)
+                       unsigned long insn, ppc_cpu_t dialect)
 {
   const struct powerpc_operand *operand;
 
@@ -193,7 +221,7 @@ static int
 print_insn_powerpc (bfd_vma memaddr,
                    struct disassemble_info *info,
                    int bigendian,
-                   int dialect)
+                   ppc_cpu_t dialect)
 {
   bfd_byte buffer[4];
   int status;
@@ -202,9 +230,6 @@ print_insn_powerpc (bfd_vma memaddr,
   const struct powerpc_opcode *opcode_end;
   unsigned long op;
 
-  if (dialect == 0)
-    dialect = powerpc_dialect (info);
-
   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
   if (status != 0)
     {
@@ -241,7 +266,8 @@ print_insn_powerpc (bfd_vma memaddr,
        continue;
 
       if ((insn & opcode->mask) != opcode->opcode
-         || (opcode->flags & dialect) == 0)
+         || (opcode->flags & dialect) == 0
+         || (opcode->deprecated & dialect) != 0)
        continue;
 
       /* Make two passes over the operands.  First see if any of them
@@ -306,6 +332,8 @@ print_insn_powerpc (bfd_vma memaddr,
            (*info->fprintf_func) (info->stream, "f%ld", value);
          else if ((operand->flags & PPC_OPERAND_VR) != 0)
            (*info->fprintf_func) (info->stream, "v%ld", value);
+         else if ((operand->flags & PPC_OPERAND_VSR) != 0)
+           (*info->fprintf_func) (info->stream, "vs%ld", value);
          else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
            (*info->print_address_func) (memaddr + value, info);
          else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
@@ -313,6 +341,12 @@ print_insn_powerpc (bfd_vma memaddr,
          else if ((operand->flags & PPC_OPERAND_CR) == 0
                   || (dialect & PPC_OPCODE_PPC) == 0)
            (*info->fprintf_func) (info->stream, "%ld", value);
+         else if ((operand->flags & PPC_OPERAND_FSL) != 0) 
+           (*info->fprintf_func) (info->stream, "fsl%ld", value);
+         else if ((operand->flags & PPC_OPERAND_FCR) != 0)
+           (*info->fprintf_func) (info->stream, "fcr%ld", value);
+         else if ((operand->flags & PPC_OPERAND_UDI) != 0)
+           (*info->fprintf_func) (info->stream, "%ld", value);
          else
            {
              if (operand->bitm == 7)
@@ -369,16 +403,19 @@ print_ppc_disassembler_options (FILE *stream)
 The following PPC specific disassembler options are supported for use with\n\
 the -M switch:\n");
 
-  fprintf (stream, "  booke|booke32|booke64    Disassemble the BookE instructions\n");
+  fprintf (stream, "  booke                    Disassemble the BookE instructions\n");
   fprintf (stream, "  e300                     Disassemble the e300 instructions\n");
   fprintf (stream, "  e500|e500x2              Disassemble the e500 instructions\n");
   fprintf (stream, "  e500mc                   Disassemble the e500mc instructions\n");
   fprintf (stream, "  440                      Disassemble the 440 instructions\n");
+  fprintf (stream, "  464                      Disassemble the 464 instructions\n");
   fprintf (stream, "  efs                      Disassemble the EFS instructions\n");
   fprintf (stream, "  ppcps                    Disassemble the PowerPC paired singles instructions\n");
   fprintf (stream, "  power4                   Disassemble the Power4 instructions\n");
   fprintf (stream, "  power5                   Disassemble the Power5 instructions\n");
   fprintf (stream, "  power6                   Disassemble the Power6 instructions\n");
+  fprintf (stream, "  power7                   Disassemble the Power7 instructions\n");
+  fprintf (stream, "  vsx                      Disassemble the Vector-Scalar (VSX) instructions\n");
   fprintf (stream, "  32                       Do not disassemble 64-bit instructions\n");
   fprintf (stream, "  64                       Allow disassembly of 64-bit instructions\n");
 }
This page took 0.02557 seconds and 4 git commands to generate.