Add a disassembly flag to omit the pc prefix and use it in the "record
[deliverable/binutils-gdb.git] / gdb / ppc-sysv-tdep.c
index 23d7a71021434b26dd5c6bfb33a920d86120ffd4..0ffeab9745c8c53dbbab4ef4fcd89eb15a2e6ea5 100644 (file)
@@ -1,8 +1,7 @@
 /* Target-dependent code for PowerPC systems using the SVR4 ABI
    for GDB, the GNU debugger.
 
-   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 2000-2013 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "target.h"
 #include "objfiles.h"
 #include "infcall.h"
+#include "dwarf2.h"
+
+
+/* Check whether FTPYE is a (pointer to) function type that should use
+   the OpenCL vector ABI.  */
+
+static int
+ppc_sysv_use_opencl_abi (struct type *ftype)
+{
+  ftype = check_typedef (ftype);
+
+  if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+    ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+
+  return (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+         && TYPE_CALLING_CONVENTION (ftype) == DW_CC_GDB_IBM_OpenCL);
+}
 
 /* Pass the arguments in either registers, or in the stack.  Using the
    ppc sysv ABI, the first eight words of the argument list (that might
@@ -50,6 +66,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int opencl_abi = ppc_sysv_use_opencl_abi (value_type (function));
   ULONGEST saved_sp;
   int argspace = 0;            /* 0 is an initial wrong guess.  */
   int write_pass;
@@ -327,6 +344,126 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 Hence we increase freg even when writing to memory.  */
              freg += 2;
            }
+         else if (len < 16
+                  && 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);
+
+             for (i = 0; i < nelt; i++)
+               {
+                 const gdb_byte *elval = val + i * TYPE_LENGTH (eltype);
+
+                 if (TYPE_CODE (eltype) == TYPE_CODE_FLT && !tdep->soft_float)
+                   {
+                     if (freg <= 8)
+                       {
+                         if (write_pass)
+                           {
+                             int regnum = tdep->ppc_fp0_regnum + freg;
+                             gdb_byte regval[MAX_REGISTER_SIZE];
+                             struct type *regtype
+                               = register_type (gdbarch, regnum);
+                             convert_typed_floating (elval, eltype,
+                                                     regval, regtype);
+                             regcache_cooked_write (regcache, regnum, regval);
+                           }
+                         freg++;
+                       }
+                     else
+                       {
+                         argoffset = align_up (argoffset, len);
+                         if (write_pass)
+                           write_memory (sp + argoffset, val, len);
+                         argoffset += len;
+                       }
+                   }
+                 else if (TYPE_LENGTH (eltype) == 8)
+                   {
+                     if (greg > 9)
+                       {
+                         /* Just in case GREG was 10.  */
+                         greg = 11;
+                         argoffset = align_up (argoffset, 8);
+                         if (write_pass)
+                           write_memory (sp + argoffset, elval,
+                                         TYPE_LENGTH (eltype));
+                         argoffset += 8;
+                       }
+                     else
+                       {
+                         /* Must start on an odd register - r3/r4 etc.  */
+                         if ((greg & 1) == 0)
+                           greg++;
+                         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);
+                           }
+                         greg += 2;
+                       }
+                   }
+                 else
+                   {
+                     gdb_byte word[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);
+                         greg++;
+                       }
+                     else
+                       {
+                         argoffset = align_up (argoffset, tdep->wordsize);
+                         if (write_pass)
+                           write_memory (sp + argoffset, word, tdep->wordsize);
+                         argoffset += tdep->wordsize;
+                       }
+                   }
+               }
+           }
+         else if (len >= 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 < len / 16; i++)
+               {
+                 const gdb_byte *elval = val + i * 16;
+
+                 if (vreg <= 13)
+                   {
+                     if (write_pass)
+                       regcache_cooked_write (regcache,
+                                              tdep->ppc_vr0_regnum + vreg,
+                                              elval);
+                     vreg++;
+                   }
+                 else
+                   {
+                     argoffset = align_up (argoffset, 16);
+                     if (write_pass)
+                       write_memory (sp + argoffset, elval, 16);
+                     argoffset += 16;
+                   }
+               }
+           }
          else if (len == 16
                   && TYPE_CODE (type) == TYPE_CODE_ARRAY
                   && TYPE_VECTOR (type)
@@ -531,7 +668,7 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
     }
   else
     /* Can't happen.  */
-    internal_error (__FILE__, __LINE__, "Unknown decimal float size.");
+    internal_error (__FILE__, __LINE__, _("Unknown decimal float size."));
 
   return RETURN_VALUE_REGISTER_CONVENTION;
 }
@@ -552,13 +689,17 @@ get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
    when returned in general-purpose registers.  */
 
 static enum return_value_convention
-do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
-                         struct regcache *regcache, gdb_byte *readbuf,
-                         const gdb_byte *writebuf, int broken_gcc)
+do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type,
+                         struct type *type, struct regcache *regcache,
+                         gdb_byte *readbuf, const gdb_byte *writebuf,
+                         int broken_gcc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int opencl_abi = func_type? ppc_sysv_use_opencl_abi (func_type) : 0;
+
   gdb_assert (tdep->wordsize == 4);
+
   if (TYPE_CODE (type) == TYPE_CODE_FLT
       && TYPE_LENGTH (type) <= 8
       && !tdep->soft_float)
@@ -691,6 +832,83 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
+  /* OpenCL vectors < 16 bytes are returned as distinct
+     scalars in f1..f2 or r3..r10.  */
+  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (type)
+      && TYPE_LENGTH (type) < 16
+      && opencl_abi)
+    {
+      struct type *eltype = check_typedef (TYPE_TARGET_TYPE (type));
+      int i, nelt = TYPE_LENGTH (type) / TYPE_LENGTH (eltype);
+
+      for (i = 0; i < nelt; i++)
+       {
+         int offset = i * TYPE_LENGTH (eltype);
+
+         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)
+               {
+                 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;
+
+             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);
+               }
+           }
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  /* OpenCL vectors >= 16 bytes are returned in v2..v9.  */
+  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+      && TYPE_VECTOR (type)
+      && TYPE_LENGTH (type) >= 16
+      && opencl_abi)
+    {
+      int n_regs = TYPE_LENGTH (type) / 16;
+      int i;
+
+      for (i = 0; i < n_regs; i++)
+       {
+         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);
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
   if (TYPE_LENGTH (type) == 16
       && TYPE_CODE (type) == TYPE_CODE_ARRAY
       && TYPE_VECTOR (type)
@@ -822,23 +1040,25 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
 }
 
 enum return_value_convention
-ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
+ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
                           struct type *valtype, struct regcache *regcache,
                           gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf,
-                                  writebuf, 0);
+  return do_ppc_sysv_return_value (gdbarch,
+                                  function ? value_type (function) : NULL,
+                                  valtype, regcache, readbuf, writebuf, 0);
 }
 
 enum return_value_convention
 ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
-                                 struct type *func_type,
+                                 struct value *function,
                                  struct type *valtype,
                                  struct regcache *regcache,
                                  gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf,
-                                  writebuf, 1);
+  return do_ppc_sysv_return_value (gdbarch,
+                                  function ? value_type (function) : NULL,
+                                  valtype, regcache, readbuf, writebuf, 1);
 }
 
 /* The helper function for 64-bit SYSV push_dummy_call.  Converts the
@@ -858,7 +1078,6 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
   struct obj_section *dot_fn_section;
   struct minimal_symbol *dot_fn;
   struct minimal_symbol *fn;
-  CORE_ADDR toc;
   /* 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);
@@ -899,12 +1118,13 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
   CORE_ADDR func_addr = find_function_addr (function, NULL);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  int opencl_abi = ppc_sysv_use_opencl_abi (value_type (function));
   ULONGEST back_chain;
   /* See for-loop comment below.  */
   int write_pass;
-  /* Size of the Altivec's vector parameter region, the final value is
+  /* Size of the by-reference parameter copy region, the final value is
      computed in the for-loop below.  */
-  LONGEST vparam_size = 0;
+  LONGEST refparam_size = 0;
   /* Size of the general parameter region, the final value is computed
      in the for-loop below.  */
   LONGEST gparam_size = 0;
@@ -948,28 +1168,28 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
       /* Next available vector register for vector arguments.  */
       int vreg = 2;
       /* The address, at which the next general purpose parameter
-         (integer, struct, float, ...) should be saved.  */
+         (integer, struct, float, vector, ...) should be saved.  */
       CORE_ADDR gparam;
-      /* Address, at which the next Altivec vector parameter should be
-         saved.  */
-      CORE_ADDR vparam;
+      /* The address, at which the next by-reference parameter
+        (non-Altivec vector, variably-sized type) should be saved.  */
+      CORE_ADDR refparam;
 
       if (!write_pass)
        {
-         /* During the first pass, GPARAM and VPARAM are more like
+         /* During the first pass, GPARAM and REFPARAM are more like
             offsets (start address zero) than addresses.  That way
             they accumulate the total stack space each region
             requires.  */
          gparam = 0;
-         vparam = 0;
+         refparam = 0;
        }
       else
        {
          /* Decrement the stack pointer making space for the Altivec
-            and general on-stack parameters.  Set vparam and gparam
+            and general on-stack parameters.  Set refparam and gparam
             to their corresponding regions.  */
-         vparam = align_down (sp - vparam_size, 16);
-         gparam = align_down (vparam - gparam_size, 16);
+         refparam = align_down (sp - refparam_size, 16);
+         gparam = align_down (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);
@@ -1143,28 +1363,156 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
              greg += 2;
              gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
            }
-         else if (TYPE_LENGTH (type) == 16 && TYPE_VECTOR (type)
+         else if (TYPE_LENGTH (type) < 16
                   && TYPE_CODE (type) == TYPE_CODE_ARRAY
-                  && tdep->ppc_vr0_regnum >= 0)
+                  && TYPE_VECTOR (type)
+                  && opencl_abi)
            {
-             /* In the Altivec ABI, vectors go in the vector
-                registers v2 .. v13, or when that runs out, a vector
-                annex which goes above all the normal parameters.
-                NOTE: cagney/2003-09-21: This is a guess based on the
-                PowerOpen Altivec ABI.  */
-             if (vreg <= 13)
+             /* 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);
+
+             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);
-                 vreg++;
+
+                 write_memory (gparam, val, TYPE_LENGTH (type));
                }
-             else
+
+             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 (write_pass)
-                   write_memory (vparam, val, TYPE_LENGTH (type));
-                 vparam = align_up (vparam + TYPE_LENGTH (type), 16);
+                 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
@@ -1308,7 +1656,7 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
       if (!write_pass)
        {
          /* Save the true region sizes ready for the second pass.  */
-         vparam_size = vparam;
+         refparam_size = refparam;
          /* Make certain that the general parameter save area is at
             least the minimum 8 registers (or doublewords) in size.  */
          if (greg < 8)
@@ -1362,12 +1710,14 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch,
    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 type *func_type,
+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);
   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
@@ -1430,6 +1780,83 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
        regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf);
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
+  /* 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);
+
+         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)
+               {
+                 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;
+
+             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);
+               }
+           }
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  /* 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)
+    {
+      int n_regs = TYPE_LENGTH (valtype) / 16;
+      int i;
+
+      for (i = 0; i < n_regs; i++)
+       {
+         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);
+       }
+
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
   /* Array type has more than one use.  */
   if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
     {
@@ -1450,7 +1877,8 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
        }
       /* A VMX vector is returned in v2.  */
       if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
-        && TYPE_VECTOR (valtype) && tdep->ppc_vr0_regnum >= 0)
+         && TYPE_VECTOR (valtype)
+         && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
         {
           if (readbuf)
             regcache_cooked_read (regcache, tdep->ppc_vr0_regnum + 2, readbuf);
@@ -1492,11 +1920,13 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
              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 (valtype) / 2),
-                                         valtype, regval, regtype);
+                                         i * TYPE_LENGTH (target_type), 
+                                         target_type, regval, regtype);
                  regcache_cooked_write (regcache,
                                          tdep->ppc_fp0_regnum + 1 + i,
                                         regval);
@@ -1508,8 +1938,8 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type,
                                         regval);
                  convert_typed_floating (regval, regtype,
                                          (bfd_byte *) readbuf +
-                                         i * (TYPE_LENGTH (valtype) / 2),
-                                         valtype);
+                                         i * TYPE_LENGTH (target_type),
+                                         target_type);
                }
            }
        }
This page took 0.033263 seconds and 4 git commands to generate.