Blame SOURCES/gdb-rhbz1125820-ppc64le-enablement-32of37.patch

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