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