[gdb] [ppc*] Import ppc64le support (BZ 1096303, Ulrich Weigand).

Jan Kratochvil jankratochvil at fedoraproject.org
Fri May 9 19:30:14 UTC 2014


commit 6e0665a33c841cb72f25624655a40e62747390ed
Author: Jan Kratochvil <jan.kratochvil at redhat.com>
Date:   Fri May 9 21:30:33 2014 +0200

    [ppc*] Import ppc64le support (BZ 1096303, Ulrich Weigand).

 gdb-rhbz795424-bitpos-23of25.patch |  256 +++----
 gdb-upstream-ppc64le02of15.patch   |   61 ++
 gdb-upstream-ppc64le03of15.patch   |   36 +
 gdb-upstream-ppc64le04of15.patch   | 1413 ++++++++++++++++++++++++++++++++++++
 gdb-upstream-ppc64le05of15.patch   |   44 ++
 gdb-upstream-ppc64le06of15.patch   |   67 ++
 gdb-upstream-ppc64le07of15.patch   |  149 ++++
 gdb-upstream-ppc64le08of15.patch   |   57 ++
 gdb-upstream-ppc64le09of15.patch   |  140 ++++
 gdb-upstream-ppc64le10of15.patch   |  159 ++++
 gdb-upstream-ppc64le11of15.patch   |  132 ++++
 gdb-upstream-ppc64le12of15.patch   |   48 ++
 gdb-upstream-ppc64le13of15.patch   |  309 ++++++++
 gdb-upstream-ppc64le14of15.patch   |  375 ++++++++++
 gdb-upstream-ppc64le15of15.patch   |   90 +++
 gdb.spec                           |   47 ++-
 16 files changed, 3244 insertions(+), 139 deletions(-)
---
diff --git a/gdb-rhbz795424-bitpos-23of25.patch b/gdb-rhbz795424-bitpos-23of25.patch
index 0f829a7..e0e13b5 100644
--- a/gdb-rhbz795424-bitpos-23of25.patch
+++ b/gdb-rhbz795424-bitpos-23of25.patch
@@ -137,10 +137,10 @@ Content-Type: text/x-patch
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment; filename=bitpos-tdep.patch
 
-Index: gdb-7.6.90.20140127/gdb/alpha-tdep.c
+Index: gdb-7.7.1/gdb/alpha-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/alpha-tdep.c	2014-02-06 18:20:52.970747716 +0100
-+++ gdb-7.6.90.20140127/gdb/alpha-tdep.c	2014-02-06 18:20:57.294752362 +0100
+--- gdb-7.7.1.orig/gdb/alpha-tdep.c	2014-05-09 19:24:18.677252769 +0200
++++ gdb-7.7.1/gdb/alpha-tdep.c	2014-05-09 20:02:09.620703767 +0200
 @@ -299,18 +299,18 @@ alpha_push_dummy_call (struct gdbarch *g
  {
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -184,10 +184,10 @@ Index: gdb-7.6.90.20140127/gdb/alpha-tdep.c
  	      memcpy (arg_reg_buffer + offset, contents, tlen);
  	      offset += tlen;
  	      contents += tlen;
-Index: gdb-7.6.90.20140127/gdb/amd64-tdep.c
+Index: gdb-7.7.1/gdb/amd64-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/amd64-tdep.c	2014-02-06 18:20:52.972747718 +0100
-+++ gdb-7.6.90.20140127/gdb/amd64-tdep.c	2014-02-06 18:21:51.106810814 +0100
+--- gdb-7.7.1.orig/gdb/amd64-tdep.c	2014-05-09 19:24:18.678252770 +0200
++++ gdb-7.7.1/gdb/amd64-tdep.c	2014-05-09 20:02:09.620703767 +0200
 @@ -633,7 +633,7 @@ amd64_return_value (struct gdbarch *gdba
  		    gdb_byte *readbuf, const gdb_byte *writebuf)
  {
@@ -217,10 +217,10 @@ Index: gdb-7.6.90.20140127/gdb/amd64-tdep.c
        enum amd64_reg_class class[2];
        int needed_integer_regs = 0;
        int needed_sse_regs = 0;
-Index: gdb-7.6.90.20140127/gdb/amd64-windows-tdep.c
+Index: gdb-7.7.1/gdb/amd64-windows-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/amd64-windows-tdep.c	2014-02-06 18:20:52.973747720 +0100
-+++ gdb-7.6.90.20140127/gdb/amd64-windows-tdep.c	2014-02-06 18:20:57.296752364 +0100
+--- gdb-7.7.1.orig/gdb/amd64-windows-tdep.c	2014-05-09 19:24:18.679252770 +0200
++++ gdb-7.7.1/gdb/amd64-windows-tdep.c	2014-05-09 20:02:09.620703767 +0200
 @@ -288,7 +288,7 @@ amd64_windows_return_value (struct gdbar
  			    struct type *type, struct regcache *regcache,
  			    gdb_byte *readbuf, const gdb_byte *writebuf)
@@ -230,10 +230,10 @@ Index: gdb-7.6.90.20140127/gdb/amd64-windows-tdep.c
    int regnum = -1;
  
    /* See if our value is returned through a register.  If it is, then
-Index: gdb-7.6.90.20140127/gdb/arm-tdep.c
+Index: gdb-7.7.1/gdb/arm-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/arm-tdep.c	2014-02-06 18:20:52.978747725 +0100
-+++ gdb-7.6.90.20140127/gdb/arm-tdep.c	2014-02-06 18:20:57.299752367 +0100
+--- gdb-7.7.1.orig/gdb/arm-tdep.c	2014-05-09 19:24:18.684252770 +0200
++++ gdb-7.7.1/gdb/arm-tdep.c	2014-05-09 20:02:09.622703768 +0200
 @@ -3498,7 +3498,7 @@ arm_vfp_cprc_reg_char (enum arm_vfp_cprc
     array).  Vectors and complex types are not currently supported,
     matching the generic AAPCS support.  */
@@ -308,10 +308,10 @@ Index: gdb-7.6.90.20140127/gdb/arm-tdep.c
        struct type *arg_type;
        struct type *target_type;
        enum type_code typecode;
-Index: gdb-7.6.90.20140127/gdb/avr-tdep.c
+Index: gdb-7.7.1/gdb/avr-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/avr-tdep.c	2014-02-06 18:20:52.980747727 +0100
-+++ gdb-7.6.90.20140127/gdb/avr-tdep.c	2014-02-06 18:20:57.299752367 +0100
+--- gdb-7.7.1.orig/gdb/avr-tdep.c	2014-05-09 19:24:18.686252771 +0200
++++ gdb-7.7.1/gdb/avr-tdep.c	2014-05-09 20:02:09.623703768 +0200
 @@ -1167,13 +1167,14 @@ avr_dummy_id (struct gdbarch *gdbarch, s
  
  struct stack_item
@@ -345,10 +345,10 @@ Index: gdb-7.6.90.20140127/gdb/avr-tdep.c
  
        /* Calculate the potential last register needed.  */
        last_regnum = regnum - (len + (len & 1));
-Index: gdb-7.6.90.20140127/gdb/bfin-tdep.c
+Index: gdb-7.7.1/gdb/bfin-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/bfin-tdep.c	2014-02-06 18:20:52.980747727 +0100
-+++ gdb-7.6.90.20140127/gdb/bfin-tdep.c	2014-02-06 18:20:57.300752368 +0100
+--- gdb-7.7.1.orig/gdb/bfin-tdep.c	2014-05-09 19:24:18.686252771 +0200
++++ gdb-7.7.1/gdb/bfin-tdep.c	2014-05-09 20:02:09.623703768 +0200
 @@ -506,7 +506,7 @@ bfin_push_dummy_call (struct gdbarch *gd
    gdb_byte buf[4];
    int i;
@@ -367,10 +367,10 @@ Index: gdb-7.6.90.20140127/gdb/bfin-tdep.c
  
        sp -= container_len;
        write_memory (sp, value_contents_writeable (args[i]), container_len);
-Index: gdb-7.6.90.20140127/gdb/cris-tdep.c
+Index: gdb-7.7.1/gdb/cris-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/cris-tdep.c	2014-02-06 18:20:52.981747728 +0100
-+++ gdb-7.6.90.20140127/gdb/cris-tdep.c	2014-02-06 18:20:57.301752369 +0100
+--- gdb-7.7.1.orig/gdb/cris-tdep.c	2014-05-09 19:24:18.687252771 +0200
++++ gdb-7.7.1/gdb/cris-tdep.c	2014-05-09 20:02:09.623703768 +0200
 @@ -665,13 +665,13 @@ static CORE_ADDR cris_unwind_sp (struct
  
  struct stack_item
@@ -405,10 +405,10 @@ Index: gdb-7.6.90.20140127/gdb/cris-tdep.c
        
        /* How may registers worth of storage do we need for this argument?  */
        reg_demand = (len / 4) + (len % 4 != 0 ? 1 : 0);
-Index: gdb-7.6.90.20140127/gdb/h8300-tdep.c
+Index: gdb-7.7.1/gdb/h8300-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/h8300-tdep.c	2014-02-06 18:20:52.981747728 +0100
-+++ gdb-7.6.90.20140127/gdb/h8300-tdep.c	2014-02-06 18:20:57.301752369 +0100
+--- gdb-7.7.1.orig/gdb/h8300-tdep.c	2014-05-09 19:24:18.688252771 +0200
++++ gdb-7.7.1/gdb/h8300-tdep.c	2014-05-09 20:02:09.624703768 +0200
 @@ -640,7 +640,7 @@ h8300_push_dummy_call (struct gdbarch *g
  		       int struct_return, CORE_ADDR struct_addr)
  {
@@ -441,10 +441,10 @@ Index: gdb-7.6.90.20140127/gdb/h8300-tdep.c
  
  	      for (offset = 0; offset < padded_len; offset += wordsize)
  		{
-Index: gdb-7.6.90.20140127/gdb/hppa-tdep.c
+Index: gdb-7.7.1/gdb/hppa-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/hppa-tdep.c	2014-02-06 18:20:52.982747729 +0100
-+++ gdb-7.6.90.20140127/gdb/hppa-tdep.c	2014-02-06 18:20:57.302752371 +0100
+--- gdb-7.7.1.orig/gdb/hppa-tdep.c	2014-05-09 19:24:18.690252771 +0200
++++ gdb-7.7.1/gdb/hppa-tdep.c	2014-05-09 20:02:09.624703768 +0200
 @@ -961,7 +961,7 @@ hppa64_push_dummy_call (struct gdbarch *
      {
        struct value *arg = args[i];
@@ -463,10 +463,10 @@ Index: gdb-7.6.90.20140127/gdb/hppa-tdep.c
    int regnum, offset;
  
    if (len > 16)
-Index: gdb-7.6.90.20140127/gdb/i386-darwin-tdep.c
+Index: gdb-7.7.1/gdb/i386-darwin-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/i386-darwin-tdep.c	2014-02-06 18:20:52.982747729 +0100
-+++ gdb-7.6.90.20140127/gdb/i386-darwin-tdep.c	2014-02-06 18:20:57.302752371 +0100
+--- gdb-7.7.1.orig/gdb/i386-darwin-tdep.c	2014-05-09 19:24:18.690252771 +0200
++++ gdb-7.7.1/gdb/i386-darwin-tdep.c	2014-05-09 20:02:09.624703768 +0200
 @@ -164,7 +164,7 @@ i386_darwin_push_dummy_call (struct gdba
  
    for (write_pass = 0; write_pass < 2; write_pass++)
@@ -476,10 +476,10 @@ Index: gdb-7.6.90.20140127/gdb/i386-darwin-tdep.c
        int num_m128 = 0;
  
        if (struct_return)
-Index: gdb-7.6.90.20140127/gdb/i386-tdep.c
+Index: gdb-7.7.1/gdb/i386-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/i386-tdep.c	2014-02-06 18:20:52.985747732 +0100
-+++ gdb-7.6.90.20140127/gdb/i386-tdep.c	2014-02-06 18:20:57.303752372 +0100
+--- gdb-7.7.1.orig/gdb/i386-tdep.c	2014-05-09 19:24:18.692252771 +0200
++++ gdb-7.7.1/gdb/i386-tdep.c	2014-05-09 20:02:09.625703769 +0200
 @@ -2473,7 +2473,7 @@ i386_push_dummy_call (struct gdbarch *gd
    gdb_byte buf[4];
    int i;
@@ -543,10 +543,10 @@ Index: gdb-7.6.90.20140127/gdb/i386-tdep.c
  
    if (i386_fp_regnum_p (get_frame_arch (frame), regnum))
      {
-Index: gdb-7.6.90.20140127/gdb/ia64-tdep.c
+Index: gdb-7.7.1/gdb/ia64-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/ia64-tdep.c	2014-02-06 18:20:52.986747733 +0100
-+++ gdb-7.6.90.20140127/gdb/ia64-tdep.c	2014-02-06 18:20:57.304752373 +0100
+--- gdb-7.7.1.orig/gdb/ia64-tdep.c	2014-05-09 19:24:18.693252771 +0200
++++ gdb-7.7.1/gdb/ia64-tdep.c	2014-05-09 20:02:09.626703769 +0200
 @@ -3851,8 +3851,10 @@ ia64_push_dummy_call (struct gdbarch *gd
    int argno;
    struct value *arg;
@@ -560,10 +560,10 @@ Index: gdb-7.6.90.20140127/gdb/ia64-tdep.c
    int floatreg;
    ULONGEST bsp;
    CORE_ADDR funcdescaddr, pc, global_pointer;
-Index: gdb-7.6.90.20140127/gdb/iq2000-tdep.c
+Index: gdb-7.7.1/gdb/iq2000-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/iq2000-tdep.c	2014-02-06 18:20:52.986747733 +0100
-+++ gdb-7.6.90.20140127/gdb/iq2000-tdep.c	2014-02-06 18:20:57.304752373 +0100
+--- gdb-7.7.1.orig/gdb/iq2000-tdep.c	2014-05-09 19:24:18.693252771 +0200
++++ gdb-7.7.1/gdb/iq2000-tdep.c	2014-05-09 20:02:09.626703769 +0200
 @@ -654,8 +654,9 @@ iq2000_push_dummy_call (struct gdbarch *
    const bfd_byte *val;
    bfd_byte buf[4];
@@ -576,10 +576,10 @@ Index: gdb-7.6.90.20140127/gdb/iq2000-tdep.c
    /* Used to copy struct arguments into the stack.  */
    CORE_ADDR struct_ptr;
  
-Index: gdb-7.6.90.20140127/gdb/m32r-tdep.c
+Index: gdb-7.7.1/gdb/m32r-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/m32r-tdep.c	2014-02-06 18:20:52.986747733 +0100
-+++ gdb-7.6.90.20140127/gdb/m32r-tdep.c	2014-02-06 18:20:57.304752373 +0100
+--- gdb-7.7.1.orig/gdb/m32r-tdep.c	2014-05-09 19:24:18.693252771 +0200
++++ gdb-7.7.1/gdb/m32r-tdep.c	2014-05-09 20:02:09.626703769 +0200
 @@ -689,7 +689,7 @@ m32r_push_dummy_call (struct gdbarch *gd
    CORE_ADDR regval;
    gdb_byte *val;
@@ -589,10 +589,10 @@ Index: gdb-7.6.90.20140127/gdb/m32r-tdep.c
  
    /* First force sp to a 4-byte alignment.  */
    sp = sp & ~3;
-Index: gdb-7.6.90.20140127/gdb/m68k-tdep.c
+Index: gdb-7.7.1/gdb/m68k-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/m68k-tdep.c	2014-02-06 18:20:52.987747735 +0100
-+++ gdb-7.6.90.20140127/gdb/m68k-tdep.c	2014-02-06 18:20:57.305752374 +0100
+--- gdb-7.7.1.orig/gdb/m68k-tdep.c	2014-05-09 19:24:18.694252771 +0200
++++ gdb-7.7.1/gdb/m68k-tdep.c	2014-05-09 20:02:09.627703769 +0200
 @@ -384,7 +384,7 @@ m68k_reg_struct_return_p (struct gdbarch
  {
    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -615,10 +615,10 @@ Index: gdb-7.6.90.20140127/gdb/m68k-tdep.c
  
        /* Non-scalars bigger than 4 bytes are left aligned, others are
  	 right aligned.  */
-Index: gdb-7.6.90.20140127/gdb/m88k-tdep.c
+Index: gdb-7.7.1/gdb/m88k-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/m88k-tdep.c	2014-02-06 18:20:52.987747735 +0100
-+++ gdb-7.6.90.20140127/gdb/m88k-tdep.c	2014-02-06 18:20:57.305752374 +0100
+--- gdb-7.7.1.orig/gdb/m88k-tdep.c	2014-05-09 19:24:18.694252771 +0200
++++ gdb-7.7.1/gdb/m88k-tdep.c	2014-05-09 20:02:09.627703769 +0200
 @@ -260,13 +260,13 @@ m88k_store_arguments (struct regcache *r
  {
    struct gdbarch *gdbarch = get_regcache_arch (regcache);
@@ -646,10 +646,10 @@ Index: gdb-7.6.90.20140127/gdb/m88k-tdep.c
  
        if (m88k_in_register_p (type))
  	{
-Index: gdb-7.6.90.20140127/gdb/mep-tdep.c
+Index: gdb-7.7.1/gdb/mep-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/mep-tdep.c	2014-02-06 18:20:52.987747735 +0100
-+++ gdb-7.6.90.20140127/gdb/mep-tdep.c	2014-02-06 18:20:57.306752375 +0100
+--- gdb-7.7.1.orig/gdb/mep-tdep.c	2014-05-09 19:24:18.695252772 +0200
++++ gdb-7.7.1/gdb/mep-tdep.c	2014-05-09 20:02:09.627703769 +0200
 @@ -2272,7 +2272,7 @@ push_large_arguments (CORE_ADDR sp, int
  
    for (i = 0; i < argc; i++)
@@ -659,10 +659,10 @@ Index: gdb-7.6.90.20140127/gdb/mep-tdep.c
  
        if (arg_len > MEP_GPR_SIZE)
          {
-Index: gdb-7.6.90.20140127/gdb/mips-tdep.c
+Index: gdb-7.7.1/gdb/mips-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/mips-tdep.c	2014-02-06 18:20:52.990747738 +0100
-+++ gdb-7.6.90.20140127/gdb/mips-tdep.c	2014-02-06 18:20:57.307752376 +0100
+--- gdb-7.7.1.orig/gdb/mips-tdep.c	2014-05-09 19:24:18.698252772 +0200
++++ gdb-7.7.1/gdb/mips-tdep.c	2014-05-09 20:02:09.628703769 +0200
 @@ -402,7 +402,7 @@ static void
  mips_xfer_register (struct gdbarch *gdbarch, struct regcache *regcache,
  		    int reg_num, int length,
@@ -808,10 +808,10 @@ Index: gdb-7.6.90.20140127/gdb/mips-tdep.c
  
        val = value_contents (arg);
  
-Index: gdb-7.6.90.20140127/gdb/mn10300-tdep.c
+Index: gdb-7.7.1/gdb/mn10300-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/mn10300-tdep.c	2014-02-06 18:20:52.991747739 +0100
-+++ gdb-7.6.90.20140127/gdb/mn10300-tdep.c	2014-02-06 18:20:57.308752377 +0100
+--- gdb-7.7.1.orig/gdb/mn10300-tdep.c	2014-05-09 19:24:18.698252772 +0200
++++ gdb-7.7.1/gdb/mn10300-tdep.c	2014-05-09 20:02:09.629703770 +0200
 @@ -1227,7 +1227,7 @@ mn10300_push_dummy_call (struct gdbarch
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    const int push_size = register_size (gdbarch, E_PC_REGNUM);
@@ -821,10 +821,10 @@ Index: gdb-7.6.90.20140127/gdb/mn10300-tdep.c
    int stack_offset = 0;
    int argnum;
    const gdb_byte *val;
-Index: gdb-7.6.90.20140127/gdb/mt-tdep.c
+Index: gdb-7.7.1/gdb/mt-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/mt-tdep.c	2014-02-06 18:20:52.991747739 +0100
-+++ gdb-7.6.90.20140127/gdb/mt-tdep.c	2014-02-06 18:20:57.308752377 +0100
+--- gdb-7.7.1.orig/gdb/mt-tdep.c	2014-05-09 19:24:18.699252772 +0200
++++ gdb-7.7.1/gdb/mt-tdep.c	2014-05-09 20:02:09.629703770 +0200
 @@ -783,9 +783,9 @@ mt_push_dummy_call (struct gdbarch *gdba
    gdb_byte buf[MT_MAX_STRUCT_SIZE];
    int argreg = MT_1ST_ARGREG;
@@ -837,10 +837,10 @@ Index: gdb-7.6.90.20140127/gdb/mt-tdep.c
    int i, j;
  
    /* First handle however many args we can fit into MT_1ST_ARGREG thru
-Index: gdb-7.6.90.20140127/gdb/ppc-sysv-tdep.c
+Index: gdb-7.7.1/gdb/ppc-sysv-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/ppc-sysv-tdep.c	2014-02-06 18:20:52.992747740 +0100
-+++ gdb-7.6.90.20140127/gdb/ppc-sysv-tdep.c	2014-02-06 18:20:57.308752377 +0100
+--- gdb-7.7.1.orig/gdb/ppc-sysv-tdep.c	2014-05-09 19:24:18.699252772 +0200
++++ gdb-7.7.1/gdb/ppc-sysv-tdep.c	2014-05-09 20:10:13.994807709 +0200
 @@ -68,7 +68,7 @@ ppc_sysv_abi_push_dummy_call (struct gdb
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    int opencl_abi = ppc_sysv_use_opencl_abi (value_type (function));
@@ -871,36 +871,24 @@ Index: gdb-7.6.90.20140127/gdb/ppc-sysv-tdep.c
  	  const bfd_byte *val = value_contents (arg);
  
  	  if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8
-@@ -1613,14 +1613,14 @@ ppc64_sysv_abi_push_dummy_call (struct g
- 	    }
- 	  else
- 	    {
--	      int byte;
-+	      ssize_t byte;
- 	      for (byte = 0; byte < TYPE_LENGTH (type);
- 		   byte += tdep->wordsize)
- 		{
- 		  if (write_pass && greg <= 10)
- 		    {
- 		      gdb_byte regval[MAX_REGISTER_SIZE];
--		      int len = TYPE_LENGTH (type) - byte;
-+		      ssize_t len = TYPE_LENGTH (type) - byte;
- 		      if (len > tdep->wordsize)
- 			len = tdep->wordsize;
- 		      memset (regval, 0, sizeof regval);
-@@ -1648,7 +1648,7 @@ ppc64_sysv_abi_push_dummy_call (struct g
- 		     register.  Work around this by always writing the
- 		     value to memory.  Fortunately, doing this
- 		     simplifies the code.  */
--		  int len = TYPE_LENGTH (type);
-+		  ssize_t len = TYPE_LENGTH (type);
- 		  if (len < tdep->wordsize)
- 		    write_memory (gparam + tdep->wordsize - len, val, len);
- 		  else
-Index: gdb-7.6.90.20140127/gdb/rl78-tdep.c
+@@ -1285,11 +1285,11 @@ struct ppc64_sysv_argpos
+ 
+ static void
+ ppc64_sysv_abi_push_val (struct gdbarch *gdbarch,
+-			 const bfd_byte *val, int len, int align,
++			 const bfd_byte *val, ssize_t len, int align,
+ 			 struct ppc64_sysv_argpos *argpos)
+ {
+   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+-  int offset = 0;
++  ssize_t offset = 0;
+ 
+   /* Enforce alignment of stack location, if requested.  */
+   if (align > tdep->wordsize)
+Index: gdb-7.7.1/gdb/rl78-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/rl78-tdep.c	2014-02-06 18:20:52.992747740 +0100
-+++ gdb-7.6.90.20140127/gdb/rl78-tdep.c	2014-02-06 18:20:57.309752378 +0100
+--- gdb-7.7.1.orig/gdb/rl78-tdep.c	2014-05-09 19:24:18.700252772 +0200
++++ gdb-7.7.1/gdb/rl78-tdep.c	2014-05-09 20:02:09.630703770 +0200
 @@ -1052,8 +1052,8 @@ rl78_push_dummy_call (struct gdbarch *gd
    for (i = nargs - 1; i >= 0; i--)
      {
@@ -912,10 +900,10 @@ Index: gdb-7.6.90.20140127/gdb/rl78-tdep.c
  
        sp -= container_len;
        write_memory (rl78_make_data_address (sp),
-Index: gdb-7.6.90.20140127/gdb/rs6000-aix-tdep.c
+Index: gdb-7.7.1/gdb/rs6000-aix-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/rs6000-aix-tdep.c	2014-02-06 18:20:52.993747741 +0100
-+++ gdb-7.6.90.20140127/gdb/rs6000-aix-tdep.c	2014-02-06 18:20:57.309752378 +0100
+--- gdb-7.7.1.orig/gdb/rs6000-aix-tdep.c	2014-05-09 19:24:18.700252772 +0200
++++ gdb-7.7.1/gdb/rs6000-aix-tdep.c	2014-05-09 20:02:09.630703770 +0200
 @@ -196,9 +196,9 @@ rs6000_push_dummy_call (struct gdbarch *
    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -937,10 +925,10 @@ Index: gdb-7.6.90.20140127/gdb/rs6000-aix-tdep.c
  
        if (argbytes)
  	{
-Index: gdb-7.6.90.20140127/gdb/s390-linux-tdep.c
+Index: gdb-7.7.1/gdb/s390-linux-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/s390-linux-tdep.c	2014-02-06 18:20:52.993747741 +0100
-+++ gdb-7.6.90.20140127/gdb/s390-linux-tdep.c	2014-02-06 18:22:17.330838389 +0100
+--- gdb-7.7.1.orig/gdb/s390-linux-tdep.c	2014-05-09 19:24:18.701252772 +0200
++++ gdb-7.7.1/gdb/s390-linux-tdep.c	2014-05-09 20:02:09.631703770 +0200
 @@ -2526,7 +2526,7 @@ is_float_like (struct type *type)
  
  
@@ -959,10 +947,10 @@ Index: gdb-7.6.90.20140127/gdb/s390-linux-tdep.c
  
  	if (s390_function_arg_pass_by_reference (type))
  	  {
-Index: gdb-7.6.90.20140127/gdb/score-tdep.c
+Index: gdb-7.7.1/gdb/score-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/score-tdep.c	2014-02-06 18:20:52.994747742 +0100
-+++ gdb-7.6.90.20140127/gdb/score-tdep.c	2014-02-06 18:20:57.310752379 +0100
+--- gdb-7.7.1.orig/gdb/score-tdep.c	2014-05-09 19:24:18.701252772 +0200
++++ gdb-7.7.1/gdb/score-tdep.c	2014-05-09 20:02:09.631703770 +0200
 @@ -515,7 +515,7 @@ score_push_dummy_call (struct gdbarch *g
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    int argnum;
@@ -972,10 +960,10 @@ Index: gdb-7.6.90.20140127/gdb/score-tdep.c
    CORE_ADDR stack_offset = 0;
    CORE_ADDR addr = 0;
  
-Index: gdb-7.6.90.20140127/gdb/sh-tdep.c
+Index: gdb-7.7.1/gdb/sh-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/sh-tdep.c	2014-02-06 18:20:52.995747743 +0100
-+++ gdb-7.6.90.20140127/gdb/sh-tdep.c	2014-02-06 18:20:57.310752379 +0100
+--- gdb-7.7.1.orig/gdb/sh-tdep.c	2014-05-09 19:24:18.702252772 +0200
++++ gdb-7.7.1/gdb/sh-tdep.c	2014-05-09 20:02:09.631703770 +0200
 @@ -807,7 +807,7 @@ sh_skip_prologue (struct gdbarch *gdbarc
  static int
  sh_use_struct_convention (int renesas_abi, struct type *type)
@@ -1014,10 +1002,10 @@ Index: gdb-7.6.90.20140127/gdb/sh-tdep.c
    int pass_on_stack = 0;
    int last_reg_arg = INT_MAX;
  
-Index: gdb-7.6.90.20140127/gdb/sh64-tdep.c
+Index: gdb-7.7.1/gdb/sh64-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/sh64-tdep.c	2014-02-06 18:20:52.995747743 +0100
-+++ gdb-7.6.90.20140127/gdb/sh64-tdep.c	2014-02-06 18:20:57.311752380 +0100
+--- gdb-7.7.1.orig/gdb/sh64-tdep.c	2014-05-09 19:24:18.702252772 +0200
++++ gdb-7.7.1/gdb/sh64-tdep.c	2014-05-09 20:02:09.632703771 +0200
 @@ -1058,7 +1058,7 @@ sh64_push_dummy_call (struct gdbarch *gd
  		      CORE_ADDR struct_addr)
  {
@@ -1036,10 +1024,10 @@ Index: gdb-7.6.90.20140127/gdb/sh64-tdep.c
    int argreg_size;
    int fp_args[12];
  
-Index: gdb-7.6.90.20140127/gdb/sparc-tdep.c
+Index: gdb-7.7.1/gdb/sparc-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/sparc-tdep.c	2014-02-06 18:20:52.996747744 +0100
-+++ gdb-7.6.90.20140127/gdb/sparc-tdep.c	2014-02-06 18:20:57.311752380 +0100
+--- gdb-7.7.1.orig/gdb/sparc-tdep.c	2014-05-09 19:24:18.703252772 +0200
++++ gdb-7.7.1/gdb/sparc-tdep.c	2014-05-09 20:02:09.632703771 +0200
 @@ -502,7 +502,7 @@ sparc32_store_arguments (struct regcache
    for (i = 0; i < nargs; i++)
      {
@@ -1049,10 +1037,10 @@ Index: gdb-7.6.90.20140127/gdb/sparc-tdep.c
  
        if (sparc_structure_or_union_p (type)
  	  || (sparc_floating_p (type) && len == 16)
-Index: gdb-7.6.90.20140127/gdb/sparc64-tdep.c
+Index: gdb-7.7.1/gdb/sparc64-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/sparc64-tdep.c	2014-02-06 18:20:52.996747744 +0100
-+++ gdb-7.6.90.20140127/gdb/sparc64-tdep.c	2014-02-06 18:20:57.311752380 +0100
+--- gdb-7.7.1.orig/gdb/sparc64-tdep.c	2014-05-09 19:24:18.704252773 +0200
++++ gdb-7.7.1/gdb/sparc64-tdep.c	2014-05-09 20:02:09.632703771 +0200
 @@ -639,7 +639,8 @@ sparc64_16_byte_align_p (struct type *ty
  
  static void
@@ -1108,10 +1096,10 @@ Index: gdb-7.6.90.20140127/gdb/sparc64-tdep.c
        int regnum = -1;
        gdb_byte buf[16];
  
-Index: gdb-7.6.90.20140127/gdb/spu-tdep.c
+Index: gdb-7.7.1/gdb/spu-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/spu-tdep.c	2014-02-06 18:20:52.997747745 +0100
-+++ gdb-7.6.90.20140127/gdb/spu-tdep.c	2014-02-06 18:20:57.312752381 +0100
+--- gdb-7.7.1.orig/gdb/spu-tdep.c	2014-05-09 19:24:18.704252773 +0200
++++ gdb-7.7.1/gdb/spu-tdep.c	2014-05-09 20:02:09.633703771 +0200
 @@ -1376,7 +1376,7 @@ spu_push_dummy_call (struct gdbarch *gdb
        struct value *arg = args[i];
        struct type *type = check_typedef (value_type (arg));
@@ -1130,10 +1118,10 @@ Index: gdb-7.6.90.20140127/gdb/spu-tdep.c
  	  int preferred_slot;
  	  
  	  if (spu_scalar_value_p (type))
-Index: gdb-7.6.90.20140127/gdb/tic6x-tdep.c
+Index: gdb-7.7.1/gdb/tic6x-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/tic6x-tdep.c	2014-02-06 18:20:52.997747745 +0100
-+++ gdb-7.6.90.20140127/gdb/tic6x-tdep.c	2014-02-06 18:20:57.312752381 +0100
+--- gdb-7.7.1.orig/gdb/tic6x-tdep.c	2014-05-09 19:24:18.705252773 +0200
++++ gdb-7.7.1/gdb/tic6x-tdep.c	2014-05-09 20:02:09.633703771 +0200
 @@ -896,7 +896,7 @@ tic6x_push_dummy_call (struct gdbarch *g
    int argreg = 0;
    int argnum;
@@ -1171,10 +1159,10 @@ Index: gdb-7.6.90.20140127/gdb/tic6x-tdep.c
  
  	  addr = sp + stack_offset;
  	  write_memory (addr, val, len);
-Index: gdb-7.6.90.20140127/gdb/tilegx-tdep.c
+Index: gdb-7.7.1/gdb/tilegx-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/tilegx-tdep.c	2014-02-06 18:20:52.998747746 +0100
-+++ gdb-7.6.90.20140127/gdb/tilegx-tdep.c	2014-02-06 18:20:57.312752381 +0100
+--- gdb-7.7.1.orig/gdb/tilegx-tdep.c	2014-05-09 19:24:18.705252773 +0200
++++ gdb-7.7.1/gdb/tilegx-tdep.c	2014-05-09 20:02:09.633703771 +0200
 @@ -290,7 +290,7 @@ tilegx_push_dummy_call (struct gdbarch *
    CORE_ADDR stack_dest = sp;
    int argreg = TILEGX_R0_REGNUM;
@@ -1184,10 +1172,10 @@ Index: gdb-7.6.90.20140127/gdb/tilegx-tdep.c
    static const gdb_byte four_zero_words[16] = { 0 };
  
    /* If struct_return is 1, then the struct return address will
-Index: gdb-7.6.90.20140127/gdb/v850-tdep.c
+Index: gdb-7.7.1/gdb/v850-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/v850-tdep.c	2014-02-06 18:20:52.998747746 +0100
-+++ gdb-7.6.90.20140127/gdb/v850-tdep.c	2014-02-06 18:20:57.313752383 +0100
+--- gdb-7.7.1.orig/gdb/v850-tdep.c	2014-05-09 19:24:18.705252773 +0200
++++ gdb-7.7.1/gdb/v850-tdep.c	2014-05-09 20:02:09.634703771 +0200
 @@ -1021,7 +1021,7 @@ v850_push_dummy_call (struct gdbarch *gd
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    int argreg;
@@ -1206,10 +1194,10 @@ Index: gdb-7.6.90.20140127/gdb/v850-tdep.c
        gdb_byte *val;
        gdb_byte valbuf[v850_reg_size];
  
-Index: gdb-7.6.90.20140127/gdb/vax-tdep.c
+Index: gdb-7.7.1/gdb/vax-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/vax-tdep.c	2014-02-06 18:20:52.998747746 +0100
-+++ gdb-7.6.90.20140127/gdb/vax-tdep.c	2014-02-06 18:20:57.313752383 +0100
+--- gdb-7.7.1.orig/gdb/vax-tdep.c	2014-05-09 19:24:18.706252773 +0200
++++ gdb-7.7.1/gdb/vax-tdep.c	2014-05-09 20:02:09.634703771 +0200
 @@ -115,7 +115,7 @@ vax_store_arguments (struct regcache *re
    struct gdbarch *gdbarch = get_regcache_arch (regcache);
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -1228,10 +1216,10 @@ Index: gdb-7.6.90.20140127/gdb/vax-tdep.c
  
        sp -= (len + 3) & ~3;
        count += (len + 3) / 4;
-Index: gdb-7.6.90.20140127/gdb/xstormy16-tdep.c
+Index: gdb-7.7.1/gdb/xstormy16-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/xstormy16-tdep.c	2014-02-06 18:20:52.999747748 +0100
-+++ gdb-7.6.90.20140127/gdb/xstormy16-tdep.c	2014-02-06 18:20:57.313752383 +0100
+--- gdb-7.7.1.orig/gdb/xstormy16-tdep.c	2014-05-09 19:24:18.706252773 +0200
++++ gdb-7.7.1/gdb/xstormy16-tdep.c	2014-05-09 20:02:09.634703771 +0200
 @@ -235,8 +235,9 @@ xstormy16_push_dummy_call (struct gdbarc
    enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
    CORE_ADDR stack_dest = sp;
@@ -1244,10 +1232,10 @@ Index: gdb-7.6.90.20140127/gdb/xstormy16-tdep.c
    const gdb_byte *val;
    gdb_byte buf[xstormy16_pc_size];
  
-Index: gdb-7.6.90.20140127/gdb/xtensa-tdep.c
+Index: gdb-7.7.1/gdb/xtensa-tdep.c
 ===================================================================
---- gdb-7.6.90.20140127.orig/gdb/xtensa-tdep.c	2014-02-06 18:20:53.000747749 +0100
-+++ gdb-7.6.90.20140127/gdb/xtensa-tdep.c	2014-02-06 18:20:57.314752384 +0100
+--- gdb-7.7.1.orig/gdb/xtensa-tdep.c	2014-05-09 19:24:18.707252773 +0200
++++ gdb-7.7.1/gdb/xtensa-tdep.c	2014-05-09 20:02:09.634703771 +0200
 @@ -1652,8 +1652,7 @@ xtensa_store_return_value (struct type *
  
        if (len > (callsize > 8 ? 8 : 16))
diff --git a/gdb-upstream-ppc64le02of15.patch b/gdb-upstream-ppc64le02of15.patch
new file mode 100644
index 0000000..202e3f5
--- /dev/null
+++ b/gdb-upstream-ppc64le02of15.patch
@@ -0,0 +1,61 @@
+commit 718ee4dc9b09491707420ae403ad1ce8dfdb61b2
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Thu Jan 30 19:12:35 2014 +0100
+
+    Add support for AT_HWCAP2 auxv entry
+    
+    Recent ppc64 Linux kernels provide a new auxv entry AT_HWCAP2,
+    which is currently not recognized by GDB, causing every use of
+    "info auxv" to show an error.
+    
+    This commit adds the AT_HWCAP2 define to include/elf/common.h
+    and handles it in GDB.
+    
+    include/elf/ChangeLog:
+    
+    	* common.h (AT_HWCAP2): Define.
+    
+    gdb/ChangeLog:
+    
+    	* auxv.c (fprint_target_auxv): Handle AT_HWCAP2.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,3 +1,7 @@
++2014-01-30  Ulrich Weigand  <uweigand at de.ibm.com>
++
++	* auxv.c (fprint_target_auxv): Handle AT_HWCAP2.
++
+ 2014-01-29  Jose E. Marchesi  <jose.marchesi at oracle.com>
+ 
+ 	* sparc64-linux-tdep.c (sparc64_linux_step_trap): Get PC from
+--- a/gdb/auxv.c
++++ b/gdb/auxv.c
+@@ -442,6 +442,7 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
+ 	  TAG (AT_IGNOREPPC, _("Entry should be ignored"), dec);
+ 	  TAG (AT_BASE_PLATFORM, _("String identifying base platform"), str);
+ 	  TAG (AT_RANDOM, _("Address of 16 random bytes"), hex);
++	  TAG (AT_HWCAP2, _("Extension of AT_HWCAP"), hex);
+ 	  TAG (AT_EXECFN, _("File name of executable"), str);
+ 	  TAG (AT_SECURE, _("Boolean, was exec setuid-like?"), dec);
+ 	  TAG (AT_SYSINFO, _("Special system info/entry points"), hex);
+### a/include/elf/ChangeLog
+### b/include/elf/ChangeLog
+## -1,3 +1,7 @@
++2014-01-30  Ulrich Weigand  <uweigand at de.ibm.com>
++
++	* common.h (AT_HWCAP2): Define.
++
+ 2013-12-13  Kuan-Lin Chen  <kuanlinchentw at gmail.com>
+ 	    Wei-Cheng Wang  <cole945 at gmail.com>
+ 
+--- a/include/elf/common.h
++++ b/include/elf/common.h
+@@ -959,6 +959,7 @@
+ #define AT_BASE_PLATFORM 24		/* String identifying real platform,
+ 					   may differ from AT_PLATFORM.  */
+ #define AT_RANDOM	25		/* Address of 16 random bytes.  */
++#define AT_HWCAP2	26		/* Extension of AT_HWCAP.  */
+ #define AT_EXECFN	31		/* Filename of executable.  */
+ /* Pointer to the global system page used for system calls and other
+    nice things.  */
diff --git a/gdb-upstream-ppc64le03of15.patch b/gdb-upstream-ppc64le03of15.patch
new file mode 100644
index 0000000..30b4fcf
--- /dev/null
+++ b/gdb-upstream-ppc64le03of15.patch
@@ -0,0 +1,36 @@
+commit 36c24d95382572e9cf4095712a8613664d7165cc
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:19:51 2014 +0100
+
+    Document support for powerpc64le-*-linux* target
+    
+    gdb/ChangeLog:
+    
+    	* NEWS: Document new target powerpc64le-*-linux*.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,3 +1,7 @@
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
++	* NEWS: Document new target powerpc64le-*-linux*.
++
+ 2014-02-04  Mark Kettenis  <kettenis at gnu.org>
+ 
+ 	* sparc64obsd-tdep.c (sparc64obsd_gregset): New variable.
+Index: gdb-7.7.1/gdb/NEWS
+===================================================================
+--- gdb-7.7.1.orig/gdb/NEWS	2014-05-09 19:21:57.798235002 +0200
++++ gdb-7.7.1/gdb/NEWS	2014-05-09 19:22:30.206239145 +0200
+@@ -1,6 +1,11 @@
+ 		What has changed in GDB?
+ 	     (Organized release by release)
+ 
++*** Changes since GDB 7.7
++
++* New targets
++PowerPC64 GNU/Linux little-endian	powerpc64le-*-linux*
++
+ *** Changes in GDB 7.7
+ 
+ * GDB now supports SystemTap SDT probes on AArch64 GNU/Linux.
diff --git a/gdb-upstream-ppc64le04of15.patch b/gdb-upstream-ppc64le04of15.patch
new file mode 100644
index 0000000..1b6730f
--- /dev/null
+++ b/gdb-upstream-ppc64le04of15.patch
@@ -0,0 +1,1413 @@
+commit e765b44c3853ed228506fc22c276becd63198238
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:24:42 2014 +0100
+
+    Refactor ppc64 function call and return value handling
+    
+    This patch refactors the ppc64 function call and return value handling code
+    in ppc-sysv-tdep.c.  The main problem to be addressed by this refactoring
+    is the code duplication caused by certain aggregate types:
+    
+    According to the ABI, some types are to be decomposed into component types
+    for parameter and return value handling.  For example, complex types are
+    to be passed as if the real and imaginary component were separate arguments.
+    Similarly, certain OpenCL vector types are passed as if they were multiple
+    separate arguments of the vector element type.  With the new ELFv2 ABI,
+    there is another case: "homogeneous aggregates" (e.g. a struct containing
+    4 floats) are passed in multiple floating point registers as well.
+    
+    Unfortunately, the current code is not structured to easily model these
+    ABI properties.  For example, code to pass complex values re-implements
+    code to pass the underlying (floating-point) type.  This has already
+    led to some unfortunate code duplication, and with the addition of
+    ELFv2 ABI support, I would have had to add yet more such duplication.
+    
+    To avoid that, I've decided to refactor the code in order to re-use
+    subroutines that handle the "base" types when handling those aggregate
+    types.  This was not intended to cause any difference on current
+    (ELFv1) ABI code, but in fact it fixes a bug:
+    
+    FAIL: gdb.base/varargs.exp: print find_max_float_real(4, fc1, fc2, fc3, fc4)
+    
+    This was caused by the old code in ppc64_sysv_abi_push_float incorrectly
+    handling floating-point arguments to vararg routines, which just happens
+    to work out correctly automatically in the refactored code ...
+    
+    gdb/ChangeLog:
+    
+    	* ppc-sysv-tdep.c (get_decimal_float_return_value): Update comment.
+    	(struct ppc64_sysv_argpos): New data structure.
+    	(ppc64_sysv_abi_push_float): Remove.
+    	(ppc64_sysv_abi_push_val): New function.
+    	(ppc64_sysv_abi_push_integer): Likewise.
+    	(ppc64_sysv_abi_push_freg): Likewise.
+    	(ppc64_sysv_abi_push_vreg): Likewise.
+    	(ppc64_sysv_abi_push_param): Likewise.
+    	(ppc64_sysv_abi_push_dummy_call): Refactor to use those new routines.
+    	(ppc64_sysv_abi_return_value_base): New function.
+    	(ppc64_sysv_abi_return_value): Refactor to use it.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,19 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-sysv-tdep.c (get_decimal_float_return_value): Update comment.
++	(struct ppc64_sysv_argpos): New data structure.
++	(ppc64_sysv_abi_push_float): Remove.
++	(ppc64_sysv_abi_push_val): New function.
++	(ppc64_sysv_abi_push_integer): Likewise.
++	(ppc64_sysv_abi_push_freg): Likewise.
++	(ppc64_sysv_abi_push_vreg): Likewise.
++	(ppc64_sysv_abi_push_param): Likewise.
++	(ppc64_sysv_abi_push_dummy_call): Refactor to use those new routines.
++	(ppc64_sysv_abi_return_value_base): New function.
++	(ppc64_sysv_abi_return_value): Refactor to use it.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* NEWS: Document new target powerpc64le-*-linux*.
+ 
+ 2014-02-04  Mark Kettenis  <kettenis at gnu.org>
+--- a/gdb/ppc-sysv-tdep.c
++++ b/gdb/ppc-sysv-tdep.c
+@@ -609,8 +609,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+   return sp;
+ }
+ 
+-/* Handle the return-value conventions for Decimal Floating Point values
+-   in both ppc32 and ppc64, which are the same.  */
++/* Handle the return-value conventions for Decimal Floating Point values.  */
+ static int
+ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
+ 				struct regcache *regcache, gdb_byte *readbuf,
+@@ -1102,80 +1101,287 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
+   return 1;
+ }
+ 
+-/* Push a float in either registers, or in the stack.  Using the ppc 64 bit
+-   SysV ABI.
++/* Structure holding the next argument position.  */
++struct ppc64_sysv_argpos
++  {
++    /* Register cache holding argument registers.  If this is NULL,
++       we only simulate argument processing without actually updating
++       any registers or memory.  */
++    struct regcache *regcache;
++    /* Next available general-purpose argument register.  */
++    int greg;
++    /* Next available floating-point argument register.  */
++    int freg;
++    /* Next available vector argument register.  */
++    int vreg;
++    /* The address, at which the next general purpose parameter
++       (integer, struct, float, vector, ...) should be saved.  */
++    CORE_ADDR gparam;
++    /* The address, at which the next by-reference parameter
++       (non-Altivec vector, variably-sized type) should be saved.  */
++    CORE_ADDR refparam;
++  };
++
++/* VAL is a value of length LEN.  Store it into the argument area on the
++   stack and load it into the corresponding general-purpose registers
++   required by the ABI, and update ARGPOS.
++
++   If ALIGN is nonzero, it specifies the minimum alignment required
++   for the on-stack copy of the argument.  */
+ 
+-   This implements a dumbed down version of the ABI.  It always writes
+-   values to memory, GPR and FPR, even when not necessary.  Doing this
+-   greatly simplifies the logic.  */
++static void
++ppc64_sysv_abi_push_val (struct gdbarch *gdbarch,
++			 const bfd_byte *val, int len, int align,
++			 struct ppc64_sysv_argpos *argpos)
++{
++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++  int offset = 0;
++
++  /* Enforce alignment of stack location, if requested.  */
++  if (align > tdep->wordsize)
++    {
++      CORE_ADDR aligned_gparam = align_up (argpos->gparam, align);
++
++      argpos->greg += (aligned_gparam - argpos->gparam) / tdep->wordsize;
++      argpos->gparam = aligned_gparam;
++    }
++
++  /* The ABI (version 1.9) specifies that values smaller than one
++     doubleword are right-aligned and those larger are left-aligned.
++     GCC versions before 3.4 implemented this incorrectly; see
++     <http://gcc.gnu.org/gcc-3.4/powerpc-abi.html>.  */
++  if (len < tdep->wordsize)
++    offset = tdep->wordsize - len;
++
++  if (argpos->regcache)
++    write_memory (argpos->gparam + offset, val, len);
++  argpos->gparam = align_up (argpos->gparam + len, tdep->wordsize);
++
++  while (len >= tdep->wordsize)
++    {
++      if (argpos->regcache && argpos->greg <= 10)
++	regcache_cooked_write (argpos->regcache,
++			       tdep->ppc_gp0_regnum + argpos->greg, val);
++      argpos->greg++;
++      len -= tdep->wordsize;
++      val += tdep->wordsize;
++    }
++
++  if (len > 0)
++    {
++      if (argpos->regcache && argpos->greg <= 10)
++	regcache_cooked_write_part (argpos->regcache,
++				    tdep->ppc_gp0_regnum + argpos->greg,
++				    offset, len, val);
++      argpos->greg++;
++    }
++}
++
++/* The same as ppc64_sysv_abi_push_val, but using a single-word integer
++   value VAL as argument.  */
+ 
+ static void
+-ppc64_sysv_abi_push_float (struct gdbarch *gdbarch, struct regcache *regcache,
+-			   struct gdbarch_tdep *tdep, struct type *type, 
+-			   const bfd_byte *val, int freg, int greg,
+-			   CORE_ADDR gparam)
++ppc64_sysv_abi_push_integer (struct gdbarch *gdbarch, ULONGEST val,
++			     struct ppc64_sysv_argpos *argpos)
+ {
+-  gdb_byte regval[MAX_REGISTER_SIZE];
+-  const gdb_byte *p;
++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
++  gdb_byte buf[MAX_REGISTER_SIZE];
+ 
+-  if (TYPE_LENGTH (type) <= 8)
++  if (argpos->regcache)
++    store_unsigned_integer (buf, tdep->wordsize, byte_order, val);
++  ppc64_sysv_abi_push_val (gdbarch, buf, tdep->wordsize, 0, argpos);
++}
++
++/* VAL is a value of TYPE, a (binary or decimal) floating-point type.
++   Load it into a floating-point register if required by the ABI,
++   and update ARGPOS.  */
++
++static void
++ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch,
++			  struct type *type, const bfd_byte *val,
++			  struct ppc64_sysv_argpos *argpos)
++{
++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++  if (tdep->soft_float)
++    return;
++
++  if (TYPE_LENGTH (type) <= 8
++      && TYPE_CODE (type) == TYPE_CODE_FLT)
+     {
+-      /* Version 1.7 of the 64-bit PowerPC ELF ABI says:
++      /* Floats and doubles go in f1 .. f13.  32-bit floats are converted
++ 	 to double first.  */
++      if (argpos->regcache && argpos->freg <= 13)
++	{
++	  int regnum = tdep->ppc_fp0_regnum + argpos->freg;
++	  struct type *regtype = register_type (gdbarch, regnum);
++	  gdb_byte regval[MAX_REGISTER_SIZE];
+ 
+-	 "Single precision floating point values are mapped to
+-	 the first word in a single doubleword."
++	  convert_typed_floating (val, type, regval, regtype);
++	  regcache_cooked_write (argpos->regcache, regnum, regval);
++	}
+ 
+-	 And version 1.9 says:
++      argpos->freg++;
++    }
++  else if (TYPE_LENGTH (type) <= 8
++	   && TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
++    {
++      /* Floats and doubles go in f1 .. f13.  32-bit decimal floats are
++	 placed in the least significant word.  */
++      if (argpos->regcache && argpos->freg <= 13)
++	{
++	  int regnum = tdep->ppc_fp0_regnum + argpos->freg;
++	  int offset = 8 - TYPE_LENGTH (type);
+ 
+-	 "Single precision floating point values are mapped to
+-	 the second word in a single doubleword."
++	  regcache_cooked_write_part (argpos->regcache, regnum,
++				      offset, TYPE_LENGTH (type), val);
++	}
+ 
+-	 GDB then writes single precision floating point values
+-	 at both words in a doubleword, to support both ABIs.  */
+-      if (TYPE_LENGTH (type) == 4)
++      argpos->freg++;
++    }
++  else if (TYPE_LENGTH (type) == 16
++	   && TYPE_CODE (type) == TYPE_CODE_FLT
++	   && (gdbarch_long_double_format (gdbarch)
++	       == floatformats_ibm_long_double))
++    {
++      /* IBM long double stored in two consecutive FPRs.  */
++      if (argpos->regcache && argpos->freg <= 13)
+ 	{
+-	  memcpy (regval, val, 4);
+-	  memcpy (regval + 4, val, 4);
+-	  p = regval;
++	  int regnum = tdep->ppc_fp0_regnum + argpos->freg;
++
++	  regcache_cooked_write (argpos->regcache, regnum, val);
++	  if (argpos->freg <= 12)
++	    regcache_cooked_write (argpos->regcache, regnum + 1, val + 8);
+ 	}
+-      else
+-	p = val;
+ 
+-      /* Write value in the stack's parameter save area.  */
+-      write_memory (gparam, p, 8);
++      argpos->freg += 2;
++    }
++  else if (TYPE_LENGTH (type) == 16
++	   && TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
++    {
++      /* 128-bit decimal floating-point values are stored in and even/odd
++	 pair of FPRs, with the even FPR holding the most significant half.  */
++      argpos->freg += argpos->freg & 1;
+ 
+-      /* Floats and Doubles go in f1 .. f13.  They also consume a left aligned
+-	 GREG, and can end up in memory.  */
+-      if (freg <= 13)
++      if (argpos->regcache && argpos->freg <= 12)
+ 	{
+-	  struct type *regtype;
++	  int regnum = tdep->ppc_fp0_regnum + argpos->freg;
+ 
+-	  regtype = register_type (gdbarch, tdep->ppc_fp0_regnum + freg);
+-	  convert_typed_floating (val, type, regval, regtype);
+-	  regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, regval);
++	  regcache_cooked_write (argpos->regcache, regnum, val);
++	  regcache_cooked_write (argpos->regcache, regnum + 1, val + 8);
+ 	}
+-      if (greg <= 10)
+-	regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, regval);
++
++      argpos->freg += 2;
+     }
+-  else
++}
++
++/* VAL is a value of AltiVec vector type.  Load it into a vector register
++   if required by the ABI, and update ARGPOS.  */
++
++static void
++ppc64_sysv_abi_push_vreg (struct gdbarch *gdbarch, const bfd_byte *val,
++			  struct ppc64_sysv_argpos *argpos)
++{
++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++
++  if (argpos->regcache && argpos->vreg <= 13)
++    regcache_cooked_write (argpos->regcache,
++			   tdep->ppc_vr0_regnum + argpos->vreg, val);
++
++  argpos->vreg++;
++}
++
++/* VAL is a value of TYPE.  Load it into memory and/or registers
++   as required by the ABI, and update ARGPOS.  */
++
++static void
++ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
++			   struct type *type, const bfd_byte *val,
++			   struct ppc64_sysv_argpos *argpos)
++{
++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++
++  if (TYPE_CODE (type) == TYPE_CODE_FLT
++      || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
++    {
++      /* Floating-point scalars are passed in floating-point registers.  */
++      ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 0, argpos);
++      ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos);
++    }
++  else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
++	   && tdep->vector_abi == POWERPC_VEC_ALTIVEC
++	   && TYPE_LENGTH (type) == 16)
++    {
++      /* AltiVec vectors are passed aligned, and in vector registers.  */
++      ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 16, argpos);
++      ppc64_sysv_abi_push_vreg (gdbarch, val, argpos);
++    }
++  else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
++	   && TYPE_LENGTH (type) >= 16)
+     {
+-      /* IBM long double stored in two doublewords of the
+-	 parameter save area and corresponding registers.  */
+-      if (!tdep->soft_float && freg <= 13)
++      /* Non-Altivec vectors are passed by reference.  */
++
++      /* Copy value onto the stack ...  */
++      CORE_ADDR addr = align_up (argpos->refparam, 16);
++      if (argpos->regcache)
++	write_memory (addr, val, TYPE_LENGTH (type));
++      argpos->refparam = align_up (addr + TYPE_LENGTH (type), tdep->wordsize);
++
++      /* ... and pass a pointer to the copy as parameter.  */
++      ppc64_sysv_abi_push_integer (gdbarch, addr, argpos);
++    }
++  else if ((TYPE_CODE (type) == TYPE_CODE_INT
++	    || TYPE_CODE (type) == TYPE_CODE_ENUM
++	    || TYPE_CODE (type) == TYPE_CODE_BOOL
++	    || TYPE_CODE (type) == TYPE_CODE_CHAR
++	    || TYPE_CODE (type) == TYPE_CODE_PTR
++	    || TYPE_CODE (type) == TYPE_CODE_REF)
++	   && TYPE_LENGTH (type) <= tdep->wordsize)
++    {
++      ULONGEST word = 0;
++
++      if (argpos->regcache)
+ 	{
+-	  regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg, val);
+-	  if (freg <= 12)
+-	    regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + freg + 1,
+-				   val + 8);
++	  /* Sign extend the value, then store it unsigned.  */
++	  word = unpack_long (type, val);
++
++	  /* Convert any function code addresses into descriptors.  */
++	  if (TYPE_CODE (type) == TYPE_CODE_PTR
++	      || TYPE_CODE (type) == TYPE_CODE_REF)
++	    {
++	      struct type *target_type
++		= check_typedef (TYPE_TARGET_TYPE (type));
++
++	      if (TYPE_CODE (target_type) == TYPE_CODE_FUNC
++		  || TYPE_CODE (target_type) == TYPE_CODE_METHOD)
++		{
++		  CORE_ADDR desc = word;
++
++		  convert_code_addr_to_desc_addr (word, &desc);
++		  word = desc;
++		}
++	    }
+ 	}
+-      if (greg <= 10)
++
++      ppc64_sysv_abi_push_integer (gdbarch, word, argpos);
++    }
++  else
++    {
++      ppc64_sysv_abi_push_val (gdbarch, val, TYPE_LENGTH (type), 0, argpos);
++
++      /* The ABI (version 1.9) specifies that structs containing a
++	 single floating-point value, at any level of nesting of
++	 single-member structs, are passed in floating-point registers.  */
++      if (TYPE_CODE (type) == TYPE_CODE_STRUCT
++	  && TYPE_NFIELDS (type) == 1)
+ 	{
+-	  regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg, val);
+-	  if (greg <= 9)
+-	    regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + greg + 1,
+-				   val + 8);
++	  while (TYPE_CODE (type) == TYPE_CODE_STRUCT
++		 && TYPE_NFIELDS (type) == 1)
++	    type = check_typedef (TYPE_FIELD_TYPE (type, 0));
++
++	  if (TYPE_CODE (type) == TYPE_CODE_FLT)
++	    ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos);
+ 	}
+-      write_memory (gparam, val, TYPE_LENGTH (type));
+     }
+ }
+ 
+@@ -1237,20 +1443,11 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+   for (write_pass = 0; write_pass < 2; write_pass++)
+     {
+       int argno;
+-      /* Next available floating point register for float and double
+-         arguments.  */
+-      int freg = 1;
+-      /* Next available general register for non-vector (but possibly
+-         float) arguments.  */
+-      int greg = 3;
+-      /* Next available vector register for vector arguments.  */
+-      int vreg = 2;
+-      /* The address, at which the next general purpose parameter
+-         (integer, struct, float, vector, ...) should be saved.  */
+-      CORE_ADDR gparam;
+-      /* The address, at which the next by-reference parameter
+-	 (non-Altivec vector, variably-sized type) should be saved.  */
+-      CORE_ADDR refparam;
++
++      struct ppc64_sysv_argpos argpos;
++      argpos.greg = 3;
++      argpos.freg = 1;
++      argpos.vreg = 2;
+ 
+       if (!write_pass)
+ 	{
+@@ -1258,19 +1455,21 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+ 	     offsets (start address zero) than addresses.  That way
+ 	     they accumulate the total stack space each region
+ 	     requires.  */
+-	  gparam = 0;
+-	  refparam = 0;
++	  argpos.regcache = NULL;
++	  argpos.gparam = 0;
++	  argpos.refparam = 0;
+ 	}
+       else
+ 	{
+ 	  /* Decrement the stack pointer making space for the Altivec
+ 	     and general on-stack parameters.  Set refparam and gparam
+ 	     to their corresponding regions.  */
+-	  refparam = align_down (sp - refparam_size, 16);
+-	  gparam = align_down (refparam - gparam_size, 16);
++	  argpos.regcache = regcache;
++	  argpos.refparam = align_down (sp - refparam_size, 16);
++	  argpos.gparam = align_down (argpos.refparam - gparam_size, 16);
+ 	  /* Add in space for the TOC, link editor double word,
+ 	     compiler double word, LR save area, CR save area.  */
+-	  sp = align_down (gparam - 48, 16);
++	  sp = align_down (argpos.gparam - 48, 16);
+ 	}
+ 
+       /* If the function is returning a `struct', then there is an
+@@ -1279,14 +1478,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+          should advance one word and start from r4 register to copy
+          parameters.  This also consumes one on-stack parameter slot.  */
+       if (struct_return)
+-	{
+-	  if (write_pass)
+-	    regcache_cooked_write_signed (regcache,
+-					  tdep->ppc_gp0_regnum + greg,
+-					  struct_addr);
+-	  greg++;
+-	  gparam = align_up (gparam + tdep->wordsize, tdep->wordsize);
+-	}
++	ppc64_sysv_abi_push_integer (gdbarch, struct_addr, &argpos);
+ 
+       for (argno = 0; argno < nargs; argno++)
+ 	{
+@@ -1294,432 +1486,54 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+ 	  struct type *type = check_typedef (value_type (arg));
+ 	  const bfd_byte *val = value_contents (arg);
+ 
+-	  if (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) <= 8)
++	  if (TYPE_CODE (type) == TYPE_CODE_COMPLEX)
+ 	    {
+-	      if (write_pass)
+-		  ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, type,
+-					     val, freg, greg, gparam);
+-
+-	      freg++;
+-	      greg++;
+-	      /* Always consume parameter stack space.  */
+-	      gparam = align_up (gparam + 8, tdep->wordsize);
+-	    }
+-	  else if (TYPE_CODE (type) == TYPE_CODE_FLT
+-		   && TYPE_LENGTH (type) == 16
+-		   && (gdbarch_long_double_format (gdbarch)
+-		       == floatformats_ibm_long_double))
+-	    {
+-	      if (write_pass)
+-		ppc64_sysv_abi_push_float (gdbarch, regcache, tdep, type,
+-					   val, freg, greg, gparam);
+-	      freg += 2;
+-	      greg += 2;
+-	      gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
+-	    }
+-	  else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX
+-	      && (TYPE_LENGTH (type) == 8 || TYPE_LENGTH (type) == 16))
+-	    {
+-	      int i;
+-
+-	      for (i = 0; i < 2; i++)
+-		{
+-		  if (write_pass)
+-		    {
+-		      struct type *target_type;
+-
+-		      target_type = check_typedef (TYPE_TARGET_TYPE (type));
+-		      ppc64_sysv_abi_push_float (gdbarch, regcache, tdep,
+-						 target_type, val + i *
+-						 TYPE_LENGTH (target_type),
+-						 freg, greg, gparam);
+-		    }
+-		  freg++;
+-		  greg++;
+-		  /* Always consume parameter stack space.  */
+-		  gparam = align_up (gparam + 8, tdep->wordsize);
+-		}
+-	    }
+-	  else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX
+-		   && TYPE_LENGTH (type) == 32
+-		   && (gdbarch_long_double_format (gdbarch)
+-		       == floatformats_ibm_long_double))
+-	    {
+-	      int i;
+-
+-	      for (i = 0; i < 2; i++)
+-		{
+-		  struct type *target_type;
+-
+-		  target_type = check_typedef (TYPE_TARGET_TYPE (type));
+-		  if (write_pass)
+-		    ppc64_sysv_abi_push_float (gdbarch, regcache, tdep,
+-					       target_type, val + i *
+-					       TYPE_LENGTH (target_type),
+-					       freg, greg, gparam);
+-		  freg += 2;
+-		  greg += 2;
+-		  gparam = align_up (gparam + TYPE_LENGTH (target_type),
+-				     tdep->wordsize);
+-		}
+-	    }
+-	  else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
+-		   && TYPE_LENGTH (type) <= 8)
+-	    {
+-	      /* 32-bit and 64-bit decimal floats go in f1 .. f13.  They can
+-	         end up in memory.  */
+-	      if (write_pass)
+-		{
+-		  gdb_byte regval[MAX_REGISTER_SIZE];
+-		  const gdb_byte *p;
+-
+-		  /* 32-bit decimal floats are right aligned in the
+-		     doubleword.  */
+-		  if (TYPE_LENGTH (type) == 4)
+-		    {
+-		      memcpy (regval + 4, val, 4);
+-		      p = regval;
+-		    }
+-		  else
+-		    p = val;
+-
+-		  /* Write value in the stack's parameter save area.  */
+-		  write_memory (gparam, p, 8);
+-
+-		  if (freg <= 13)
+-		    regcache_cooked_write (regcache,
+-					   tdep->ppc_fp0_regnum + freg, p);
+-		}
+-
+-	      freg++;
+-	      greg++;
+-	      /* Always consume parameter stack space.  */
+-	      gparam = align_up (gparam + 8, tdep->wordsize);
+-	    }
+-	  else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT &&
+-		   TYPE_LENGTH (type) == 16)
+-	    {
+-	      /* 128-bit decimal floats go in f2 .. f12, always in even/odd
+-	         pairs.  They can end up in memory, using two doublewords.  */
+-	      if (write_pass)
+-		{
+-		  if (freg <= 12)
+-		    {
+-		      /* Make sure freg is even.  */
+-		      freg += freg & 1;
+-		      regcache_cooked_write (regcache,
+-                                             tdep->ppc_fp0_regnum + freg, val);
+-		      regcache_cooked_write (regcache,
+-			  tdep->ppc_fp0_regnum + freg + 1, val + 8);
+-		    }
+-
+-		  write_memory (gparam, val, TYPE_LENGTH (type));
+-		}
++	      /* Complex types are passed as if two independent scalars.  */
++	      struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+ 
+-	      freg += 2;
+-	      greg += 2;
+-	      gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
++	      ppc64_sysv_abi_push_param (gdbarch, eltype, val, &argpos);
++	      ppc64_sysv_abi_push_param (gdbarch, eltype,
++				 	 val + TYPE_LENGTH (eltype), &argpos);
+ 	    }
+-	  else if (TYPE_LENGTH (type) < 16
+-		   && TYPE_CODE (type) == TYPE_CODE_ARRAY
+-		   && TYPE_VECTOR (type)
++	  else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)
+ 		   && opencl_abi)
+ 	    {
+ 	      /* OpenCL vectors shorter than 16 bytes are passed as if
+-		 a series of independent scalars.  */
+-	      struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+-	      int i, nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
++		 a series of independent scalars; OpenCL vectors 16 bytes
++		 or longer are passed as if a series of AltiVec vectors.  */
++	      struct type *eltype;
++	      int i, nelt;
+ 
++	      if (TYPE_LENGTH (type) < 16)
++		eltype = check_typedef (TYPE_TARGET_TYPE (type));
++	      else
++		eltype = register_type (gdbarch, tdep->ppc_vr0_regnum);
++
++	      nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
+ 	      for (i = 0; i < nelt; i++)
+ 		{
+ 		  const gdb_byte *elval = val + i * TYPE_LENGTH (eltype);
+ 
+-		  if (TYPE_CODE (eltype) == TYPE_CODE_FLT)
+-		    {
+-		      if (write_pass)
+-			{
+-			  gdb_byte regval[MAX_REGISTER_SIZE];
+-			  const gdb_byte *p;
+-
+-			  if (TYPE_LENGTH (eltype) == 4)
+-			    {
+-			      memcpy (regval, elval, 4);
+-			      memcpy (regval + 4, elval, 4);
+-			      p = regval;
+-			    }
+-			  else
+-			    p = elval;
+-
+-			  write_memory (gparam, p, 8);
+-
+-			  if (freg <= 13)
+-			    {
+-			      int regnum = tdep->ppc_fp0_regnum + freg;
+-			      struct type *regtype
+-				= register_type (gdbarch, regnum);
+-
+-			      convert_typed_floating (elval, eltype,
+-						      regval, regtype);
+-			      regcache_cooked_write (regcache, regnum, regval);
+-			    }
+-
+-			  if (greg <= 10)
+-			    regcache_cooked_write (regcache,
+-						   tdep->ppc_gp0_regnum + greg,
+-						   regval);
+-			}
+-
+-		      freg++;
+-		      greg++;
+-		      gparam = align_up (gparam + 8, tdep->wordsize);
+-		    }
+-		  else
+-		    {
+-		      if (write_pass)
+-			{
+-			  ULONGEST word = unpack_long (eltype, elval);
+-			  if (greg <= 10)
+-			    regcache_cooked_write_unsigned
+-			      (regcache, tdep->ppc_gp0_regnum + greg, word);
+-
+-			  write_memory_unsigned_integer
+-			    (gparam, tdep->wordsize, byte_order, word);
+-			}
+-
+-		      greg++;
+-		      gparam = align_up (gparam + TYPE_LENGTH (eltype),
+-					 tdep->wordsize);
+-		    }
+-		}
+-	    }
+-	  else if (TYPE_LENGTH (type) >= 16
+-		   && TYPE_CODE (type) == TYPE_CODE_ARRAY
+-		   && TYPE_VECTOR (type)
+-		   && opencl_abi)
+-	    {
+-	      /* OpenCL vectors 16 bytes or longer are passed as if
+-		 a series of AltiVec vectors.  */
+-	      int i;
+-
+-	      for (i = 0; i < TYPE_LENGTH (type) / 16; i++)
+-		{
+-		  const gdb_byte *elval = val + i * 16;
+-
+-		  gparam = align_up (gparam, 16);
+-		  greg += greg & 1;
+-
+-		  if (write_pass)
+-		    {
+-		      if (vreg <= 13)
+-			regcache_cooked_write (regcache,
+-					       tdep->ppc_vr0_regnum + vreg,
+-					       elval);
+-
+-		      write_memory (gparam, elval, 16);
+-		    }
+-
+-		  greg += 2;
+-		  vreg++;
+-		  gparam += 16;
+-		}
+-	    }
+-	  else if (TYPE_LENGTH (type) == 16 && TYPE_VECTOR (type)
+-		   && TYPE_CODE (type) == TYPE_CODE_ARRAY
+-		   && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
+-	    {
+-	      /* In the Altivec ABI, vectors go in the vector registers
+-		 v2 .. v13, as well as the parameter area -- always at
+-		 16-byte aligned addresses.  */
+-
+-	      gparam = align_up (gparam, 16);
+-	      greg += greg & 1;
+-
+-	      if (write_pass)
+-		{
+-		  if (vreg <= 13)
+-		    regcache_cooked_write (regcache,
+-					   tdep->ppc_vr0_regnum + vreg, val);
+-
+-		  write_memory (gparam, val, TYPE_LENGTH (type));
+-		}
+-
+-	      greg += 2;
+-	      vreg++;
+-	      gparam += 16;
+-	    }
+-	  else if (TYPE_LENGTH (type) >= 16 && TYPE_VECTOR (type)
+-		   && TYPE_CODE (type) == TYPE_CODE_ARRAY)
+-	    {
+-	      /* Non-Altivec vectors are passed by reference.  */
+-
+-	      /* Copy value onto the stack ...  */
+-	      refparam = align_up (refparam, 16);
+-	      if (write_pass)
+-		write_memory (refparam, val, TYPE_LENGTH (type));
+-
+-	      /* ... and pass a pointer to the copy as parameter.  */
+-	      if (write_pass)
+-		{
+-		  if (greg <= 10)
+-		    regcache_cooked_write_unsigned (regcache,
+-						    tdep->ppc_gp0_regnum +
+-						    greg, refparam);
+-		  write_memory_unsigned_integer (gparam, tdep->wordsize,
+-						 byte_order, refparam);
+-		}
+-	      greg++;
+-	      gparam = align_up (gparam + tdep->wordsize, tdep->wordsize);
+-	      refparam = align_up (refparam + TYPE_LENGTH (type), tdep->wordsize);
+-	    }
+-	  else if ((TYPE_CODE (type) == TYPE_CODE_INT
+-		    || TYPE_CODE (type) == TYPE_CODE_ENUM
+-		    || TYPE_CODE (type) == TYPE_CODE_BOOL
+-		    || TYPE_CODE (type) == TYPE_CODE_CHAR
+-		    || TYPE_CODE (type) == TYPE_CODE_PTR
+-		    || TYPE_CODE (type) == TYPE_CODE_REF)
+-		   && TYPE_LENGTH (type) <= 8)
+-	    {
+-	      /* Scalars and Pointers get sign[un]extended and go in
+-	         gpr3 .. gpr10.  They can also end up in memory.  */
+-	      if (write_pass)
+-		{
+-		  /* Sign extend the value, then store it unsigned.  */
+-		  ULONGEST word = unpack_long (type, val);
+-		  /* Convert any function code addresses into
+-		     descriptors.  */
+-		  if (TYPE_CODE (type) == TYPE_CODE_PTR
+-		      || TYPE_CODE (type) == TYPE_CODE_REF)
+-		    {
+-		      struct type *target_type;
+-		      target_type = check_typedef (TYPE_TARGET_TYPE (type));
+-
+-		      if (TYPE_CODE (target_type) == TYPE_CODE_FUNC
+-			  || TYPE_CODE (target_type) == TYPE_CODE_METHOD)
+-			{
+-			  CORE_ADDR desc = word;
+-			  convert_code_addr_to_desc_addr (word, &desc);
+-			  word = desc;
+-			}
+-		    }
+-		  if (greg <= 10)
+-		    regcache_cooked_write_unsigned (regcache,
+-						    tdep->ppc_gp0_regnum +
+-						    greg, word);
+-		  write_memory_unsigned_integer (gparam, tdep->wordsize,
+-						 byte_order, word);
++		  ppc64_sysv_abi_push_param (gdbarch, eltype, elval, &argpos);
+ 		}
+-	      greg++;
+-	      gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
+ 	    }
+ 	  else
+ 	    {
+-	      int byte;
+-	      for (byte = 0; byte < TYPE_LENGTH (type);
+-		   byte += tdep->wordsize)
+-		{
+-		  if (write_pass && greg <= 10)
+-		    {
+-		      gdb_byte regval[MAX_REGISTER_SIZE];
+-		      int len = TYPE_LENGTH (type) - byte;
+-		      if (len > tdep->wordsize)
+-			len = tdep->wordsize;
+-		      memset (regval, 0, sizeof regval);
+-		      /* The ABI (version 1.9) specifies that values
+-			 smaller than one doubleword are right-aligned
+-			 and those larger are left-aligned.  GCC
+-			 versions before 3.4 implemented this
+-			 incorrectly; see
+-			 <http://gcc.gnu.org/gcc-3.4/powerpc-abi.html>.  */
+-		      if (byte == 0)
+-			memcpy (regval + tdep->wordsize - len,
+-				val + byte, len);
+-		      else
+-			memcpy (regval, val + byte, len);
+-		      regcache_cooked_write (regcache, greg, regval);
+-		    }
+-		  greg++;
+-		}
+-	      if (write_pass)
+-		{
+-		  /* WARNING: cagney/2003-09-21: Strictly speaking, this
+-		     isn't necessary, unfortunately, GCC appears to get
+-		     "struct convention" parameter passing wrong putting
+-		     odd sized structures in memory instead of in a
+-		     register.  Work around this by always writing the
+-		     value to memory.  Fortunately, doing this
+-		     simplifies the code.  */
+-		  int len = TYPE_LENGTH (type);
+-		  if (len < tdep->wordsize)
+-		    write_memory (gparam + tdep->wordsize - len, val, len);
+-		  else
+-		    write_memory (gparam, val, len);
+-		}
+-	      if (freg <= 13
+-		  && TYPE_CODE (type) == TYPE_CODE_STRUCT
+-		  && TYPE_NFIELDS (type) == 1
+-		  && TYPE_LENGTH (type) <= 16)
+-		{
+-		  /* The ABI (version 1.9) specifies that structs
+-		     containing a single floating-point value, at any
+-		     level of nesting of single-member structs, are
+-		     passed in floating-point registers.  */
+-		  while (TYPE_CODE (type) == TYPE_CODE_STRUCT
+-			 && TYPE_NFIELDS (type) == 1)
+-		    type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+-		  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+-		    {
+-		      if (TYPE_LENGTH (type) <= 8)
+-			{
+-			  if (write_pass)
+-			    {
+-			      gdb_byte regval[MAX_REGISTER_SIZE];
+-			      struct type *regtype
+-				= register_type (gdbarch,
+-						 tdep->ppc_fp0_regnum);
+-			      convert_typed_floating (val, type, regval,
+-						      regtype);
+-			      regcache_cooked_write (regcache,
+-						     (tdep->ppc_fp0_regnum
+-						      + freg),
+-						     regval);
+-			    }
+-			  freg++;
+-			}
+-		      else if (TYPE_LENGTH (type) == 16
+-			       && (gdbarch_long_double_format (gdbarch)
+-				   == floatformats_ibm_long_double))
+-			{
+-			  if (write_pass)
+-			    {
+-			      regcache_cooked_write (regcache,
+-						     (tdep->ppc_fp0_regnum
+-						      + freg),
+-						     val);
+-			      if (freg <= 12)
+-				regcache_cooked_write (regcache,
+-						       (tdep->ppc_fp0_regnum
+-							+ freg + 1),
+-						       val + 8);
+-			    }
+-			  freg += 2;
+-			}
+-		    }
+-		}
+-	      /* Always consume parameter stack space.  */
+-	      gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
++	      /* All other types are passed as single arguments.  */
++	      ppc64_sysv_abi_push_param (gdbarch, type, val, &argpos);
+ 	    }
+ 	}
+ 
+       if (!write_pass)
+ 	{
+ 	  /* Save the true region sizes ready for the second pass.  */
+-	  refparam_size = refparam;
++	  refparam_size = argpos.refparam;
+ 	  /* Make certain that the general parameter save area is at
+ 	     least the minimum 8 registers (or doublewords) in size.  */
+-	  if (greg < 8)
++	  if (argpos.greg < 8)
+ 	    gparam_size = 8 * tdep->wordsize;
+ 	  else
+-	    gparam_size = gparam;
++	    gparam_size = argpos.gparam;
+ 	}
+     }
+ 
+@@ -1755,271 +1569,252 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+   return sp;
+ }
+ 
++/* Subroutine of ppc64_sysv_abi_return_value that handles "base" types:
++   integer, floating-point, and AltiVec vector types.
+ 
+-/* The 64 bit ABI return value convention.
+-
+-   Return non-zero if the return-value is stored in a register, return
+-   0 if the return-value is instead stored on the stack (a.k.a.,
+-   struct return convention).
++   This routine also handles components of aggregate return types;
++   INDEX describes which part of the aggregate is to be handled.
+ 
+-   For a return-value stored in a register: when WRITEBUF is non-NULL,
+-   copy the buffer to the corresponding register return-value location
+-   location; when READBUF is non-NULL, fill the buffer from the
+-   corresponding register return-value location.  */
+-enum return_value_convention
+-ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
+-			     struct type *valtype, struct regcache *regcache,
+-			     gdb_byte *readbuf, const gdb_byte *writebuf)
++   Returns true if VALTYPE is some such base type that could be handled,
++   false otherwise.  */
++static int
++ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype,
++				  struct regcache *regcache, gdb_byte *readbuf,
++				  const gdb_byte *writebuf, int index)
+ {
+   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+-  struct type *func_type = function ? value_type (function) : NULL;
+-  int opencl_abi = func_type? ppc_sysv_use_opencl_abi (func_type) : 0;
+ 
+-  /* This function exists to support a calling convention that
+-     requires floating-point registers.  It shouldn't be used on
+-     processors that lack them.  */
+-  gdb_assert (ppc_floating_point_unit_p (gdbarch));
+-
+-  /* Floats and doubles in F1.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT && TYPE_LENGTH (valtype) <= 8)
+-    {
+-      gdb_byte regval[MAX_REGISTER_SIZE];
+-      struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
+-      if (writebuf != NULL)
+-	{
+-	  convert_typed_floating (writebuf, valtype, regval, regtype);
+-	  regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
+-	}
+-      if (readbuf != NULL)
+-	{
+-	  regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
+-	  convert_typed_floating (regval, regtype, readbuf, valtype);
+-	}
+-      return RETURN_VALUE_REGISTER_CONVENTION;
+-    }
+-  if (TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
+-    return get_decimal_float_return_value (gdbarch, valtype, regcache, readbuf,
+-					   writebuf);
+-  /* Integers in r3.  */
++  /* Integers live in GPRs starting at r3.  */
+   if ((TYPE_CODE (valtype) == TYPE_CODE_INT
+        || TYPE_CODE (valtype) == TYPE_CODE_ENUM
+        || TYPE_CODE (valtype) == TYPE_CODE_CHAR
+        || TYPE_CODE (valtype) == TYPE_CODE_BOOL)
+       && TYPE_LENGTH (valtype) <= 8)
+     {
++      int regnum = tdep->ppc_gp0_regnum + 3 + index;
++
+       if (writebuf != NULL)
+ 	{
+ 	  /* Be careful to sign extend the value.  */
+-	  regcache_cooked_write_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
++	  regcache_cooked_write_unsigned (regcache, regnum,
+ 					  unpack_long (valtype, writebuf));
+ 	}
+       if (readbuf != NULL)
+ 	{
+-	  /* Extract the integer from r3.  Since this is truncating the
++	  /* Extract the integer from GPR.  Since this is truncating the
+ 	     value, there isn't a sign extension problem.  */
+ 	  ULONGEST regval;
+-	  regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 3,
+-					 &regval);
+-	  store_unsigned_integer (readbuf, TYPE_LENGTH (valtype), byte_order,
+-				  regval);
++
++	  regcache_cooked_read_unsigned (regcache, regnum, &regval);
++	  store_unsigned_integer (readbuf, TYPE_LENGTH (valtype),
++				  gdbarch_byte_order (gdbarch), regval);
+ 	}
+-      return RETURN_VALUE_REGISTER_CONVENTION;
++      return 1;
+     }
+-  /* All pointers live in r3.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_PTR
+-      || TYPE_CODE (valtype) == TYPE_CODE_REF)
++
++  /* Floats and doubles go in f1 .. f13.  32-bit floats are converted
++     to double first.  */
++  if (TYPE_LENGTH (valtype) <= 8
++      && TYPE_CODE (valtype) == TYPE_CODE_FLT)
+     {
+-      /* All pointers live in r3.  */
++      int regnum = tdep->ppc_fp0_regnum + 1 + index;
++      struct type *regtype = register_type (gdbarch, regnum);
++      gdb_byte regval[MAX_REGISTER_SIZE];
++
+       if (writebuf != NULL)
+-	regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
++	{
++	  convert_typed_floating (writebuf, valtype, regval, regtype);
++	  regcache_cooked_write (regcache, regnum, regval);
++	}
+       if (readbuf != NULL)
+-	regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf);
+-      return RETURN_VALUE_REGISTER_CONVENTION;
++	{
++	  regcache_cooked_read (regcache, regnum, regval);
++	  convert_typed_floating (regval, regtype, readbuf, valtype);
++	}
++      return 1;
+     }
+-  /* OpenCL vectors < 16 bytes are returned as distinct
+-     scalars in f1..f2 or r3..r10.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+-      && TYPE_VECTOR (valtype)
+-      && TYPE_LENGTH (valtype) < 16
+-      && opencl_abi)
+-    {
+-      struct type *eltype = check_typedef (TYPE_TARGET_TYPE (valtype));
+-      int i, nelt = TYPE_LENGTH (valtype) / TYPE_LENGTH (eltype);
+ 
+-      for (i = 0; i < nelt; i++)
+-	{
+-	  int offset = i * TYPE_LENGTH (eltype);
++  /* Floats and doubles go in f1 .. f13.  32-bit decimal floats are
++     placed in the least significant word.  */
++  if (TYPE_LENGTH (valtype) <= 8
++      && TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
++    {
++      int regnum = tdep->ppc_fp0_regnum + 1 + index;
++      int offset = 8 - TYPE_LENGTH (valtype);
+ 
+-	  if (TYPE_CODE (eltype) == TYPE_CODE_FLT)
+-	    {
+-	      int regnum = tdep->ppc_fp0_regnum + 1 + i;
+-	      gdb_byte regval[MAX_REGISTER_SIZE];
+-	      struct type *regtype = register_type (gdbarch, regnum);
++      if (writebuf != NULL)
++	regcache_cooked_write_part (regcache, regnum,
++				    offset, TYPE_LENGTH (valtype), writebuf);
++      if (readbuf != NULL)
++	regcache_cooked_read_part (regcache, regnum,
++				   offset, TYPE_LENGTH (valtype), readbuf);
++      return 1;
++    }
+ 
+-	      if (writebuf != NULL)
+-		{
+-		  convert_typed_floating (writebuf + offset, eltype,
+-					  regval, regtype);
+-		  regcache_cooked_write (regcache, regnum, regval);
+-		}
+-	      if (readbuf != NULL)
+-		{
+-		  regcache_cooked_read (regcache, regnum, regval);
+-		  convert_typed_floating (regval, regtype,
+-					  readbuf + offset, eltype);
+-		}
+-	    }
+-	  else
+-	    {
+-	      int regnum = tdep->ppc_gp0_regnum + 3 + i;
+-	      ULONGEST regval;
++  /* IBM long double stored in two consecutive FPRs.  */
++  if (TYPE_LENGTH (valtype) == 16
++      && TYPE_CODE (valtype) == TYPE_CODE_FLT
++      && (gdbarch_long_double_format (gdbarch)
++	  == floatformats_ibm_long_double))
++    {
++      int regnum = tdep->ppc_fp0_regnum + 1 + 2 * index;
+ 
+-	      if (writebuf != NULL)
+-		{
+-		  regval = unpack_long (eltype, writebuf + offset);
+-		  regcache_cooked_write_unsigned (regcache, regnum, regval);
+-		}
+-	      if (readbuf != NULL)
+-		{
+-		  regcache_cooked_read_unsigned (regcache, regnum, &regval);
+-		  store_unsigned_integer (readbuf + offset,
+-					  TYPE_LENGTH (eltype), byte_order,
+-					  regval);
+-		}
+-	    }
++      if (writebuf != NULL)
++	{
++	  regcache_cooked_write (regcache, regnum, writebuf);
++	  regcache_cooked_write (regcache, regnum + 1, writebuf + 8);
+ 	}
+-
+-      return RETURN_VALUE_REGISTER_CONVENTION;
++      if (readbuf != NULL)
++	{
++	  regcache_cooked_read (regcache, regnum, readbuf);
++	  regcache_cooked_read (regcache, regnum + 1, readbuf + 8);
++	}
++      return 1;
+     }
+-  /* OpenCL vectors >= 16 bytes are returned in v2..v9.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+-      && TYPE_VECTOR (valtype)
+-      && TYPE_LENGTH (valtype) >= 16
+-      && opencl_abi)
++
++  /* 128-bit decimal floating-point values are stored in an even/odd
++     pair of FPRs, with the even FPR holding the most significant half.  */
++  if (TYPE_LENGTH (valtype) == 16
++      && TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
+     {
+-      int n_regs = TYPE_LENGTH (valtype) / 16;
+-      int i;
++      int regnum = tdep->ppc_fp0_regnum + 2 + 2 * index;
+ 
+-      for (i = 0; i < n_regs; i++)
++      if (writebuf != NULL)
+ 	{
+-	  int offset = i * 16;
+-	  int regnum = tdep->ppc_vr0_regnum + 2 + i;
+-
+-	  if (writebuf != NULL)
+-	    regcache_cooked_write (regcache, regnum, writebuf + offset);
+-	  if (readbuf != NULL)
+-	    regcache_cooked_read (regcache, regnum, readbuf + offset);
++	  regcache_cooked_write (regcache, regnum, writebuf);
++	  regcache_cooked_write (regcache, regnum + 1, writebuf + 8);
+ 	}
+-
+-      return RETURN_VALUE_REGISTER_CONVENTION;
++      if (readbuf != NULL)
++	{
++	  regcache_cooked_read (regcache, regnum, readbuf);
++	  regcache_cooked_read (regcache, regnum + 1, readbuf + 8);
++	}
++      return 1;
+     }
+-  /* Array type has more than one use.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
++
++  /* AltiVec vectors are returned in VRs starting at v2.  */
++  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
++      && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
+     {
+-      /* Small character arrays are returned, right justified, in r3.  */
+-      if (TYPE_LENGTH (valtype) <= 8
+-        && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT
+-        && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1)
+-        {
+-          int offset = (register_size (gdbarch, tdep->ppc_gp0_regnum + 3)
+-                       - TYPE_LENGTH (valtype));
+-          if (writebuf != NULL)
+-           regcache_cooked_write_part (regcache, tdep->ppc_gp0_regnum + 3,
+-                                      offset, TYPE_LENGTH (valtype), writebuf);
+-          if (readbuf != NULL)
+-           regcache_cooked_read_part (regcache, tdep->ppc_gp0_regnum + 3,
+-                                      offset, TYPE_LENGTH (valtype), readbuf);
+-          return RETURN_VALUE_REGISTER_CONVENTION;
+-	}
+-      /* A VMX vector is returned in v2.  */
+-      if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+-	  && TYPE_VECTOR (valtype)
+-	  && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
+-        {
+-          if (readbuf)
+-            regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
+-          if (writebuf)
+-            regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2,
+-				   writebuf);
+-          return RETURN_VALUE_REGISTER_CONVENTION;
+-        }
++      int regnum = tdep->ppc_vr0_regnum + 2 + index;
++
++      if (writebuf != NULL)
++	regcache_cooked_write (regcache, regnum, writebuf);
++      if (readbuf != NULL)
++	regcache_cooked_read (regcache, regnum, readbuf);
++      return 1;
+     }
+-  /* Big floating point values get stored in adjacent floating
+-     point registers, starting with F1.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT
+-      && (TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 32))
++
++  return 0;
++}
++
++/* The 64 bit ABI return value convention.
++
++   Return non-zero if the return-value is stored in a register, return
++   0 if the return-value is instead stored on the stack (a.k.a.,
++   struct return convention).
++
++   For a return-value stored in a register: when WRITEBUF is non-NULL,
++   copy the buffer to the corresponding register return-value location
++   location; when READBUF is non-NULL, fill the buffer from the
++   corresponding register return-value location.  */
++enum return_value_convention
++ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
++			     struct type *valtype, struct regcache *regcache,
++			     gdb_byte *readbuf, const gdb_byte *writebuf)
++{
++  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
++  struct type *func_type = function ? value_type (function) : NULL;
++  int opencl_abi = func_type? ppc_sysv_use_opencl_abi (func_type) : 0;
++  struct type *eltype;
++  int nelt, i, ok;
++
++  /* This function exists to support a calling convention that
++     requires floating-point registers.  It shouldn't be used on
++     processors that lack them.  */
++  gdb_assert (ppc_floating_point_unit_p (gdbarch));
++
++  /* Complex types are returned as if two independent scalars.  */
++  if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX)
+     {
+-      if (writebuf || readbuf != NULL)
++      eltype = check_typedef (TYPE_TARGET_TYPE (valtype));
++
++      for (i = 0; i < 2; i++)
+ 	{
+-	  int i;
+-	  for (i = 0; i < TYPE_LENGTH (valtype) / 8; i++)
+-	    {
+-	      if (writebuf != NULL)
+-		regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i,
+-				       (const bfd_byte *) writebuf + i * 8);
+-	      if (readbuf != NULL)
+-		regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i,
+-				      (bfd_byte *) readbuf + i * 8);
+-	    }
++	  ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache,
++						 readbuf, writebuf, i);
++	  gdb_assert (ok);
++
++	  if (readbuf)
++	    readbuf += TYPE_LENGTH (eltype);
++	  if (writebuf)
++	    writebuf += TYPE_LENGTH (eltype);
+ 	}
+       return RETURN_VALUE_REGISTER_CONVENTION;
+     }
+-  /* Complex values get returned in f1:f2, need to convert.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX
+-      && (TYPE_LENGTH (valtype) == 8 || TYPE_LENGTH (valtype) == 16))
++
++  /* OpenCL vectors shorter than 16 bytes are returned as if
++     a series of independent scalars; OpenCL vectors 16 bytes
++     or longer are returned as if a series of AltiVec vectors.  */
++  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
++      && opencl_abi)
+     {
+-      if (regcache != NULL)
++      if (TYPE_LENGTH (valtype) < 16)
++	eltype = check_typedef (TYPE_TARGET_TYPE (valtype));
++      else
++	eltype = register_type (gdbarch, tdep->ppc_vr0_regnum);
++
++      nelt = TYPE_LENGTH (valtype) / TYPE_LENGTH (eltype);
++      for (i = 0; i < nelt; i++)
+ 	{
+-	  int i;
+-	  for (i = 0; i < 2; i++)
+-	    {
+-	      gdb_byte regval[MAX_REGISTER_SIZE];
+-	      struct type *regtype =
+-		register_type (gdbarch, tdep->ppc_fp0_regnum);
+-	      struct type *target_type;
+-	      target_type = check_typedef (TYPE_TARGET_TYPE (valtype));
+-	      if (writebuf != NULL)
+-		{
+-		  convert_typed_floating ((const bfd_byte *) writebuf +
+-					  i * TYPE_LENGTH (target_type), 
+-					  target_type, regval, regtype);
+-		  regcache_cooked_write (regcache,
+-                                         tdep->ppc_fp0_regnum + 1 + i,
+-					 regval);
+-		}
+-	      if (readbuf != NULL)
+-		{
+-		  regcache_cooked_read (regcache,
+-                                        tdep->ppc_fp0_regnum + 1 + i,
+-                                        regval);
+-		  convert_typed_floating (regval, regtype,
+-					  (bfd_byte *) readbuf +
+-					  i * TYPE_LENGTH (target_type),
+-					  target_type);
+-		}
+-	    }
++	  ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache,
++						 readbuf, writebuf, i);
++	  gdb_assert (ok);
++
++	  if (readbuf)
++	    readbuf += TYPE_LENGTH (eltype);
++	  if (writebuf)
++	    writebuf += TYPE_LENGTH (eltype);
+ 	}
+       return RETURN_VALUE_REGISTER_CONVENTION;
+     }
+-  /* Big complex values get stored in f1:f4.  */
+-  if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX && TYPE_LENGTH (valtype) == 32)
++
++  /* All pointers live in r3.  */
++  if (TYPE_CODE (valtype) == TYPE_CODE_PTR
++      || TYPE_CODE (valtype) == TYPE_CODE_REF)
+     {
+-      if (regcache != NULL)
+-	{
+-	  int i;
+-	  for (i = 0; i < 4; i++)
+-	    {
+-	      if (writebuf != NULL)
+-		regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1 + i,
+-				       (const bfd_byte *) writebuf + i * 8);
+-	      if (readbuf != NULL)
+-		regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1 + i,
+-				      (bfd_byte *) readbuf + i * 8);
+-	    }
+-	}
++      int regnum = tdep->ppc_gp0_regnum + 3;
++
++      if (writebuf != NULL)
++	regcache_cooked_write (regcache, regnum, writebuf);
++      if (readbuf != NULL)
++	regcache_cooked_read (regcache, regnum, readbuf);
+       return RETURN_VALUE_REGISTER_CONVENTION;
+     }
++
++  /* Small character arrays are returned, right justified, in r3.  */
++  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
++      && TYPE_LENGTH (valtype) <= 8
++      && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT
++      && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1)
++    {
++      int regnum = tdep->ppc_gp0_regnum + 3;
++      int offset = (register_size (gdbarch, regnum) - TYPE_LENGTH (valtype));
++
++      if (writebuf != NULL)
++	regcache_cooked_write_part (regcache, regnum,
++				    offset, TYPE_LENGTH (valtype), writebuf);
++      if (readbuf != NULL)
++	regcache_cooked_read_part (regcache, regnum,
++				   offset, TYPE_LENGTH (valtype), readbuf);
++      return RETURN_VALUE_REGISTER_CONVENTION;
++    }
++
++  /* Handle plain base types.  */
++  if (ppc64_sysv_abi_return_value_base (gdbarch, valtype, regcache,
++					readbuf, writebuf, 0))
++    return RETURN_VALUE_REGISTER_CONVENTION;
++
+   return RETURN_VALUE_STRUCT_CONVENTION;
+ }
+ 
diff --git a/gdb-upstream-ppc64le05of15.patch b/gdb-upstream-ppc64le05of15.patch
new file mode 100644
index 0000000..fa3fda0
--- /dev/null
+++ b/gdb-upstream-ppc64le05of15.patch
@@ -0,0 +1,44 @@
+commit d63167affc2a56189e3ba2cc47dd9a3451208b59
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:26:26 2014 +0100
+
+    PowerPC64 little-endian fixes: structure passing
+    
+    When passing a small structure in a GPR, the ABI specifies that it
+    should be passed in the least-significant bytes of the register
+    (or stack slot).  On big-endian systems, this means the value
+    needs to be stored at an offset, which is what current code does.
+    
+    However, on little-endian systems, the least-significant bytes are
+    addresses with offset 0.  This patch fixes that.
+    
+    gdb/ChangeLog:
+    
+    	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_val): Use correct
+    	offset on little-endian when passing small structures.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,10 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_val): Use correct
++	offset on little-endian when passing small structures.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-sysv-tdep.c (get_decimal_float_return_value): Update comment.
+ 	(struct ppc64_sysv_argpos): New data structure.
+ 	(ppc64_sysv_abi_push_float): Remove.
+--- a/gdb/ppc-sysv-tdep.c
++++ b/gdb/ppc-sysv-tdep.c
+@@ -1150,7 +1150,8 @@ ppc64_sysv_abi_push_val (struct gdbarch *gdbarch,
+      doubleword are right-aligned and those larger are left-aligned.
+      GCC versions before 3.4 implemented this incorrectly; see
+      <http://gcc.gnu.org/gcc-3.4/powerpc-abi.html>.  */
+-  if (len < tdep->wordsize)
++  if (len < tdep->wordsize
++      && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+     offset = tdep->wordsize - len;
+ 
+   if (argpos->regcache)
diff --git a/gdb-upstream-ppc64le06of15.patch b/gdb-upstream-ppc64le06of15.patch
new file mode 100644
index 0000000..d03258d
--- /dev/null
+++ b/gdb-upstream-ppc64le06of15.patch
@@ -0,0 +1,67 @@
+commit 6ed14ff33979bc48367c35b1b235fef8c5e2229b
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:28:24 2014 +0100
+
+    PowerPC64 little-endian fixes: AltiVec tests
+    
+    A couple of AltiVec tests fail spuriously on powerpc64le-linux, because
+    they compare against an incorrect pattern.  Note that those tests already
+    contain little-endian variants of the patterns, but those seem to have
+    bit-rotted a bit: when outputting a vector, GDB no longer omits trailing
+    zero elements (as it used to do in the past).
+    
+    This patch updates the pattern to the new GDB output behavior.
+    
+    In addition, the patch updates the endian test to use the new
+    gdb_test_multiple logic instead of gdb_expect.
+    
+    gdb/testsuite/ChangeLog:
+    
+    	* gdb.arch/altivec-regs.exp: Use gdb_test_multiple for endian test.
+    	(decimal_vector): Fix for little-endian.
+
+### a/gdb/testsuite/ChangeLog
+### b/gdb/testsuite/ChangeLog
+## -1,3 +1,8 @@
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
++	* gdb.arch/altivec-regs.exp: Use gdb_test_multiple for endian test.
++	(decimal_vector): Fix for little-endian.
++
+ 2014-01-29  Jose E. Marchesi  <jose.marchesi at oracle.com>
+ 
+ 	* gdb.arch/sparc-sysstep.exp: New file.
+--- a/gdb/testsuite/gdb.arch/altivec-regs.exp
++++ b/gdb/testsuite/gdb.arch/altivec-regs.exp
+@@ -79,17 +79,16 @@ gdb_test "set \$vrsave = 1" "" ""
+ 
+ gdb_test "next" "" ""
+ 
+-send_gdb "show endian\n"
+ set endianness ""
+-gdb_expect {
++set msg "detect endianness"
++gdb_test_multiple "show endian" "$msg" {
+     -re "(The target endianness is set automatically .currently )(big|little)( endian.*)$gdb_prompt $" {
+-        pass "endianness"
+-	set endianness $expect_out(2,string)
++        pass "$msg"
++        set endianness $expect_out(2,string)
+     }
+     -re ".*$gdb_prompt $" {
+-	fail "couldn't get endianness"
++        fail "$msg"
+     }
+-    timeout		{ fail "(timeout) endianness" }
+ }
+ 
+ # And then read the AltiVec registers back, to see that
+@@ -118,7 +117,7 @@ gdb_test "info reg vscr" "vscr.*0x1\t1" "info reg vscr"
+ if {$endianness == "big"} {
+      set decimal_vector ".uint128 = 0x00000001000000010000000100000001, v4_float = .1.*e-45, 1.*e-45, 1.*e-45, 1.*e-45., v4_int32 = .1, 1, 1, 1., v8_int16 = .0, 1, 0, 1, 0, 1, 0, 1., v16_int8 = .0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1.."
+ } else {
+-     set decimal_vector ".uint128 = 0x00000001000000010000000100000001, v4_float = .1.*e-45, 1.*e-45, 1.*e-45, 1.*e-45., v4_int32 = .1, 1, 1, 1., v8_int16 = .1, 0, 1, 0, 1, 0, 1, 0., v16_int8 = .1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.."
++     set decimal_vector ".uint128 = 0x00000001000000010000000100000001, v4_float = .1.*e-45, 1.*e-45, 1.*e-45, 1.*e-45., v4_int32 = .1, 1, 1, 1., v8_int16 = .1, 0, 1, 0, 1, 0, 1, 0., v16_int8 = .1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.."
+ }
+ 
+ for {set i 0} {$i < 32} {incr i 1} {
diff --git a/gdb-upstream-ppc64le07of15.patch b/gdb-upstream-ppc64le07of15.patch
new file mode 100644
index 0000000..c48d419
--- /dev/null
+++ b/gdb-upstream-ppc64le07of15.patch
@@ -0,0 +1,149 @@
+commit 084ee54552f6c35d740e8b9bc81a4fe8d8bb178b
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:31:38 2014 +0100
+
+    PowerPC64 little-endian fixes: VSX tests and pseudo-regs
+    
+    Many VSX test were failing on powerpc64le-linux, since -as opposed to the
+    AltiVec tests- there never were little-endian versions of the test patterns.
+    
+    This patch adds such patterns, along the lines of altivec-regs.exp.
+    
+    In addition, there is an actual code change required: For those VSX
+    registers that overlap a floating-point register, the FP register
+    overlaps the most-significant half of the VSX register both on big-
+    and little-endian systems.  However, on little-endian systems, that
+    half is stored at an offset of 8 bytes (not 0).  This works already
+    for the "real" FP registers, but current code gets it wrong for
+    the "extended" pseudo FP register GDB generates for the second
+    half of the VSX register bank.
+    
+    This patch updates the corresponding pseudo read/write routines
+    to take the appropriate offset into consideration.
+    
+    gdb/ChangeLog:
+    
+    	* rs6000-tdep.c (efpr_pseudo_register_read): Use correct offset
+    	of the overlapped FP register within the VSX register on little-
+    	endian platforms.
+    	(efpr_pseudo_register_write): Likewise.
+    
+    gdb/testsuite/ChangeLog:
+    
+    	* gdb.arch/vsx-regs.exp: Check target endianness.  Provide variants
+    	of the test patterns for use on little-endian systems.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,12 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* rs6000-tdep.c (efpr_pseudo_register_read): Use correct offset
++	of the overlapped FP register within the VSX register on little-
++	endian platforms.
++	(efpr_pseudo_register_write): Likewise.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_val): Use correct
+ 	offset on little-endian when passing small structures.
+ 
+--- a/gdb/rs6000-tdep.c
++++ b/gdb/rs6000-tdep.c
+@@ -2779,10 +2779,12 @@ efpr_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+ {
+   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+   int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
++  int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
+ 
+   /* Read the portion that overlaps the VMX register.  */
+-  return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0,
+-				 register_size (gdbarch, reg_nr), buffer);
++  return regcache_raw_read_part (regcache, tdep->ppc_vr0_regnum + reg_index,
++				 offset, register_size (gdbarch, reg_nr),
++				 buffer);
+ }
+ 
+ /* Write method for POWER7 Extended FP pseudo-registers.  */
+@@ -2792,10 +2794,12 @@ efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+ {
+   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+   int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
++  int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
+ 
+   /* Write the portion that overlaps the VMX register.  */
+-  regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index, 0,
+-			   register_size (gdbarch, reg_nr), buffer);
++  regcache_raw_write_part (regcache, tdep->ppc_vr0_regnum + reg_index,
++			   offset, register_size (gdbarch, reg_nr),
++			   buffer);
+ }
+ 
+ static enum register_status
+### a/gdb/testsuite/ChangeLog
+### b/gdb/testsuite/ChangeLog
+## -1,5 +1,10 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* gdb.arch/vsx-regs.exp: Check target endianness.  Provide variants
++	of the test patterns for use on little-endian systems.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* gdb.arch/altivec-regs.exp: Use gdb_test_multiple for endian test.
+ 	(decimal_vector): Fix for little-endian.
+ 
+--- a/gdb/testsuite/gdb.arch/vsx-regs.exp
++++ b/gdb/testsuite/gdb.arch/vsx-regs.exp
+@@ -58,19 +58,45 @@ if ![runto_main] then {
+     gdb_suppress_tests
+ }
+ 
++set endianness ""
++set msg "detect endianness"
++gdb_test_multiple "show endian" "$msg" {
++    -re "(The target endianness is set automatically .currently )(big|little)( endian.*)$gdb_prompt $" {
++        pass "$msg"
++        set endianness $expect_out(2,string)
++    }
++    -re ".*$gdb_prompt $" {
++        fail "$msg"
++    }
++}
++
+ # Data sets used throughout the test
+ 
+-set vector_register1 ".uint128 = 0x3ff4cccccccccccc0000000000000000, v2_double = .0x1, 0x0., v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x0, 0x0., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x0, 0x0, 0x0., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0.."
++if {$endianness == "big"} {
++    set vector_register1 ".uint128 = 0x3ff4cccccccccccc0000000000000000, v2_double = .0x1, 0x0., v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x0, 0x0., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x0, 0x0, 0x0., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0.."
++
++    set vector_register1_vr ".uint128 = 0x3ff4cccccccccccc0000000100000001, v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x1, 0x1., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.."
+ 
+-set vector_register1_vr ".uint128 = 0x3ff4cccccccccccc0000000100000001, v4_float = .0x1, 0xf99999a0, 0x0, 0x0., v4_int32 = .0x3ff4cccc, 0xcccccccc, 0x1, 0x1., v8_int16 = .0x3ff4, 0xcccc, 0xcccc, 0xcccc, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x3f, 0xf4, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.."
++    set vector_register2 "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v2_double = .0x1, 0x1., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.."
+ 
+-set vector_register2 "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v2_double = .0x1, 0x1., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.."
++    set vector_register2_vr "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.."
+ 
+-set vector_register2_vr "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef., v16_int8 = .0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef.."
++    set vector_register3 ".uint128 = 0x00000001000000010000000100000001, v2_double = .0x0, 0x0., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.."
++
++    set vector_register3_vr ".uint128 = 0x00000001000000010000000100000001, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.."
++} else {
++    set vector_register1 ".uint128 = 0x3ff4cccccccccccc0000000000000000, v2_double = .0x0, 0x1., v4_float = .0x0, 0x0, 0xf99999a0, 0x1., v4_int32 = .0x0, 0x0, 0xcccccccc, 0x3ff4cccc., v8_int16 = .0x0, 0x0, 0x0, 0x0, 0xcccc, 0xcccc, 0xcccc, 0x3ff4., v16_int8 = .0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf4, 0x3f.."
+ 
+-set vector_register3 ".uint128 = 0x00000001000000010000000100000001, v2_double = .0x0, 0x0., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.."
++    set vector_register1_vr ".uint128 = 0x3ff4cccccccccccc0000000100000001, v4_float = .0x0, 0x0, 0xf99999a0, 0x1., v4_int32 = .0x1, 0x1, 0xcccccccc, 0x3ff4cccc., v8_int16 = .0x1, 0x0, 0x1, 0x0, 0xcccc, 0xcccc, 0xcccc, 0x3ff4., v16_int8 = .0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xf4, 0x3f.."
+ 
+-set vector_register3_vr ".uint128 = 0x00000001000000010000000100000001, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1., v16_int8 = .0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1.."
++    set vector_register2 "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v2_double = .0x1, 0x1., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead., v16_int8 = .0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde.."
++
++    set vector_register2_vr "uint128 = 0xdeadbeefdeadbeefdeadbeefdeadbeef, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0xdeadbeef, 0xdeadbeef, 0xdeadbeef, 0xdeadbeef., v8_int16 = .0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead, 0xbeef, 0xdead., v16_int8 = .0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde, 0xef, 0xbe, 0xad, 0xde.."
++
++    set vector_register3 ".uint128 = 0x00000001000000010000000100000001, v2_double = .0x0, 0x0., v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0., v16_int8 = .0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0.."
++
++    set vector_register3_vr ".uint128 = 0x00000001000000010000000100000001, v4_float = .0x0, 0x0, 0x0, 0x0., v4_int32 = .0x1, 0x1, 0x1, 0x1., v8_int16 = .0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0., v16_int8 = .0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0.."
++}
+ 
+ set float_register ".raw 0xdeadbeefdeadbeef."
+ 
diff --git a/gdb-upstream-ppc64le08of15.patch b/gdb-upstream-ppc64le08of15.patch
new file mode 100644
index 0000000..292ff3b
--- /dev/null
+++ b/gdb-upstream-ppc64le08of15.patch
@@ -0,0 +1,57 @@
+commit 5b757e5ddbd9ad252d9c51103f1aa52b41c2e947
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:33:04 2014 +0100
+
+    PowerPC64 little-endian fixes: 32-bit DFP parameters
+    
+    Passing a 32-bit DFP in register needs to use the least-significant part
+    of the register.  Like with a previous patch that addressed the same
+    issue for small structs, this patch makes sure the appropriate offset
+    is used on little-endian systems.
+    
+    gdb/ChangeLog:
+    
+    	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct
+    	offset on little-endian when passing _Decimal32.
+    	(ppc64_sysv_abi_return_value_base): Likewise for return values.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,11 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct
++	offset on little-endian when passing _Decimal32.
++	(ppc64_sysv_abi_return_value_base): Likewise for return values.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* rs6000-tdep.c (efpr_pseudo_register_read): Use correct offset
+ 	of the overlapped FP register within the VSX register on little-
+ 	endian platforms.
+--- a/gdb/ppc-sysv-tdep.c
++++ b/gdb/ppc-sysv-tdep.c
+@@ -1232,7 +1232,10 @@ ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch,
+       if (argpos->regcache && argpos->freg <= 13)
+ 	{
+ 	  int regnum = tdep->ppc_fp0_regnum + argpos->freg;
+-	  int offset = 8 - TYPE_LENGTH (type);
++	  int offset = 0;
++
++	  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
++	    offset = 8 - TYPE_LENGTH (type);
+ 
+ 	  regcache_cooked_write_part (argpos->regcache, regnum,
+ 				      offset, TYPE_LENGTH (type), val);
+@@ -1641,7 +1644,10 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype,
+       && TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
+     {
+       int regnum = tdep->ppc_fp0_regnum + 1 + index;
+-      int offset = 8 - TYPE_LENGTH (valtype);
++      int offset = 0;
++
++      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
++	offset = 8 - TYPE_LENGTH (valtype);
+ 
+       if (writebuf != NULL)
+ 	regcache_cooked_write_part (regcache, regnum,
diff --git a/gdb-upstream-ppc64le09of15.patch b/gdb-upstream-ppc64le09of15.patch
new file mode 100644
index 0000000..94f7edd
--- /dev/null
+++ b/gdb-upstream-ppc64le09of15.patch
@@ -0,0 +1,140 @@
+commit 0ff3e01fdc67a3842ee54224cf197e9a55f0a750
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:34:19 2014 +0100
+
+    PowerPC64 little-endian fixes: 128-bit DFP parameters / registers
+    
+    The powerpc64le-linux ABI specifies that when a 128-bit DFP value is
+    passed in a pair of floating-point registers, the first register holds
+    the most-significant part of the value.  This is as opposed to the
+    usual rule on little-endian systems, where the first register would
+    hold the least-significant part.
+    
+    This affects two places in GDB, the read/write routines for the
+    128-bit DFP pseudo-registers, and the function call / return
+    sequence.  For the former, current code already distinguishes
+    between big- and little-endian targets, but gets the latter
+    wrong.  This is presumably because *GCC* also got it wrong,
+    and GDB matches the old GCC behavior.  But GCC is now fixed:
+    http://gcc.gnu.org/ml/gcc-patches/2013-11/msg02145.html
+    so GDB needs to be fixed too.  (Old code shouldn't really be
+    an issue since there is no code "out there" so far that uses
+    dfp128 on little-endian ...)
+    
+    gdb/ChangeLog:
+    
+    	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct order
+    	within a register pair holding a DFP 128-bit value on little-endian.
+    	(ppc64_sysv_abi_return_value_base): Likewise.
+    	* rs6000-tdep.c (dfp_pseudo_register_read): Likewise.
+    	(dfp_pseudo_register_write): Likewise.
+    
+    gdb/testsuite/ChangeLog:
+    
+    	* gdb.arch/powerpc-d128-regs.exp: Enable on powerpc64*-*.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,13 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct order
++	within a register pair holding a DFP 128-bit value on little-endian.
++	(ppc64_sysv_abi_return_value_base): Likewise.
++	* rs6000-tdep.c (dfp_pseudo_register_read): Likewise.
++	(dfp_pseudo_register_write): Likewise.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct
+ 	offset on little-endian when passing _Decimal32.
+ 	(ppc64_sysv_abi_return_value_base): Likewise for return values.
+--- a/gdb/ppc-sysv-tdep.c
++++ b/gdb/ppc-sysv-tdep.c
+@@ -1270,9 +1270,11 @@ ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch,
+       if (argpos->regcache && argpos->freg <= 12)
+ 	{
+ 	  int regnum = tdep->ppc_fp0_regnum + argpos->freg;
++	  int lopart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 : 0;
++	  int hipart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
+ 
+-	  regcache_cooked_write (argpos->regcache, regnum, val);
+-	  regcache_cooked_write (argpos->regcache, regnum + 1, val + 8);
++	  regcache_cooked_write (argpos->regcache, regnum, val + hipart);
++	  regcache_cooked_write (argpos->regcache, regnum + 1, val + lopart);
+ 	}
+ 
+       argpos->freg += 2;
+@@ -1685,16 +1687,18 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype,
+       && TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
+     {
+       int regnum = tdep->ppc_fp0_regnum + 2 + 2 * index;
++      int lopart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 : 0;
++      int hipart = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
+ 
+       if (writebuf != NULL)
+ 	{
+-	  regcache_cooked_write (regcache, regnum, writebuf);
+-	  regcache_cooked_write (regcache, regnum + 1, writebuf + 8);
++	  regcache_cooked_write (regcache, regnum, writebuf + hipart);
++	  regcache_cooked_write (regcache, regnum + 1, writebuf + lopart);
+ 	}
+       if (readbuf != NULL)
+ 	{
+-	  regcache_cooked_read (regcache, regnum, readbuf);
+-	  regcache_cooked_read (regcache, regnum + 1, readbuf + 8);
++	  regcache_cooked_read (regcache, regnum, readbuf + hipart);
++	  regcache_cooked_read (regcache, regnum + 1, readbuf + lopart);
+ 	}
+       return 1;
+     }
+--- a/gdb/rs6000-tdep.c
++++ b/gdb/rs6000-tdep.c
+@@ -2672,10 +2672,10 @@ dfp_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+   else
+     {
+       status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+-				  2 * reg_index + 1, buffer + 8);
++				  2 * reg_index + 1, buffer);
+       if (status == REG_VALID)
+ 	status = regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+-				    2 * reg_index, buffer);
++				    2 * reg_index, buffer + 8);
+     }
+ 
+   return status;
+@@ -2701,9 +2701,9 @@ dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+   else
+     {
+       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+-			  2 * reg_index + 1, buffer + 8);
++			  2 * reg_index + 1, buffer);
+       regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+-			  2 * reg_index, buffer);
++			  2 * reg_index, buffer + 8);
+     }
+ }
+ 
+### a/gdb/testsuite/ChangeLog
+### b/gdb/testsuite/ChangeLog
+## -1,5 +1,9 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* gdb.arch/powerpc-d128-regs.exp: Enable on powerpc64*-*.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* gdb.arch/vsx-regs.exp: Check target endianness.  Provide variants
+ 	of the test patterns for use on little-endian systems.
+ 
+--- a/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
++++ b/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
+@@ -20,7 +20,7 @@
+ 
+ # Testcase for ppc decimal128 pseudo-registers.
+ 
+-if ![istarget "powerpc64-*"] then {
++if ![istarget "powerpc64*-*"] then {
+     verbose "Skipping powerpc Decimal128 pseudo-registers testcase."
+     return
+ }
diff --git a/gdb-upstream-ppc64le10of15.patch b/gdb-upstream-ppc64le10of15.patch
new file mode 100644
index 0000000..2e307d9
--- /dev/null
+++ b/gdb-upstream-ppc64le10of15.patch
@@ -0,0 +1,159 @@
+commit cd453cd072004d26ede355b850b3831acffaeddd
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:38:56 2014 +0100
+
+    PowerPC64 ELFv2 ABI: base support
+    
+    This is the first patch of a series to implement support for the
+    PowerPC ELFv2 ABI.  While powerpc64le-linux will use ELFv2, and
+    the existing powerpc64-linux code will continue to use ELFv1,
+    in theory ELFv2 is also defined for big-endian systems (and
+    ELFv1 was also defined for little-endian systems).
+    
+    Therefore this patch adds a new tdep->elf_abi variable to decide
+    which ABI version to use.  This is detected from the ELF header
+    e_flags value; if this is not present, we default to ELFv2 on
+    little-endian and ELFv1 otherwise.
+    
+    This patch does not yet introduce any actual difference in GDB's
+    handling of the two ABIs.  Those will be added by the remainder
+    of this patch series.
+    
+    For an overview of the changes in ELFv2, have a look at the
+    comments in the patch series that added ELFv2 to GCC, starting at:
+    http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01144.html
+    
+    gdb/ChangeLog:
+    
+    	* ppc-tdep.h (enum powerpc_elf_abi): New data type.
+    	(struct gdbarch_tdep): New member elf_abi.
+    
+    	* rs6000-tdep.c: Include "elf/ppc64.h".
+    	(rs6000_gdbarch_init): Detect ELF ABI version.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,13 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-tdep.h (enum powerpc_elf_abi): New data type.
++	(struct gdbarch_tdep): New member elf_abi.
++
++	* rs6000-tdep.c: Include "elf/ppc64.h".
++	(rs6000_gdbarch_init): Detect ELF ABI version.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_freg): Use correct order
+ 	within a register pair holding a DFP 128-bit value on little-endian.
+ 	(ppc64_sysv_abi_return_value_base): Likewise.
+Index: gdb-7.7.1/gdb/ppc-tdep.h
+===================================================================
+--- gdb-7.7.1.orig/gdb/ppc-tdep.h	2014-05-09 19:23:40.892248064 +0200
++++ gdb-7.7.1/gdb/ppc-tdep.h	2014-05-09 19:23:42.346248246 +0200
+@@ -182,6 +182,15 @@ extern void ppc_collect_vsxregset (const
+ 
+ /* Private data that this module attaches to struct gdbarch.  */
+ 
++/* ELF ABI version used by the inferior.  */
++enum powerpc_elf_abi
++{
++  POWERPC_ELF_AUTO,
++  POWERPC_ELF_V1,
++  POWERPC_ELF_V2,
++  POWERPC_ELF_LAST
++};
++
+ /* Vector ABI used by the inferior.  */
+ enum powerpc_vector_abi
+ {
+@@ -197,6 +206,8 @@ struct gdbarch_tdep
+     int wordsize;		/* Size in bytes of fixed-point word.  */
+     int soft_float;		/* Avoid FP registers for arguments?  */
+ 
++    enum powerpc_elf_abi elf_abi;	/* ELF ABI version.  */
++
+     /* How to pass vector arguments.  Never set to AUTO or LAST.  */
+     enum powerpc_vector_abi vector_abi;
+ 
+Index: gdb-7.7.1/gdb/rs6000-tdep.c
+===================================================================
+--- gdb-7.7.1.orig/gdb/rs6000-tdep.c	2014-05-09 19:23:40.894248064 +0200
++++ gdb-7.7.1/gdb/rs6000-tdep.c	2014-05-09 19:23:57.974250197 +0200
+@@ -48,6 +48,7 @@
+ 
+ #include "elf-bfd.h"
+ #include "elf/ppc.h"
++#include "elf/ppc64.h"
+ 
+ #include "solib-svr4.h"
+ #include "ppc-tdep.h"
+@@ -3554,6 +3555,7 @@ rs6000_gdbarch_init (struct gdbarch_info
+   enum auto_boolean soft_float_flag = powerpc_soft_float_global;
+   int soft_float;
+   enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
++  enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO;
+   int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
+       have_vsx = 0;
+   int tdesc_wordsize = -1;
+@@ -3860,6 +3862,21 @@ rs6000_gdbarch_init (struct gdbarch_info
+     }
+ 
+ #ifdef HAVE_ELF
++  if (from_elf_exec)
++    {
++      switch (elf_elfheader (info.abfd)->e_flags & EF_PPC64_ABI)
++	{
++	case 1:
++	  elf_abi = POWERPC_ELF_V1;
++	  break;
++	case 2:
++	  elf_abi = POWERPC_ELF_V2;
++	  break;
++	default:
++	  break;
++	}
++    }
++
+   if (soft_float_flag == AUTO_BOOLEAN_AUTO && from_elf_exec)
+     {
+       switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
+@@ -3896,6 +3913,21 @@ rs6000_gdbarch_init (struct gdbarch_info
+     }
+ #endif
+ 
++  /* At this point, the only supported ELF-based 64-bit little-endian
++     operating system is GNU/Linux, and this uses the ELFv2 ABI by
++     default.  All other supported ELF-based operating systems use the
++     ELFv1 ABI by default.  Therefore, if the ABI marker is missing,
++     e.g. because we run a legacy binary, or have attached to a process
++     and have not found any associated binary file, set the default
++     according to this heuristic.  */
++  if (elf_abi == POWERPC_ELF_AUTO)
++    {
++      if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE)
++        elf_abi = POWERPC_ELF_V2;
++      else
++        elf_abi = POWERPC_ELF_V1;
++    }
++
+   if (soft_float_flag == AUTO_BOOLEAN_TRUE)
+     soft_float = 1;
+   else if (soft_float_flag == AUTO_BOOLEAN_FALSE)
+@@ -3938,6 +3970,8 @@ rs6000_gdbarch_init (struct gdbarch_info
+          meaningful, because 64-bit CPUs can run in 32-bit mode.  So, perform
+          separate word size check.  */
+       tdep = gdbarch_tdep (arches->gdbarch);
++      if (tdep && tdep->elf_abi != elf_abi)
++	continue;
+       if (tdep && tdep->soft_float != soft_float)
+ 	continue;
+       if (tdep && tdep->vector_abi != vector_abi)
+@@ -3960,6 +3994,7 @@ rs6000_gdbarch_init (struct gdbarch_info
+ 
+   tdep = XCALLOC (1, struct gdbarch_tdep);
+   tdep->wordsize = wordsize;
++  tdep->elf_abi = elf_abi;
+   tdep->soft_float = soft_float;
+   tdep->vector_abi = vector_abi;
+ 
diff --git a/gdb-upstream-ppc64le11of15.patch b/gdb-upstream-ppc64le11of15.patch
new file mode 100644
index 0000000..fdbd7ab
--- /dev/null
+++ b/gdb-upstream-ppc64le11of15.patch
@@ -0,0 +1,132 @@
+commit d4094b6a8883ae481c7644c5a210254efe92e9ad
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:40:16 2014 +0100
+
+    PowerPC64 ELFv2 ABI: no function descriptors
+    
+    This implements the most significant difference with the ELFv2 ABI:
+    we no longer use function descriptors.  The patch consists mostly
+    of switching off code to deal with descriptors :-)
+    
+    In addition, when calling an inferior function, we no longer need
+    to provide its TOC in r2.  Instead, ELFv2 code expects to be called
+    with r12 pointing to the code address itself.
+    
+    gdb/ChangeLog:
+    
+    	* ppc-linux-tdep.c (ppc_linux_init_abi): Only call
+    	set_gdbarch_convert_from_func_ptr_addr and
+    	set_gdbarch_elf_make_msymbol_special for ELFv1.
+    	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_param): Only handle
+    	function descriptors on ELFv1.
+    	(ppc64_sysv_abi_push_dummy_call): Likewise.  On ELFv2,
+    	set up r12 at function entry.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,15 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-linux-tdep.c (ppc_linux_init_abi): Only call
++	set_gdbarch_convert_from_func_ptr_addr and
++	set_gdbarch_elf_make_msymbol_special for ELFv1.
++	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_param): Only handle
++	function descriptors on ELFv1.
++	(ppc64_sysv_abi_push_dummy_call): Likewise.  On ELFv2,
++	set up r12 at function entry.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-tdep.h (enum powerpc_elf_abi): New data type.
+ 	(struct gdbarch_tdep): New member elf_abi.
+ 
+--- a/gdb/ppc-linux-tdep.c
++++ b/gdb/ppc-linux-tdep.c
+@@ -1339,13 +1339,16 @@ ppc_linux_init_abi (struct gdbarch_info info,
+   
+   if (tdep->wordsize == 8)
+     {
+-      /* Handle PPC GNU/Linux 64-bit function pointers (which are really
+-	 function descriptors).  */
+-      set_gdbarch_convert_from_func_ptr_addr
+-	(gdbarch, ppc64_convert_from_func_ptr_addr);
++      if (tdep->elf_abi == POWERPC_ELF_V1)
++	{
++	  /* Handle PPC GNU/Linux 64-bit function pointers (which are really
++	     function descriptors).  */
++	  set_gdbarch_convert_from_func_ptr_addr
++	    (gdbarch, ppc64_convert_from_func_ptr_addr);
+ 
+-      set_gdbarch_elf_make_msymbol_special (gdbarch,
+-					    ppc64_elf_make_msymbol_special);
++	  set_gdbarch_elf_make_msymbol_special
++	    (gdbarch, ppc64_elf_make_msymbol_special);
++	}
+ 
+       /* Shared library handling.  */
+       set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
+--- a/gdb/ppc-sysv-tdep.c
++++ b/gdb/ppc-sysv-tdep.c
+@@ -1352,8 +1352,9 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
+ 	  word = unpack_long (type, val);
+ 
+ 	  /* Convert any function code addresses into descriptors.  */
+-	  if (TYPE_CODE (type) == TYPE_CODE_PTR
+-	      || TYPE_CODE (type) == TYPE_CODE_REF)
++	  if (tdep->elf_abi == POWERPC_ELF_V1
++	      && (TYPE_CODE (type) == TYPE_CODE_PTR
++		  || TYPE_CODE (type) == TYPE_CODE_REF))
+ 	    {
+ 	      struct type *target_type
+ 		= check_typedef (TYPE_TARGET_TYPE (type));
+@@ -1553,24 +1554,32 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+      breakpoint.  */
+   regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
+ 
+-  /* Use the func_addr to find the descriptor, and use that to find
+-     the TOC.  If we're calling via a function pointer, the pointer
+-     itself identifies the descriptor.  */
+-  {
+-    struct type *ftype = check_typedef (value_type (function));
+-    CORE_ADDR desc_addr = value_as_address (function);
+-
+-    if (TYPE_CODE (ftype) == TYPE_CODE_PTR
+-	|| convert_code_addr_to_desc_addr (func_addr, &desc_addr))
+-      {
+-	/* The TOC is the second double word in the descriptor.  */
+-	CORE_ADDR toc =
+-	  read_memory_unsigned_integer (desc_addr + tdep->wordsize,
+-					tdep->wordsize, byte_order);
+-	regcache_cooked_write_unsigned (regcache,
+-					tdep->ppc_gp0_regnum + 2, toc);
+-      }
+-  }
++  /* In the ELFv1 ABI, use the func_addr to find the descriptor, and use
++     that to find the TOC.  If we're calling via a function pointer,
++     the pointer itself identifies the descriptor.  */
++  if (tdep->elf_abi == POWERPC_ELF_V1)
++    {
++      struct type *ftype = check_typedef (value_type (function));
++      CORE_ADDR desc_addr = value_as_address (function);
++
++      if (TYPE_CODE (ftype) == TYPE_CODE_PTR
++	  || convert_code_addr_to_desc_addr (func_addr, &desc_addr))
++	{
++	  /* The TOC is the second double word in the descriptor.  */
++	  CORE_ADDR toc =
++	    read_memory_unsigned_integer (desc_addr + tdep->wordsize,
++					  tdep->wordsize, byte_order);
++
++	  regcache_cooked_write_unsigned (regcache,
++					  tdep->ppc_gp0_regnum + 2, toc);
++	}
++    }
++
++  /* In the ELFv2 ABI, we need to pass the target address in r12 since
++     we may be calling a global entry point.  */
++  if (tdep->elf_abi == POWERPC_ELF_V2)
++    regcache_cooked_write_unsigned (regcache,
++				    tdep->ppc_gp0_regnum + 12, func_addr);
+ 
+   return sp;
+ }
diff --git a/gdb-upstream-ppc64le12of15.patch b/gdb-upstream-ppc64le12of15.patch
new file mode 100644
index 0000000..3b38682
--- /dev/null
+++ b/gdb-upstream-ppc64le12of15.patch
@@ -0,0 +1,48 @@
+commit 52f548e41f085550d7740c350c1c8a239532af77
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:41:36 2014 +0100
+
+    PowerPC64 ELFv2 ABI: stack frame layout changes
+    
+    This implementes another change in ELFv2: the stack frame no longer
+    contains the reserved double words for linker and compiler use
+    (which weren't really used for much of anything anyway).  This
+    affects placement of on-stack parameters in inferior calls.
+    
+    gdb/ChangeLog:
+    
+    	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Use correct
+    	offset to the stack parameter list for the ELFv2 ABI.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,10 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Use correct
++	offset to the stack parameter list for the ELFv2 ABI.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-linux-tdep.c (ppc_linux_init_abi): Only call
+ 	set_gdbarch_convert_from_func_ptr_addr and
+ 	set_gdbarch_elf_make_msymbol_special for ELFv1.
+--- a/gdb/ppc-sysv-tdep.c
++++ b/gdb/ppc-sysv-tdep.c
+@@ -1474,9 +1474,13 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
+ 	  argpos.regcache = regcache;
+ 	  argpos.refparam = align_down (sp - refparam_size, 16);
+ 	  argpos.gparam = align_down (argpos.refparam - gparam_size, 16);
+-	  /* Add in space for the TOC, link editor double word,
+-	     compiler double word, LR save area, CR save area.  */
+-	  sp = align_down (argpos.gparam - 48, 16);
++	  /* Add in space for the TOC, link editor double word (v1 only),
++	     compiler double word (v1 only), LR save area, CR save area,
++	     and backchain.  */
++	  if (tdep->elf_abi == POWERPC_ELF_V1)
++	    sp = align_down (argpos.gparam - 48, 16);
++	  else
++	    sp = align_down (argpos.gparam - 32, 16);
+ 	}
+ 
+       /* If the function is returning a `struct', then there is an
diff --git a/gdb-upstream-ppc64le13of15.patch b/gdb-upstream-ppc64le13of15.patch
new file mode 100644
index 0000000..79ce599
--- /dev/null
+++ b/gdb-upstream-ppc64le13of15.patch
@@ -0,0 +1,309 @@
+commit cc0e89c519912e0e4e75a2fc0d836f715cdc6806
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:42:35 2014 +0100
+
+    PowerPC64 ELFv2 ABI: structure passing / return
+    
+    Another significant difference in the ELFv2 ABI is that "homogeneous"
+    floating-point and vector aggregates, i.e. aggregates the consist
+    (recursively) only of members of the same floating-point or vector type,
+    are passed in a series of floating-point / vector registers, as if they
+    were seperate parameters.  (This is similar to the ARM ABI.)  This
+    applies to both calls and returns.
+    
+    In addition when returning any aggregate of up to 16 bytes, ELFv2 now
+    used general-purpose registers.
+    
+    This patch adds support for these aspects of the ABI, which is relatively
+    straightforward after the refactoring patch to ppc-sysv-tdep.c.
+    
+    gdb/ChangeLog:
+    
+    	* ppc-sysv-tdep.c (ppc64_aggregate_candidate): New routine.
+    	(ppc64_elfv2_abi_homogeneous_aggregate): Likewise.
+    	(ppc64_sysv_abi_push_param): Handle ELFv2 homogeneous structs.
+    	(ppc64_sysv_abi_return_value): Likewise.  Also, handle small
+    	structures returned in GPRs.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,13 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* ppc-sysv-tdep.c (ppc64_aggregate_candidate): New routine.
++	(ppc64_elfv2_abi_homogeneous_aggregate): Likewise.
++	(ppc64_sysv_abi_push_param): Handle ELFv2 homogeneous structs.
++	(ppc64_sysv_abi_return_value): Likewise.  Also, handle small
++	structures returned in GPRs.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Use correct
+ 	offset to the stack parameter list for the ELFv2 ABI.
+ 
+--- a/gdb/ppc-sysv-tdep.c
++++ b/gdb/ppc-sysv-tdep.c
+@@ -1101,6 +1101,160 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
+   return 1;
+ }
+ 
++/* Walk down the type tree of TYPE counting consecutive base elements.
++   If *FIELD_TYPE is NULL, then set it to the first valid floating point
++   or vector type.  If a non-floating point or vector type is found, or
++   if a floating point or vector type that doesn't match a non-NULL
++   *FIELD_TYPE is found, then return -1, otherwise return the count in the
++   sub-tree.  */
++
++static LONGEST
++ppc64_aggregate_candidate (struct type *type,
++			   struct type **field_type)
++{
++  type = check_typedef (type);
++
++  switch (TYPE_CODE (type))
++    {
++    case TYPE_CODE_FLT:
++    case TYPE_CODE_DECFLOAT:
++      if (!*field_type)
++	*field_type = type;
++      if (TYPE_CODE (*field_type) == TYPE_CODE (type)
++	  && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type))
++	return 1;
++      break;
++
++    case TYPE_CODE_COMPLEX:
++      type = TYPE_TARGET_TYPE (type);
++      if (TYPE_CODE (type) == TYPE_CODE_FLT
++	  || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
++	{
++	  if (!*field_type)
++	    *field_type = type;
++	  if (TYPE_CODE (*field_type) == TYPE_CODE (type)
++	      && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type))
++	    return 2;
++	}
++      break;
++
++    case TYPE_CODE_ARRAY:
++      if (TYPE_VECTOR (type))
++	{
++	  if (!*field_type)
++	    *field_type = type;
++	  if (TYPE_CODE (*field_type) == TYPE_CODE (type)
++	      && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type))
++	    return 1;
++	}
++      else
++	{
++	  LONGEST count, low_bound, high_bound;
++
++	  count = ppc64_aggregate_candidate
++		   (TYPE_TARGET_TYPE (type), field_type);
++	  if (count == -1)
++	    return -1;
++
++	  if (!get_array_bounds (type, &low_bound, &high_bound))
++	    return -1;
++	  count *= high_bound - low_bound;
++
++	  /* There must be no padding.  */
++	  if (count == 0)
++	    return TYPE_LENGTH (type) == 0 ? 0 : -1;
++	  else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type))
++	    return -1;
++
++	  return count;
++	}
++      break;
++
++    case TYPE_CODE_STRUCT:
++    case TYPE_CODE_UNION:
++	{
++	  LONGEST count = 0;
++	  int i;
++
++	  for (i = 0; i < TYPE_NFIELDS (type); i++)
++	    {
++	      LONGEST sub_count;
++
++	      if (field_is_static (&TYPE_FIELD (type, i)))
++		continue;
++
++	      sub_count = ppc64_aggregate_candidate
++			   (TYPE_FIELD_TYPE (type, i), field_type);
++	      if (sub_count == -1)
++		return -1;
++
++	      if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
++		count += sub_count;
++	      else
++		count = max (count, sub_count);
++	    }
++
++	  /* There must be no padding.  */
++	  if (count == 0)
++	    return TYPE_LENGTH (type) == 0 ? 0 : -1;
++	  else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type))
++	    return -1;
++
++	  return count;
++	}
++      break;
++
++    default:
++      break;
++    }
++
++  return -1;
++}
++
++/* If an argument of type TYPE is a homogeneous float or vector aggregate
++   that shall be passed in FP/vector registers according to the ELFv2 ABI,
++   return the homogeneous element type in *ELT_TYPE and the number of
++   elements in *N_ELTS, and return non-zero.  Otherwise, return zero.  */
++
++static int
++ppc64_elfv2_abi_homogeneous_aggregate (struct type *type,
++				       struct type **elt_type, int *n_elts)
++{
++  /* Complex types at the top level are treated separately.  However,
++     complex types can be elements of homogeneous aggregates.  */
++  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
++      || TYPE_CODE (type) == TYPE_CODE_UNION
++      || (TYPE_CODE (type) == TYPE_CODE_ARRAY && !TYPE_VECTOR (type)))
++    {
++      struct type *field_type = NULL;
++      LONGEST field_count = ppc64_aggregate_candidate (type, &field_type);
++
++      if (field_count > 0)
++	{
++	  int n_regs = ((TYPE_CODE (field_type) == TYPE_CODE_FLT
++			 || TYPE_CODE (field_type) == TYPE_CODE_DECFLOAT)?
++			(TYPE_LENGTH (field_type) + 7) >> 3 : 1);
++
++	  /* The ELFv2 ABI allows homogeneous aggregates to occupy
++	     up to 8 registers.  */
++	  if (field_count * n_regs <= 8)
++	    {
++	      if (elt_type)
++		*elt_type = field_type;
++	      if (n_elts)
++		*n_elts = (int) field_count;
++	      /* Note that field_count is LONGEST since it may hold the size
++		 of an array, while *n_elts is int since its value is bounded
++		 by the number of registers used for argument passing.  The
++		 cast cannot overflow due to the bounds checking above.  */
++	      return 1;
++	    }
++	}
++    }
++
++  return 0;
++}
++
+ /* Structure holding the next argument position.  */
+ struct ppc64_sysv_argpos
+   {
+@@ -1389,6 +1543,29 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
+ 	  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ 	    ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos);
+ 	}
++
++      /* In the ELFv2 ABI, homogeneous floating-point or vector
++	 aggregates are passed in a series of registers.  */
++      if (tdep->elf_abi == POWERPC_ELF_V2)
++	{
++	  struct type *eltype;
++	  int i, nelt;
++
++	  if (ppc64_elfv2_abi_homogeneous_aggregate (type, &eltype, &nelt))
++	    for (i = 0; i < nelt; i++)
++	      {
++		const gdb_byte *elval = val + i * TYPE_LENGTH (eltype);
++
++		if (TYPE_CODE (eltype) == TYPE_CODE_FLT
++		    || TYPE_CODE (eltype) == TYPE_CODE_DECFLOAT)
++		  ppc64_sysv_abi_push_freg (gdbarch, eltype, elval, argpos);
++		else if (TYPE_CODE (eltype) == TYPE_CODE_ARRAY
++			 && TYPE_VECTOR (eltype)
++			 && tdep->vector_abi == POWERPC_VEC_ALTIVEC
++			 && TYPE_LENGTH (eltype) == 16)
++		  ppc64_sysv_abi_push_vreg (gdbarch, elval, argpos);
++	      }
++	}
+     }
+ }
+ 
+@@ -1834,6 +2011,72 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
+       return RETURN_VALUE_REGISTER_CONVENTION;
+     }
+ 
++  /* In the ELFv2 ABI, homogeneous floating-point or vector
++     aggregates are returned in registers.  */
++  if (tdep->elf_abi == POWERPC_ELF_V2
++      && ppc64_elfv2_abi_homogeneous_aggregate (valtype, &eltype, &nelt))
++    {
++      for (i = 0; i < nelt; i++)
++	{
++	  ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache,
++						 readbuf, writebuf, i);
++	  gdb_assert (ok);
++
++	  if (readbuf)
++	    readbuf += TYPE_LENGTH (eltype);
++	  if (writebuf)
++	    writebuf += TYPE_LENGTH (eltype);
++	}
++
++      return RETURN_VALUE_REGISTER_CONVENTION;
++    }
++
++  /* In the ELFv2 ABI, aggregate types of up to 16 bytes are
++     returned in registers r3:r4.  */
++  if (tdep->elf_abi == POWERPC_ELF_V2
++      && TYPE_LENGTH (valtype) <= 16
++      && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
++	  || TYPE_CODE (valtype) == TYPE_CODE_UNION
++	  || (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
++	      && !TYPE_VECTOR (valtype))))
++    {
++      int n_regs = ((TYPE_LENGTH (valtype) + tdep->wordsize - 1)
++		    / tdep->wordsize);
++      int i;
++
++      for (i = 0; i < n_regs; i++)
++	{
++	  gdb_byte regval[MAX_REGISTER_SIZE];
++	  int regnum = tdep->ppc_gp0_regnum + 3 + i;
++	  int offset = i * tdep->wordsize;
++	  int len = TYPE_LENGTH (valtype) - offset;
++
++	  if (len > tdep->wordsize)
++	    len = tdep->wordsize;
++
++	  if (writebuf != NULL)
++	    {
++	      memset (regval, 0, sizeof regval);
++	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
++		  && offset == 0)
++		memcpy (regval + tdep->wordsize - len, writebuf, len);
++	      else
++		memcpy (regval, writebuf + offset, len);
++	      regcache_cooked_write (regcache, regnum, regval);
++	    }
++	  if (readbuf != NULL)
++	    {
++	      regcache_cooked_read (regcache, regnum, regval);
++	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
++		  && offset == 0)
++		memcpy (readbuf, regval + tdep->wordsize - len, len);
++	      else
++		memcpy (readbuf + offset, regval, len);
++	    }
++	}
++      return RETURN_VALUE_REGISTER_CONVENTION;
++    }
++
+   /* Handle plain base types.  */
+   if (ppc64_sysv_abi_return_value_base (gdbarch, valtype, regcache,
+ 					readbuf, writebuf, 0))
diff --git a/gdb-upstream-ppc64le14of15.patch b/gdb-upstream-ppc64le14of15.patch
new file mode 100644
index 0000000..abee983
--- /dev/null
+++ b/gdb-upstream-ppc64le14of15.patch
@@ -0,0 +1,375 @@
+commit 591a12a1d4c8843343eb999145d8bcc1efedf408
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Feb 4 18:44:14 2014 +0100
+
+    PowerPC64 ELFv2 ABI: skip global entry point code
+    
+    This patch handles another aspect of the ELFv2 ABI, which unfortunately
+    requires common code changes.
+    
+    In ELFv2, functions may provide both a global and a local entry point.
+    The global entry point (where the function symbol points to) is intended
+    to be used for function-pointer or cross-module (PLT) calls, and requires
+    r12 to be set up to the entry point address itself.   The local entry
+    point (which is found at a fixed offset after the global entry point,
+    as defined by bits in the symbol table entries' st_other field), instead
+    expects r2 to be set up to the current TOC.
+    
+    Now, when setting a breakpoint on a function by name, you really want
+    that breakpoint to trigger either way, no matter whether the function
+    is called via its local or global entry point.  Since the global entry
+    point will always fall through into the local entry point, the way to
+    achieve that is to simply set the breakpoint at the local entry point.
+    
+    One way to do that would be to have prologue parsing skip the code
+    sequence that makes up the global entry point.  Unfortunately, this
+    does not work reliably, since -for optimized code- GDB these days
+    will not actuall invoke the prologue parsing code but instead just
+    set the breakpoint at the symbol address and rely on DWARF being
+    correct at any point throughout the function ...
+    
+    Unfortunately, I don't really see any way to express the notion of
+    local entry points with the current set of gdbarch callbacks.
+    
+    Thus this patch adds a new callback, skip_entrypoint, that is
+    somewhat analogous to skip_prologue, but is called every time
+    GDB needs to determine a function start address, even in those
+    cases where GDB decides to not call skip_prologue.
+    
+    As a side effect, the skip_entrypoint implementation on ppc64
+    does not need to perform any instruction parsing; it can simply
+    rely on the local entry point flags in the symbol table entry.
+    
+    With this implemented, two test cases would still fail to set
+    the breakpoint correctly, but that's because they use the construct:
+    
+     gdb_test "break *hello"
+    
+    Now, using "*hello" explicitly instructs GDB to set the breakpoint
+    at the numerical value of "hello" treated as function pointer, so
+    it will by definition only hit the global entry point.
+    
+    I think this behaviour is unavoidable, but acceptable -- most people
+    do not use this construct, and if they do, they get what they
+    asked for ...
+    
+    In one of those two test cases, use of this construct is really
+    not appropriate.  I think this was added way back when as a means
+    to work around prologue skipping problems on some platforms.  These
+    days that shouldn't really be necessary any more ...
+    
+    For the other (step-bt), we really want to make sure backtracing
+    works on the very first instruction of the routine.  To enable that
+    test also on powerpc64le-linux, we can modify the code to call the
+    test function via function pointer (which makes it use the global
+    entry point in the ELFv2 ABI).
+    
+    gdb/ChangeLog:
+    
+    	* gdbarch.sh (skip_entrypoint): New callback.
+    	* gdbarch.c, gdbarch.h: Regenerate.
+    	* symtab.c (skip_prologue_sal): Call gdbarch_skip_entrypoint.
+    	* infrun.c (fill_in_stop_func): Likewise.
+    	* ppc-linux-tdep.c: Include "elf/ppc64.h".
+    	(ppc_elfv2_elf_make_msymbol_special): New function.
+    	(ppc_elfv2_skip_entrypoint): Likewise.
+    	(ppc_linux_init_abi): Install them for ELFv2.
+    
+    gdb/testsuite/ChangeLog:
+    
+    	* gdb.base/sigbpt.exp: Do not use "*" when setting breakpoint
+    	on a function.
+    	* gdb.base/step-bt.c: Call hello via function pointer to make
+    	sure its first instruction is executed on powerpc64le-linux.
+
+### a/gdb/ChangeLog
+### b/gdb/ChangeLog
+## -1,5 +1,16 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* gdbarch.sh (skip_entrypoint): New callback.
++	* gdbarch.c, gdbarch.h: Regenerate.
++	* symtab.c (skip_prologue_sal): Call gdbarch_skip_entrypoint.
++	* infrun.c (fill_in_stop_func): Likewise.
++	* ppc-linux-tdep.c: Include "elf/ppc64.h".
++	(ppc_elfv2_elf_make_msymbol_special): New function.
++	(ppc_elfv2_skip_entrypoint): Likewise.
++	(ppc_linux_init_abi): Install them for ELFv2.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* ppc-sysv-tdep.c (ppc64_aggregate_candidate): New routine.
+ 	(ppc64_elfv2_abi_homogeneous_aggregate): Likewise.
+ 	(ppc64_sysv_abi_push_param): Handle ELFv2 homogeneous structs.
+--- a/gdb/gdbarch.c
++++ b/gdb/gdbarch.c
+@@ -229,6 +229,7 @@ struct gdbarch
+   gdbarch_return_in_first_hidden_param_p_ftype *return_in_first_hidden_param_p;
+   gdbarch_skip_prologue_ftype *skip_prologue;
+   gdbarch_skip_main_prologue_ftype *skip_main_prologue;
++  gdbarch_skip_entrypoint_ftype *skip_entrypoint;
+   gdbarch_inner_than_ftype *inner_than;
+   gdbarch_breakpoint_from_pc_ftype *breakpoint_from_pc;
+   gdbarch_remote_breakpoint_from_pc_ftype *remote_breakpoint_from_pc;
+@@ -405,6 +406,7 @@ struct gdbarch startup_gdbarch =
+   default_return_in_first_hidden_param_p,  /* return_in_first_hidden_param_p */
+   0,  /* skip_prologue */
+   0,  /* skip_main_prologue */
++  0,  /* skip_entrypoint */
+   0,  /* inner_than */
+   0,  /* breakpoint_from_pc */
+   default_remote_breakpoint_from_pc,  /* remote_breakpoint_from_pc */
+@@ -714,6 +716,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
+   if (gdbarch->skip_prologue == 0)
+     fprintf_unfiltered (log, "\n\tskip_prologue");
+   /* Skip verify of skip_main_prologue, has predicate.  */
++  /* Skip verify of skip_entrypoint, has predicate.  */
+   if (gdbarch->inner_than == 0)
+     fprintf_unfiltered (log, "\n\tinner_than");
+   if (gdbarch->breakpoint_from_pc == 0)
+@@ -1353,6 +1356,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
+                       "gdbarch_dump: single_step_through_delay = <%s>\n",
+                       host_address_to_string (gdbarch->single_step_through_delay));
+   fprintf_unfiltered (file,
++                      "gdbarch_dump: gdbarch_skip_entrypoint_p() = %d\n",
++                      gdbarch_skip_entrypoint_p (gdbarch));
++  fprintf_unfiltered (file,
++                      "gdbarch_dump: skip_entrypoint = <%s>\n",
++                      host_address_to_string (gdbarch->skip_entrypoint));
++  fprintf_unfiltered (file,
+                       "gdbarch_dump: gdbarch_skip_main_prologue_p() = %d\n",
+                       gdbarch_skip_main_prologue_p (gdbarch));
+   fprintf_unfiltered (file,
+@@ -2703,6 +2712,30 @@ set_gdbarch_skip_main_prologue (struct gdbarch *gdbarch,
+ }
+ 
+ int
++gdbarch_skip_entrypoint_p (struct gdbarch *gdbarch)
++{
++  gdb_assert (gdbarch != NULL);
++  return gdbarch->skip_entrypoint != NULL;
++}
++
++CORE_ADDR
++gdbarch_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR ip)
++{
++  gdb_assert (gdbarch != NULL);
++  gdb_assert (gdbarch->skip_entrypoint != NULL);
++  if (gdbarch_debug >= 2)
++    fprintf_unfiltered (gdb_stdlog, "gdbarch_skip_entrypoint called\n");
++  return gdbarch->skip_entrypoint (gdbarch, ip);
++}
++
++void
++set_gdbarch_skip_entrypoint (struct gdbarch *gdbarch,
++                             gdbarch_skip_entrypoint_ftype skip_entrypoint)
++{
++  gdbarch->skip_entrypoint = skip_entrypoint;
++}
++
++int
+ gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs)
+ {
+   gdb_assert (gdbarch != NULL);
+--- a/gdb/gdbarch.h
++++ b/gdb/gdbarch.h
+@@ -486,6 +486,24 @@ typedef CORE_ADDR (gdbarch_skip_main_prologue_ftype) (struct gdbarch *gdbarch, C
+ extern CORE_ADDR gdbarch_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR ip);
+ extern void set_gdbarch_skip_main_prologue (struct gdbarch *gdbarch, gdbarch_skip_main_prologue_ftype *skip_main_prologue);
+ 
++/* On some platforms, a single function may provide multiple entry points,
++   e.g. one that is used for function-pointer calls and a different one
++   that is used for direct function calls.
++   In order to ensure that breakpoints set on the function will trigger
++   no matter via which entry point the function is entered, a platform
++   may provide the skip_entrypoint callback.  It is called with IP set
++   to the main entry point of a function (as determined by the symbol table),
++   and should return the address of the innermost entry point, where the
++   actual breakpoint needs to be set.  Note that skip_entrypoint is used
++   by GDB common code even when debugging optimized code, where skip_prologue
++   is not used. */
++
++extern int gdbarch_skip_entrypoint_p (struct gdbarch *gdbarch);
++
++typedef CORE_ADDR (gdbarch_skip_entrypoint_ftype) (struct gdbarch *gdbarch, CORE_ADDR ip);
++extern CORE_ADDR gdbarch_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR ip);
++extern void set_gdbarch_skip_entrypoint (struct gdbarch *gdbarch, gdbarch_skip_entrypoint_ftype *skip_entrypoint);
++
+ typedef int (gdbarch_inner_than_ftype) (CORE_ADDR lhs, CORE_ADDR rhs);
+ extern int gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs);
+ extern void set_gdbarch_inner_than (struct gdbarch *gdbarch, gdbarch_inner_than_ftype *inner_than);
+--- a/gdb/gdbarch.sh
++++ b/gdb/gdbarch.sh
+@@ -530,6 +530,19 @@ m:int:return_in_first_hidden_param_p:struct type *type:type::default_return_in_f
+ 
+ m:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip:0:0
+ M:CORE_ADDR:skip_main_prologue:CORE_ADDR ip:ip
++# On some platforms, a single function may provide multiple entry points,
++# e.g. one that is used for function-pointer calls and a different one
++# that is used for direct function calls.
++# In order to ensure that breakpoints set on the function will trigger
++# no matter via which entry point the function is entered, a platform
++# may provide the skip_entrypoint callback.  It is called with IP set
++# to the main entry point of a function (as determined by the symbol table),
++# and should return the address of the innermost entry point, where the
++# actual breakpoint needs to be set.  Note that skip_entrypoint is used
++# by GDB common code even when debugging optimized code, where skip_prologue
++# is not used.
++M:CORE_ADDR:skip_entrypoint:CORE_ADDR ip:ip
++
+ f:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0
+ m:const gdb_byte *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr::0:
+ # Return the adjusted address and kind to use for Z0/Z1 packets.
+--- a/gdb/infrun.c
++++ b/gdb/infrun.c
+@@ -3159,6 +3159,10 @@ fill_in_stop_func (struct gdbarch *gdbarch,
+       ecs->stop_func_start
+ 	+= gdbarch_deprecated_function_start_offset (gdbarch);
+ 
++      if (gdbarch_skip_entrypoint_p (gdbarch))
++	ecs->stop_func_start = gdbarch_skip_entrypoint (gdbarch,
++							ecs->stop_func_start);
++
+       ecs->stop_func_filled_in = 1;
+     }
+ }
+--- a/gdb/ppc-linux-tdep.c
++++ b/gdb/ppc-linux-tdep.c
+@@ -44,6 +44,7 @@
+ #include "observer.h"
+ #include "auxv.h"
+ #include "elf/common.h"
++#include "elf/ppc64.h"
+ #include "exceptions.h"
+ #include "arch-utils.h"
+ #include "spu-tdep.h"
+@@ -876,6 +877,55 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
+     }
+ }
+ 
++
++/* Implementation of `gdbarch_elf_make_msymbol_special', as defined in
++   gdbarch.h.  This implementation is used for the ELFv2 ABI only.  */
++
++static void
++ppc_elfv2_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
++{
++  elf_symbol_type *elf_sym = (elf_symbol_type *)sym;
++
++  /* If the symbol is marked as having a local entry point, set a target
++     flag in the msymbol.  We currently only support local entry point
++     offsets of 8 bytes, which is the only entry point offset ever used
++     by current compilers.  If/when other offsets are ever used, we will
++     have to use additional target flag bits to store them.  */
++  switch (PPC64_LOCAL_ENTRY_OFFSET (elf_sym->internal_elf_sym.st_other))
++    {
++    default:
++      break;
++    case 8:
++      MSYMBOL_TARGET_FLAG_1 (msym) = 1;
++      break;
++    }
++}
++
++/* Implementation of `gdbarch_skip_entrypoint', as defined in
++   gdbarch.h.  This implementation is used for the ELFv2 ABI only.  */
++
++static CORE_ADDR
++ppc_elfv2_skip_entrypoint (struct gdbarch *gdbarch, CORE_ADDR pc)
++{
++  struct bound_minimal_symbol fun;
++  int local_entry_offset = 0;
++
++  fun = lookup_minimal_symbol_by_pc (pc);
++  if (fun.minsym == NULL)
++    return pc;
++
++  /* See ppc_elfv2_elf_make_msymbol_special for how local entry point
++     offset values are encoded.  */
++  if (MSYMBOL_TARGET_FLAG_1 (fun.minsym))
++    local_entry_offset = 8;
++
++  if (SYMBOL_VALUE_ADDRESS (fun.minsym) <= pc
++      && pc < SYMBOL_VALUE_ADDRESS (fun.minsym) + local_entry_offset)
++    return SYMBOL_VALUE_ADDRESS (fun.minsym) + local_entry_offset;
++
++  return pc;
++}
++
+ /* Implementation of `gdbarch_stap_is_single_operand', as defined in
+    gdbarch.h.  */
+ 
+@@ -1349,6 +1399,13 @@ ppc_linux_init_abi (struct gdbarch_info info,
+ 	  set_gdbarch_elf_make_msymbol_special
+ 	    (gdbarch, ppc64_elf_make_msymbol_special);
+ 	}
++      else
++	{
++	  set_gdbarch_elf_make_msymbol_special
++	    (gdbarch, ppc_elfv2_elf_make_msymbol_special);
++
++	  set_gdbarch_skip_entrypoint (gdbarch, ppc_elfv2_skip_entrypoint);
++	}
+ 
+       /* Shared library handling.  */
+       set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
+--- a/gdb/symtab.c
++++ b/gdb/symtab.c
+@@ -2950,6 +2950,8 @@ skip_prologue_sal (struct symtab_and_line *sal)
+ 
+       /* Skip "first line" of function (which is actually its prologue).  */
+       pc += gdbarch_deprecated_function_start_offset (gdbarch);
++      if (gdbarch_skip_entrypoint_p (gdbarch))
++        pc = gdbarch_skip_entrypoint (gdbarch, pc);
+       if (skip)
+ 	pc = gdbarch_skip_prologue (gdbarch, pc);
+ 
+### a/gdb/testsuite/ChangeLog
+### b/gdb/testsuite/ChangeLog
+## -1,5 +1,12 @@
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+ 
++	* gdb.base/sigbpt.exp: Do not use "*" when setting breakpoint
++	on a function.
++	* gdb.base/step-bt.c: Call hello via function pointer to make
++	sure its first instruction is executed on powerpc64le-linux.
++
++2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
++
+ 	* gdb.arch/powerpc-d128-regs.exp: Enable on powerpc64*-*.
+ 
+ 2014-02-04  Ulrich Weigand  <uweigand at de.ibm.com>
+--- a/gdb/testsuite/gdb.base/sigbpt.exp
++++ b/gdb/testsuite/gdb.base/sigbpt.exp
+@@ -76,7 +76,7 @@ gdb_test "break keeper"
+ set bowler_addrs bowler
+ set segv_addr none
+ gdb_test {display/i $pc}
+-gdb_test "advance *bowler" "bowler.*" "advance to the bowler"
++gdb_test "advance bowler" "bowler.*" "advance to the bowler"
+ set test "stepping to fault"
+ set signame "SIGSEGV"
+ gdb_test_multiple "stepi" "$test" {
+--- a/gdb/testsuite/gdb.base/step-bt.c
++++ b/gdb/testsuite/gdb.base/step-bt.c
+@@ -23,10 +23,19 @@ hello (void)
+   printf ("Hello world.\n");
+ }
+ 
++/* The test case uses "break *hello" to make sure to step at the very
++   first instruction of the function.  This causes a problem running
++   the test on powerpc64le-linux, since the first instruction belongs
++   to the global entry point prologue, which is skipped when doing a
++   local direct function call.  To make sure that first instruction is
++   indeed being executed and the breakpoint hits, we make sure to call
++   the routine via an indirect call.  */
++void (*ptr) (void) = hello;
++
+ int
+ main (void)
+ {
+-  hello ();
++  ptr ();
+ 
+   return 0;
+ }
diff --git a/gdb-upstream-ppc64le15of15.patch b/gdb-upstream-ppc64le15of15.patch
new file mode 100644
index 0000000..961bf68
--- /dev/null
+++ b/gdb-upstream-ppc64le15of15.patch
@@ -0,0 +1,90 @@
+commit bc9a55253ed7122cfeee90cd23d964f44c8b0e6a
+Author: Ulrich Weigand <ulrich.weigand at de.ibm.com>
+Date:   Tue Mar 25 15:39:32 2014 +0100
+
+    Support gdb.asm/asm-source.exp on powerpc64le
+    
+    Add new powerpc64le.inc file appropriate for the ELFv2 ABI and
+    use it to support the asm-source.exp test case on powerpc64le.
+    
+    gdb/testsuite/
+    2014-03-25  Ulrich Weigand  <uweigand at de.ibm.com>
+    
+    	* gdb.asm/asm-source.exp: Handle powerpc64le-* targets.
+    	* gdb.asm/powerpc64le.inc: New file.
+
+### a/gdb/testsuite/ChangeLog
+### b/gdb/testsuite/ChangeLog
+## -1,3 +1,8 @@
++2014-03-25  Ulrich Weigand  <uweigand at de.ibm.com>
++
++	* gdb.asm/asm-source.exp: Handle powerpc64le-* targets.
++	* gdb.asm/powerpc64le.inc: New file.
++
+ 2014-03-25  Pedro Alves  <palves at redhat.com>
+ 	    Doug Evans  <dje at google.com>
+ 
+--- a/gdb/testsuite/gdb.asm/asm-source.exp
++++ b/gdb/testsuite/gdb.asm/asm-source.exp
+@@ -97,6 +97,11 @@ switch -glob -- [istarget] {
+     "mips*-*" {
+         set asm-arch mips
+     }
++    "powerpc64le-*" {
++        set asm-arch powerpc64le
++        set asm-flags "-a64 -I${srcdir}/${subdir} $obj_include"
++        append link-flags " -m elf64lppc"
++    }
+     "powerpc*-*" {
+         if { [is_lp64_target] } {
+             set asm-arch powerpc64
+--- /dev/null
++++ b/gdb/testsuite/gdb.asm/powerpc64le.inc
+@@ -0,0 +1,47 @@
++	comment "subroutine prologue"
++	.macro gdbasm_enter
++	stdu 1, -32(1)
++	mflr 0
++	std 0, 48(1)
++	.endm
++
++	comment "subroutine epilogue"
++	.macro gdbasm_leave
++	ld 0, 48(1)
++	mtlr 0
++	ld 1, 0(1)
++	blr
++	.endm
++
++	.macro gdbasm_call subr
++	bl \subr
++	nop
++	.endm
++
++	.macro gdbasm_several_nops
++	nop
++	nop
++	nop
++	nop
++	.endm
++
++	comment "exit (0)"
++	.macro gdbasm_exit0
++	comment "sys_exit"
++	li	0, 1
++	sc
++	.endm
++
++	comment "crt0 startup"
++	.macro gdbasm_startup
++	.abiversion 2
++	.p2align 2
++	.endm
++
++	comment "Declare a data variable"
++	.purgem gdbasm_datavar
++	.macro gdbasm_datavar name value
++	.section	".data"
++\name:
++	.long \value
++	.endm
diff --git a/gdb.spec b/gdb.spec
index 86cfade..fb43891 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -39,7 +39,7 @@ Version: 7.7.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: 10%{?dist}
+Release: 11%{?dist}
 
 License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain and GFDL
 Group: Development/Debuggers
@@ -237,6 +237,20 @@ Patch231: gdb-6.3-bz202689-exec-from-pthread-test.patch
 # Backported fixups post the source tarball.
 #Xdrop: Just backports.
 Patch232: gdb-upstream.patch
+Patch868: gdb-upstream-ppc64le02of15.patch
+Patch869: gdb-upstream-ppc64le03of15.patch
+Patch870: gdb-upstream-ppc64le04of15.patch
+Patch871: gdb-upstream-ppc64le05of15.patch
+Patch872: gdb-upstream-ppc64le06of15.patch
+Patch873: gdb-upstream-ppc64le07of15.patch
+Patch874: gdb-upstream-ppc64le08of15.patch
+Patch875: gdb-upstream-ppc64le09of15.patch
+Patch876: gdb-upstream-ppc64le10of15.patch
+Patch877: gdb-upstream-ppc64le11of15.patch
+Patch878: gdb-upstream-ppc64le12of15.patch
+Patch879: gdb-upstream-ppc64le13of15.patch
+Patch880: gdb-upstream-ppc64le14of15.patch
+Patch881: gdb-upstream-ppc64le15of15.patch
 
 # Testcase for PPC Power6/DFP instructions disassembly (BZ 230000).
 #=fedoratest+ppc
@@ -609,8 +623,11 @@ BuildRequires: gcc gcc-c++ gcc-gfortran gcc-objc
 BuildRequires: gcc-java libgcj%{bits_local} libgcj%{bits_other}
 %endif
 %if 0%{!?rhel:1} || 0%{?rhel} > 6
+# Fedora ppc64le does not yet have gcc-go built.
+%ifnarch ppc64le
 BuildRequires: gcc-go
 %endif
+%endif
 # archer-sergiodj-stap-patch-split
 BuildRequires: systemtap-sdt-devel
 # Copied from prelink-0.4.2-3.fc13.
@@ -621,8 +638,8 @@ BuildRequires: prelink
 %endif
 %endif
 %if 0%{!?rhel:1}
-# Fedora arm does not yet have fpc built.
-%ifnarch %{arm}
+# Fedora arm+ppc64le do not yet have fpc built.
+%ifnarch %{arm} ppc64le
 BuildRequires: fpc
 %endif
 %endif
@@ -639,8 +656,11 @@ BuildRequires: libgcc%{bits_local} libgcc%{bits_other}
 # libstdc++-devel of matching bits is required only for g++ -static.
 BuildRequires: libstdc++%{bits_local} libstdc++%{bits_other}
 %if 0%{!?rhel:1} || 0%{?rhel} > 6
+# Fedora ppc64le does not yet have gcc-go built.
+%ifnarch ppc64le
 BuildRequires: libgo-devel%{bits_local} libgo-devel%{bits_other}
 %endif
+%endif
 %if 0%{!?el5:1}
 BuildRequires: glibc-static%{bits_local}
 %endif
@@ -736,6 +756,20 @@ find -name "*.info*"|xargs rm -f
 
 %patch349 -p1
 %patch232 -p1
+%patch868 -p1
+%patch869 -p1
+%patch870 -p1
+%patch871 -p1
+%patch872 -p1
+%patch873 -p1
+%patch874 -p1
+%patch875 -p1
+%patch876 -p1
+%patch877 -p1
+%patch878 -p1
+%patch879 -p1
+%patch880 -p1
+%patch881 -p1
 %patch1 -p1
 
 %patch105 -p1
@@ -921,7 +955,7 @@ export LDFLAGS="%{?__global_ldflags} %{?_with_asan:-fsanitize=address}"
 	--with-system-gdbinit=%{_sysconfdir}/gdbinit		\
 	--with-gdb-datadir=%{_datadir}/gdb			\
 	--enable-gdb-build-warnings=,-Wno-unused		\
-%ifnarch %{ix86} alpha ppc s390 s390x x86_64 ppc64 sparc sparcv9 sparc64
+%ifnarch %{ix86} alpha ppc s390 s390x x86_64 ppc64 ppc64le sparc sparcv9 sparc64
 	--disable-werror					\
 %else
 	--enable-werror						\
@@ -1370,7 +1404,10 @@ fi
 %endif # 0%{!?el5:1} || "%{_target_cpu}" == "noarch"
 
 %changelog
-* Tue May  6 2014 Sergio Durigan Junior <sergiodj at redhat.com> - 7.7.1-10.fc21
+* Fri May  9 2014 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.7.1-11.fc21
+- [ppc*] Import ppc64le support (BZ 1096303, Ulrich Weigand).
+
+* Tue May  6 2014 Jan Kratochvil <jan.kratochvil at redhat.com> - 7.7.1-10.fc21
 - Rebase to FSF GDB 7.7.1.
 
 * Mon May  5 2014 Sergio Durigan Junior <sergiodj at redhat.com> - 7.7-9.fc21


More information about the scm-commits mailing list