From 52be03fd13a26ecda4f27c451a434f19eded0ca6 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 29 Mar 2017 13:43:06 +1030 Subject: [PATCH] PowerPC -Mraw disassembly 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 | 4 ++ binutils/doc/binutils.texi | 34 +++++++++++++--- gas/ChangeLog | 4 ++ gas/config/tc-ppc.c | 3 +- include/ChangeLog | 5 +++ include/opcode/ppc.h | 80 ++++++++++++++++++++------------------ opcodes/ChangeLog | 9 +++++ opcodes/ppc-dis.c | 27 ++++++++----- 8 files changed, 112 insertions(+), 54 deletions(-) diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 5ee8073f057..95595876bef 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,7 @@ +2017-03-29 Alan Modra + + * doc/binutils.texi (objdump): Document PowerPC -M options. + 2017-03-21 Andi Kleen * objdump.c (unwind_inlines): Add. diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi index ffa7dfd9092..da4ed52dc46 100644 --- a/binutils/doc/binutils.texi +++ b/binutils/doc/binutils.texi @@ -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 diff --git a/gas/ChangeLog b/gas/ChangeLog index 1ec3708f614..f24e821c7c3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,7 @@ +2017-03-29 Alan Modra + + * config/tc-ppc.c (md_parse_option): Reject -mraw. + 2017-03-27 Alan Modra PR 21303 diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index 05e2c730833..47cc8756900 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -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) diff --git a/include/ChangeLog b/include/ChangeLog index daaad17d733..76957741ae4 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2017-03-29 Alan Modra + + * opcode/ppc.h (PPC_OPCODE_RAW): Define. + (PPC_OPCODE_*): Make them all unsigned long long constants. + 2017-03-27 Pip Cet * elf/wasm32.h: New file to support wasm32 architecture. diff --git a/include/opcode/ppc.h b/include/opcode/ppc.h index 34cf27ed424..c4de8340125 100644 --- a/include/opcode/ppc.h +++ b/include/opcode/ppc.h @@ -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) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index b6a2a5a1f89..fe6f27be7c2 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,12 @@ +2017-03-29 Alan Modra + + * 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 PR 21303 diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index f3db0620956..ee8016a7842 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -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) { -- 2.30.2