Blame SOURCES/gdb-rhbz1182151-ibm-z13-16of22.patch

2c2fa1
commit 417c80f9e456477935cdc74461d35630dfdbfdff
2c2fa1
Author: Andreas Arnez <arnez@linux.vnet.ibm.com>
2c2fa1
Date:   Mon Apr 27 11:38:47 2015 +0200
2c2fa1
2c2fa1
    S390: Vector ABI support
2c2fa1
    
2c2fa1
    With the S390 vector ABI, vector registers are used for passing vector
2c2fa1
    arguments and for returning a vector.  Support this ABI in inferior
2c2fa1
    function calls and when setting or retrieving a function's return
2c2fa1
    value.
2c2fa1
    
2c2fa1
    gdb/ChangeLog:
2c2fa1
    
2c2fa1
    	* s390-linux-tdep.c: Include "elf/s390.h" and "elf-bfd.h".
2c2fa1
    	(enum s390_vector_abi_kind): New enum.
2c2fa1
    	(struct gdbarch_tdep)<vector_abi>: New field.
2c2fa1
    	(s390_effective_inner_type): Add parameter min_size.  Stop
2c2fa1
    	unwrapping if the inner type is smaller than min_size.
2c2fa1
    	(s390_function_arg_float): Adjust call to
2c2fa1
    	s390_effective_inner_type.
2c2fa1
    	(s390_function_arg_vector): New function.
2c2fa1
    	(s390_function_arg_integer): Adjust comment.
2c2fa1
    	(struct s390_arg_state)<vr>: New field.
2c2fa1
    	(s390_handle_arg): Add parameter 'is_unnamed'.  Pass vector
2c2fa1
    	arguments according to vector ABI when appropriate.
2c2fa1
    	(s390_push_dummy_call): Initialize the argument state's field
2c2fa1
    	'vr'.  Adjust calls to s390_handle_arg.
2c2fa1
    	(s390_register_return_value): Handle vector return values.
2c2fa1
    	(s390_return_value): Apply the "register" return value convention
2c2fa1
    	to a vector when appropriate.
2c2fa1
    	(s390_gdbarch_init): Initialize tdep->vector_abi.
2c2fa1
    	* NEWS: Announce S390 vector ABI support.
2c2fa1
2c2fa1
### a/gdb/ChangeLog
2c2fa1
### b/gdb/ChangeLog
2c2fa1
## -1,5 +1,27 @@
2c2fa1
 2015-04-27  Andreas Arnez  <arnez@linux.vnet.ibm.com>
2c2fa1
 
2c2fa1
+	* s390-linux-tdep.c: Include "elf/s390.h" and "elf-bfd.h".
2c2fa1
+	(enum s390_vector_abi_kind): New enum.
2c2fa1
+	(struct gdbarch_tdep)<vector_abi>: New field.
2c2fa1
+	(s390_effective_inner_type): Add parameter min_size.  Stop
2c2fa1
+	unwrapping if the inner type is smaller than min_size.
2c2fa1
+	(s390_function_arg_float): Adjust call to
2c2fa1
+	s390_effective_inner_type.
2c2fa1
+	(s390_function_arg_vector): New function.
2c2fa1
+	(s390_function_arg_integer): Adjust comment.
2c2fa1
+	(struct s390_arg_state)<vr>: New field.
2c2fa1
+	(s390_handle_arg): Add parameter 'is_unnamed'.  Pass vector
2c2fa1
+	arguments according to vector ABI when appropriate.
2c2fa1
+	(s390_push_dummy_call): Initialize the argument state's field
2c2fa1
+	'vr'.  Adjust calls to s390_handle_arg.
2c2fa1
+	(s390_register_return_value): Handle vector return values.
2c2fa1
+	(s390_return_value): Apply the "register" return value convention
2c2fa1
+	to a vector when appropriate.
2c2fa1
+	(s390_gdbarch_init): Initialize tdep->vector_abi.
2c2fa1
+	* NEWS: Announce S390 vector ABI support.
2c2fa1
+
2c2fa1
+2015-04-27  Andreas Arnez  <arnez@linux.vnet.ibm.com>
2c2fa1
+
2c2fa1
 	* s390-linux-tdep.c (s390_return_value_convention): Remove
2c2fa1
 	function.  Inline its logic...
2c2fa1
 	(s390_return_value): ...here.  Instead, move the handling of the
2c2fa1
Index: gdb-7.6.1/gdb/NEWS
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/NEWS	2016-02-21 22:34:07.599040574 +0100
2c2fa1
+++ gdb-7.6.1/gdb/NEWS	2016-02-21 22:34:13.476086880 +0100
2c2fa1
@@ -21,6 +21,8 @@
2c2fa1
 * GDB now supports access to vector registers on S/390 GNU/Linux
2c2fa1
   targets.
2c2fa1
 
2c2fa1
+* GDB now supports the vector ABI on S/390 GNU/Linux targets.
2c2fa1
+
2c2fa1
 * GDB now honors the content of the file /proc/PID/coredump_filter
2c2fa1
   (PID is the process ID) on GNU/Linux systems.  This file can be used
2c2fa1
   to specify the types of memory mappings that will be included in a
2c2fa1
Index: gdb-7.6.1/gdb/s390-tdep.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/s390-tdep.c	2016-02-21 22:34:07.599040574 +0100
2c2fa1
+++ gdb-7.6.1/gdb/s390-tdep.c	2016-02-21 22:35:45.273797475 +0100
2c2fa1
@@ -52,7 +52,9 @@
2c2fa1
 #include "user-regs.h"
2c2fa1
 #include "cli/cli-utils.h"
2c2fa1
 #include <ctype.h>
2c2fa1
-#include <elf.h>
2c2fa1
+//#include <elf.h> // Conflicts with "elf-bfd.h".
2c2fa1
+#include "elf/s390.h"
2c2fa1
+#include "elf-bfd.h"
2c2fa1
 
2c2fa1
 #include "features/s390-linux32.c"
2c2fa1
 #include "features/s390-linux32v1.c"
2c2fa1
@@ -70,6 +72,12 @@
2c2fa1
 #include "features/s390x-vx-linux64.c"
2c2fa1
 #include "features/s390x-tevx-linux64.c"
2c2fa1
 
2c2fa1
+enum s390_vector_abi_kind
2c2fa1
+{
2c2fa1
+  S390_VECTOR_ABI_NONE,
2c2fa1
+  S390_VECTOR_ABI_128
2c2fa1
+};
2c2fa1
+
2c2fa1
 /* The tdep structure.  */
2c2fa1
 
2c2fa1
 struct gdbarch_tdep
2c2fa1
@@ -77,6 +85,9 @@
2c2fa1
   /* ABI version.  */
2c2fa1
   enum { ABI_LINUX_S390, ABI_LINUX_ZSERIES } abi;
2c2fa1
 
2c2fa1
+  /* Vector ABI.  */
2c2fa1
+  enum s390_vector_abi_kind vector_abi;
2c2fa1
+
2c2fa1
   /* Pseudo register numbers.  */
2c2fa1
   int gpr_full_regnum;
2c2fa1
   int pc_regnum;
2c2fa1
@@ -2552,14 +2563,24 @@
2c2fa1
      float x;
2c2fa1
      struct { float x };
2c2fa1
      struct { struct { float x; } x; };
2c2fa1
-     struct { struct { struct { float x; } x; } x; };  */
2c2fa1
+     struct { struct { struct { float x; } x; } x; };
2c2fa1
+
2c2fa1
+   However, if an inner type is smaller than MIN_SIZE, abort the
2c2fa1
+   unwrapping.  */
2c2fa1
 
2c2fa1
 static struct type *
2c2fa1
-s390_effective_inner_type (struct type *type)
2c2fa1
+s390_effective_inner_type (struct type *type, unsigned int min_size)
2c2fa1
 {
2c2fa1
   while (TYPE_CODE (type) == TYPE_CODE_STRUCT
2c2fa1
 	 && TYPE_NFIELDS (type) == 1)
2c2fa1
-    type = check_typedef (TYPE_FIELD_TYPE (type, 0));
2c2fa1
+    {
2c2fa1
+      struct type *inner = check_typedef (TYPE_FIELD_TYPE (type, 0));
2c2fa1
+
2c2fa1
+      if (TYPE_LENGTH (inner) < min_size)
2c2fa1
+	break;
2c2fa1
+      type = inner;
2c2fa1
+    }
2c2fa1
+
2c2fa1
   return type;
2c2fa1
 }
2c2fa1
 
2c2fa1
@@ -2576,12 +2597,26 @@
2c2fa1
 
2c2fa1
   /* A struct containing just a float or double is passed like a float
2c2fa1
      or double.  */
2c2fa1
-  type = s390_effective_inner_type (type);
2c2fa1
+  type = s390_effective_inner_type (type, 0);
2c2fa1
 
2c2fa1
   return (TYPE_CODE (type) == TYPE_CODE_FLT
2c2fa1
 	  || TYPE_CODE (type) == TYPE_CODE_DECFLOAT);
2c2fa1
 }
2c2fa1
 
2c2fa1
+/* Return non-zero if TYPE should be passed like a vector.  */
2c2fa1
+
2c2fa1
+static int
2c2fa1
+s390_function_arg_vector (struct type *type)
2c2fa1
+{
2c2fa1
+  if (TYPE_LENGTH (type) > 16)
2c2fa1
+    return 0;
2c2fa1
+
2c2fa1
+  /* Structs containing just a vector are passed like a vector.  */
2c2fa1
+  type = s390_effective_inner_type (type, TYPE_LENGTH (type));
2c2fa1
+
2c2fa1
+  return TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type);
2c2fa1
+}
2c2fa1
+
2c2fa1
 /* Determine whether N is a power of two.  */
2c2fa1
 
2c2fa1
 static int
2c2fa1
@@ -2591,8 +2626,8 @@
2c2fa1
 }
2c2fa1
 
2c2fa1
 /* For an argument whose type is TYPE and which is not passed like a
2c2fa1
-   float, return non-zero if it should be passed like "int" or "long
2c2fa1
-   long".  */
2c2fa1
+   float or vector, return non-zero if it should be passed like "int"
2c2fa1
+   or "long long".  */
2c2fa1
 
2c2fa1
 static int
2c2fa1
 s390_function_arg_integer (struct type *type)
2c2fa1
@@ -2622,9 +2657,9 @@
2c2fa1
   {
2c2fa1
     /* Register cache, or NULL, if we are in "preparation mode".  */
2c2fa1
     struct regcache *regcache;
2c2fa1
-    /* Next available general/floating-point register for argument
2c2fa1
-       passing.  */
2c2fa1
-    int gr, fr;
2c2fa1
+    /* Next available general/floating-point/vector register for
2c2fa1
+       argument passing.  */
2c2fa1
+    int gr, fr, vr;
2c2fa1
     /* Current pointer to copy area (grows downwards).  */
2c2fa1
     CORE_ADDR copy;
2c2fa1
     /* Current pointer to parameter area (grows upwards).  */
2c2fa1
@@ -2639,7 +2674,7 @@
2c2fa1
 static void
2c2fa1
 s390_handle_arg (struct s390_arg_state *as, struct value *arg,
2c2fa1
 		 struct gdbarch_tdep *tdep, int word_size,
2c2fa1
-		 enum bfd_endian byte_order)
2c2fa1
+		 enum bfd_endian byte_order, int is_unnamed)
2c2fa1
 {
2c2fa1
   struct type *type = check_typedef (value_type (arg));
2c2fa1
   ULONGEST length = TYPE_LENGTH (type);
2c2fa1
@@ -2671,6 +2706,28 @@
2c2fa1
 			  length);
2c2fa1
 	}
2c2fa1
     }
2c2fa1
+  else if (tdep->vector_abi == S390_VECTOR_ABI_128
2c2fa1
+	   && s390_function_arg_vector (type))
2c2fa1
+    {
2c2fa1
+      static const char use_vr[] = {24, 26, 28, 30, 25, 27, 29, 31};
2c2fa1
+
2c2fa1
+      if (!is_unnamed && as->vr < ARRAY_SIZE (use_vr))
2c2fa1
+	{
2c2fa1
+	  int regnum = S390_V24_REGNUM + use_vr[as->vr] - 24;
2c2fa1
+
2c2fa1
+	  if (write_mode)
2c2fa1
+	    regcache_cooked_write_part (as->regcache, regnum,
2c2fa1
+					0, length,
2c2fa1
+					value_contents (arg));
2c2fa1
+	  as->vr++;
2c2fa1
+	}
2c2fa1
+      else
2c2fa1
+	{
2c2fa1
+	  if (write_mode)
2c2fa1
+	    write_memory (as->argp, value_contents (arg), length);
2c2fa1
+	  as->argp = align_up (as->argp + length, word_size);
2c2fa1
+	}
2c2fa1
+    }
2c2fa1
   else if (s390_function_arg_integer (type) && length <= word_size)
2c2fa1
     {
2c2fa1
       ULONGEST val;
2c2fa1
@@ -2783,10 +2840,15 @@
2c2fa1
   int i;
2c2fa1
   struct s390_arg_state arg_state, arg_prep;
2c2fa1
   CORE_ADDR param_area_start, new_sp;
2c2fa1
+  struct type *ftype = check_typedef (value_type (function));
2c2fa1
+
2c2fa1
+  if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
2c2fa1
+    ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
2c2fa1
 
2c2fa1
   arg_prep.copy = sp;
2c2fa1
   arg_prep.gr = struct_return ? 3 : 2;
2c2fa1
   arg_prep.fr = 0;
2c2fa1
+  arg_prep.vr = 0;
2c2fa1
   arg_prep.argp = 0;
2c2fa1
   arg_prep.regcache = NULL;
2c2fa1
 
2c2fa1
@@ -2796,7 +2858,8 @@
2c2fa1
   /* Update arg_state.copy with the start of the reference-to-copy area
2c2fa1
      and arg_state.argp with the size of the parameter area.  */
2c2fa1
   for (i = 0; i < nargs; i++)
2c2fa1
-    s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order);
2c2fa1
+    s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order,
2c2fa1
+		     TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
2c2fa1
 
2c2fa1
   param_area_start = align_down (arg_state.copy - arg_state.argp, 8);
2c2fa1
 
2c2fa1
@@ -2822,7 +2885,8 @@
2c2fa1
 
2c2fa1
   /* Write all parameters.  */
2c2fa1
   for (i = 0; i < nargs; i++)
2c2fa1
-    s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order);
2c2fa1
+    s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order,
2c2fa1
+		     TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype));
2c2fa1
 
2c2fa1
   /* Store return PSWA.  In 31-bit mode, keep addressing mode bit.  */
2c2fa1
   if (word_size == 4)
2c2fa1
@@ -2888,6 +2952,16 @@
2c2fa1
 	regcache_cooked_read_part (regcache, S390_F0_REGNUM,
2c2fa1
 				   0, length, out);
2c2fa1
     }
2c2fa1
+  else if (code == TYPE_CODE_ARRAY)
2c2fa1
+    {
2c2fa1
+      /* Vector: left-aligned in v24.  */
2c2fa1
+      if (in != NULL)
2c2fa1
+	regcache_cooked_write_part (regcache, S390_V24_REGNUM,
2c2fa1
+				    0, length, in);
2c2fa1
+      else
2c2fa1
+	regcache_cooked_read_part (regcache, S390_V24_REGNUM,
2c2fa1
+				   0, length, out);
2c2fa1
+    }
2c2fa1
   else if (length <= word_size)
2c2fa1
     {
2c2fa1
       /* Integer: zero- or sign-extended in r2.  */
2c2fa1
@@ -2939,10 +3013,15 @@
2c2fa1
     {
2c2fa1
     case TYPE_CODE_STRUCT:
2c2fa1
     case TYPE_CODE_UNION:
2c2fa1
-    case TYPE_CODE_ARRAY:
2c2fa1
     case TYPE_CODE_COMPLEX:
2c2fa1
       rvc = RETURN_VALUE_STRUCT_CONVENTION;
2c2fa1
       break;
2c2fa1
+    case TYPE_CODE_ARRAY:
2c2fa1
+      rvc = (gdbarch_tdep (gdbarch)->vector_abi == S390_VECTOR_ABI_128
2c2fa1
+	     && TYPE_LENGTH (type) <= 16 && TYPE_VECTOR (type))
2c2fa1
+	? RETURN_VALUE_REGISTER_CONVENTION
2c2fa1
+	: RETURN_VALUE_STRUCT_CONVENTION;
2c2fa1
+      break;
2c2fa1
     default:
2c2fa1
       rvc = TYPE_LENGTH (type) <= 8
2c2fa1
 	? RETURN_VALUE_REGISTER_CONVENTION
2c2fa1
@@ -3038,6 +3117,7 @@
2c2fa1
   struct gdbarch *gdbarch;
2c2fa1
   struct gdbarch_tdep *tdep;
2c2fa1
   int tdep_abi;
2c2fa1
+  enum s390_vector_abi_kind vector_abi;
2c2fa1
   int have_upper = 0;
2c2fa1
   int have_linux_v1 = 0;
2c2fa1
   int have_linux_v2 = 0;
2c2fa1
@@ -3220,6 +3300,18 @@
2c2fa1
 	}
2c2fa1
     }
2c2fa1
 
2c2fa1
+  /* Determine vector ABI.  */
2c2fa1
+  vector_abi = S390_VECTOR_ABI_NONE;
2c2fa1
+#ifdef HAVE_ELF
2c2fa1
+  if (have_vx
2c2fa1
+      && info.abfd != NULL
2c2fa1
+      && info.abfd->format == bfd_object
2c2fa1
+      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
2c2fa1
+      && bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU,
2c2fa1
+				   Tag_GNU_S390_ABI_Vector) == 2)
2c2fa1
+    vector_abi = S390_VECTOR_ABI_128;
2c2fa1
+#endif
2c2fa1
+
2c2fa1
   /* Find a candidate among extant architectures.  */
2c2fa1
   for (arches = gdbarch_list_lookup_by_info (arches, &info;;
2c2fa1
        arches != NULL;
2c2fa1
@@ -3230,6 +3322,8 @@
2c2fa1
 	continue;
2c2fa1
       if (tdep->abi != tdep_abi)
2c2fa1
 	continue;
2c2fa1
+      if (tdep->vector_abi != vector_abi)
2c2fa1
+	continue;
2c2fa1
       if ((tdep->gpr_full_regnum != -1) != have_upper)
2c2fa1
 	continue;
2c2fa1
       if (tdesc_data != NULL)
2c2fa1
@@ -3240,6 +3334,7 @@
2c2fa1
   /* Otherwise create a new gdbarch for the specified machine type.  */
2c2fa1
   tdep = XCALLOC (1, struct gdbarch_tdep);
2c2fa1
   tdep->abi = tdep_abi;
2c2fa1
+  tdep->vector_abi = vector_abi;
2c2fa1
   tdep->have_linux_v1 = have_linux_v1;
2c2fa1
   tdep->have_linux_v2 = have_linux_v2;
2c2fa1
   tdep->have_tdb = have_tdb;