From patchwork Fri Apr 24 14:45:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Arnez X-Patchwork-Id: 6428 Received: (qmail 34319 invoked by alias); 24 Apr 2015 14:46:02 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 34293 invoked by uid 89); 24 Apr 2015 14:46:01 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: e06smtp17.uk.ibm.com Received: from e06smtp17.uk.ibm.com (HELO e06smtp17.uk.ibm.com) (195.75.94.113) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 24 Apr 2015 14:46:00 +0000 Received: from /spool/local by e06smtp17.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 24 Apr 2015 15:45:56 +0100 Received: from d06dlp01.portsmouth.uk.ibm.com (9.149.20.13) by e06smtp17.uk.ibm.com (192.168.101.147) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Fri, 24 Apr 2015 15:45:55 +0100 Received: from b06cxnps3074.portsmouth.uk.ibm.com (d06relay09.portsmouth.uk.ibm.com [9.149.109.194]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id D110217D805F for ; Fri, 24 Apr 2015 15:46:34 +0100 (BST) Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t3OEjtdE11207116 for ; Fri, 24 Apr 2015 14:45:55 GMT Received: from d06av07.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t3OEjs2B002353 for ; Fri, 24 Apr 2015 10:45:54 -0400 Received: from br87z6lw.de.ibm.com (dyn-9-152-212-115.boeblingen.de.ibm.com [9.152.212.115]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t3OEjrNj002328; Fri, 24 Apr 2015 10:45:54 -0400 From: Andreas Arnez To: "Ulrich Weigand" Cc: gdb-patches@sourceware.org, sergiodj@redhat.com (Sergio Durigan Junior) Subject: Re: [PATCH 4/4] S390: Vector ABI support References: <20150423160739.19A56B8EB@oc7340732750.ibm.com> Date: Fri, 24 Apr 2015 16:45:53 +0200 In-Reply-To: <20150423160739.19A56B8EB@oc7340732750.ibm.com> (Ulrich Weigand's message of "Thu, 23 Apr 2015 18:07:39 +0200 (CEST)") Message-ID: <87vbgl7ffh.fsf@br87z6lw.de.ibm.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.3 (gnu/linux) MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15042414-0029-0000-0000-0000045A06E7 X-IsSubscribed: yes On Thu, Apr 23 2015, Ulrich Weigand wrote: > Andreas Arnez wrote: > > [...] > >> static void >> s390_handle_arg (struct s390_arg_state *as, struct value *arg, >> struct gdbarch_tdep *tdep, int word_size, >> - enum bfd_endian byte_order) >> + enum bfd_endian byte_order, int is_vararg) > > Maybe "is_unnamed" would be better than "is_vararg". OK, changed. >> + /* Determine vector ABI. */ >> + if (have_vx >> + && info.abfd != NULL >> + && info.abfd->format == bfd_object >> + && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour >> + && bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, >> + Tag_GNU_S390_ABI_Vector) == 2) > > I think this needs to be under an #ifdef HAVE_ELF, otherwise we'd > get compile errors when building GDB on a non-ELF host system. OK, added the #ifdef. > Otherwise, this is OK once the binutils patch is committed. Thanks for reviewing! Updated patch below. -- >8 -- Subject: [PATCH v2] S390: Vector ABI support With the S390 vector ABI, vector registers are used for passing vector arguments and for returning a vector. Support this ABI in inferior function calls and when setting or retrieving a function's return value. gdb/ChangeLog: * s390-linux-tdep.c: Include "elf/s390.h" and "elf-bfd.h". (enum s390_vector_abi_kind): New enum. (struct gdbarch_tdep): New field. (s390_effective_inner_type): Add parameter min_size. Stop unwrapping if the inner type is smaller than min_size. (s390_function_arg_float): Adjust call to s390_effective_inner_type. (s390_function_arg_vector): New function. (s390_function_arg_integer): Adjust comment. (struct s390_arg_state): New field. (s390_handle_arg): Add parameter 'is_unnamed'. Pass vector arguments according to vector ABI when appropriate. (s390_push_dummy_call): Initialize the argument state's field 'vr'. Adjust calls to s390_handle_arg. (s390_register_return_value): Handle vector return values. (s390_return_value): Apply the "register" return value convention to a vector when appropriate. (s390_gdbarch_init): Initialize tdep->vector_abi. * NEWS: Announce S390 vector ABI support. --- gdb/NEWS | 2 + gdb/s390-linux-tdep.c | 121 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 110 insertions(+), 13 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 62cbdcb..b2c92b1 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -42,6 +42,8 @@ (no "set sysroot" or "file" commands are required). See "New remote packets" below. +* GDB now supports the vector ABI on S/390 GNU/Linux targets. + * Python Scripting ** gdb.Objfile objects have a new attribute "username", diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c index bb9b28e..edc0da1 100644 --- a/gdb/s390-linux-tdep.c +++ b/gdb/s390-linux-tdep.c @@ -54,6 +54,8 @@ #include "cli/cli-utils.h" #include #include "elf/common.h" +#include "elf/s390.h" +#include "elf-bfd.h" #include "features/s390-linux32.c" #include "features/s390-linux32v1.c" @@ -80,6 +82,12 @@ enum s390_abi_kind ABI_LINUX_ZSERIES }; +enum s390_vector_abi_kind +{ + S390_VECTOR_ABI_NONE, + S390_VECTOR_ABI_128 +}; + /* The tdep structure. */ struct gdbarch_tdep @@ -87,6 +95,9 @@ struct gdbarch_tdep /* ABI version. */ enum s390_abi_kind abi; + /* Vector ABI. */ + enum s390_vector_abi_kind vector_abi; + /* Pseudo register numbers. */ int gpr_full_regnum; int pc_regnum; @@ -2395,14 +2406,24 @@ s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, float x; struct { float x }; struct { struct { float x; } x; }; - struct { struct { struct { float x; } x; } x; }; */ + struct { struct { struct { float x; } x; } x; }; + + However, if an inner type is smaller than MIN_SIZE, abort the + unwrapping. */ static struct type * -s390_effective_inner_type (struct type *type) +s390_effective_inner_type (struct type *type, unsigned int min_size) { while (TYPE_CODE (type) == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1) - type = check_typedef (TYPE_FIELD_TYPE (type, 0)); + { + struct type *inner = check_typedef (TYPE_FIELD_TYPE (type, 0)); + + if (TYPE_LENGTH (inner) < min_size) + break; + type = inner; + } + return type; } @@ -2419,12 +2440,26 @@ s390_function_arg_float (struct type *type) /* A struct containing just a float or double is passed like a float or double. */ - type = s390_effective_inner_type (type); + type = s390_effective_inner_type (type, 0); return (TYPE_CODE (type) == TYPE_CODE_FLT || TYPE_CODE (type) == TYPE_CODE_DECFLOAT); } +/* Return non-zero if TYPE should be passed like a vector. */ + +static int +s390_function_arg_vector (struct type *type) +{ + if (TYPE_LENGTH (type) > 16) + return 0; + + /* Structs containing just a vector are passed like a vector. */ + type = s390_effective_inner_type (type, TYPE_LENGTH (type)); + + return TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type); +} + /* Determine whether N is a power of two. */ static int @@ -2434,8 +2469,8 @@ is_power_of_two (unsigned int n) } /* For an argument whose type is TYPE and which is not passed like a - float, return non-zero if it should be passed like "int" or "long - long". */ + float or vector, return non-zero if it should be passed like "int" + or "long long". */ static int s390_function_arg_integer (struct type *type) @@ -2465,9 +2500,9 @@ struct s390_arg_state { /* Register cache, or NULL, if we are in "preparation mode". */ struct regcache *regcache; - /* Next available general/floating-point register for argument - passing. */ - int gr, fr; + /* Next available general/floating-point/vector register for + argument passing. */ + int gr, fr, vr; /* Current pointer to copy area (grows downwards). */ CORE_ADDR copy; /* Current pointer to parameter area (grows upwards). */ @@ -2482,7 +2517,7 @@ struct s390_arg_state static void s390_handle_arg (struct s390_arg_state *as, struct value *arg, struct gdbarch_tdep *tdep, int word_size, - enum bfd_endian byte_order) + enum bfd_endian byte_order, int is_unnamed) { struct type *type = check_typedef (value_type (arg)); unsigned int length = TYPE_LENGTH (type); @@ -2514,6 +2549,28 @@ s390_handle_arg (struct s390_arg_state *as, struct value *arg, length); } } + else if (tdep->vector_abi == S390_VECTOR_ABI_128 + && s390_function_arg_vector (type)) + { + static const char use_vr[] = {24, 26, 28, 30, 25, 27, 29, 31}; + + if (!is_unnamed && as->vr < ARRAY_SIZE (use_vr)) + { + int regnum = S390_V24_REGNUM + use_vr[as->vr] - 24; + + if (write_mode) + regcache_cooked_write_part (as->regcache, regnum, + 0, length, + value_contents (arg)); + as->vr++; + } + else + { + if (write_mode) + write_memory (as->argp, value_contents (arg), length); + as->argp = align_up (as->argp + length, word_size); + } + } else if (s390_function_arg_integer (type) && length <= word_size) { ULONGEST val; @@ -2626,10 +2683,15 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function, int i; struct s390_arg_state arg_state, arg_prep; CORE_ADDR param_area_start, new_sp; + struct type *ftype = check_typedef (value_type (function)); + + if (TYPE_CODE (ftype) == TYPE_CODE_PTR) + ftype = check_typedef (TYPE_TARGET_TYPE (ftype)); arg_prep.copy = sp; arg_prep.gr = struct_return ? 3 : 2; arg_prep.fr = 0; + arg_prep.vr = 0; arg_prep.argp = 0; arg_prep.regcache = NULL; @@ -2639,7 +2701,8 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Update arg_state.copy with the start of the reference-to-copy area and arg_state.argp with the size of the parameter area. */ for (i = 0; i < nargs; i++) - s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order); + s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order, + TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype)); param_area_start = align_down (arg_state.copy - arg_state.argp, 8); @@ -2665,7 +2728,8 @@ s390_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Write all parameters. */ for (i = 0; i < nargs; i++) - s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order); + s390_handle_arg (&arg_state, args[i], tdep, word_size, byte_order, + TYPE_VARARGS (ftype) && i >= TYPE_NFIELDS (ftype)); /* Store return PSWA. In 31-bit mode, keep addressing mode bit. */ if (word_size == 4) @@ -2731,6 +2795,16 @@ s390_register_return_value (struct gdbarch *gdbarch, struct type *type, regcache_cooked_read_part (regcache, S390_F0_REGNUM, 0, length, out); } + else if (code == TYPE_CODE_ARRAY) + { + /* Vector: left-aligned in v24. */ + if (in != NULL) + regcache_cooked_write_part (regcache, S390_V24_REGNUM, + 0, length, in); + else + regcache_cooked_read_part (regcache, S390_V24_REGNUM, + 0, length, out); + } else if (length <= word_size) { /* Integer: zero- or sign-extended in r2. */ @@ -2782,10 +2856,15 @@ s390_return_value (struct gdbarch *gdbarch, struct value *function, { case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: - case TYPE_CODE_ARRAY: case TYPE_CODE_COMPLEX: rvc = RETURN_VALUE_STRUCT_CONVENTION; break; + case TYPE_CODE_ARRAY: + rvc = (gdbarch_tdep (gdbarch)->vector_abi == S390_VECTOR_ABI_128 + && TYPE_LENGTH (type) <= 16 && TYPE_VECTOR (type)) + ? RETURN_VALUE_REGISTER_CONVENTION + : RETURN_VALUE_STRUCT_CONVENTION; + break; default: rvc = TYPE_LENGTH (type) <= 8 ? RETURN_VALUE_REGISTER_CONVENTION @@ -2901,6 +2980,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) struct gdbarch *gdbarch; struct gdbarch_tdep *tdep; int tdep_abi; + enum s390_vector_abi_kind vector_abi; int have_upper = 0; int have_linux_v1 = 0; int have_linux_v2 = 0; @@ -3083,6 +3163,18 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } } + /* Determine vector ABI. */ + vector_abi = S390_VECTOR_ABI_NONE; +#ifdef HAVE_ELF + if (have_vx + && info.abfd != NULL + && info.abfd->format == bfd_object + && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour + && bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_GNU, + Tag_GNU_S390_ABI_Vector) == 2) + vector_abi = S390_VECTOR_ABI_128; +#endif + /* Find a candidate among extant architectures. */ for (arches = gdbarch_list_lookup_by_info (arches, &info); arches != NULL; @@ -3093,6 +3185,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) continue; if (tdep->abi != tdep_abi) continue; + if (tdep->vector_abi != vector_abi) + continue; if ((tdep->gpr_full_regnum != -1) != have_upper) continue; if (tdesc_data != NULL) @@ -3103,6 +3197,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Otherwise create a new gdbarch for the specified machine type. */ tdep = XCNEW (struct gdbarch_tdep); tdep->abi = tdep_abi; + tdep->vector_abi = vector_abi; tdep->have_linux_v1 = have_linux_v1; tdep->have_linux_v2 = have_linux_v2; tdep->have_tdb = have_tdb;