Fix indentation (and clang warning) in c-lang.c
[deliverable/binutils-gdb.git] / gdb / ppc-sysv-tdep.c
index 77a71bc987a09afa50362a4e276e273d402b381e..fb8c9e2fe01f52379587ae567f7d0ac060046f8d 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for PowerPC systems using the SVR4 ABI
    for GDB, the GNU debugger.
 
-   Copyright (C) 2000-2014 Free Software Foundation, Inc.
+   Copyright (C) 2000-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "inferior.h"
 #include "regcache.h"
 #include "value.h"
-#include <string.h>
-#include "gdb_assert.h"
 #include "ppc-tdep.h"
 #include "target.h"
 #include "objfiles.h"
 #include "infcall.h"
 #include "dwarf2.h"
+#include "target-float.h"
+#include <algorithm>
 
 
 /* Check whether FTPYE is a (pointer to) function type that should use
@@ -55,14 +55,15 @@ ppc_sysv_use_opencl_abi (struct type *ftype)
    are passed in user stack.
 
    If the function is returning a structure, then the return address is passed
-   in r3, then the first 7 words of the parametes can be passed in registers,
+   in r3, then the first 7 words of the parameters can be passed in registers,
    starting from r4.  */
 
 CORE_ADDR
 ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                              struct regcache *regcache, CORE_ADDR bp_addr,
                              int nargs, struct value **args, CORE_ADDR sp,
-                             int struct_return, CORE_ADDR struct_addr)
+                             function_call_return_method return_method,
+                             CORE_ADDR struct_addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -107,7 +108,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          (which will be passed in r3) is used for struct return
          address.  In that case we should advance one word and start
          from r4 register to copy parameters.  */
-      if (struct_return)
+      if (return_method == return_method_struct)
        {
          if (write_pass)
            regcache_cooked_write_signed (regcache,
@@ -135,13 +136,12 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                    {
                      /* Always store the floating point value using
                         the register's floating-point format.  */
-                     gdb_byte regval[MAX_REGISTER_SIZE];
+                     gdb_byte regval[PPC_MAX_REGISTER_SIZE];
                      struct type *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);
+                     target_float_convert (val, type, regval, regtype);
+                     regcache->cooked_write (tdep->ppc_fp0_regnum + freg,
+                                             regval);
                    }
                  freg++;
                }
@@ -176,12 +176,9 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                {
                  if (write_pass)
                    {
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_fp0_regnum + freg,
-                                            val);
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_fp0_regnum + freg + 1,
-                                            val + 8);
+                     regcache->cooked_write (tdep->ppc_fp0_regnum + freg, val);
+                     regcache->cooked_write (tdep->ppc_fp0_regnum + freg + 1,
+                                             val + 8);
                    }
                  freg += 2;
                }
@@ -221,12 +218,10 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                    greg++;
                  if (write_pass)
                    {
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_gp0_regnum + greg + 0,
-                                            val + 0);
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_gp0_regnum + greg + 1,
-                                            val + 4);
+                     regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 0,
+                                             val + 0);
+                     regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 1,
+                                             val + 4);
                    }
                  greg += 2;
                }
@@ -253,18 +248,14 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                {
                  if (write_pass)
                    {
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_gp0_regnum + greg + 0,
-                                            val + 0);
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_gp0_regnum + greg + 1,
-                                            val + 4);
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_gp0_regnum + greg + 2,
-                                            val + 8);
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_gp0_regnum + greg + 3,
-                                            val + 12);
+                     regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 0,
+                                             val + 0);
+                     regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 1,
+                                             val + 4);
+                     regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 2,
+                                             val + 8);
+                     regcache->cooked_write (tdep->ppc_gp0_regnum + greg + 3,
+                                             val + 12);
                    }
                  greg += 4;
                }
@@ -279,7 +270,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                {
                  if (write_pass)
                    {
-                     gdb_byte regval[MAX_REGISTER_SIZE];
+                     gdb_byte regval[PPC_MAX_REGISTER_SIZE];
                      const gdb_byte *p;
 
                      /* 32-bit decimal floats are right aligned in the
@@ -292,8 +283,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                      else
                        p = val;
 
-                     regcache_cooked_write (regcache,
-                         tdep->ppc_fp0_regnum + freg, p);
+                     regcache->cooked_write (tdep->ppc_fp0_regnum + freg, p);
                    }
 
                  freg++;
@@ -322,10 +312,9 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
                  if (write_pass)
                    {
-                     regcache_cooked_write (regcache,
-                                            tdep->ppc_fp0_regnum + freg, val);
-                     regcache_cooked_write (regcache,
-                         tdep->ppc_fp0_regnum + freg + 1, val + 8);
+                     regcache->cooked_write (tdep->ppc_fp0_regnum + freg, val);
+                     regcache->cooked_write (tdep->ppc_fp0_regnum + freg + 1,
+                                             val + 8);
                    }
                }
              else
@@ -365,12 +354,12 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                          if (write_pass)
                            {
                              int regnum = tdep->ppc_fp0_regnum + freg;
-                             gdb_byte regval[MAX_REGISTER_SIZE];
+                             gdb_byte regval[PPC_MAX_REGISTER_SIZE];
                              struct type *regtype
                                = register_type (gdbarch, regnum);
-                             convert_typed_floating (elval, eltype,
-                                                     regval, regtype);
-                             regcache_cooked_write (regcache, regnum, regval);
+                             target_float_convert (elval, eltype,
+                                                   regval, regtype);
+                             regcache->cooked_write (regnum, regval);
                            }
                          freg++;
                        }
@@ -402,26 +391,23 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                          if (write_pass)
                            {
                              int regnum = tdep->ppc_gp0_regnum + greg;
-                             regcache_cooked_write (regcache,
-                                                    regnum + 0, elval + 0);
-                             regcache_cooked_write (regcache,
-                                                    regnum + 1, elval + 4);
+                             regcache->cooked_write (regnum + 0, elval + 0);
+                             regcache->cooked_write (regnum + 1, elval + 4);
                            }
                          greg += 2;
                        }
                    }
                  else
                    {
-                     gdb_byte word[MAX_REGISTER_SIZE];
+                     gdb_byte word[PPC_MAX_REGISTER_SIZE];
                      store_unsigned_integer (word, tdep->wordsize, byte_order,
                                              unpack_long (eltype, elval));
 
                      if (greg <= 10)
                        {
                          if (write_pass)
-                           regcache_cooked_write (regcache,
-                                                  tdep->ppc_gp0_regnum + greg,
-                                                  word);
+                           regcache->cooked_write (tdep->ppc_gp0_regnum + greg,
+                                                   word);
                          greg++;
                        }
                      else
@@ -450,9 +436,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  if (vreg <= 13)
                    {
                      if (write_pass)
-                       regcache_cooked_write (regcache,
-                                              tdep->ppc_vr0_regnum + vreg,
-                                              elval);
+                       regcache->cooked_write (tdep->ppc_vr0_regnum + vreg,
+                                               elval);
                      vreg++;
                    }
                  else
@@ -474,8 +459,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              if (vreg <= 13)
                {
                  if (write_pass)
-                   regcache_cooked_write (regcache,
-                                          tdep->ppc_vr0_regnum + vreg, val);
+                   regcache->cooked_write (tdep->ppc_vr0_regnum + vreg, val);
                  vreg++;
                }
              else
@@ -501,8 +485,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              if (greg <= 10)
                {
                  if (write_pass)
-                   regcache_cooked_write (regcache,
-                                          tdep->ppc_ev0_regnum + greg, val);
+                   regcache->cooked_write (tdep->ppc_ev0_regnum + greg, val);
                  greg++;
                }
              else
@@ -517,8 +500,8 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            {
              /* Reduce the parameter down to something that fits in a
                 "word".  */
-             gdb_byte word[MAX_REGISTER_SIZE];
-             memset (word, 0, MAX_REGISTER_SIZE);
+             gdb_byte word[PPC_MAX_REGISTER_SIZE];
+             memset (word, 0, PPC_MAX_REGISTER_SIZE);
              if (len > tdep->wordsize
                  || TYPE_CODE (type) == TYPE_CODE_STRUCT
                  || TYPE_CODE (type) == TYPE_CODE_UNION)
@@ -552,8 +535,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              if (greg <= 10)
                {
                  if (write_pass)
-                   regcache_cooked_write (regcache,
-                                          tdep->ppc_gp0_regnum + greg, word);
+                   regcache->cooked_write (tdep->ppc_gp0_regnum + greg, word);
                  greg++;
                }
              else
@@ -610,7 +592,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 }
 
 /* Handle the return-value conventions for Decimal Floating Point values.  */
-static int
+static enum return_value_convention
 get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
                                struct regcache *regcache, gdb_byte *readbuf,
                                const gdb_byte *writebuf)
@@ -624,7 +606,7 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
     {
       if (writebuf != NULL)
        {
-         gdb_byte regval[MAX_REGISTER_SIZE];
+         gdb_byte regval[PPC_MAX_REGISTER_SIZE];
          const gdb_byte *p;
 
          /* 32-bit decimal float is right aligned in the doubleword.  */
@@ -636,11 +618,11 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
          else
            p = writebuf;
 
-         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, p);
+         regcache->cooked_write (tdep->ppc_fp0_regnum + 1, p);
        }
       if (readbuf != NULL)
        {
-         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf);
+         regcache->cooked_read (tdep->ppc_fp0_regnum + 1, readbuf);
 
          /* Left align 32-bit decimal float.  */
          if (TYPE_LENGTH (valtype) == 4)
@@ -657,11 +639,11 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
          for (i = 0; i < 2; i++)
            {
              if (writebuf != NULL)
-               regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2 + i,
-                                      writebuf + i * 8);
+               regcache->cooked_write (tdep->ppc_fp0_regnum + 2 + i,
+                                       writebuf + i * 8);
              if (readbuf != NULL)
-               regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 2 + i,
-                                     readbuf + i * 8);
+               regcache->cooked_read (tdep->ppc_fp0_regnum + 2 + i,
+                                      readbuf + i * 8);
            }
        }
     }
@@ -707,20 +689,20 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
        {
          /* Floats and doubles stored in "f1".  Convert the value to
             the required type.  */
-         gdb_byte regval[MAX_REGISTER_SIZE];
+         gdb_byte regval[PPC_MAX_REGISTER_SIZE];
          struct type *regtype = register_type (gdbarch,
                                                 tdep->ppc_fp0_regnum + 1);
-         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, regval);
-         convert_typed_floating (regval, regtype, readbuf, type);
+         regcache->cooked_read (tdep->ppc_fp0_regnum + 1, regval);
+         target_float_convert (regval, regtype, readbuf, type);
        }
       if (writebuf)
        {
          /* Floats and doubles stored in "f1".  Convert the value to
             the register's "double" type.  */
-         gdb_byte regval[MAX_REGISTER_SIZE];
+         gdb_byte regval[PPC_MAX_REGISTER_SIZE];
          struct type *regtype = register_type (gdbarch, tdep->ppc_fp0_regnum);
-         convert_typed_floating (writebuf, type, regval, regtype);
-         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, regval);
+         target_float_convert (writebuf, type, regval, regtype);
+         regcache->cooked_write (tdep->ppc_fp0_regnum + 1, regval);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -733,15 +715,13 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
       /* IBM long double stored in f1 and f2.  */
       if (readbuf)
        {
-         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf);
-         regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 2,
-                               readbuf + 8);
+         regcache->cooked_read (tdep->ppc_fp0_regnum + 1, readbuf);
+         regcache->cooked_read (tdep->ppc_fp0_regnum + 2, readbuf + 8);
        }
       if (writebuf)
        {
-         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, writebuf);
-         regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2,
-                                writebuf + 8);
+         regcache->cooked_write (tdep->ppc_fp0_regnum + 1, writebuf);
+         regcache->cooked_write (tdep->ppc_fp0_regnum + 2, writebuf + 8);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -755,23 +735,17 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
         r5, r6.  */
       if (readbuf)
        {
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
-                               readbuf + 4);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5,
-                               readbuf + 8);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6,
-                               readbuf + 12);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 3, readbuf);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 4, readbuf + 4);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 5, readbuf + 8);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 6, readbuf + 12);
        }
       if (writebuf)
        {
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
-                                writebuf + 4);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5,
-                                writebuf + 8);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6,
-                                writebuf + 12);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 3, writebuf);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 4, writebuf + 4);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 5, writebuf + 8);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 6, writebuf + 12);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -784,19 +758,15 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
        {
          /* A long long, double or _Decimal64 stored in the 32 bit
             r3/r4.  */
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
-                               readbuf + 0);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
-                               readbuf + 4);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 3, readbuf + 0);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 4, readbuf + 4);
        }
       if (writebuf)
        {
          /* A long long, double or _Decimal64 stored in the 32 bit
             r3/r4.  */
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
-                                writebuf + 0);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
-                                writebuf + 4);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 3, writebuf + 0);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 4, writebuf + 4);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -807,7 +777,7 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
            || TYPE_CODE (type) == TYPE_CODE_CHAR
            || TYPE_CODE (type) == TYPE_CODE_BOOL
            || TYPE_CODE (type) == TYPE_CODE_PTR
-           || TYPE_CODE (type) == TYPE_CODE_REF
+           || TYPE_IS_REFERENCE (type)
            || TYPE_CODE (type) == TYPE_CODE_ENUM)
           && TYPE_LENGTH (type) <= tdep->wordsize)
     {
@@ -848,20 +818,20 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
          if (TYPE_CODE (eltype) == TYPE_CODE_FLT)
            {
              int regnum = tdep->ppc_fp0_regnum + 1 + i;
-             gdb_byte regval[MAX_REGISTER_SIZE];
+             gdb_byte regval[PPC_MAX_REGISTER_SIZE];
              struct type *regtype = register_type (gdbarch, regnum);
 
              if (writebuf != NULL)
                {
-                 convert_typed_floating (writebuf + offset, eltype,
-                                         regval, regtype);
-                 regcache_cooked_write (regcache, regnum, regval);
+                 target_float_convert (writebuf + offset, eltype,
+                                       regval, regtype);
+                 regcache->cooked_write (regnum, regval);
                }
              if (readbuf != NULL)
                {
-                 regcache_cooked_read (regcache, regnum, regval);
-                 convert_typed_floating (regval, regtype,
-                                         readbuf + offset, eltype);
+                 regcache->cooked_read (regnum, regval);
+                 target_float_convert (regval, regtype,
+                                       readbuf + offset, eltype);
                }
            }
          else
@@ -901,9 +871,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
          int regnum = tdep->ppc_vr0_regnum + 2 + i;
 
          if (writebuf != NULL)
-           regcache_cooked_write (regcache, regnum, writebuf + offset);
+           regcache->cooked_write (regnum, writebuf + offset);
          if (readbuf != NULL)
-           regcache_cooked_read (regcache, regnum, readbuf + offset);
+           regcache->cooked_read (regnum, readbuf + offset);
        }
 
       return RETURN_VALUE_REGISTER_CONVENTION;
@@ -916,12 +886,12 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
       if (readbuf)
        {
          /* Altivec places the return value in "v2".  */
-         regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
+         regcache->cooked_read (tdep->ppc_vr0_regnum + 2, readbuf);
        }
       if (writebuf)
        {
          /* Altivec places the return value in "v2".  */
-         regcache_cooked_write (regcache, tdep->ppc_vr0_regnum + 2, writebuf);
+         regcache->cooked_write (tdep->ppc_vr0_regnum + 2, writebuf);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -935,25 +905,17 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
         ABI risks in that case; we don't try to support it.  */
       if (readbuf)
        {
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
-                               readbuf + 0);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
-                               readbuf + 4);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5,
-                               readbuf + 8);
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6,
-                               readbuf + 12);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 3, readbuf + 0);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 4, readbuf + 4);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 5, readbuf + 8);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 6, readbuf + 12);
        }
       if (writebuf)
        {
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
-                                writebuf + 0);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
-                                writebuf + 4);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5,
-                                writebuf + 8);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6,
-                                writebuf + 12);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 3, writebuf + 0);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 4, writebuf + 4);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 5, writebuf + 8);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 6, writebuf + 12);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -968,9 +930,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
         only corresponds to the least significant 32-bits.  So place
         the 64-bit DSP type's value in ev3.  */
       if (readbuf)
-       regcache_cooked_read (regcache, tdep->ppc_ev0_regnum + 3, readbuf);
+       regcache->cooked_read (tdep->ppc_ev0_regnum + 3, readbuf);
       if (writebuf)
-       regcache_cooked_write (regcache, tdep->ppc_ev0_regnum + 3, writebuf);
+       regcache->cooked_write (tdep->ppc_ev0_regnum + 3, writebuf);
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
   if (broken_gcc && TYPE_LENGTH (type) <= 8)
@@ -978,28 +940,28 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
       /* GCC screwed up for structures or unions whose size is less
         than or equal to 8 bytes..  Instead of left-aligning, it
         right-aligns the data into the buffer formed by r3, r4.  */
-      gdb_byte regvals[MAX_REGISTER_SIZE * 2];
+      gdb_byte regvals[PPC_MAX_REGISTER_SIZE * 2];
       int len = TYPE_LENGTH (type);
       int offset = (2 * tdep->wordsize - len) % tdep->wordsize;
 
       if (readbuf)
        {
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
-                               regvals + 0 * tdep->wordsize);
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 3,
+                                regvals + 0 * tdep->wordsize);
          if (len > tdep->wordsize)
-           regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
-                                 regvals + 1 * tdep->wordsize);
+           regcache->cooked_read (tdep->ppc_gp0_regnum + 4,
+                                  regvals + 1 * tdep->wordsize);
          memcpy (readbuf, regvals + offset, len);
        }
       if (writebuf)
        {
          memset (regvals, 0, sizeof regvals);
          memcpy (regvals + offset, writebuf, len);
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
-                                regvals + 0 * tdep->wordsize);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 3,
+                                 regvals + 0 * tdep->wordsize);
          if (len > tdep->wordsize)
-           regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
-                                  regvals + 1 * tdep->wordsize);
+           regcache->cooked_write (tdep->ppc_gp0_regnum + 4,
+                                   regvals + 1 * tdep->wordsize);
        }
 
       return RETURN_VALUE_REGISTER_CONVENTION;
@@ -1011,12 +973,12 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
          /* This matches SVr4 PPC, it does not match GCC.  */
          /* The value is right-padded to 8 bytes and then loaded, as
             two "words", into r3/r4.  */
-         gdb_byte regvals[MAX_REGISTER_SIZE * 2];
-         regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
-                               regvals + 0 * tdep->wordsize);
+         gdb_byte regvals[PPC_MAX_REGISTER_SIZE * 2];
+         regcache->cooked_read (tdep->ppc_gp0_regnum + 3,
+                                regvals + 0 * tdep->wordsize);
          if (TYPE_LENGTH (type) > tdep->wordsize)
-           regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
-                                 regvals + 1 * tdep->wordsize);
+           regcache->cooked_read (tdep->ppc_gp0_regnum + 4,
+                                  regvals + 1 * tdep->wordsize);
          memcpy (readbuf, regvals, TYPE_LENGTH (type));
        }
       if (writebuf)
@@ -1024,14 +986,14 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
          /* This matches SVr4 PPC, it does not match GCC.  */
          /* The value is padded out to 8 bytes and then loaded, as
             two "words" into r3/r4.  */
-         gdb_byte regvals[MAX_REGISTER_SIZE * 2];
+         gdb_byte regvals[PPC_MAX_REGISTER_SIZE * 2];
          memset (regvals, 0, sizeof regvals);
          memcpy (regvals, writebuf, TYPE_LENGTH (type));
-         regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
-                                regvals + 0 * tdep->wordsize);
+         regcache->cooked_write (tdep->ppc_gp0_regnum + 3,
+                                 regvals + 0 * tdep->wordsize);
          if (TYPE_LENGTH (type) > tdep->wordsize)
-           regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
-                                  regvals + 1 * tdep->wordsize);
+           regcache->cooked_write (tdep->ppc_gp0_regnum + 4,
+                                   regvals + 1 * tdep->wordsize);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -1076,12 +1038,12 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
 {
   struct obj_section *dot_fn_section;
   struct bound_minimal_symbol dot_fn;
-  struct minimal_symbol *fn;
+  struct bound_minimal_symbol fn;
 
   /* Find the minimal symbol that corresponds to CODE_ADDR (should
      have a name of the form ".FN").  */
   dot_fn = lookup_minimal_symbol_by_pc (code_addr);
-  if (dot_fn.minsym == NULL || SYMBOL_LINKAGE_NAME (dot_fn.minsym)[0] != '.')
+  if (dot_fn.minsym == NULL || dot_fn.minsym->linkage_name ()[0] != '.')
     return 0;
   /* Get the section that contains CODE_ADDR.  Need this for the
      "objfile" that it contains.  */
@@ -1092,15 +1054,169 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
      address.  Only look for the minimal symbol in ".FN"'s object file
      - avoids problems when two object files (i.e., shared libraries)
      contain a minimal symbol with the same name.  */
-  fn = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn.minsym) + 1, NULL,
+  fn = lookup_minimal_symbol (dot_fn.minsym->linkage_name () + 1, NULL,
                              dot_fn_section->objfile);
-  if (fn == NULL)
+  if (fn.minsym == NULL)
     return 0;
   /* Found a descriptor.  */
-  (*desc_addr) = SYMBOL_VALUE_ADDRESS (fn);
+  (*desc_addr) = BMSYMBOL_VALUE_ADDRESS (fn);
   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 = std::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
   {
@@ -1150,7 +1266,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)
@@ -1160,8 +1277,8 @@ ppc64_sysv_abi_push_val (struct gdbarch *gdbarch,
   while (len >= tdep->wordsize)
     {
       if (argpos->regcache && argpos->greg <= 10)
-       regcache_cooked_write (argpos->regcache,
-                              tdep->ppc_gp0_regnum + argpos->greg, val);
+       argpos->regcache->cooked_write (tdep->ppc_gp0_regnum + argpos->greg,
+                                       val);
       argpos->greg++;
       len -= tdep->wordsize;
       val += tdep->wordsize;
@@ -1170,9 +1287,8 @@ ppc64_sysv_abi_push_val (struct gdbarch *gdbarch,
   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->regcache->cooked_write_part
+         (tdep->ppc_gp0_regnum + argpos->greg, offset, len, val);
       argpos->greg++;
     }
 }
@@ -1186,7 +1302,7 @@ ppc64_sysv_abi_push_integer (struct gdbarch *gdbarch, ULONGEST val,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  gdb_byte buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[PPC_MAX_REGISTER_SIZE];
 
   if (argpos->regcache)
     store_unsigned_integer (buf, tdep->wordsize, byte_order, val);
@@ -1215,10 +1331,10 @@ ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch,
        {
          int regnum = tdep->ppc_fp0_regnum + argpos->freg;
          struct type *regtype = register_type (gdbarch, regnum);
-         gdb_byte regval[MAX_REGISTER_SIZE];
+         gdb_byte regval[PPC_MAX_REGISTER_SIZE];
 
-         convert_typed_floating (val, type, regval, regtype);
-         regcache_cooked_write (argpos->regcache, regnum, regval);
+         target_float_convert (val, type, regval, regtype);
+         argpos->regcache->cooked_write (regnum, regval);
        }
 
       argpos->freg++;
@@ -1231,10 +1347,13 @@ 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);
+         argpos->regcache->cooked_write_part (regnum, offset,
+                                              TYPE_LENGTH (type), val);
        }
 
       argpos->freg++;
@@ -1249,9 +1368,9 @@ ppc64_sysv_abi_push_freg (struct gdbarch *gdbarch,
        {
          int regnum = tdep->ppc_fp0_regnum + argpos->freg;
 
-         regcache_cooked_write (argpos->regcache, regnum, val);
+         argpos->regcache->cooked_write (regnum, val);
          if (argpos->freg <= 12)
-           regcache_cooked_write (argpos->regcache, regnum + 1, val + 8);
+           argpos->regcache->cooked_write (regnum + 1, val + 8);
        }
 
       argpos->freg += 2;
@@ -1266,9 +1385,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);
+         argpos->regcache->cooked_write (regnum, val + hipart);
+         argpos->regcache->cooked_write (regnum + 1, val + lopart);
        }
 
       argpos->freg += 2;
@@ -1285,8 +1406,7 @@ ppc64_sysv_abi_push_vreg (struct gdbarch *gdbarch, const bfd_byte *val,
   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->regcache->cooked_write (tdep->ppc_vr0_regnum + argpos->vreg, val);
 
   argpos->vreg++;
 }
@@ -1335,7 +1455,7 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
            || 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_IS_REFERENCE (type))
           && TYPE_LENGTH (type) <= tdep->wordsize)
     {
       ULONGEST word = 0;
@@ -1346,8 +1466,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));
@@ -1382,6 +1503,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);
+             }
+       }
     }
 }
 
@@ -1397,7 +1541,8 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
                                struct value *function,
                                struct regcache *regcache, CORE_ADDR bp_addr,
                                int nargs, struct value **args, CORE_ADDR sp,
-                               int struct_return, CORE_ADDR struct_addr)
+                               function_call_return_method return_method,
+                               CORE_ADDR struct_addr)
 {
   CORE_ADDR func_addr = find_function_addr (function, NULL);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
@@ -1467,9 +1612,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
@@ -1477,7 +1626,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
          containing the address of that struct..  In that case we
          should advance one word and start from r4 register to copy
          parameters.  This also consumes one on-stack parameter slot.  */
-      if (struct_return)
+      if (return_method == return_method_struct)
        ppc64_sysv_abi_push_integer (gdbarch, struct_addr, &argpos);
 
       for (argno = 0; argno < nargs; argno++)
@@ -1547,24 +1696,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;
 }
@@ -1619,17 +1776,17 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype,
     {
       int regnum = tdep->ppc_fp0_regnum + 1 + index;
       struct type *regtype = register_type (gdbarch, regnum);
-      gdb_byte regval[MAX_REGISTER_SIZE];
+      gdb_byte regval[PPC_MAX_REGISTER_SIZE];
 
       if (writebuf != NULL)
        {
-         convert_typed_floating (writebuf, valtype, regval, regtype);
-         regcache_cooked_write (regcache, regnum, regval);
+         target_float_convert (writebuf, valtype, regval, regtype);
+         regcache->cooked_write (regnum, regval);
        }
       if (readbuf != NULL)
        {
-         regcache_cooked_read (regcache, regnum, regval);
-         convert_typed_floating (regval, regtype, readbuf, valtype);
+         regcache->cooked_read (regnum, regval);
+         target_float_convert (regval, regtype, readbuf, valtype);
        }
       return 1;
     }
@@ -1640,14 +1797,17 @@ 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,
-                                   offset, TYPE_LENGTH (valtype), writebuf);
+       regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype),
+                                    writebuf);
       if (readbuf != NULL)
-       regcache_cooked_read_part (regcache, regnum,
-                                  offset, TYPE_LENGTH (valtype), readbuf);
+       regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype),
+                                   readbuf);
       return 1;
     }
 
@@ -1661,13 +1821,13 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype,
 
       if (writebuf != NULL)
        {
-         regcache_cooked_write (regcache, regnum, writebuf);
-         regcache_cooked_write (regcache, regnum + 1, writebuf + 8);
+         regcache->cooked_write (regnum, writebuf);
+         regcache->cooked_write (regnum + 1, writebuf + 8);
        }
       if (readbuf != NULL)
        {
-         regcache_cooked_read (regcache, regnum, readbuf);
-         regcache_cooked_read (regcache, regnum + 1, readbuf + 8);
+         regcache->cooked_read (regnum, readbuf);
+         regcache->cooked_read (regnum + 1, readbuf + 8);
        }
       return 1;
     }
@@ -1678,30 +1838,52 @@ 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 (regnum, writebuf + hipart);
+         regcache->cooked_write (regnum + 1, writebuf + lopart);
        }
       if (readbuf != NULL)
        {
-         regcache_cooked_read (regcache, regnum, readbuf);
-         regcache_cooked_read (regcache, regnum + 1, readbuf + 8);
+         regcache->cooked_read (regnum, readbuf + hipart);
+         regcache->cooked_read (regnum + 1, readbuf + lopart);
        }
       return 1;
     }
 
   /* AltiVec vectors are returned in VRs starting at v2.  */
-  if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
+  if (TYPE_LENGTH (valtype) == 16
+      && TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)
       && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
     {
       int regnum = tdep->ppc_vr0_regnum + 2 + index;
 
       if (writebuf != NULL)
-       regcache_cooked_write (regcache, regnum, writebuf);
+       regcache->cooked_write (regnum, writebuf);
       if (readbuf != NULL)
-       regcache_cooked_read (regcache, regnum, readbuf);
+       regcache->cooked_read (regnum, readbuf);
+      return 1;
+    }
+
+  /* Short vectors are returned in GPRs starting at r3.  */
+  if (TYPE_LENGTH (valtype) <= 8
+      && TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype))
+    {
+      int regnum = tdep->ppc_gp0_regnum + 3 + index;
+      int offset = 0;
+
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+       offset = 8 - TYPE_LENGTH (valtype);
+
+      if (writebuf != NULL)
+       regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype),
+                                    writebuf);
+      if (readbuf != NULL)
+       regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype),
+                                   readbuf);
       return 1;
     }
 
@@ -1727,7 +1909,7 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
   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;
+  int nelt, ok;
 
   /* This function exists to support a calling convention that
      requires floating-point registers.  It shouldn't be used on
@@ -1739,7 +1921,7 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
     {
       eltype = check_typedef (TYPE_TARGET_TYPE (valtype));
 
-      for (i = 0; i < 2; i++)
+      for (int i = 0; i < 2; i++)
        {
          ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache,
                                                 readbuf, writebuf, i);
@@ -1765,7 +1947,7 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
        eltype = register_type (gdbarch, tdep->ppc_vr0_regnum);
 
       nelt = TYPE_LENGTH (valtype) / TYPE_LENGTH (eltype);
-      for (i = 0; i < nelt; i++)
+      for (int i = 0; i < nelt; i++)
        {
          ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache,
                                                 readbuf, writebuf, i);
@@ -1780,20 +1962,20 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
     }
 
   /* All pointers live in r3.  */
-  if (TYPE_CODE (valtype) == TYPE_CODE_PTR
-      || TYPE_CODE (valtype) == TYPE_CODE_REF)
+  if (TYPE_CODE (valtype) == TYPE_CODE_PTR || TYPE_IS_REFERENCE (valtype))
     {
       int regnum = tdep->ppc_gp0_regnum + 3;
 
       if (writebuf != NULL)
-       regcache_cooked_write (regcache, regnum, writebuf);
+       regcache->cooked_write (regnum, writebuf);
       if (readbuf != NULL)
-       regcache_cooked_read (regcache, regnum, readbuf);
+       regcache->cooked_read (regnum, readbuf);
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
 
   /* Small character arrays are returned, right justified, in r3.  */
   if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
+      && !TYPE_VECTOR (valtype)
       && TYPE_LENGTH (valtype) <= 8
       && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT
       && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1)
@@ -1802,11 +1984,82 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
       int offset = (register_size (gdbarch, regnum) - TYPE_LENGTH (valtype));
 
       if (writebuf != NULL)
-       regcache_cooked_write_part (regcache, regnum,
-                                   offset, TYPE_LENGTH (valtype), writebuf);
+       regcache->cooked_write_part (regnum, offset, TYPE_LENGTH (valtype),
+                                    writebuf);
       if (readbuf != NULL)
-       regcache_cooked_read_part (regcache, regnum,
-                                  offset, TYPE_LENGTH (valtype), readbuf);
+       regcache->cooked_read_part (regnum, offset, TYPE_LENGTH (valtype),
+                                   readbuf);
+      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)
+      && (TYPE_CODE (eltype) == TYPE_CODE_FLT
+         || TYPE_CODE (eltype) == TYPE_CODE_DECFLOAT
+         || (TYPE_CODE (eltype) == TYPE_CODE_ARRAY
+             && TYPE_VECTOR (eltype)
+             && tdep->vector_abi == POWERPC_VEC_ALTIVEC
+             && TYPE_LENGTH (eltype) == 16)))
+    {
+      for (int 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);
+
+      for (int i = 0; i < n_regs; i++)
+       {
+         gdb_byte regval[PPC_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 (regnum, regval);
+           }
+         if (readbuf != NULL)
+           {
+             regcache->cooked_read (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;
     }
 
This page took 0.043122 seconds and 4 git commands to generate.