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

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