gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / opcodes / ppc-dis.c
index 41dce276bfa4a14a8dd11ae4e875bbe3a4e10c98..162f770697514b8180555a25cb9bb2ebe5a65cb5 100644 (file)
@@ -1,6 +1,5 @@
 /* ppc-dis.c -- Disassemble PowerPC instructions
-   Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-   2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 1994-2020 Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support
 
    This file is part of the GNU opcodes library.
 
 #include "sysdep.h"
 #include <stdio.h>
-#include "dis-asm.h"
+#include "disassemble.h"
 #include "elf-bfd.h"
 #include "elf/ppc.h"
 #include "opintl.h"
 #include "opcode/ppc.h"
+#include "libiberty.h"
 
 /* This file provides several disassembler functions, all of which use
    the disassembler interface defined in dis-asm.h.  Several functions
@@ -40,21 +40,32 @@ struct dis_private
 {
   /* Stash the result of parsing disassembler_options here.  */
   ppc_cpu_t dialect;
-} private;
+};
 
 #define POWERPC_DIALECT(INFO) \
   (((struct dis_private *) ((INFO)->private_data))->dialect)
 
 struct ppc_mopt {
+  /* Option string, without -m or -M prefix.  */
   const char *opt;
+  /* CPU option flags.  */
   ppc_cpu_t cpu;
+  /* Flags that should stay on, even when combined with another cpu
+     option.  This should only be used for generic options like
+     "-many" or "-maltivec" where it is reasonable to add some
+     capability to another cpu selection.  The added flags are sticky
+     so that, for example, "-many -me500" and "-me500 -many" result in
+     the same assembler or disassembler behaviour.  Do not use
+     "sticky" for specific cpus, as this will prevent that cpu's flags
+     from overriding the defaults set in powerpc_init_dialect or a
+     prior -m option.  */
   ppc_cpu_t sticky;
 };
 
 struct ppc_mopt ppc_opts[] = {
-  { "403",     (PPC_OPCODE_PPC | PPC_OPCODE_403),
+  { "403",     PPC_OPCODE_PPC | PPC_OPCODE_403,
     0 },
-  { "405",     (PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405),
+  { "405",     PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
     0 },
   { "440",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
                | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
@@ -62,45 +73,61 @@ 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),
+  { "601",     PPC_OPCODE_PPC | PPC_OPCODE_601,
     0 },
-  { "603",     (PPC_OPCODE_PPC),
+  { "603",     PPC_OPCODE_PPC,
     0 },
-  { "604",     (PPC_OPCODE_PPC),
+  { "604",     PPC_OPCODE_PPC,
     0 },
-  { "620",     (PPC_OPCODE_PPC | PPC_OPCODE_64),
+  { "620",     PPC_OPCODE_PPC | PPC_OPCODE_64,
     0 },
-  { "7400",    (PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC),
+  { "7400",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
     0 },
-  { "7410",    (PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC),
+  { "7410",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
     0 },
-  { "7450",    (PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC),
+  { "7450",    PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
     0 },
-  { "7455",    (PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC),
+  { "7455",    PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
     0 },
-  { "750cl",   (PPC_OPCODE_PPC | PPC_OPCODE_PPCPS)
+  { "750cl",   PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
+    , 0 },
+  { "gekko",   PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
+    , 0 },
+  { "broadway", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
     , 0 },
+  { "821",     PPC_OPCODE_PPC | PPC_OPCODE_860,
+    0 },
+  { "850",     PPC_OPCODE_PPC | PPC_OPCODE_860,
+    0 },
+  { "860",     PPC_OPCODE_PPC | PPC_OPCODE_860,
+    0 },
   { "a2",      (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
                | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
                | PPC_OPCODE_A2),
     0 },
-  { "altivec", (PPC_OPCODE_PPC),
-    PPC_OPCODE_ALTIVEC | PPC_OPCODE_ALTIVEC2 },
-  { "any",     0,
+  { "altivec", PPC_OPCODE_PPC,
+    PPC_OPCODE_ALTIVEC },
+  { "any",     PPC_OPCODE_PPC,
     PPC_OPCODE_ANY },
-  { "booke",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE),
+  { "booke",   PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
     0 },
-  { "booke32", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE),
+  { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
     0 },
   { "cell",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
                | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
     0 },
-  { "com",     (PPC_OPCODE_COMMON),
+  { "com",     PPC_OPCODE_COMMON,
     0 },
-  { "e300",    (PPC_OPCODE_PPC | PPC_OPCODE_E300),
+  { "e200z4",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
+               | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+               | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
+               | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4
+               | PPC_OPCODE_EFS2 | PPC_OPCODE_LSP),
+    0 },
+  { "e300",    PPC_OPCODE_PPC | PPC_OPCODE_E300,
     0 },
   { "e500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
                | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
@@ -119,13 +146,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
@@ -133,9 +159,11 @@ struct ppc_mopt ppc_opts[] = {
                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
                | PPC_OPCODE_E500),
     0 },
-  { "efs",     (PPC_OPCODE_PPC | PPC_OPCODE_EFS),
+  { "efs",     PPC_OPCODE_PPC | PPC_OPCODE_EFS,
+    0 },
+  { "efs2",    PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2,
     0 },
-  { "power4",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4),
+  { "power4",  PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
     0 },
   { "power5",  (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
                | PPC_OPCODE_POWER5),
@@ -147,21 +175,45 @@ struct ppc_mopt ppc_opts[] = {
                | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
                | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
     0 },
-  { "ppc",     (PPC_OPCODE_PPC),
+  { "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_ALTIVEC | PPC_OPCODE_VSX),
     0 },
-  { "ppc32",   (PPC_OPCODE_PPC),
+  { "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_ALTIVEC | PPC_OPCODE_VSX),
+    0 },
+  { "power10", (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_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
+    0 },
+  { "future",  (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_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
+    0 },
+  { "ppc",     PPC_OPCODE_PPC,
     0 },
-  { "ppc64",   (PPC_OPCODE_PPC | PPC_OPCODE_64),
+  { "ppc32",   PPC_OPCODE_PPC,
     0 },
-  { "ppc64bridge", (PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE),
+  { "32",      PPC_OPCODE_PPC,
     0 },
-  { "ppcps",   (PPC_OPCODE_PPC | PPC_OPCODE_PPCPS),
+  { "ppc64",   PPC_OPCODE_PPC | PPC_OPCODE_64,
     0 },
-  { "pwr",     (PPC_OPCODE_POWER),
+  { "64",      PPC_OPCODE_PPC | PPC_OPCODE_64,
     0 },
-  { "pwr2",    (PPC_OPCODE_POWER | PPC_OPCODE_POWER2),
+  { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
     0 },
-  { "pwr4",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4),
+  { "ppcps",   PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
+    0 },
+  { "pwr",     PPC_OPCODE_POWER,
+    0 },
+  { "pwr2",    PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
+    0 },
+  { "pwr4",    PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
     0 },
   { "pwr5",    (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
                | PPC_OPCODE_POWER5),
@@ -176,16 +228,33 @@ struct ppc_mopt ppc_opts[] = {
                | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
                | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
     0 },
-  { "pwrx",    (PPC_OPCODE_POWER | PPC_OPCODE_POWER2),
+  { "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_ALTIVEC | PPC_OPCODE_VSX),
     0 },
-  { "spe",     (PPC_OPCODE_PPC | PPC_OPCODE_EFS),
+  { "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_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 },
+  { "spe2",     PPC_OPCODE_PPC | PPC_OPCODE_EFS | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE,
+    PPC_OPCODE_SPE2 },
   { "titan",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
                | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
     0 },
-  { "vle",     (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_VLE),
+  { "vle",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
+               | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+               | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
+               | PPC_OPCODE_LSP | PPC_OPCODE_EFS2 | PPC_OPCODE_SPE2),
     PPC_OPCODE_VLE },
-  { "vsx",     (PPC_OPCODE_PPC),
+  { "vsx",     PPC_OPCODE_PPC,
     PPC_OPCODE_VSX },
 };
 
@@ -195,11 +264,12 @@ get_powerpc_dialect (struct disassemble_info *info)
 {
   ppc_cpu_t dialect = 0;
 
-  dialect = POWERPC_DIALECT (info);
+  if (info->private_data)
+    dialect = POWERPC_DIALECT (info);
 
   /* Disassemble according to the section headers flags for VLE-mode.  */
   if (dialect & PPC_OPCODE_VLE
-      && info->section->owner != NULL
+      && info->section != NULL && info->section->owner != NULL
       && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
       && elf_object_id (info->section->owner) == PPC32_ELF_DATA
       && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
@@ -215,8 +285,8 @@ ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
 {
   unsigned int i;
 
-  for (i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++)
-    if (strcmp (ppc_opts[i].opt, arg) == 0)
+  for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
+    if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
       {
        if (ppc_opts[i].sticky)
          {
@@ -227,7 +297,7 @@ ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
        ppc_cpu = ppc_opts[i].cpu;
        break;
       }
-  if (i >= sizeof (ppc_opts) / sizeof (ppc_opts[0]))
+  if (i >= ARRAY_SIZE (ppc_opts))
     return 0;
 
   ppc_cpu |= *sticky;
@@ -241,105 +311,88 @@ powerpc_init_dialect (struct disassemble_info *info)
 {
   ppc_cpu_t dialect = 0;
   ppc_cpu_t sticky = 0;
-  char *arg;
   struct dis_private *priv = calloc (sizeof (*priv), 1);
 
   if (priv == NULL)
-    priv = &private;
+    return;
 
   switch (info->mach)
     {
     case bfd_mach_ppc_403:
     case bfd_mach_ppc_403gc:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_403);
+      dialect = ppc_parse_cpu (dialect, &sticky, "403");
       break;
     case bfd_mach_ppc_405:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405);
+      dialect = ppc_parse_cpu (dialect, &sticky, "405");
       break;
     case bfd_mach_ppc_601:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_601);
+      dialect = ppc_parse_cpu (dialect, &sticky, "601");
+      break;
+    case bfd_mach_ppc_750:
+      dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
       break;
     case bfd_mach_ppc_a35:
     case bfd_mach_ppc_rs64ii:
     case bfd_mach_ppc_rs64iii:
-      dialect = (PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_64);
+      dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
       break;
     case bfd_mach_ppc_e500:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
-                | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
-                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
-                | PPC_OPCODE_E500);
+      dialect = ppc_parse_cpu (dialect, &sticky, "e500");
       break;
     case bfd_mach_ppc_e500mc:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
-                | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
-                | PPC_OPCODE_E500MC);
+      dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
       break;
     case bfd_mach_ppc_e500mc64:
-      dialect = (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_POWER5
-                | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7);
+      dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
       break;
     case bfd_mach_ppc_e5500:
-      dialect = (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);
+      dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
       break;
     case bfd_mach_ppc_e6500:
-      dialect = (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_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7);
+      dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
       break;
     case bfd_mach_ppc_titan:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
-                | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN);
+      dialect = ppc_parse_cpu (dialect, &sticky, "titan");
       break;
     case bfd_mach_ppc_vle:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_VLE);
+      dialect = ppc_parse_cpu (dialect, &sticky, "vle");
       break;
     default:
-      dialect = (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
-                | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
-                | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
-                | PPC_OPCODE_ANY);
+      if (info->arch == bfd_arch_powerpc)
+       dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
+      else
+       dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
+      break;
     }
 
-  arg = info->disassembler_options;
-  while (arg != NULL)
+  const char *opt;
+  FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
     {
       ppc_cpu_t new_cpu = 0;
-      char *end = strchr (arg, ',');
-
-      if (end != NULL)
-       *end = 0;
 
-      if ((new_cpu = ppc_parse_cpu (dialect, &sticky, arg)) != 0)
-       dialect = new_cpu;
-      else if (strcmp (arg, "32") == 0)
+      if (disassembler_options_cmp (opt, "32") == 0)
        dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
-      else if (strcmp (arg, "64") == 0)
+      else if (disassembler_options_cmp (opt, "64") == 0)
        dialect |= PPC_OPCODE_64;
+      else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
+       dialect = new_cpu;
       else
-       fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), arg);
-
-      if (end != NULL)
-       *end++ = ',';
-      arg = end;
+       /* xgettext: c-format */
+       opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt);
     }
 
   info->private_data = priv;
   POWERPC_DIALECT(info) = dialect;
 }
 
-#define PPC_OPCD_SEGS 64
-static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS+1];
-#define VLE_OPCD_SEGS 32
-static unsigned short vle_opcd_indices[VLE_OPCD_SEGS+1];
+#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
+static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
+#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
+static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
+#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
+static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
+#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
+static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
 
 /* Calculate opcode table indices to speed up disassembly,
    and init dialect.  */
@@ -347,44 +400,54 @@ static unsigned short vle_opcd_indices[VLE_OPCD_SEGS+1];
 void
 disassemble_init_powerpc (struct disassemble_info *info)
 {
-  int i;
-  unsigned short last;
-
-  i = powerpc_num_opcodes;
-  while (--i >= 0)
+  if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
     {
-      unsigned op = PPC_OP (powerpc_opcodes[i].opcode);
-
-      powerpc_opcd_indices[op] = i;
-    }
+      unsigned seg, idx, op;
 
-  last = powerpc_num_opcodes;
-  for (i = PPC_OPCD_SEGS; i > 0; --i)
-    {
-      if (powerpc_opcd_indices[i] == 0)
-       powerpc_opcd_indices[i] = last;
-      last = powerpc_opcd_indices[i];
-    }
+      /* PPC opcodes */
+      for (seg = 0, idx = 0; seg <= PPC_OPCD_SEGS; seg++)
+       {
+         powerpc_opcd_indices[seg] = idx;
+         for (; idx < powerpc_num_opcodes; idx++)
+           if (seg < PPC_OP (powerpc_opcodes[idx].opcode))
+             break;
+       }
 
-  i = vle_num_opcodes;
-  while (--i >= 0)
-    {
-      unsigned op = VLE_OP (vle_opcodes[i].opcode, vle_opcodes[i].mask);
-      unsigned seg = VLE_OP_TO_SEG (op);
+      /* 64-bit prefix opcodes */
+      for (seg = 0, idx = 0; seg <= PREFIX_OPCD_SEGS; seg++)
+       {
+         prefix_opcd_indices[seg] = idx;
+         for (; idx < prefix_num_opcodes; idx++)
+           if (seg < PPC_PREFIX_SEG (prefix_opcodes[idx].opcode))
+             break;
+       }
 
-      vle_opcd_indices[seg] = i;
-    }
+      /* VLE opcodes */
+      for (seg = 0, idx = 0; seg <= VLE_OPCD_SEGS; seg++)
+       {
+         vle_opcd_indices[seg] = idx;
+         for (; idx < vle_num_opcodes; idx++)
+           {
+             op = VLE_OP (vle_opcodes[idx].opcode, vle_opcodes[idx].mask);
+             if (seg < VLE_OP_TO_SEG (op))
+               break;
+           }
+       }
 
-  last = vle_num_opcodes;
-  for (i = VLE_OPCD_SEGS; i > 0; --i)
-    {
-      if (vle_opcd_indices[i] == 0)
-       vle_opcd_indices[i] = last;
-      last = vle_opcd_indices[i];
+      /* SPE2 opcodes */
+      for (seg = 0, idx = 0; seg <= SPE2_OPCD_SEGS; seg++)
+       {
+         spe2_opcd_indices[seg] = idx;
+         for (; idx < spe2_num_opcodes; idx++)
+           {
+             op = SPE2_XOP (spe2_opcodes[idx].opcode);
+             if (seg < SPE2_XOP_TO_SEG (op))
+               break;
+           }
+       }
     }
 
-  if (info->arch == bfd_arch_powerpc)
-    powerpc_init_dialect (info);
+  powerpc_init_dialect (info);
 }
 
 /* Print a big endian PowerPC instruction.  */
@@ -403,22 +466,14 @@ print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
   return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
 }
 
-/* Print a POWER (RS/6000) instruction.  */
-
-int
-print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
-{
-  return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
-}
-
 /* Extract the operand value from the PowerPC or POWER instruction.  */
 
-static long
+static int64_t
 operand_value_powerpc (const struct powerpc_operand *operand,
-                      unsigned long insn, ppc_cpu_t dialect)
+                      uint64_t insn, ppc_cpu_t dialect)
 {
-  long value;
-  int invalid;
+  int64_t value;
+  int invalid = 0;
   /* Extract the value from the instruction.  */
   if (operand->extract)
     value = (*operand->extract) (insn, dialect, &invalid);
@@ -432,7 +487,7 @@ operand_value_powerpc (const struct powerpc_operand *operand,
        {
          /* BITM is always some number of zeros followed by some
             number of ones, followed by some number of zeros.  */
-         unsigned long top = operand->bitm;
+         uint64_t top = operand->bitm;
          /* top & -top gives the rightmost 1 bit, so this
             fills in any trailing zeros.  */
          top |= (top & -top) - 1;
@@ -446,32 +501,38 @@ operand_value_powerpc (const struct powerpc_operand *operand,
 
 /* Determine whether the optional operand(s) should be printed.  */
 
-static int
+static bfd_boolean
 skip_optional_operands (const unsigned char *opindex,
-                       unsigned long insn, ppc_cpu_t dialect)
+                       uint64_t insn, ppc_cpu_t dialect)
 {
   const struct powerpc_operand *operand;
+  int num_optional;
 
-  for (; *opindex != 0; opindex++)
+  for (num_optional = 0; *opindex != 0; opindex++)
     {
       operand = &powerpc_operands[*opindex];
-      if ((operand->flags & PPC_OPERAND_NEXT) != 0
-         || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
-             && operand_value_powerpc (operand, insn, dialect) != 0))
-       return 0;
+      if ((operand->flags & PPC_OPERAND_NEXT) != 0)
+       return FALSE;
+      if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
+       {
+         /* Negative count is used as a flag to extract function.  */
+         --num_optional;
+         if (operand_value_powerpc (operand, insn, dialect)
+             != ppc_optional_operand_value (operand, insn, dialect,
+                                            num_optional))
+           return FALSE;
+       }
     }
 
-  return 1;
+  return TRUE;
 }
 
-/* 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)
+lookup_powerpc (uint64_t 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.  */
@@ -479,6 +540,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)
@@ -488,7 +550,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;
@@ -504,16 +566,73 @@ 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 PREFIX opcode table.  */
+
+static const struct powerpc_opcode *
+lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
+{
+  const struct powerpc_opcode *opcode, *opcode_end, *last;
+  unsigned long seg;
+
+  /* Get the opcode segment of the instruction.  */
+  seg = PPC_PREFIX_SEG (insn);
+
+  /* Find the first match in the opcode table for this major opcode.  */
+  opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
+  last = NULL;
+  for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
+       opcode < opcode_end;
+       ++opcode)
+    {
+      const unsigned char *opindex;
+      const struct powerpc_operand *operand;
+      int invalid;
+
+      if ((insn & opcode->mask) != opcode->opcode
+         || ((dialect & PPC_OPCODE_ANY) == 0
+             && ((opcode->flags & dialect) == 0
+                 || (opcode->deprecated & dialect) != 0)))
+       continue;
+
+      /* Check validity of operands.  */
+      invalid = 0;
+      for (opindex = opcode->operands; *opindex != 0; opindex++)
+       {
+         operand = powerpc_operands + *opindex;
+         if (operand->extract)
+           (*operand->extract) (insn, dialect, &invalid);
+       }
+      if (invalid)
+       continue;
+
+      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 last;
 }
 
 /* Find a match for INSN in the VLE opcode table.  */
 
 static const struct powerpc_opcode *
-lookup_vle (unsigned long insn)
+lookup_vle (uint64_t insn)
 {
   const struct powerpc_opcode *opcode;
   const struct powerpc_opcode *opcode_end;
@@ -533,10 +652,10 @@ lookup_vle (unsigned long insn)
        opcode < opcode_end;
        ++opcode)
     {
-      unsigned long table_opcd = opcode->opcode;
-      unsigned long table_mask = opcode->mask;
+      uint64_t table_opcd = opcode->opcode;
+      uint64_t table_mask = opcode->mask;
       bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
-      unsigned long insn2;
+      uint64_t insn2;
       const unsigned char *opindex;
       const struct powerpc_operand *operand;
       int invalid;
@@ -564,6 +683,58 @@ lookup_vle (unsigned long insn)
   return NULL;
 }
 
+/* Find a match for INSN in the SPE2 opcode table.  */
+
+static const struct powerpc_opcode *
+lookup_spe2 (uint64_t insn)
+{
+  const struct powerpc_opcode *opcode, *opcode_end;
+  unsigned op, xop, seg;
+
+  op = PPC_OP (insn);
+  if (op != 0x4)
+    {
+      /* This is not SPE2 insn.
+       * All SPE2 instructions have OP=4 and differs by XOP  */
+      return NULL;
+    }
+  xop = SPE2_XOP (insn);
+  seg = SPE2_XOP_TO_SEG (xop);
+
+  /* Find the first match in the opcode table for this major opcode.  */
+  opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
+  for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
+       opcode < opcode_end;
+       ++opcode)
+    {
+      uint64_t table_opcd = opcode->opcode;
+      uint64_t table_mask = opcode->mask;
+      uint64_t insn2;
+      const unsigned char *opindex;
+      const struct powerpc_operand *operand;
+      int invalid;
+
+      insn2 = insn;
+      if ((insn2 & table_mask) != table_opcd)
+       continue;
+
+      /* Check validity of operands.  */
+      invalid = 0;
+      for (opindex = opcode->operands; *opindex != 0; ++opindex)
+       {
+         operand = powerpc_operands + *opindex;
+         if (operand->extract)
+           (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
+       }
+      if (invalid)
+       continue;
+
+      return opcode;
+    }
+
+  return NULL;
+}
+
 /* Print a PowerPC or POWER instruction.  */
 
 static int
@@ -574,30 +745,25 @@ print_insn_powerpc (bfd_vma memaddr,
 {
   bfd_byte buffer[4];
   int status;
-  unsigned long insn;
+  uint64_t insn;
   const struct powerpc_opcode *opcode;
-  bfd_boolean insn_is_short;
+  int insn_length = 4;  /* Assume we have a normal 4-byte instruction.  */
 
   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+
+  /* The final instruction may be a 2-byte VLE insn.  */
+  if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
+    {
+      /* Clear buffer so unused bytes will not have garbage in them.  */
+      buffer[2] = buffer[3] = 0;
+      status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+      insn_length = 2;
+    }
+
   if (status != 0)
     {
-      /* The final instruction may be a 2-byte VLE insn.  */
-      if ((dialect & PPC_OPCODE_VLE) != 0)
-        {
-          /* Clear buffer so unused bytes will not have garbage in them.  */
-          buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
-          status = (*info->read_memory_func) (memaddr, buffer, 2, info);
-          if (status != 0)
-            {
-              (*info->memory_error_func) (status, memaddr, info);
-              return -1;
-            }
-        }
-      else
-        {
-          (*info->memory_error_func) (status, memaddr, info);
-          return -1;
-        }
+      (*info->memory_error_func) (status, memaddr, info);
+      return -1;
     }
 
   if (bigendian)
@@ -607,95 +773,133 @@ print_insn_powerpc (bfd_vma memaddr,
 
   /* Get the major opcode of the insn.  */
   opcode = NULL;
-  insn_is_short = FALSE;
-  if ((dialect & PPC_OPCODE_VLE) != 0)
+  if ((dialect & PPC_OPCODE_POWER10) != 0
+      && PPC_OP (insn) == 0x1)
+    {
+      uint64_t temp_insn, suffix;
+      status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
+      if (status == 0)
+       {
+         if (bigendian)
+           suffix = bfd_getb32 (buffer);
+         else
+           suffix = bfd_getl32 (buffer);
+         temp_insn = (insn << 32) | suffix;
+         opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
+         if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
+           opcode = lookup_prefix (temp_insn, dialect);
+         if (opcode != NULL)
+           {
+             insn = temp_insn;
+             insn_length = 8;
+             if ((info->flags & WIDE_OUTPUT) != 0)
+               info->bytes_per_line = 8;
+           }
+       }
+    }
+  if (opcode == NULL && (dialect & PPC_OPCODE_VLE) != 0)
     {
       opcode = lookup_vle (insn);
-      if (opcode != NULL)
-       insn_is_short = PPC_OP_SE_VLE(opcode->mask);
+      if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
+       {
+         /* The operands will be fetched out of the 16-bit instruction.  */
+         insn >>= 16;
+         insn_length = 2;
+       }
+    }
+  if (opcode == NULL && insn_length == 4)
+    {
+      if ((dialect & PPC_OPCODE_SPE2) != 0)
+       opcode = lookup_spe2 (insn);
+      if (opcode == NULL)
+       opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
+      if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
+       opcode = lookup_powerpc (insn, dialect);
     }
-  if (opcode == NULL)
-    opcode = lookup_powerpc (insn, dialect);
-  if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
-    opcode = lookup_powerpc (insn, (ppc_cpu_t) -1);
 
   if (opcode != NULL)
     {
       const unsigned char *opindex;
       const struct powerpc_operand *operand;
-      int need_comma;
-      int need_paren;
-      int skip_optional;
-
-      if (opcode->operands[0] != 0)
-       (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
-      else
-       (*info->fprintf_func) (info->stream, "%s", opcode->name);
-
-      if (insn_is_short)
-        /* The operands will be fetched out of the 16-bit instruction.  */
-        insn >>= 16;
+      enum {
+       need_comma = 0,
+       need_1space = 1,
+       need_2spaces = 2,
+       need_3spaces = 3,
+       need_4spaces = 4,
+       need_5spaces = 5,
+       need_6spaces = 6,
+       need_7spaces = 7,
+       need_paren
+      } op_separator;
+      bfd_boolean skip_optional;
+      int blanks;
+
+      (*info->fprintf_func) (info->stream, "%s", opcode->name);
+      /* gdb fprintf_func doesn't return count printed.  */
+      blanks = 8 - strlen (opcode->name);
+      if (blanks <= 0)
+       blanks = 1;
 
       /* Now extract and print the operands.  */
-      need_comma = 0;
-      need_paren = 0;
-      skip_optional = -1;
+      op_separator = blanks;
+      skip_optional = FALSE;
       for (opindex = opcode->operands; *opindex != 0; opindex++)
        {
-         long value;
+         int64_t value;
 
          operand = powerpc_operands + *opindex;
 
-         /* Operands that are marked FAKE are simply ignored.  We
-            already made sure that the extract function considered
-            the instruction to be valid.  */
-         if ((operand->flags & PPC_OPERAND_FAKE) != 0)
-           continue;
-
-         /* If all of the optional operands have the value zero,
-            then don't print any of them.  */
-         if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
+         /* If all of the optional operands past this one have their
+            default value, then don't print any of them.  Except in
+            raw mode, print them all.  */
+         if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
+             && (dialect & PPC_OPCODE_RAW) == 0)
            {
-             if (skip_optional < 0)
-               skip_optional = skip_optional_operands (opindex, insn,
-                                                       dialect);
+             if (!skip_optional)
+               skip_optional = skip_optional_operands (opindex, insn, dialect);
              if (skip_optional)
                continue;
            }
 
          value = operand_value_powerpc (operand, insn, dialect);
 
-         if (need_comma)
-           {
-             (*info->fprintf_func) (info->stream, ",");
-             need_comma = 0;
-           }
+         if (op_separator == need_comma)
+           (*info->fprintf_func) (info->stream, ",");
+         else if (op_separator == need_paren)
+           (*info->fprintf_func) (info->stream, "(");
+         else
+           (*info->fprintf_func) (info->stream, "%*s", op_separator, " ");
 
          /* Print the operand as directed by the flags.  */
          if ((operand->flags & PPC_OPERAND_GPR) != 0
              || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
-           (*info->fprintf_func) (info->stream, "r%ld", value);
+           (*info->fprintf_func) (info->stream, "r%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_FPR) != 0)
-           (*info->fprintf_func) (info->stream, "f%ld", value);
+           (*info->fprintf_func) (info->stream, "f%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_VR) != 0)
-           (*info->fprintf_func) (info->stream, "v%ld", value);
+           (*info->fprintf_func) (info->stream, "v%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_VSR) != 0)
-           (*info->fprintf_func) (info->stream, "vs%ld", value);
+           (*info->fprintf_func) (info->stream, "vs%" PRId64, value);
+         else if ((operand->flags & PPC_OPERAND_ACC) != 0)
+           (*info->fprintf_func) (info->stream, "a%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
            (*info->print_address_func) (memaddr + value, info);
          else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
            (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
-         else if ((operand->flags & PPC_OPERAND_FSL) != 0) 
-           (*info->fprintf_func) (info->stream, "fsl%ld", value);
+         else if ((operand->flags & PPC_OPERAND_FSL) != 0)
+           (*info->fprintf_func) (info->stream, "fsl%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_FCR) != 0)
-           (*info->fprintf_func) (info->stream, "fcr%ld", value);
+           (*info->fprintf_func) (info->stream, "fcr%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_UDI) != 0)
-           (*info->fprintf_func) (info->stream, "%ld", value);
+           (*info->fprintf_func) (info->stream, "%" PRId64, value);
          else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
+                  && (operand->flags & PPC_OPERAND_CR_BIT) == 0
                   && (((dialect & PPC_OPCODE_PPC) != 0)
                       || ((dialect & PPC_OPCODE_VLE) != 0)))
-           (*info->fprintf_func) (info->stream, "cr%ld", value);
-         else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
+           (*info->fprintf_func) (info->stream, "cr%" PRId64, value);
+         else if ((operand->flags & PPC_OPERAND_CR_BIT) != 0
+                  && (operand->flags & PPC_OPERAND_CR_REG) == 0
                   && (((dialect & PPC_OPCODE_PPC) != 0)
                       || ((dialect & PPC_OPCODE_VLE) != 0)))
            {
@@ -710,39 +914,54 @@ print_insn_powerpc (bfd_vma memaddr,
              (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
            }
          else
-           (*info->fprintf_func) (info->stream, "%d", (int) value);
+           (*info->fprintf_func) (info->stream, "%" PRId64, value);
 
-         if (need_paren)
-           {
-             (*info->fprintf_func) (info->stream, ")");
-             need_paren = 0;
-           }
+         if (op_separator == need_paren)
+           (*info->fprintf_func) (info->stream, ")");
 
-         if ((operand->flags & PPC_OPERAND_PARENS) == 0)
-           need_comma = 1;
-         else
-           {
-             (*info->fprintf_func) (info->stream, "(");
-             need_paren = 1;
-           }
+         op_separator = need_comma;
+         if ((operand->flags & PPC_OPERAND_PARENS) != 0)
+           op_separator = need_paren;
        }
 
-      /* We have found and printed an instruction.
-         If it was a short VLE instruction we have more to do.  */
-      if (insn_is_short)
-        {
-          memaddr += 2;
-          return 2;
-        }
-      else
-        /* Otherwise, return.  */
-        return 4;
+      /* We have found and printed an instruction.  */
+      return insn_length;
     }
 
   /* We could not find a match.  */
-  (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
+  if (insn_length == 4)
+    (*info->fprintf_func) (info->stream, ".long 0x%x",
+                          (unsigned int) insn);
+  else
+    (*info->fprintf_func) (info->stream, ".word 0x%x",
+                          (unsigned int) insn >> 16);
+  return insn_length;
+}
+
+const disasm_options_and_args_t *
+disassembler_options_powerpc (void)
+{
+  static disasm_options_and_args_t *opts_and_args;
+
+  if (opts_and_args == NULL)
+    {
+      size_t i, num_options = ARRAY_SIZE (ppc_opts);
+      disasm_options_t *opts;
+
+      opts_and_args = XNEW (disasm_options_and_args_t);
+      opts_and_args->args = NULL;
+
+      opts = &opts_and_args->options;
+      opts->name = XNEWVEC (const char *, num_options + 1);
+      opts->description = NULL;
+      opts->arg = NULL;
+      for (i = 0; i < num_options; i++)
+       opts->name[i] = ppc_opts[i].opt;
+      /* The array we return must be NULL terminated.  */
+      opts->name[i] = NULL;
+    }
 
-  return 4;
+  return opts_and_args;
 }
 
 void
@@ -754,7 +973,7 @@ print_ppc_disassembler_options (FILE *stream)
 The following PPC specific disassembler options are supported for use with\n\
 the -M switch:\n"));
 
-  for (col = 0, i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++)
+  for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
     {
       col += fprintf (stream, " %s,", ppc_opts[i].opt);
       if (col > 66)
@@ -763,5 +982,5 @@ the -M switch:\n"));
          col = 0;
        }
     }
-  fprintf (stream, " 32, 64\n");
+  fprintf (stream, "\n");
 }
This page took 0.03585 seconds and 4 git commands to generate.