* Makefile.am ($(srcdir)/ia64-asmtab.c): Remove line continuation.
[deliverable/binutils-gdb.git] / opcodes / ppc-dis.c
index 861881bb81cbb9c3d15f715e5915017ad4d8b9f3..7d4f9e1dc97c488b96e70ad8a74ef0e69c38a4a2 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;
@@ -51,6 +64,12 @@ powerpc_dialect (struct disassemble_info *info)
   else if (info->disassembler_options
       && strstr (info->disassembler_options, "booke") != NULL)
     dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
+  else if ((info->mach == bfd_mach_ppc_e500mc)
+          || (info->disassembler_options
+              && strstr (info->disassembler_options, "e500mc") != NULL))
+    dialect |= (PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
+               | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+               | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
   else if ((info->mach == bfd_mach_ppc_e500)
           || (info->disassembler_options
               && strstr (info->disassembler_options, "e500") != NULL))
@@ -58,7 +77,7 @@ powerpc_dialect (struct disassemble_info *info)
                | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
                | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
-               | PPC_OPCODE_RFMCI);
+               | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
   else if (info->disassembler_options
           && strstr (info->disassembler_options, "efs") != NULL)
     dialect |= PPC_OPCODE_EFS;
@@ -66,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
@@ -101,8 +121,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.  */
@@ -110,8 +132,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.  */
@@ -119,8 +142,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.  */
@@ -135,7 +159,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;
@@ -165,7 +189,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;
 
@@ -187,7 +211,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;
@@ -196,9 +220,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)
     {
@@ -307,6 +328,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)
@@ -366,7 +393,9 @@ the -M switch:\n");
   fprintf (stream, "  booke|booke32|booke64    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");
This page took 0.025131 seconds and 4 git commands to generate.