PowerPC -Mraw disassembly
authorAlan Modra <amodra@gmail.com>
Wed, 29 Mar 2017 03:13:06 +0000 (13:43 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 29 Mar 2017 12:25:18 +0000 (22:55 +1030)
This adds -Mraw for PowerPC objdump, a disassembler option to display
the underlying machine instruction rather than aliases.  For example,
"rlwinm" always rather than "rotlwi" when the instruction is
performing a simple rotate.

binutils/
* doc/binutils.texi (objdump): Document PowerPC -M options.
gas/
* config/tc-ppc.c (md_parse_option): Reject -mraw.
include/
* opcode/ppc.h (PPC_OPCODE_RAW): Define.
(PPC_OPCODE_*): Make them all unsigned long long constants.
opcodes/
* ppc-dis.c (ppc_opts): Set PPC_OPCODE_PPC for "any" flags.  Add
"raw" option.
(lookup_powerpc): Don't special case -1 dialect.  Handle
PPC_OPCODE_RAW.
(print_insn_powerpc): Mask out PPC_OPCODE_ANY on first
lookup_powerpc call, pass it on second.

binutils/ChangeLog
binutils/doc/binutils.texi
gas/ChangeLog
gas/config/tc-ppc.c
include/ChangeLog
include/opcode/ppc.h
opcodes/ChangeLog
opcodes/ppc-dis.c

index 5ee8073..9559587 100644 (file)
@@ -1,3 +1,7 @@
+2017-03-29  Alan Modra  <amodra@gmail.com>
+
+       * doc/binutils.texi (objdump): Document PowerPC -M options.
+
 2017-03-21  Andi Kleen  <ak@linux.intel.com>
 
        * objdump.c (unwind_inlines): Add.
index ffa7dfd..da4ed52 100644 (file)
@@ -2369,12 +2369,34 @@ When in AT&T mode, instructs the disassembler to print a mnemonic
 suffix even when the suffix could be inferred by the operands.
 @end table
 
-For PowerPC, @option{booke} controls the disassembly of BookE
-instructions.  @option{32} and @option{64} select PowerPC and
-PowerPC64 disassembly, respectively.  @option{e300} selects
-disassembly for the e300 family.  @option{440} selects disassembly for
-the PowerPC 440.  @option{ppcps} selects disassembly for the paired
-single instructions of the PPC750CL.
+For PowerPC, the @option{-M} argument @option{raw} selects
+disasssembly of hardware insns rather than aliases.  For example, you
+will see @code{rlwinm} rather than @code{clrlwi}, and @code{addi}
+rather than @code{li}.  All of the @option{-m} arguments for
+@command{gas} that select a CPU are supported.  These are:
+@option{403}, @option{405}, @option{440}, @option{464}, @option{476},
+@option{601}, @option{603}, @option{604}, @option{620}, @option{7400},
+@option{7410}, @option{7450}, @option{7455}, @option{750cl},
+@option{821}, @option{850}, @option{860}, @option{a2}, @option{booke},
+@option{booke32}, @option{cell}, @option{com}, @option{e200z4},
+@option{e300}, @option{e500}, @option{e500mc}, @option{e500mc64},
+@option{e500x2}, @option{e5500}, @option{e6500}, @option{efs},
+@option{power4}, @option{power5}, @option{power6}, @option{power7},
+@option{power8}, @option{power9}, @option{ppc}, @option{ppc32},
+@option{ppc64}, @option{ppc64bridge}, @option{ppcps}, @option{pwr},
+@option{pwr2}, @option{pwr4}, @option{pwr5}, @option{pwr5x},
+@option{pwr6}, @option{pwr7}, @option{pwr8}, @option{pwr9},
+@option{pwrx}, @option{titan}, and @option{vle}.
+@option{32} and @option{64} modify the default or a prior CPU
+selection, disabling and enabling 64-bit insns respectively.  In
+addition, @option{altivec}, @option{any}, @option{htm}, @option{vsx},
+and @option{spe} add capabilities to a previous @emph{or later} CPU
+selection.  @option{any} will disassemble any opcode known to
+binutils, but in cases where an opcode has two different meanings or
+different arguments, you may not see the disassembly you expect.
+If you disassemble without giving a CPU selection, a default will be
+chosen from information gleaned by BFD from the object files headers,
+but the result again may not be as you expect.
 
 For MIPS, this option controls the printing of instruction mnemonic
 names and register names in disassembled instructions.  Multiple
index 1ec3708..f24e821 100644 (file)
@@ -1,3 +1,7 @@
+2017-03-29  Alan Modra  <amodra@gmail.com>
+
+       * config/tc-ppc.c (md_parse_option): Reject -mraw.
+
 2017-03-27  Alan Modra  <amodra@gmail.com>
 
        PR 21303
index 05e2c73..47cc875 100644 (file)
@@ -1193,7 +1193,8 @@ md_parse_option (int c, const char *arg)
 
     case 'm':
       new_cpu = ppc_parse_cpu (ppc_cpu, &sticky, arg);
-      if (new_cpu != 0)
+      /* "raw" is only valid for the disassembler.  */
+      if (new_cpu != 0 && (new_cpu & PPC_OPCODE_RAW) == 0)
        {
          ppc_cpu = new_cpu;
          if (strcmp (arg, "vle") == 0)
index daaad17..7695774 100644 (file)
@@ -1,3 +1,8 @@
+2017-03-29  Alan Modra  <amodra@gmail.com>
+
+       * opcode/ppc.h (PPC_OPCODE_RAW): Define.
+       (PPC_OPCODE_*): Make them all unsigned long long constants.
+
 2017-03-27  Pip Cet  <pipcet@gmail.com>
 
        * elf/wasm32.h: New file to support wasm32 architecture.
index 34cf27e..c4de834 100644 (file)
@@ -74,107 +74,107 @@ extern const int vle_num_opcodes;
 /* Values defined for the flags field of a struct powerpc_opcode.  */
 
 /* Opcode is defined for the PowerPC architecture.  */
-#define PPC_OPCODE_PPC                  1
+#define PPC_OPCODE_PPC                0x1ull
 
 /* Opcode is defined for the POWER (RS/6000) architecture.  */
-#define PPC_OPCODE_POWER                2
+#define PPC_OPCODE_POWER              0x2ull
 
 /* Opcode is defined for the POWER2 (Rios 2) architecture.  */
-#define PPC_OPCODE_POWER2               4
+#define PPC_OPCODE_POWER2             0x4ull
 
 /* Opcode is supported by the Motorola PowerPC 601 processor.  The 601
    is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
    but it also supports many additional POWER instructions.  */
-#define PPC_OPCODE_601                  8
+#define PPC_OPCODE_601                0x8ull
 
 /* Opcode is supported in both the Power and PowerPC architectures
    (ie, compiler's -mcpu=common or assembler's -mcom).  More than just
    the intersection of PPC_OPCODE_PPC with the union of PPC_OPCODE_POWER
    and PPC_OPCODE_POWER2 because many instructions changed mnemonics
    between POWER and POWERPC.  */
-#define PPC_OPCODE_COMMON            0x10
+#define PPC_OPCODE_COMMON            0x10ull
 
 /* Opcode is supported for any Power or PowerPC platform (this is
    for the assembler's -many option, and it eliminates duplicates).  */
-#define PPC_OPCODE_ANY               0x20
+#define PPC_OPCODE_ANY               0x20ull
 
 /* Opcode is only defined on 64 bit architectures.  */
-#define PPC_OPCODE_64                0x40
+#define PPC_OPCODE_64                0x40ull
 
 /* Opcode is supported as part of the 64-bit bridge.  */
-#define PPC_OPCODE_64_BRIDGE         0x80
+#define PPC_OPCODE_64_BRIDGE         0x80ull
 
 /* Opcode is supported by Altivec Vector Unit */
-#define PPC_OPCODE_ALTIVEC          0x100
+#define PPC_OPCODE_ALTIVEC          0x100ull
 
 /* Opcode is supported by PowerPC 403 processor.  */
-#define PPC_OPCODE_403              0x200
+#define PPC_OPCODE_403              0x200ull
 
 /* Opcode is supported by PowerPC BookE processor.  */
-#define PPC_OPCODE_BOOKE            0x400
+#define PPC_OPCODE_BOOKE            0x400ull
 
 /* Opcode is supported by PowerPC 440 processor.  */
-#define PPC_OPCODE_440              0x800
+#define PPC_OPCODE_440              0x800ull
 
 /* Opcode is only supported by Power4 architecture.  */
-#define PPC_OPCODE_POWER4          0x1000
+#define PPC_OPCODE_POWER4          0x1000ull
 
 /* Opcode is only supported by Power7 architecture.  */
-#define PPC_OPCODE_POWER7          0x2000
+#define PPC_OPCODE_POWER7          0x2000ull
 
 /* Opcode is only supported by e500x2 Core.  */
-#define PPC_OPCODE_SPE             0x4000
+#define PPC_OPCODE_SPE             0x4000ull
 
 /* Opcode is supported by e500x2 Integer select APU.  */
-#define PPC_OPCODE_ISEL                    0x8000
+#define PPC_OPCODE_ISEL                    0x8000ull
 
 /* Opcode is an e500 SPE floating point instruction.  */
-#define PPC_OPCODE_EFS            0x10000
+#define PPC_OPCODE_EFS            0x10000ull
 
 /* Opcode is supported by branch locking APU.  */
-#define PPC_OPCODE_BRLOCK         0x20000
+#define PPC_OPCODE_BRLOCK         0x20000ull
 
 /* Opcode is supported by performance monitor APU.  */
-#define PPC_OPCODE_PMR            0x40000
+#define PPC_OPCODE_PMR            0x40000ull
 
 /* Opcode is supported by cache locking APU.  */
-#define PPC_OPCODE_CACHELCK       0x80000
+#define PPC_OPCODE_CACHELCK       0x80000ull
 
 /* Opcode is supported by machine check APU.  */
-#define PPC_OPCODE_RFMCI         0x100000
+#define PPC_OPCODE_RFMCI         0x100000ull
 
 /* Opcode is only supported by Power5 architecture.  */
-#define PPC_OPCODE_POWER5        0x200000
+#define PPC_OPCODE_POWER5        0x200000ull
 
 /* Opcode is supported by PowerPC e300 family.  */
-#define PPC_OPCODE_E300           0x400000
+#define PPC_OPCODE_E300           0x400000ull
 
 /* Opcode is only supported by Power6 architecture.  */
-#define PPC_OPCODE_POWER6        0x800000
+#define PPC_OPCODE_POWER6        0x800000ull
 
 /* Opcode is only supported by PowerPC Cell family.  */
-#define PPC_OPCODE_CELL                 0x1000000
+#define PPC_OPCODE_CELL                 0x1000000ull
 
 /* Opcode is supported by CPUs with paired singles support.  */
-#define PPC_OPCODE_PPCPS        0x2000000
+#define PPC_OPCODE_PPCPS        0x2000000ull
 
 /* Opcode is supported by Power E500MC */
-#define PPC_OPCODE_E500MC        0x4000000
+#define PPC_OPCODE_E500MC        0x4000000ull
 
 /* Opcode is supported by PowerPC 405 processor.  */
-#define PPC_OPCODE_405          0x8000000
+#define PPC_OPCODE_405          0x8000000ull
 
 /* Opcode is supported by Vector-Scalar (VSX) Unit */
-#define PPC_OPCODE_VSX         0x10000000
+#define PPC_OPCODE_VSX         0x10000000ull
 
 /* Opcode is supported by A2.  */
-#define PPC_OPCODE_A2          0x20000000
+#define PPC_OPCODE_A2          0x20000000ull
 
 /* Opcode is supported by PowerPC 476 processor.  */
-#define PPC_OPCODE_476         0x40000000
+#define PPC_OPCODE_476         0x40000000ull
 
 /* Opcode is supported by AppliedMicro Titan core */
-#define PPC_OPCODE_TITAN        0x80000000
+#define PPC_OPCODE_TITAN        0x80000000ull
 
 /* Opcode which is supported by the e500 family */
 #define PPC_OPCODE_E500               0x100000000ull
@@ -206,16 +206,22 @@ extern const int vle_num_opcodes;
 #define PPC_OPCODE_7450              0x8000000000ull
 
 /* Opcode is supported by ppc821/850/860.  */
-#define PPC_OPCODE_860       0x10000000000ull
+#define PPC_OPCODE_860      0x10000000000ull
 
 /* Opcode is only supported by Power9 architecture.  */
-#define PPC_OPCODE_POWER9     0x20000000000ull
+#define PPC_OPCODE_POWER9    0x20000000000ull
 
 /* Opcode is supported by Vector-Scalar (VSX) Unit from ISA 2.08.  */
-#define PPC_OPCODE_VSX3       0x40000000000ull
+#define PPC_OPCODE_VSX3      0x40000000000ull
 
-  /* Opcode is supported by e200z4.  */
-#define PPC_OPCODE_E200Z4     0x80000000000ull
+/* Opcode is supported by e200z4.  */
+#define PPC_OPCODE_E200Z4    0x80000000000ull
+
+/* Disassemble to instructions matching later in the opcode table
+   with fewer "mask" bits set rather than the earlist match.  Fewer
+   "mask" bits set imply a more general form of the opcode, in fact
+   the underlying machine instruction.  */
+#define PPC_OPCODE_RAW     0x100000000000ull
 
 /* A macro to extract the major opcode from an instruction.  */
 #define PPC_OP(i) (((i) >> 26) & 0x3f)
index b6a2a5a..fe6f27b 100644 (file)
@@ -1,3 +1,12 @@
+2017-03-29  Alan Modra  <amodra@gmail.com>
+
+       * ppc-dis.c (ppc_opts): Set PPC_OPCODE_PPC for "any" flags.  Add
+       "raw" option.
+       (lookup_powerpc): Don't special case -1 dialect.  Handle
+       PPC_OPCODE_RAW.
+       (print_insn_powerpc): Mask out PPC_OPCODE_ANY on first
+       lookup_powerpc call, pass it on second.
+
 2017-03-27  Alan Modra  <amodra@gmail.com>
 
        PR 21303
index f3db062..ee8016a 100644 (file)
@@ -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 },
@@ -226,6 +226,8 @@ struct ppc_mopt ppc_opts[] = {
     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
@@ -494,14 +496,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 +509,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 +519,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 +535,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 +652,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)
     {