Sync libiberty with upstream GCC.
[binutils-gdb.git] / opcodes / ppc-dis.c
index f3db0620956224f751179af35549b421c9443042..5e89c50faa6d0cc5a586244e60573f490de8952e 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "sysdep.h"
 #include <stdio.h>
-#include "dis-asm.h"
+#include "disassemble.h"
 #include "elf-bfd.h"
 #include "elf/ppc.h"
 #include "opintl.h"
@@ -73,8 +73,8 @@ struct ppc_mopt ppc_opts[] = {
   { "464",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
                | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
     0 },
-  { "476",     (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_440
-               | PPC_OPCODE_476 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
+  { "476",     (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476
+               | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
     0 },
   { "601",     PPC_OPCODE_PPC | PPC_OPCODE_601,
     0 },
@@ -106,7 +106,7 @@ struct ppc_mopt ppc_opts[] = {
     0 },
   { "altivec", PPC_OPCODE_PPC,
     PPC_OPCODE_ALTIVEC },
-  { "any",     0,
+  { "any",     PPC_OPCODE_PPC,
     PPC_OPCODE_ANY },
   { "booke",   PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
     0 },
@@ -141,13 +141,12 @@ struct ppc_mopt ppc_opts[] = {
   { "e5500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
                | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
-               | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
-               | PPC_OPCODE_POWER7),
+               | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
     0 },
   { "e6500",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
                | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
-               | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_E6500 | PPC_OPCODE_POWER4
+               | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
                | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
     0 },
   { "e500x2",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
@@ -171,14 +170,13 @@ struct ppc_mopt ppc_opts[] = {
     0 },
   { "power8",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
                | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
-               | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
-               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
+               | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
+               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
     0 },
   { "power9",  (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
                | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
                | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
-               | PPC_OPCODE_HTM | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
-               | PPC_OPCODE_VSX | PPC_OPCODE_VSX3 ),
+               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
     0 },
   { "ppc",     PPC_OPCODE_PPC,
     0 },
@@ -215,17 +213,18 @@ struct ppc_mopt ppc_opts[] = {
     0 },
   { "pwr8",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
                | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
-               | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_HTM
-               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 | PPC_OPCODE_VSX),
+               | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
+               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
     0 },
   { "pwr9",    (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
                | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
                | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
-               | PPC_OPCODE_HTM | PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2
-               | PPC_OPCODE_VSX | PPC_OPCODE_VSX3 ),
+               | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
     0 },
   { "pwrx",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
     0 },
+  { "raw",     PPC_OPCODE_PPC,
+    PPC_OPCODE_RAW },
   { "spe",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
     PPC_OPCODE_SPE },
   { "titan",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
@@ -238,8 +237,6 @@ struct ppc_mopt ppc_opts[] = {
     PPC_OPCODE_VLE },
   { "vsx",     PPC_OPCODE_PPC,
     PPC_OPCODE_VSX },
-  { "htm",     PPC_OPCODE_PPC,
-    PPC_OPCODE_HTM },
 };
 
 /* Switch between Booke and VLE dialects for interlinked dumps.  */
@@ -342,7 +339,7 @@ powerpc_init_dialect (struct disassemble_info *info)
       break;
     }
 
-  char *opt;
+  const char *opt;
   FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
     {
       ppc_cpu_t new_cpu = 0;
@@ -494,14 +491,12 @@ skip_optional_operands (const unsigned char *opindex,
   return 1;
 }
 
-/* Find a match for INSN in the opcode table, given machine DIALECT.
-   A DIALECT of -1 is special, matching all machine opcode variations.  */
+/* Find a match for INSN in the opcode table, given machine DIALECT.  */
 
 static const struct powerpc_opcode *
 lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
 {
-  const struct powerpc_opcode *opcode;
-  const struct powerpc_opcode *opcode_end;
+  const struct powerpc_opcode *opcode, *opcode_end, *last;
   unsigned long op;
 
   /* Get the major opcode of the instruction.  */
@@ -509,6 +504,7 @@ lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
 
   /* Find the first match in the opcode table for this major opcode.  */
   opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
+  last = NULL;
   for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
        opcode < opcode_end;
        ++opcode)
@@ -518,7 +514,7 @@ lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
       int invalid;
 
       if ((insn & opcode->mask) != opcode->opcode
-         || (dialect != (ppc_cpu_t) -1
+         || ((dialect & PPC_OPCODE_ANY) == 0
              && ((opcode->flags & dialect) == 0
                  || (opcode->deprecated & dialect) != 0)))
        continue;
@@ -534,10 +530,16 @@ lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
       if (invalid)
        continue;
 
-      return opcode;
+      if ((dialect & PPC_OPCODE_RAW) == 0)
+       return opcode;
+
+      /* The raw machine insn is one that is not a specialization.  */
+      if (last == NULL
+         || (last->mask & ~opcode->mask) != 0)
+       last = opcode;
     }
 
-  return NULL;
+  return last;
 }
 
 /* Find a match for INSN in the VLE opcode table.  */
@@ -645,9 +647,9 @@ print_insn_powerpc (bfd_vma memaddr,
        insn_is_short = PPC_OP_SE_VLE(opcode->mask);
     }
   if (opcode == NULL)
-    opcode = lookup_powerpc (insn, dialect);
+    opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
   if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
-    opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
+    opcode = lookup_powerpc (insn, dialect);
 
   if (opcode != NULL)
     {