From 4f4aedebed5397ba285c2abcd13fa0206d8af291 Mon Sep 17 00:00:00 2001 From: Alan Hayward Date: Wed, 29 Aug 2018 11:41:45 +0100 Subject: [PATCH] Aarch64: Float register detection for return values Use aapcs_is_vfp_call_or_return_candidate to detect float register args. gdb/ PR gdb/22943: * aarch64-tdep.c (is_hfa_or_hva): Remove function. (aarch64_extract_return_value): Use aapcs_is_vfp_call_or_return_candidate. (aarch64_return_in_memory): Likewise. (aarch64_store_return_value): Likewise. --- gdb/ChangeLog | 9 ++ gdb/aarch64-tdep.c | 200 +++++++++++---------------------------------- 2 files changed, 56 insertions(+), 153 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c06d1d4fd40..373e1b13b45 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2018-08-29 Alan Hayward + + PR gdb/22943: + * aarch64-tdep.c (is_hfa_or_hva): Remove function. + (aarch64_extract_return_value): Use + aapcs_is_vfp_call_or_return_candidate. + (aarch64_return_in_memory): Likewise. + (aarch64_store_return_value): Likewise. + 2018-08-29 Alan Hayward * aarch64-tdep.c diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index bfa0385417b..d2e6ac64d54 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1151,68 +1151,6 @@ aarch64_type_align (struct type *t) } } -/* Return 1 if *TY is a homogeneous floating-point aggregate or - homogeneous short-vector aggregate as defined in the AAPCS64 ABI - document; otherwise return 0. */ - -static int -is_hfa_or_hva (struct type *ty) -{ - switch (TYPE_CODE (ty)) - { - case TYPE_CODE_ARRAY: - { - struct type *target_ty = TYPE_TARGET_TYPE (ty); - - if (TYPE_VECTOR (ty)) - return 0; - - if (TYPE_LENGTH (ty) <= 4 /* HFA or HVA has at most 4 members. */ - && (TYPE_CODE (target_ty) == TYPE_CODE_FLT /* HFA */ - || (TYPE_CODE (target_ty) == TYPE_CODE_ARRAY /* HVA */ - && TYPE_VECTOR (target_ty)))) - return 1; - break; - } - - case TYPE_CODE_UNION: - case TYPE_CODE_STRUCT: - { - /* HFA or HVA has at most four members. */ - if (TYPE_NFIELDS (ty) > 0 && TYPE_NFIELDS (ty) <= 4) - { - struct type *member0_type; - - member0_type = check_typedef (TYPE_FIELD_TYPE (ty, 0)); - if (TYPE_CODE (member0_type) == TYPE_CODE_FLT - || (TYPE_CODE (member0_type) == TYPE_CODE_ARRAY - && TYPE_VECTOR (member0_type))) - { - int i; - - for (i = 0; i < TYPE_NFIELDS (ty); i++) - { - struct type *member1_type; - - member1_type = check_typedef (TYPE_FIELD_TYPE (ty, i)); - if (TYPE_CODE (member0_type) != TYPE_CODE (member1_type) - || (TYPE_LENGTH (member0_type) - != TYPE_LENGTH (member1_type))) - return 0; - } - return 1; - } - } - return 0; - } - - default: - break; - } - - return 0; -} - /* Worker function for aapcs_is_vfp_call_or_return_candidate. Return the number of register required, or -1 on failure. @@ -1988,14 +1926,30 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs, { struct gdbarch *gdbarch = regs->arch (); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int elements; + struct type *fundamental_type; - if (TYPE_CODE (type) == TYPE_CODE_FLT) + if (aapcs_is_vfp_call_or_return_candidate (type, &elements, + &fundamental_type)) { - bfd_byte buf[V_REGISTER_SIZE]; - int len = TYPE_LENGTH (type); + int len = TYPE_LENGTH (fundamental_type); - regs->cooked_read (AARCH64_V0_REGNUM, buf); - memcpy (valbuf, buf, len); + for (int i = 0; i < elements; i++) + { + int regno = AARCH64_V0_REGNUM + i; + bfd_byte buf[V_REGISTER_SIZE]; + + if (aarch64_debug) + { + debug_printf ("read HFA or HVA return value element %d from %s\n", + i + 1, + gdbarch_register_name (gdbarch, regno)); + } + regs->cooked_read (regno, buf); + + memcpy (valbuf, buf, len); + valbuf += len; + } } else if (TYPE_CODE (type) == TYPE_CODE_INT || TYPE_CODE (type) == TYPE_CODE_CHAR @@ -2023,53 +1977,6 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs, valbuf += X_REGISTER_SIZE; } } - else if (TYPE_CODE (type) == TYPE_CODE_COMPLEX) - { - int regno = AARCH64_V0_REGNUM; - bfd_byte buf[V_REGISTER_SIZE]; - struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type)); - int len = TYPE_LENGTH (target_type); - - regs->cooked_read (regno, buf); - memcpy (valbuf, buf, len); - valbuf += len; - regs->cooked_read (regno + 1, buf); - memcpy (valbuf, buf, len); - valbuf += len; - } - else if (is_hfa_or_hva (type)) - { - int elements = TYPE_NFIELDS (type); - struct type *member_type = check_typedef (TYPE_FIELD_TYPE (type, 0)); - int len = TYPE_LENGTH (member_type); - int i; - - for (i = 0; i < elements; i++) - { - int regno = AARCH64_V0_REGNUM + i; - bfd_byte buf[V_REGISTER_SIZE]; - - if (aarch64_debug) - { - debug_printf ("read HFA or HVA return value element %d from %s\n", - i + 1, - gdbarch_register_name (gdbarch, regno)); - } - regs->cooked_read (regno, buf); - - memcpy (valbuf, buf, len); - valbuf += len; - } - } - else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) - && (TYPE_LENGTH (type) == 16 || TYPE_LENGTH (type) == 8)) - { - /* Short vector is returned in V register. */ - gdb_byte buf[V_REGISTER_SIZE]; - - regs->cooked_read (AARCH64_V0_REGNUM, buf); - memcpy (valbuf, buf, TYPE_LENGTH (type)); - } else { /* For a structure or union the behaviour is as if the value had @@ -2098,8 +2005,11 @@ static int aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type) { type = check_typedef (type); + int elements; + struct type *fundamental_type; - if (is_hfa_or_hva (type)) + if (aapcs_is_vfp_call_or_return_candidate (type, &elements, + &fundamental_type)) { /* v0-v7 are used to return values and one register is allocated for one member. However, HFA or HVA has at most four members. */ @@ -2126,14 +2036,31 @@ aarch64_store_return_value (struct type *type, struct regcache *regs, { struct gdbarch *gdbarch = regs->arch (); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int elements; + struct type *fundamental_type; - if (TYPE_CODE (type) == TYPE_CODE_FLT) + if (aapcs_is_vfp_call_or_return_candidate (type, &elements, + &fundamental_type)) { - bfd_byte buf[V_REGISTER_SIZE]; - int len = TYPE_LENGTH (type); + int len = TYPE_LENGTH (fundamental_type); + + for (int i = 0; i < elements; i++) + { + int regno = AARCH64_V0_REGNUM + i; + bfd_byte tmpbuf[V_REGISTER_SIZE]; + + if (aarch64_debug) + { + debug_printf ("write HFA or HVA return value element %d to %s\n", + i + 1, + gdbarch_register_name (gdbarch, regno)); + } - memcpy (buf, valbuf, len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len); - regs->cooked_write (AARCH64_V0_REGNUM, buf); + memcpy (tmpbuf, valbuf, + len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len); + regs->cooked_write (regno, tmpbuf); + valbuf += len; + } } else if (TYPE_CODE (type) == TYPE_CODE_INT || TYPE_CODE (type) == TYPE_CODE_CHAR @@ -2168,39 +2095,6 @@ aarch64_store_return_value (struct type *type, struct regcache *regs, } } } - else if (is_hfa_or_hva (type)) - { - int elements = TYPE_NFIELDS (type); - struct type *member_type = check_typedef (TYPE_FIELD_TYPE (type, 0)); - int len = TYPE_LENGTH (member_type); - int i; - - for (i = 0; i < elements; i++) - { - int regno = AARCH64_V0_REGNUM + i; - bfd_byte tmpbuf[V_REGISTER_SIZE]; - - if (aarch64_debug) - { - debug_printf ("write HFA or HVA return value element %d to %s\n", - i + 1, - gdbarch_register_name (gdbarch, regno)); - } - - memcpy (tmpbuf, valbuf, len); - regs->cooked_write (regno, tmpbuf); - valbuf += len; - } - } - else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type) - && (TYPE_LENGTH (type) == 8 || TYPE_LENGTH (type) == 16)) - { - /* Short vector. */ - gdb_byte buf[V_REGISTER_SIZE]; - - memcpy (buf, valbuf, TYPE_LENGTH (type)); - regs->cooked_write (AARCH64_V0_REGNUM, buf); - } else { /* For a structure or union the behaviour is as if the value had -- 2.30.2