diff options
Diffstat (limited to 'meta/recipes-devtools/elfutils/elfutils-0.166/0002-Add-support-for-mips64-abis-in-mips_retval.c.patch')
-rw-r--r-- | meta/recipes-devtools/elfutils/elfutils-0.166/0002-Add-support-for-mips64-abis-in-mips_retval.c.patch | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/meta/recipes-devtools/elfutils/elfutils-0.166/0002-Add-support-for-mips64-abis-in-mips_retval.c.patch b/meta/recipes-devtools/elfutils/elfutils-0.166/0002-Add-support-for-mips64-abis-in-mips_retval.c.patch new file mode 100644 index 0000000000..72125c9ff0 --- /dev/null +++ b/meta/recipes-devtools/elfutils/elfutils-0.166/0002-Add-support-for-mips64-abis-in-mips_retval.c.patch | |||
@@ -0,0 +1,168 @@ | |||
1 | From fdaab18a65ed2529656baa64cb6169f34d7e507b Mon Sep 17 00:00:00 2001 | ||
2 | From: James Cowgill <james410@cowgill.org.uk> | ||
3 | Date: Mon, 5 Jan 2015 15:17:01 +0000 | ||
4 | Subject: [PATCH 2/3] Add support for mips64 abis in mips_retval.c | ||
5 | |||
6 | Signed-off-by: James Cowgill <james410@cowgill.org.uk> | ||
7 | --- | ||
8 | backends/mips_retval.c | 104 ++++++++++++++++++++++++++++++++++++++++++++----- | ||
9 | 1 file changed, 94 insertions(+), 10 deletions(-) | ||
10 | |||
11 | diff --git a/backends/mips_retval.c b/backends/mips_retval.c | ||
12 | index 33f12a7..d5c6ef0 100644 | ||
13 | --- a/backends/mips_retval.c | ||
14 | +++ b/backends/mips_retval.c | ||
15 | @@ -91,6 +91,8 @@ enum mips_abi find_mips_abi(Elf *elf) | ||
16 | default: | ||
17 | if ((elf_flags & EF_MIPS_ABI2)) | ||
18 | return MIPS_ABI_N32; | ||
19 | + else if ((ehdr->e_ident[EI_CLASS] == ELFCLASS64)) | ||
20 | + return MIPS_ABI_N64; | ||
21 | } | ||
22 | |||
23 | /* GCC creates a pseudo-section whose name describes the ABI. */ | ||
24 | @@ -195,6 +197,57 @@ static const Dwarf_Op loc_aggregate[] = | ||
25 | }; | ||
26 | #define nloc_aggregate 1 | ||
27 | |||
28 | +/* Test if a struct member is a float */ | ||
29 | +static int is_float_child(Dwarf_Die *childdie) | ||
30 | +{ | ||
31 | + /* Test if this is actually a struct member */ | ||
32 | + if (dwarf_tag(childdie) != DW_TAG_member) | ||
33 | + return 0; | ||
34 | + | ||
35 | + /* Get type of member */ | ||
36 | + Dwarf_Attribute attr_mem; | ||
37 | + Dwarf_Die child_type_mem; | ||
38 | + Dwarf_Die *child_typedie = | ||
39 | + dwarf_formref_die(dwarf_attr_integrate(childdie, | ||
40 | + DW_AT_type, | ||
41 | + &attr_mem), &child_type_mem); | ||
42 | + | ||
43 | + if (dwarf_tag(child_typedie) != DW_TAG_base_type) | ||
44 | + return 0; | ||
45 | + | ||
46 | + /* Get base subtype */ | ||
47 | + Dwarf_Word encoding; | ||
48 | + if (dwarf_formudata (dwarf_attr_integrate (child_typedie, | ||
49 | + DW_AT_encoding, | ||
50 | + &attr_mem), &encoding) != 0) | ||
51 | + return 0; | ||
52 | + | ||
53 | + return encoding == DW_ATE_float; | ||
54 | +} | ||
55 | + | ||
56 | +/* Returns the number of fpregs which can be returned in the given struct */ | ||
57 | +static int get_struct_fpregs(Dwarf_Die *structtypedie) | ||
58 | +{ | ||
59 | + Dwarf_Die child_mem; | ||
60 | + int fpregs = 0; | ||
61 | + | ||
62 | + /* Get first structure member */ | ||
63 | + if (dwarf_child(structtypedie, &child_mem) != 0) | ||
64 | + return 0; | ||
65 | + | ||
66 | + do | ||
67 | + { | ||
68 | + /* Ensure this register is a float */ | ||
69 | + if (!is_float_child(&child_mem)) | ||
70 | + return 0; | ||
71 | + | ||
72 | + fpregs++; | ||
73 | + } | ||
74 | + while (dwarf_siblingof (&child_mem, &child_mem) == 0); | ||
75 | + | ||
76 | + return fpregs; | ||
77 | +} | ||
78 | + | ||
79 | int | ||
80 | mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) | ||
81 | { | ||
82 | @@ -240,6 +293,7 @@ mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) | ||
83 | tag = dwarf_tag (typedie); | ||
84 | } | ||
85 | |||
86 | + Dwarf_Word size; | ||
87 | switch (tag) | ||
88 | { | ||
89 | case -1: | ||
90 | @@ -258,8 +312,6 @@ mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) | ||
91 | case DW_TAG_enumeration_type: | ||
92 | case DW_TAG_pointer_type: | ||
93 | case DW_TAG_ptr_to_member_type: | ||
94 | - { | ||
95 | - Dwarf_Word size; | ||
96 | if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size, | ||
97 | &attr_mem), &size) != 0) | ||
98 | { | ||
99 | @@ -289,7 +341,7 @@ mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) | ||
100 | if (size <= 4*regsize && abi == MIPS_ABI_O32) | ||
101 | return nloc_fpregquad; | ||
102 | |||
103 | - goto aggregate; | ||
104 | + goto large; | ||
105 | } | ||
106 | } | ||
107 | *locp = ABI_LOC(loc_intreg, regsize); | ||
108 | @@ -298,18 +350,50 @@ mips_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp) | ||
109 | if (size <= 2*regsize) | ||
110 | return nloc_intregpair; | ||
111 | |||
112 | - /* Else fall through. Shouldn't happen though (at least with gcc) */ | ||
113 | - } | ||
114 | + /* Else pass in memory. Shouldn't happen though (at least with gcc) */ | ||
115 | + goto large; | ||
116 | |||
117 | case DW_TAG_structure_type: | ||
118 | case DW_TAG_class_type: | ||
119 | case DW_TAG_union_type: | ||
120 | - case DW_TAG_array_type: | ||
121 | - aggregate: | ||
122 | - /* XXX TODO: Can't handle structure return with other ABI's yet :-/ */ | ||
123 | - if ((abi != MIPS_ABI_O32) && (abi != MIPS_ABI_O64)) | ||
124 | - return -2; | ||
125 | + /* Handle special cases for structures <= 128 bytes in newer ABIs */ | ||
126 | + if (abi == MIPS_ABI_EABI32 || abi == MIPS_ABI_EABI64 || | ||
127 | + abi == MIPS_ABI_N32 || abi == MIPS_ABI_N64) | ||
128 | + { | ||
129 | + if (dwarf_aggregate_size (typedie, &size) == 0 && size <= 16) | ||
130 | + { | ||
131 | + /* | ||
132 | + * Special case in N64 / N32 - | ||
133 | + * structures containing only floats are returned in fp regs. | ||
134 | + * Everything else is returned in integer regs. | ||
135 | + */ | ||
136 | + if (tag != DW_TAG_union_type && | ||
137 | + (abi == MIPS_ABI_N32 || abi == MIPS_ABI_N64)) | ||
138 | + { | ||
139 | + int num_fpregs = get_struct_fpregs(typedie); | ||
140 | + if (num_fpregs == 1 || num_fpregs == 2) | ||
141 | + { | ||
142 | + *locp = loc_fpreg; | ||
143 | + if (num_fpregs == 1) | ||
144 | + return nloc_fpreg; | ||
145 | + else | ||
146 | + return nloc_fpregpair; | ||
147 | + } | ||
148 | + } | ||
149 | + | ||
150 | + *locp = loc_intreg; | ||
151 | + if (size <= 8) | ||
152 | + return nloc_intreg; | ||
153 | + else | ||
154 | + return nloc_intregpair; | ||
155 | + } | ||
156 | + } | ||
157 | + | ||
158 | + /* Fallthrough to handle large types */ | ||
159 | |||
160 | + case DW_TAG_array_type: | ||
161 | + large: | ||
162 | + /* Return large structures in memory */ | ||
163 | *locp = loc_aggregate; | ||
164 | return nloc_aggregate; | ||
165 | } | ||
166 | -- | ||
167 | 2.1.4 | ||
168 | |||