[ppc*] Fix PowerPC disassembly regression (Alan Modra, Edjunior Machado).

This commit is contained in:
Jan Kratochvil 2013-01-04 00:06:50 +01:00
parent ed2617e547
commit 5f3b63a0d4
3 changed files with 298 additions and 1 deletions

View File

@ -0,0 +1,228 @@
http://sourceware.org/ml/binutils/2012-11/msg00352.html
Subject: Re: [PATCH] Fix gdb disassemble for power6/power7 instructions
On Wed, Nov 14, 2012 at 10:16:38AM +1030, Alan Modra wrote:
> What I think should happen is that the default handling, ie. the block
> that starts with
> if ((dialect & ~(ppc_cpu_t) PPC_OPCODE_64) == 0)
> should be deleted and a switch on info->mach setting up dialect added
> before we parse disassembler_options. That way -m32 and -m64 can
> override the default as they are supposed to. See bfd/archures.c for
> values of bfd_mach_ppc_*.
Well that idea didn't turn out to be simple. If we want to bring the
default up to something more up-to-date than the current ppc601, then
you run into difficulty with "retain_mask" in ppc_parse_cpu. Choosing
any of the bits in that mask as a default, eg. PPC_OPCODE_VSX, results
in not being able to get rid of those bits.
Now the idea of "retain_mask" was to cover cases where people pass
something like -mppc -maltivec (or even -maltivec -mppc) to the
assembler. Historically that has resulted in both PPC_OPCODE_PPC and
PPC_OPCODE_ALTIVEC being set; Some options accumulate. So I've
redone code handling these sticky options to just keep track of the
bits selected by ppc_opts.sticky. Any default selection won't make
these bits sticky, you'll only get that effect from -maltivec, -many,
-mspe, -mvle and -mvsx on the command line or in .machine directives
(and similarly for the corresponding -M disassembler options). I'm
not sure why PPC_OPCODE_PMR was ever in "retain_mask". People
interested in VLE might need to investigate that.
One of the effects of updating to a power7 default is that conditional
branch hints are displayed for "at" style hints rather than the older
"y" hints. When using "y" hints the disassembler always showed the
hint, eg. "bne-" or "bne+". Now you'll see "bne" most times. This
meant updating the testsuite. I made one gas test disassemble for
plain ppc just to ensure the older "y" hints continue to be available.
Committed.
include/opcode/
* ppc.h (ppc_parse_cpu): Update prototype.
opcodes/
* ppc-dis.c (ppc_parse_cpu): Add "sticky" param. Track bits
set from ppc_opts.sticky in it. Delete "retain_mask".
(powerpc_init_dialect): Choose default dialect from info->mach
before parsing -M options. Handle more bfd_mach_ppc variants.
Update common default to power7.
gas/
* config/tc-ppc.c (sticky): New var.
(md_parse_option, ppc_machine): Update ppc_parse_cpu calls.
gas/testsuite/
* gas/ppc/astest2.d: Pass -Mppc to objdump.
ld/testsuite/
* ld-powerpc/plt1.d: Update for default "at" branch hints.
* ld-powerpc/tlsexe.d: Likewise.
* ld-powerpc/tlsexetoc.d: Likewise.
* ld-powerpc/tlsopt1.d: Likewise.
* ld-powerpc/tlsopt1_32.d: Likewise.
* ld-powerpc/tlsopt2.d: Likewise.
* ld-powerpc/tlsopt2_32.d: Likewise.
* ld-powerpc/tlsopt4.d: Likewise.
* ld-powerpc/tlsopt4_32.d: Likewise.
* ld-powerpc/tlsso.d: Likewise.
* ld-powerpc/tlstocso.d: Likewise.
Index: include/opcode/ppc.h
===================================================================
RCS file: /cvs/src/src/include/opcode/ppc.h,v
retrieving revision 1.44
diff -u -p -r1.44 ppc.h
--- ./include/opcode/ppc.h 14 May 2012 19:45:27 -0000 1.44
+++ ./include/opcode/ppc.h 22 Nov 2012 22:45:18 -0000
@@ -400,6 +400,6 @@ struct powerpc_macro
extern const struct powerpc_macro powerpc_macros[];
extern const int powerpc_num_macros;
-extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, const char *);
+extern ppc_cpu_t ppc_parse_cpu (ppc_cpu_t, ppc_cpu_t *, const char *);
#endif /* PPC_H */
Index: opcodes/ppc-dis.c
===================================================================
RCS file: /cvs/src/src/opcodes/ppc-dis.c,v
retrieving revision 1.60
diff -u -p -r1.60 ppc-dis.c
--- ./opcodes/ppc-dis.c 5 Oct 2012 14:06:20 -0000 1.60
+++ ./opcodes/ppc-dis.c 22 Nov 2012 22:45:19 -0000
@@ -211,13 +211,8 @@ get_powerpc_dialect (struct disassemble_
/* Handle -m and -M options that set cpu type, and .machine arg. */
ppc_cpu_t
-ppc_parse_cpu (ppc_cpu_t ppc_cpu, const char *arg)
+ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
{
- const ppc_cpu_t retain_mask = (PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
- | PPC_OPCODE_SPE | PPC_OPCODE_ANY
- | PPC_OPCODE_VLE | PPC_OPCODE_PMR);
- /* Sticky bits. */
- ppc_cpu_t retain_flags = ppc_cpu & retain_mask;
unsigned int i;
for (i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++)
@@ -225,8 +220,8 @@ ppc_parse_cpu (ppc_cpu_t ppc_cpu, const
{
if (ppc_opts[i].sticky)
{
- retain_flags |= ppc_opts[i].sticky;
- if ((ppc_cpu & ~retain_mask) != 0)
+ *sticky |= ppc_opts[i].sticky;
+ if ((ppc_cpu & ~*sticky) != 0)
break;
}
ppc_cpu = ppc_opts[i].cpu;
@@ -235,7 +230,7 @@ ppc_parse_cpu (ppc_cpu_t ppc_cpu, const
if (i >= sizeof (ppc_opts) / sizeof (ppc_opts[0]))
return 0;
- ppc_cpu |= retain_flags;
+ ppc_cpu |= *sticky;
return ppc_cpu;
}
@@ -245,12 +240,75 @@ static void
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;
+ switch (info->mach)
+ {
+ case bfd_mach_ppc_403:
+ case bfd_mach_ppc_403gc:
+ dialect = (PPC_OPCODE_PPC | PPC_OPCODE_403);
+ break;
+ case bfd_mach_ppc_405:
+ dialect = (PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405);
+ break;
+ case bfd_mach_ppc_601:
+ dialect = (PPC_OPCODE_PPC | PPC_OPCODE_601);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ break;
+ case bfd_mach_ppc_titan:
+ dialect = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
+ | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN);
+ break;
+ case bfd_mach_ppc_vle:
+ dialect = (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_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);
+ }
+
arg = info->disassembler_options;
while (arg != NULL)
{
@@ -260,7 +318,7 @@ powerpc_init_dialect (struct disassemble
if (end != NULL)
*end = 0;
- if ((new_cpu = ppc_parse_cpu (dialect, arg)) != 0)
+ if ((new_cpu = ppc_parse_cpu (dialect, &sticky, arg)) != 0)
dialect = new_cpu;
else if (strcmp (arg, "32") == 0)
dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
@@ -274,20 +332,6 @@ powerpc_init_dialect (struct disassemble
arg = end;
}
- if ((dialect & ~(ppc_cpu_t) PPC_OPCODE_64) == 0)
- {
- if (info->mach == bfd_mach_ppc64)
- dialect |= PPC_OPCODE_64;
- else
- dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
- if (info->mach == bfd_mach_ppc_vle)
- dialect |= PPC_OPCODE_PPC | PPC_OPCODE_VLE;
- else
- /* Choose a reasonable default. */
- dialect |= (PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_601
- | PPC_OPCODE_ALTIVEC);
- }
-
info->private_data = priv;
POWERPC_DIALECT(info) = dialect;
}

View File

@ -0,0 +1,60 @@
http://sourceware.org/ml/gdb-patches/2012-11/msg00624.html
Subject: Re: [PATCH] Fix gdb disassemble for power6/power7 instructions
On 11/23/2012 01:28 AM, Alan Modra wrote:
> One of the effects of updating to a power7 default is that conditional
> branch hints are displayed for "at" style hints rather than the older
> "y" hints. When using "y" hints the disassembler always showed the
> hint, eg. "bne-" or "bne+". Now you'll see "bne" most times. This
> meant updating the testsuite. I made one gas test disassemble for
> plain ppc just to ensure the older "y" hints continue to be available.
>
> Committed.
Thanks a lot for the patch, Alan. This also fixes the issues with gdb
disassemble for power6 and power7 instructions.
With these changes on powerpc_init_dialect(), I'd suggest to remove the info->mach
checking from gdb. Ok?
--
Edjunior
2012-11-23 Edjunior Machado <emachado@linux.vnet.ibm.com>
* rs6000-tdep.c (gdb_print_insn_powerpc): Remove info->mach checking,
since now it is being done in binutils' powerpc_init_dialect().
---
gdb/rs6000-tdep.c | 15 ---------------
1 files changed, 0 insertions(+), 15 deletions(-)
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 1797cc5..07b81bc 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -3084,21 +3084,6 @@ find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
static int
gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info)
{
- if (!info->disassembler_options)
- {
- /* When debugging E500 binaries and disassembling code containing
- E500-specific (SPE) instructions, one sometimes sees AltiVec
- instructions instead. The opcode spaces for SPE instructions
- and AltiVec instructions overlap, and specifiying the "any" cpu
- looks for AltiVec instructions first. If we know we're
- debugging an E500 binary, however, we can specify the "e500x2"
- cpu and get much more sane disassembly output. */
- if (info->mach == bfd_mach_ppc_e500)
- info->disassembler_options = "e500x2";
- else
- info->disassembler_options = "any";
- }
-
if (info->endian == BFD_ENDIAN_BIG)
return print_insn_big_powerpc (memaddr, info);
else
--
1.7.1

View File

@ -34,7 +34,7 @@ Version: 7.5.1
# The release always contains a leading reserved number, start it at 1.
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
Release: 32%{?dist}
Release: 33%{?dist}
License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain
Group: Development/Debuggers
@ -602,6 +602,10 @@ Patch818: gdb-rhbz795424-bitpos-lazyvalue.patch
# Fix DW_OP_GNU_implicit_pointer offset bug (Tom Tromey).
Patch819: gdb-implicitpointer-offset.patch
# [ppc*] Fix PowerPC disassembly regression (Alan Modra, Edjunior Machado).
Patch820: gdb-rhbz890900-ppc-dis-1of2.patch
Patch821: gdb-rhbz890900-ppc-dis-2of2.patch
%if 0%{!?rhel:1} || 0%{?rhel} > 6
# RL_STATE_FEDORA_GDB would not be found for:
# Patch642: gdb-readline62-ask-more-rh.patch
@ -940,6 +944,8 @@ find -name "*.info*"|xargs rm -f
%patch817 -p1
%patch818 -p1
%patch819 -p1
%patch820 -p1
%patch821 -p1
%patch393 -p1
%if 0%{!?el5:1} || 0%{?scl:1}
@ -1438,6 +1444,9 @@ fi
%endif # 0%{!?el5:1} || "%{_target_cpu}" == "noarch"
%changelog
* Thu Jan 3 2013 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.5.1-33.fc18
- [ppc*] Fix PowerPC disassembly regression (Alan Modra, Edjunior Machado).
* Thu Dec 13 2012 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.5.1-32.fc18
- 'dwz -m' parsing fix (Tom Tromey).