103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Function return value location for Linux/AArch64 ABI. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2013 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of either 703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU Lesser General Public License as published by the Free 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 3 of the License, or (at 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes * the GNU General Public License as published by the Free 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Software Foundation; either version 2 of the License, or (at 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes your option) any later version 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes or both in parallel, as here. 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes WITHOUT ANY WARRANTY; without even the implied warranty of 2203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes General Public License for more details. 2403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received copies of the GNU General Public License and 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the GNU Lesser General Public License along with this program. If 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes not, see <http://www.gnu.org/licenses/>. */ 2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 2903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef HAVE_CONFIG_H 3003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes# include <config.h> 3103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif 3203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <stdio.h> 3403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <inttypes.h> 3503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <assert.h> 3703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <dwarf.h> 3803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define BACKEND aarch64_ 4003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include "libebl_CPU.h" 4103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 4303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesskip_until (Dwarf_Die *child, int tag) 4403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 4503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int i; 4603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (DWARF_TAG_OR_RETURN (child) != tag) 4703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((i = dwarf_siblingof (child, child)) != 0) 4803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* If there are no members, then this is not a HFA. Errors 4903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes are propagated. */ 5003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return i; 5103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 5203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 5303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 5503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdwarf_bytesize_aux (Dwarf_Die *die, Dwarf_Word *sizep) 5603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 5703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int bits; 5803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (((bits = 8 * dwarf_bytesize (die)) < 0 5903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && (bits = dwarf_bitsize (die)) < 0) 6003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || bits % 8 != 0) 6103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 6203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *sizep = bits / 8; 6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* HFA (Homogeneous Floating-point Aggregate) is an aggregate type 6803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes whose members are all of the same floating-point type, which is 6903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes then base type of this HFA. Instead of being floating-point types 7003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes directly, members can instead themselves be HFA. Such HFA fields 7103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes are handled as if their type were HFA base type. 7203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 7303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This function returns 0 if TYPEDIE is HFA, 1 if it is not, or -1 if 7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes there were errors. In the former case, *SIZEP contains byte size 7503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes of the base type (e.g. 8 for IEEE double). *COUNT is set to the 7603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes number of leaf members of the HFA. */ 7703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int hfa_type (Dwarf_Die *ftypedie, int tag, 7803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word *sizep, Dwarf_Word *countp); 7903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 8003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Return 0 if MEMBDIE refers to a member with a floating-point or HFA 8103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes type, or 1 if it's not. Return -1 for errors. The meaning of the 8203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes remaining arguments is as documented at hfa_type. */ 8303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 8403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesmember_is_fp (Dwarf_Die *membdie, Dwarf_Word *sizep, Dwarf_Word *countp) 8503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die typedie; 8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int tag = dwarf_peeled_die_type (membdie, &typedie); 8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (tag) 8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 9003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_base_type:; 9103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word encoding; 9203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr_mem; 9303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_attr_integrate (&typedie, DW_AT_encoding, &attr_mem) == NULL 9403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || dwarf_formudata (&attr_mem, &encoding) != 0) 9503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 9603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 9703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (encoding) 9803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 9903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_complex_float: 10003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *countp = 2; 10103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 10203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 10303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_float: 10403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *countp = 1; 10503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 10603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 10703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 10803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 1; 10903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 11003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 11103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_bytesize_aux (&typedie, sizep) < 0) 11203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 11303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 11403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *sizep /= *countp; 11503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 11603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 11703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_structure_type: 11803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_union_type: 11903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_TAG_array_type: 12003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return hfa_type (&typedie, tag, sizep, countp); 12103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 12203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 12303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 1; 12403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 12503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 12603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 12703333823c75a1c1887e923828113a1b0fd12020cElliott Hugheshfa_type (Dwarf_Die *ftypedie, int tag, Dwarf_Word *sizep, Dwarf_Word *countp) 12803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 12903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (tag == DW_TAG_structure_type || tag == DW_TAG_class_type 13003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || tag == DW_TAG_union_type || tag == DW_TAG_array_type); 13103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 13203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int i; 13303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_array_type) 13403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 13503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word tot_size; 13603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_aggregate_size (ftypedie, &tot_size) < 0) 13703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 13803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 13903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* For vector types, we don't care about the underlying 14003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes type, but only about the vector type itself. */ 14103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool vec; 14203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr_mem; 14303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formflag (dwarf_attr_integrate (ftypedie, DW_AT_GNU_vector, 14403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr_mem), &vec) == 0 14503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && vec) 14603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *sizep = tot_size; 14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *countp = 1; 14903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 15003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 15103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 15203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 15303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((i = member_is_fp (ftypedie, sizep, countp)) == 0) 15403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 15503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *countp = tot_size / *sizep; 15603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 15703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 15803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 15903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return i; 16003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 16103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 16203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Find first DW_TAG_member and determine its type. */ 16303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die member; 16403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((i = dwarf_child (ftypedie, &member) != 0)) 16503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return i; 16603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 16703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((i = skip_until (&member, DW_TAG_member)) != 0) 16803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return i; 16903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 17003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *countp = 0; 17103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((i = member_is_fp (&member, sizep, countp)) != 0) 17203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return i; 17303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 17403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while ((i = dwarf_siblingof (&member, &member)) == 0 17503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && (i = skip_until (&member, DW_TAG_member)) == 0) 17603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 17703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word size, count; 17803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((i = member_is_fp (&member, &size, &count)) != 0) 17903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return i; 18003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 18103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (*sizep != size) 18203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 1; 18303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 18403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *countp += count; 18503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 18603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 18703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* At this point we already have at least one FP member, which means 18803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes FTYPEDIE is an HFA. So either return 0, or propagate error. */ 18903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return i < 0 ? i : 0; 19003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 19103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 19203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 19303333823c75a1c1887e923828113a1b0fd12020cElliott Hughespass_in_gpr (const Dwarf_Op **locp, Dwarf_Word size) 19403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 19503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes static const Dwarf_Op loc[] = 19603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 19703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 }, 19803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 } 19903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes }; 20003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 20103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc; 20203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return size <= 8 ? 1 : 4; 20303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 20403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 20503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 20603333823c75a1c1887e923828113a1b0fd12020cElliott Hughespass_by_ref (const Dwarf_Op **locp) 20703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 20803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes static const Dwarf_Op loc[] = { { .atom = DW_OP_breg0 } }; 20903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 21003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc; 21103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 1; 21203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 21303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 21403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 21503333823c75a1c1887e923828113a1b0fd12020cElliott Hughespass_hfa (const Dwarf_Op **locp, Dwarf_Word size, Dwarf_Word count) 21603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 21703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (count >= 1 && count <= 4); 21803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (size == 2 || size == 4 || size == 8 || size == 16); 21903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 22003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define DEFINE_FPREG(NAME, SIZE) \ 22103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes static const Dwarf_Op NAME[] = { \ 22203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_regx, .number = 64 }, \ 22303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_piece, .number = SIZE }, \ 22403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_regx, .number = 65 }, \ 22503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_piece, .number = SIZE }, \ 22603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_regx, .number = 66 }, \ 22703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_piece, .number = SIZE }, \ 22803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_regx, .number = 67 }, \ 22903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { .atom = DW_OP_piece, .number = SIZE } \ 23003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 23103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 23203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (size) 23303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 23403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 2:; 23503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DEFINE_FPREG (loc_hfa_2, 2); 23603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc_hfa_2; 23703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 23803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 23903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 4:; 24003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DEFINE_FPREG (loc_hfa_4, 4); 24103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc_hfa_4; 24203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 24303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 24403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 8:; 24503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DEFINE_FPREG (loc_hfa_8, 8); 24603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc_hfa_8; 24703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 24803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 24903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 16:; 25003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DEFINE_FPREG (loc_hfa_16, 16); 25103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = loc_hfa_16; 25203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 25303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 25403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#undef DEFINE_FPREG 25503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 25603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return count == 1 ? 1 : 2 * count; 25703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 25803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 25903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 26003333823c75a1c1887e923828113a1b0fd12020cElliott Hughespass_in_simd (const Dwarf_Op **locp) 26103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 26203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* This is like passing single-element HFA. Size doesn't matter, so 26303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pretend it's for example double. */ 26403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return pass_hfa (locp, 8, 1); 26503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 26603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 26703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint 26803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesaarch64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) 26903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 27003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Start with the function's type, and get the DW_AT_type attribute, 27103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes which is the type of the return value. */ 27203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die typedie; 27303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int tag = dwarf_peeled_die_type (functypedie, &typedie); 27403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag <= 0) 27503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return tag; 27603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 27703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word size = (Dwarf_Word)-1; 27803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 27903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* If the argument type is a Composite Type that is larger than 16 28003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bytes, then the argument is copied to memory allocated by the 28103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes caller and the argument is replaced by a pointer to the copy. */ 28203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type 28303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || tag == DW_TAG_class_type || tag == DW_TAG_array_type) 28403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 28503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word base_size, count; 28603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (hfa_type (&typedie, tag, &base_size, &count)) 28703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 28803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 28903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 29003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 29103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 0: 29203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (count > 0); 29303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (count <= 4) 29403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return pass_hfa (locp, base_size, count); 29503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Fall through. */ 29603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 29703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 1: 29803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Not a HFA. */ 29903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_aggregate_size (&typedie, &size) < 0) 30003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 30103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (size > 16) 30203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return pass_by_ref (locp); 30303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 30403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 30503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 30603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_base_type 30703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type) 30803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 30903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_bytesize_aux (&typedie, &size) < 0) 31003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 31103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type) 31203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size = 8; 31303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 31403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 31503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 31603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 31703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr_mem; 31803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_base_type) 31903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 32003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word encoding; 32103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formudata (dwarf_attr_integrate (&typedie, DW_AT_encoding, 32203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr_mem), 32303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &encoding) != 0) 32403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 32503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 32603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (encoding) 32703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 32803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* If the argument is a Half-, Single-, Double- or Quad- 32903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes precision Floating-point [...] the argument is allocated 33003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes to the least significant bits of register v[NSRN]. */ 33103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_float: 33203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (size) 33303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 33403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 2: /* half */ 33503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 4: /* sigle */ 33603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 8: /* double */ 33703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 16: /* quad */ 33803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return pass_in_simd (locp); 33903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 34003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 34103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -2; 34203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 34303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 34403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_complex_float: 34503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (size) 34603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 34703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 8: /* float _Complex */ 34803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 16: /* double _Complex */ 34903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 32: /* long double _Complex */ 35003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return pass_hfa (locp, size / 2, 2); 35103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 35203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 35303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -2; 35403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 35503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 35603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* If the argument is an Integral or Pointer Type, the 35703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes size of the argument is less than or equal to 8 bytes 35803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes [...] the argument is copied to the least significant 35903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bits in x[NGRN]. */ 36003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_boolean: 36103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_signed: 36203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_unsigned: 36303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_unsigned_char: 36403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DW_ATE_signed_char: 36503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return pass_in_gpr (locp, size); 36603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 36703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 36803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -2; 36903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 37003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 37103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return pass_in_gpr (locp, size); 37203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 37303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 37403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes *locp = NULL; 37503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 37603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 377