Jan Kratochvil 6e0665a
commit cc0e89c519912e0e4e75a2fc0d836f715cdc6806
Jan Kratochvil 6e0665a
Author: Ulrich Weigand <ulrich.weigand@de.ibm.com>
Jan Kratochvil 6e0665a
Date:   Tue Feb 4 18:42:35 2014 +0100
Jan Kratochvil 6e0665a
Jan Kratochvil 6e0665a
    PowerPC64 ELFv2 ABI: structure passing / return
Jan Kratochvil 6e0665a
    
Jan Kratochvil 6e0665a
    Another significant difference in the ELFv2 ABI is that "homogeneous"
Jan Kratochvil 6e0665a
    floating-point and vector aggregates, i.e. aggregates the consist
Jan Kratochvil 6e0665a
    (recursively) only of members of the same floating-point or vector type,
Jan Kratochvil 6e0665a
    are passed in a series of floating-point / vector registers, as if they
Jan Kratochvil 6e0665a
    were seperate parameters.  (This is similar to the ARM ABI.)  This
Jan Kratochvil 6e0665a
    applies to both calls and returns.
Jan Kratochvil 6e0665a
    
Jan Kratochvil 6e0665a
    In addition when returning any aggregate of up to 16 bytes, ELFv2 now
Jan Kratochvil 6e0665a
    used general-purpose registers.
Jan Kratochvil 6e0665a
    
Jan Kratochvil 6e0665a
    This patch adds support for these aspects of the ABI, which is relatively
Jan Kratochvil 6e0665a
    straightforward after the refactoring patch to ppc-sysv-tdep.c.
Jan Kratochvil 6e0665a
    
Jan Kratochvil 6e0665a
    gdb/ChangeLog:
Jan Kratochvil 6e0665a
    
Jan Kratochvil 6e0665a
    	* ppc-sysv-tdep.c (ppc64_aggregate_candidate): New routine.
Jan Kratochvil 6e0665a
    	(ppc64_elfv2_abi_homogeneous_aggregate): Likewise.
Jan Kratochvil 6e0665a
    	(ppc64_sysv_abi_push_param): Handle ELFv2 homogeneous structs.
Jan Kratochvil 6e0665a
    	(ppc64_sysv_abi_return_value): Likewise.  Also, handle small
Jan Kratochvil 6e0665a
    	structures returned in GPRs.
Jan Kratochvil 6e0665a
Jan Kratochvil 6e0665a
### a/gdb/ChangeLog
Jan Kratochvil 6e0665a
### b/gdb/ChangeLog
Jan Kratochvil 6e0665a
## -1,5 +1,13 @@
Jan Kratochvil 6e0665a
 2014-02-04  Ulrich Weigand  <uweigand@de.ibm.com>
Jan Kratochvil 6e0665a
 
Jan Kratochvil 6e0665a
+	* ppc-sysv-tdep.c (ppc64_aggregate_candidate): New routine.
Jan Kratochvil 6e0665a
+	(ppc64_elfv2_abi_homogeneous_aggregate): Likewise.
Jan Kratochvil 6e0665a
+	(ppc64_sysv_abi_push_param): Handle ELFv2 homogeneous structs.
Jan Kratochvil 6e0665a
+	(ppc64_sysv_abi_return_value): Likewise.  Also, handle small
Jan Kratochvil 6e0665a
+	structures returned in GPRs.
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+2014-02-04  Ulrich Weigand  <uweigand@de.ibm.com>
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
 	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Use correct
Jan Kratochvil 6e0665a
 	offset to the stack parameter list for the ELFv2 ABI.
Jan Kratochvil 6e0665a
 
Jan Kratochvil 6e0665a
--- a/gdb/ppc-sysv-tdep.c
Jan Kratochvil 6e0665a
+++ b/gdb/ppc-sysv-tdep.c
Jan Kratochvil 6e0665a
@@ -1101,6 +1101,160 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr)
Jan Kratochvil 6e0665a
   return 1;
Jan Kratochvil 6e0665a
 }
Jan Kratochvil 6e0665a
 
Jan Kratochvil 6e0665a
+/* Walk down the type tree of TYPE counting consecutive base elements.
Jan Kratochvil 6e0665a
+   If *FIELD_TYPE is NULL, then set it to the first valid floating point
Jan Kratochvil 6e0665a
+   or vector type.  If a non-floating point or vector type is found, or
Jan Kratochvil 6e0665a
+   if a floating point or vector type that doesn't match a non-NULL
Jan Kratochvil 6e0665a
+   *FIELD_TYPE is found, then return -1, otherwise return the count in the
Jan Kratochvil 6e0665a
+   sub-tree.  */
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+static LONGEST
Jan Kratochvil 6e0665a
+ppc64_aggregate_candidate (struct type *type,
Jan Kratochvil 6e0665a
+			   struct type **field_type)
Jan Kratochvil 6e0665a
+{
Jan Kratochvil 6e0665a
+  type = check_typedef (type);
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+  switch (TYPE_CODE (type))
Jan Kratochvil 6e0665a
+    {
Jan Kratochvil 6e0665a
+    case TYPE_CODE_FLT:
Jan Kratochvil 6e0665a
+    case TYPE_CODE_DECFLOAT:
Jan Kratochvil 6e0665a
+      if (!*field_type)
Jan Kratochvil 6e0665a
+	*field_type = type;
Jan Kratochvil 6e0665a
+      if (TYPE_CODE (*field_type) == TYPE_CODE (type)
Jan Kratochvil 6e0665a
+	  && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type))
Jan Kratochvil 6e0665a
+	return 1;
Jan Kratochvil 6e0665a
+      break;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+    case TYPE_CODE_COMPLEX:
Jan Kratochvil 6e0665a
+      type = TYPE_TARGET_TYPE (type);
Jan Kratochvil 6e0665a
+      if (TYPE_CODE (type) == TYPE_CODE_FLT
Jan Kratochvil 6e0665a
+	  || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  if (!*field_type)
Jan Kratochvil 6e0665a
+	    *field_type = type;
Jan Kratochvil 6e0665a
+	  if (TYPE_CODE (*field_type) == TYPE_CODE (type)
Jan Kratochvil 6e0665a
+	      && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type))
Jan Kratochvil 6e0665a
+	    return 2;
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
+      break;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+    case TYPE_CODE_ARRAY:
Jan Kratochvil 6e0665a
+      if (TYPE_VECTOR (type))
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  if (!*field_type)
Jan Kratochvil 6e0665a
+	    *field_type = type;
Jan Kratochvil 6e0665a
+	  if (TYPE_CODE (*field_type) == TYPE_CODE (type)
Jan Kratochvil 6e0665a
+	      && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type))
Jan Kratochvil 6e0665a
+	    return 1;
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
+      else
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  LONGEST count, low_bound, high_bound;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  count = ppc64_aggregate_candidate
Jan Kratochvil 6e0665a
+		   (TYPE_TARGET_TYPE (type), field_type);
Jan Kratochvil 6e0665a
+	  if (count == -1)
Jan Kratochvil 6e0665a
+	    return -1;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  if (!get_array_bounds (type, &low_bound, &high_bound))
Jan Kratochvil 6e0665a
+	    return -1;
Jan Kratochvil 6e0665a
+	  count *= high_bound - low_bound;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  /* There must be no padding.  */
Jan Kratochvil 6e0665a
+	  if (count == 0)
Jan Kratochvil 6e0665a
+	    return TYPE_LENGTH (type) == 0 ? 0 : -1;
Jan Kratochvil 6e0665a
+	  else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type))
Jan Kratochvil 6e0665a
+	    return -1;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  return count;
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
+      break;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+    case TYPE_CODE_STRUCT:
Jan Kratochvil 6e0665a
+    case TYPE_CODE_UNION:
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  LONGEST count = 0;
Jan Kratochvil 6e0665a
+	  int i;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  for (i = 0; i < TYPE_NFIELDS (type); i++)
Jan Kratochvil 6e0665a
+	    {
Jan Kratochvil 6e0665a
+	      LONGEST sub_count;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	      if (field_is_static (&TYPE_FIELD (type, i)))
Jan Kratochvil 6e0665a
+		continue;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	      sub_count = ppc64_aggregate_candidate
Jan Kratochvil 6e0665a
+			   (TYPE_FIELD_TYPE (type, i), field_type);
Jan Kratochvil 6e0665a
+	      if (sub_count == -1)
Jan Kratochvil 6e0665a
+		return -1;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	      if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
Jan Kratochvil 6e0665a
+		count += sub_count;
Jan Kratochvil 6e0665a
+	      else
Jan Kratochvil 6e0665a
+		count = max (count, sub_count);
Jan Kratochvil 6e0665a
+	    }
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  /* There must be no padding.  */
Jan Kratochvil 6e0665a
+	  if (count == 0)
Jan Kratochvil 6e0665a
+	    return TYPE_LENGTH (type) == 0 ? 0 : -1;
Jan Kratochvil 6e0665a
+	  else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type))
Jan Kratochvil 6e0665a
+	    return -1;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  return count;
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
+      break;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+    default:
Jan Kratochvil 6e0665a
+      break;
Jan Kratochvil 6e0665a
+    }
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+  return -1;
Jan Kratochvil 6e0665a
+}
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+/* If an argument of type TYPE is a homogeneous float or vector aggregate
Jan Kratochvil 6e0665a
+   that shall be passed in FP/vector registers according to the ELFv2 ABI,
Jan Kratochvil 6e0665a
+   return the homogeneous element type in *ELT_TYPE and the number of
Jan Kratochvil 6e0665a
+   elements in *N_ELTS, and return non-zero.  Otherwise, return zero.  */
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+static int
Jan Kratochvil 6e0665a
+ppc64_elfv2_abi_homogeneous_aggregate (struct type *type,
Jan Kratochvil 6e0665a
+				       struct type **elt_type, int *n_elts)
Jan Kratochvil 6e0665a
+{
Jan Kratochvil 6e0665a
+  /* Complex types at the top level are treated separately.  However,
Jan Kratochvil 6e0665a
+     complex types can be elements of homogeneous aggregates.  */
Jan Kratochvil 6e0665a
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
Jan Kratochvil 6e0665a
+      || TYPE_CODE (type) == TYPE_CODE_UNION
Jan Kratochvil 6e0665a
+      || (TYPE_CODE (type) == TYPE_CODE_ARRAY && !TYPE_VECTOR (type)))
Jan Kratochvil 6e0665a
+    {
Jan Kratochvil 6e0665a
+      struct type *field_type = NULL;
Jan Kratochvil 6e0665a
+      LONGEST field_count = ppc64_aggregate_candidate (type, &field_type);
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+      if (field_count > 0)
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  int n_regs = ((TYPE_CODE (field_type) == TYPE_CODE_FLT
Jan Kratochvil 6e0665a
+			 || TYPE_CODE (field_type) == TYPE_CODE_DECFLOAT)?
Jan Kratochvil 6e0665a
+			(TYPE_LENGTH (field_type) + 7) >> 3 : 1);
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  /* The ELFv2 ABI allows homogeneous aggregates to occupy
Jan Kratochvil 6e0665a
+	     up to 8 registers.  */
Jan Kratochvil 6e0665a
+	  if (field_count * n_regs <= 8)
Jan Kratochvil 6e0665a
+	    {
Jan Kratochvil 6e0665a
+	      if (elt_type)
Jan Kratochvil 6e0665a
+		*elt_type = field_type;
Jan Kratochvil 6e0665a
+	      if (n_elts)
Jan Kratochvil 6e0665a
+		*n_elts = (int) field_count;
Jan Kratochvil 6e0665a
+	      /* Note that field_count is LONGEST since it may hold the size
Jan Kratochvil 6e0665a
+		 of an array, while *n_elts is int since its value is bounded
Jan Kratochvil 6e0665a
+		 by the number of registers used for argument passing.  The
Jan Kratochvil 6e0665a
+		 cast cannot overflow due to the bounds checking above.  */
Jan Kratochvil 6e0665a
+	      return 1;
Jan Kratochvil 6e0665a
+	    }
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
+    }
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+  return 0;
Jan Kratochvil 6e0665a
+}
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
 /* Structure holding the next argument position.  */
Jan Kratochvil 6e0665a
 struct ppc64_sysv_argpos
Jan Kratochvil 6e0665a
   {
Jan Kratochvil 6e0665a
@@ -1389,6 +1543,29 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch,
Jan Kratochvil 6e0665a
 	  if (TYPE_CODE (type) == TYPE_CODE_FLT)
Jan Kratochvil 6e0665a
 	    ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos);
Jan Kratochvil 6e0665a
 	}
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+      /* In the ELFv2 ABI, homogeneous floating-point or vector
Jan Kratochvil 6e0665a
+	 aggregates are passed in a series of registers.  */
Jan Kratochvil 6e0665a
+      if (tdep->elf_abi == POWERPC_ELF_V2)
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  struct type *eltype;
Jan Kratochvil 6e0665a
+	  int i, nelt;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  if (ppc64_elfv2_abi_homogeneous_aggregate (type, &eltype, &nelt))
Jan Kratochvil 6e0665a
+	    for (i = 0; i < nelt; i++)
Jan Kratochvil 6e0665a
+	      {
Jan Kratochvil 6e0665a
+		const gdb_byte *elval = val + i * TYPE_LENGTH (eltype);
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+		if (TYPE_CODE (eltype) == TYPE_CODE_FLT
Jan Kratochvil 6e0665a
+		    || TYPE_CODE (eltype) == TYPE_CODE_DECFLOAT)
Jan Kratochvil 6e0665a
+		  ppc64_sysv_abi_push_freg (gdbarch, eltype, elval, argpos);
Jan Kratochvil 6e0665a
+		else if (TYPE_CODE (eltype) == TYPE_CODE_ARRAY
Jan Kratochvil 6e0665a
+			 && TYPE_VECTOR (eltype)
Jan Kratochvil 6e0665a
+			 && tdep->vector_abi == POWERPC_VEC_ALTIVEC
Jan Kratochvil 6e0665a
+			 && TYPE_LENGTH (eltype) == 16)
Jan Kratochvil 6e0665a
+		  ppc64_sysv_abi_push_vreg (gdbarch, elval, argpos);
Jan Kratochvil 6e0665a
+	      }
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
     }
Jan Kratochvil 6e0665a
 }
Jan Kratochvil 6e0665a
 
Jan Kratochvil 6e0665a
@@ -1834,6 +2011,72 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function,
Jan Kratochvil 6e0665a
       return RETURN_VALUE_REGISTER_CONVENTION;
Jan Kratochvil 6e0665a
     }
Jan Kratochvil 6e0665a
 
Jan Kratochvil 6e0665a
+  /* In the ELFv2 ABI, homogeneous floating-point or vector
Jan Kratochvil 6e0665a
+     aggregates are returned in registers.  */
Jan Kratochvil 6e0665a
+  if (tdep->elf_abi == POWERPC_ELF_V2
Jan Kratochvil 6e0665a
+      && ppc64_elfv2_abi_homogeneous_aggregate (valtype, &eltype, &nelt))
Jan Kratochvil 6e0665a
+    {
Jan Kratochvil 6e0665a
+      for (i = 0; i < nelt; i++)
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache,
Jan Kratochvil 6e0665a
+						 readbuf, writebuf, i);
Jan Kratochvil 6e0665a
+	  gdb_assert (ok);
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  if (readbuf)
Jan Kratochvil 6e0665a
+	    readbuf += TYPE_LENGTH (eltype);
Jan Kratochvil 6e0665a
+	  if (writebuf)
Jan Kratochvil 6e0665a
+	    writebuf += TYPE_LENGTH (eltype);
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+      return RETURN_VALUE_REGISTER_CONVENTION;
Jan Kratochvil 6e0665a
+    }
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+  /* In the ELFv2 ABI, aggregate types of up to 16 bytes are
Jan Kratochvil 6e0665a
+     returned in registers r3:r4.  */
Jan Kratochvil 6e0665a
+  if (tdep->elf_abi == POWERPC_ELF_V2
Jan Kratochvil 6e0665a
+      && TYPE_LENGTH (valtype) <= 16
Jan Kratochvil 6e0665a
+      && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
Jan Kratochvil 6e0665a
+	  || TYPE_CODE (valtype) == TYPE_CODE_UNION
Jan Kratochvil 6e0665a
+	  || (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
Jan Kratochvil 6e0665a
+	      && !TYPE_VECTOR (valtype))))
Jan Kratochvil 6e0665a
+    {
Jan Kratochvil 6e0665a
+      int n_regs = ((TYPE_LENGTH (valtype) + tdep->wordsize - 1)
Jan Kratochvil 6e0665a
+		    / tdep->wordsize);
Jan Kratochvil 6e0665a
+      int i;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+      for (i = 0; i < n_regs; i++)
Jan Kratochvil 6e0665a
+	{
Jan Kratochvil 6e0665a
+	  gdb_byte regval[MAX_REGISTER_SIZE];
Jan Kratochvil 6e0665a
+	  int regnum = tdep->ppc_gp0_regnum + 3 + i;
Jan Kratochvil 6e0665a
+	  int offset = i * tdep->wordsize;
Jan Kratochvil 6e0665a
+	  int len = TYPE_LENGTH (valtype) - offset;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  if (len > tdep->wordsize)
Jan Kratochvil 6e0665a
+	    len = tdep->wordsize;
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
+	  if (writebuf != NULL)
Jan Kratochvil 6e0665a
+	    {
Jan Kratochvil 6e0665a
+	      memset (regval, 0, sizeof regval);
Jan Kratochvil 6e0665a
+	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
Jan Kratochvil 6e0665a
+		  && offset == 0)
Jan Kratochvil 6e0665a
+		memcpy (regval + tdep->wordsize - len, writebuf, len);
Jan Kratochvil 6e0665a
+	      else
Jan Kratochvil 6e0665a
+		memcpy (regval, writebuf + offset, len);
Jan Kratochvil 6e0665a
+	      regcache_cooked_write (regcache, regnum, regval);
Jan Kratochvil 6e0665a
+	    }
Jan Kratochvil 6e0665a
+	  if (readbuf != NULL)
Jan Kratochvil 6e0665a
+	    {
Jan Kratochvil 6e0665a
+	      regcache_cooked_read (regcache, regnum, regval);
Jan Kratochvil 6e0665a
+	      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
Jan Kratochvil 6e0665a
+		  && offset == 0)
Jan Kratochvil 6e0665a
+		memcpy (readbuf, regval + tdep->wordsize - len, len);
Jan Kratochvil 6e0665a
+	      else
Jan Kratochvil 6e0665a
+		memcpy (readbuf + offset, regval, len);
Jan Kratochvil 6e0665a
+	    }
Jan Kratochvil 6e0665a
+	}
Jan Kratochvil 6e0665a
+      return RETURN_VALUE_REGISTER_CONVENTION;
Jan Kratochvil 6e0665a
+    }
Jan Kratochvil 6e0665a
+
Jan Kratochvil 6e0665a
   /* Handle plain base types.  */
Jan Kratochvil 6e0665a
   if (ppc64_sysv_abi_return_value_base (gdbarch, valtype, regcache,
Jan Kratochvil 6e0665a
 					readbuf, writebuf, 0))