|
1 --- mozilla/js/src/ctypes/libffi/src/powerpc/aix.S 2013-10-24 09:56:51.844587814 +0200 |
|
2 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/aix.S 2013-11-29 17:23:26.000000000 +0100 |
|
3 @@ -1,5 +1,5 @@ |
|
4 /* ----------------------------------------------------------------------- |
|
5 - aix.S - Copyright (c) 2002,2009 Free Software Foundation, Inc. |
|
6 + aix.S - Copyright (c) 2002, 2009 Free Software Foundation, Inc. |
|
7 based on darwin.S by John Hornkvist |
|
8 |
|
9 PowerPC Assembly glue. |
|
10 @@ -79,6 +79,8 @@ |
|
11 .set f20,20 |
|
12 .set f21,21 |
|
13 |
|
14 + .extern .ffi_prep_args |
|
15 + |
|
16 #define LIBFFI_ASM |
|
17 #include <fficonfig.h> |
|
18 #include <ffi.h> |
|
19 @@ -125,6 +127,7 @@ ffi_call_AIX: |
|
20 /* Call ffi_prep_args. */ |
|
21 mr r4, r1 |
|
22 bl .ffi_prep_args |
|
23 + nop |
|
24 |
|
25 /* Now do the call. */ |
|
26 ld r0, 0(r29) |
|
27 @@ -226,6 +229,7 @@ L(float_return_value): |
|
28 /* Call ffi_prep_args. */ |
|
29 mr r4, r1 |
|
30 bl .ffi_prep_args |
|
31 + nop |
|
32 |
|
33 /* Now do the call. */ |
|
34 lwz r0, 0(r29) |
|
35 --- mozilla/js/src/ctypes/libffi/src/powerpc/ffi.c 2013-10-24 09:56:51.846587814 +0200 |
|
36 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/ffi.c 2013-11-29 17:23:26.000000000 +0100 |
|
37 @@ -1,7 +1,9 @@ |
|
38 /* ----------------------------------------------------------------------- |
|
39 - ffi.c - Copyright (c) 1998 Geoffrey Keating |
|
40 - Copyright (C) 2007, 2008 Free Software Foundation, Inc |
|
41 - Copyright (C) 2008 Red Hat, Inc |
|
42 + ffi.c - Copyright (C) 2011 Anthony Green |
|
43 + Copyright (C) 2011 Kyle Moffett |
|
44 + Copyright (C) 2008 Red Hat, Inc |
|
45 + Copyright (C) 2007, 2008 Free Software Foundation, Inc |
|
46 + Copyright (c) 1998 Geoffrey Keating |
|
47 |
|
48 PowerPC Foreign Function Interface |
|
49 |
|
50 @@ -39,32 +41,29 @@ enum { |
|
51 /* The assembly depends on these exact flags. */ |
|
52 FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */ |
|
53 FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ |
|
54 +#ifndef __NO_FPRS__ |
|
55 FLAG_RETURNS_FP = 1 << (31-29), |
|
56 +#endif |
|
57 FLAG_RETURNS_64BITS = 1 << (31-28), |
|
58 |
|
59 FLAG_RETURNS_128BITS = 1 << (31-27), /* cr6 */ |
|
60 - FLAG_SYSV_SMST_R4 = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte |
|
61 - structs. */ |
|
62 - FLAG_SYSV_SMST_R3 = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte |
|
63 - structs. */ |
|
64 - /* Bits (31-24) through (31-19) store shift value for SMST */ |
|
65 |
|
66 FLAG_ARG_NEEDS_COPY = 1 << (31- 7), |
|
67 + FLAG_ARG_NEEDS_PSAVE = FLAG_ARG_NEEDS_COPY, /* Used by ELFv2 */ |
|
68 +#ifndef __NO_FPRS__ |
|
69 FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ |
|
70 +#endif |
|
71 FLAG_4_GPR_ARGUMENTS = 1 << (31- 5), |
|
72 FLAG_RETVAL_REFERENCE = 1 << (31- 4) |
|
73 }; |
|
74 |
|
75 /* About the SYSV ABI. */ |
|
76 -unsigned int NUM_GPR_ARG_REGISTERS = 8; |
|
77 +#define ASM_NEEDS_REGISTERS 4 |
|
78 +#define NUM_GPR_ARG_REGISTERS 8 |
|
79 #ifndef __NO_FPRS__ |
|
80 -unsigned int NUM_FPR_ARG_REGISTERS = 8; |
|
81 -#else |
|
82 -unsigned int NUM_FPR_ARG_REGISTERS = 0; |
|
83 +# define NUM_FPR_ARG_REGISTERS 8 |
|
84 #endif |
|
85 |
|
86 -enum { ASM_NEEDS_REGISTERS = 4 }; |
|
87 - |
|
88 /* ffi_prep_args_SYSV is called by the assembly routine once stack space |
|
89 has been allocated for the function's arguments. |
|
90 |
|
91 @@ -113,10 +112,12 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
92 valp gpr_base; |
|
93 int intarg_count; |
|
94 |
|
95 +#ifndef __NO_FPRS__ |
|
96 /* 'fpr_base' points at the space for fpr1, and grows upwards as |
|
97 we use FPR registers. */ |
|
98 valp fpr_base; |
|
99 int fparg_count; |
|
100 +#endif |
|
101 |
|
102 /* 'copy_space' grows down as we put structures in it. It should |
|
103 stay 16-byte aligned. */ |
|
104 @@ -125,9 +126,11 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
105 /* 'next_arg' grows up as we put parameters in it. */ |
|
106 valp next_arg; |
|
107 |
|
108 - int i, ii MAYBE_UNUSED; |
|
109 + int i; |
|
110 ffi_type **ptr; |
|
111 +#ifndef __NO_FPRS__ |
|
112 double double_tmp; |
|
113 +#endif |
|
114 union { |
|
115 void **v; |
|
116 char **c; |
|
117 @@ -143,21 +146,22 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
118 size_t struct_copy_size; |
|
119 unsigned gprvalue; |
|
120 |
|
121 - if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
122 - NUM_FPR_ARG_REGISTERS = 0; |
|
123 - |
|
124 stacktop.c = (char *) stack + bytes; |
|
125 gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS; |
|
126 intarg_count = 0; |
|
127 +#ifndef __NO_FPRS__ |
|
128 fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS; |
|
129 fparg_count = 0; |
|
130 copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c); |
|
131 +#else |
|
132 + copy_space.c = gpr_base.c; |
|
133 +#endif |
|
134 next_arg.u = stack + 2; |
|
135 |
|
136 /* Check that everything starts aligned properly. */ |
|
137 - FFI_ASSERT (((unsigned) (char *) stack & 0xF) == 0); |
|
138 - FFI_ASSERT (((unsigned) copy_space.c & 0xF) == 0); |
|
139 - FFI_ASSERT (((unsigned) stacktop.c & 0xF) == 0); |
|
140 + FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0); |
|
141 + FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0); |
|
142 + FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0); |
|
143 FFI_ASSERT ((bytes & 0xF) == 0); |
|
144 FFI_ASSERT (copy_space.c >= next_arg.c); |
|
145 |
|
146 @@ -174,12 +178,28 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
147 i > 0; |
|
148 i--, ptr++, p_argv.v++) |
|
149 { |
|
150 - switch ((*ptr)->type) |
|
151 - { |
|
152 + unsigned short typenum = (*ptr)->type; |
|
153 + |
|
154 + /* We may need to handle some values depending on ABI */ |
|
155 + if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) { |
|
156 + if (typenum == FFI_TYPE_FLOAT) |
|
157 + typenum = FFI_TYPE_UINT32; |
|
158 + if (typenum == FFI_TYPE_DOUBLE) |
|
159 + typenum = FFI_TYPE_UINT64; |
|
160 + if (typenum == FFI_TYPE_LONGDOUBLE) |
|
161 + typenum = FFI_TYPE_UINT128; |
|
162 + } else if (ecif->cif->abi != FFI_LINUX) { |
|
163 +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
164 + if (typenum == FFI_TYPE_LONGDOUBLE) |
|
165 + typenum = FFI_TYPE_STRUCT; |
|
166 +#endif |
|
167 + } |
|
168 + |
|
169 + /* Now test the translated value */ |
|
170 + switch (typenum) { |
|
171 +#ifndef __NO_FPRS__ |
|
172 case FFI_TYPE_FLOAT: |
|
173 /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */ |
|
174 - if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
175 - goto soft_float_prep; |
|
176 double_tmp = **p_argv.f; |
|
177 if (fparg_count >= NUM_FPR_ARG_REGISTERS) |
|
178 { |
|
179 @@ -195,8 +215,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
180 |
|
181 case FFI_TYPE_DOUBLE: |
|
182 /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */ |
|
183 - if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
184 - goto soft_double_prep; |
|
185 double_tmp = **p_argv.d; |
|
186 |
|
187 if (fparg_count >= NUM_FPR_ARG_REGISTERS) |
|
188 @@ -218,43 +236,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
189 |
|
190 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
191 case FFI_TYPE_LONGDOUBLE: |
|
192 - if ((ecif->cif->abi != FFI_LINUX) |
|
193 - && (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT)) |
|
194 - goto do_struct; |
|
195 - /* The soft float ABI for long doubles works like this, |
|
196 - a long double is passed in four consecutive gprs if available. |
|
197 - A maximum of 2 long doubles can be passed in gprs. |
|
198 - If we do not have 4 gprs left, the long double is passed on the |
|
199 - stack, 4-byte aligned. */ |
|
200 - if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
201 - { |
|
202 - unsigned int int_tmp = (*p_argv.ui)[0]; |
|
203 - if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) |
|
204 - { |
|
205 - if (intarg_count < NUM_GPR_ARG_REGISTERS) |
|
206 - intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count; |
|
207 - *next_arg.u = int_tmp; |
|
208 - next_arg.u++; |
|
209 - for (ii = 1; ii < 4; ii++) |
|
210 - { |
|
211 - int_tmp = (*p_argv.ui)[ii]; |
|
212 - *next_arg.u = int_tmp; |
|
213 - next_arg.u++; |
|
214 - } |
|
215 - } |
|
216 - else |
|
217 - { |
|
218 - *gpr_base.u++ = int_tmp; |
|
219 - for (ii = 1; ii < 4; ii++) |
|
220 - { |
|
221 - int_tmp = (*p_argv.ui)[ii]; |
|
222 - *gpr_base.u++ = int_tmp; |
|
223 - } |
|
224 - } |
|
225 - intarg_count +=4; |
|
226 - } |
|
227 - else |
|
228 - { |
|
229 double_tmp = (*p_argv.d)[0]; |
|
230 |
|
231 if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1) |
|
232 @@ -280,13 +261,40 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
233 |
|
234 fparg_count += 2; |
|
235 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); |
|
236 - } |
|
237 break; |
|
238 #endif |
|
239 +#endif /* have FPRs */ |
|
240 + |
|
241 + /* |
|
242 + * The soft float ABI for long doubles works like this, a long double |
|
243 + * is passed in four consecutive GPRs if available. A maximum of 2 |
|
244 + * long doubles can be passed in gprs. If we do not have 4 GPRs |
|
245 + * left, the long double is passed on the stack, 4-byte aligned. |
|
246 + */ |
|
247 + case FFI_TYPE_UINT128: { |
|
248 + unsigned int int_tmp = (*p_argv.ui)[0]; |
|
249 + unsigned int ii; |
|
250 + if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3) { |
|
251 + if (intarg_count < NUM_GPR_ARG_REGISTERS) |
|
252 + intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count; |
|
253 + *(next_arg.u++) = int_tmp; |
|
254 + for (ii = 1; ii < 4; ii++) { |
|
255 + int_tmp = (*p_argv.ui)[ii]; |
|
256 + *(next_arg.u++) = int_tmp; |
|
257 + } |
|
258 + } else { |
|
259 + *(gpr_base.u++) = int_tmp; |
|
260 + for (ii = 1; ii < 4; ii++) { |
|
261 + int_tmp = (*p_argv.ui)[ii]; |
|
262 + *(gpr_base.u++) = int_tmp; |
|
263 + } |
|
264 + } |
|
265 + intarg_count += 4; |
|
266 + break; |
|
267 + } |
|
268 |
|
269 case FFI_TYPE_UINT64: |
|
270 case FFI_TYPE_SINT64: |
|
271 - soft_double_prep: |
|
272 if (intarg_count == NUM_GPR_ARG_REGISTERS-1) |
|
273 intarg_count++; |
|
274 if (intarg_count >= NUM_GPR_ARG_REGISTERS) |
|
275 @@ -319,9 +327,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
276 break; |
|
277 |
|
278 case FFI_TYPE_STRUCT: |
|
279 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
280 - do_struct: |
|
281 -#endif |
|
282 struct_copy_size = ((*ptr)->size + 15) & ~0xF; |
|
283 copy_space.c -= struct_copy_size; |
|
284 memcpy (copy_space.c, *p_argv.c, (*ptr)->size); |
|
285 @@ -349,7 +354,6 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
286 case FFI_TYPE_UINT32: |
|
287 case FFI_TYPE_SINT32: |
|
288 case FFI_TYPE_POINTER: |
|
289 - soft_float_prep: |
|
290 |
|
291 gprvalue = **p_argv.ui; |
|
292 |
|
293 @@ -366,8 +370,16 @@ ffi_prep_args_SYSV (extended_cif *ecif, |
|
294 /* Check that we didn't overrun the stack... */ |
|
295 FFI_ASSERT (copy_space.c >= next_arg.c); |
|
296 FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS); |
|
297 + /* The assert below is testing that the number of integer arguments agrees |
|
298 + with the number found in ffi_prep_cif_machdep(). However, intarg_count |
|
299 + is incremented whenever we place an FP arg on the stack, so account for |
|
300 + that before our assert test. */ |
|
301 +#ifndef __NO_FPRS__ |
|
302 + if (fparg_count > NUM_FPR_ARG_REGISTERS) |
|
303 + intarg_count -= fparg_count - NUM_FPR_ARG_REGISTERS; |
|
304 FFI_ASSERT (fpr_base.u |
|
305 <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); |
|
306 +#endif |
|
307 FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); |
|
308 } |
|
309 |
|
310 @@ -378,6 +390,45 @@ enum { |
|
311 }; |
|
312 enum { ASM_NEEDS_REGISTERS64 = 4 }; |
|
313 |
|
314 +#if _CALL_ELF == 2 |
|
315 +static unsigned int |
|
316 +discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) |
|
317 +{ |
|
318 + switch (t->type) |
|
319 + { |
|
320 + case FFI_TYPE_FLOAT: |
|
321 + case FFI_TYPE_DOUBLE: |
|
322 + *elnum = 1; |
|
323 + return (int) t->type; |
|
324 + |
|
325 + case FFI_TYPE_STRUCT:; |
|
326 + { |
|
327 + unsigned int base_elt = 0, total_elnum = 0; |
|
328 + ffi_type **el = t->elements; |
|
329 + while (*el) |
|
330 + { |
|
331 + unsigned int el_elt, el_elnum = 0; |
|
332 + el_elt = discover_homogeneous_aggregate (*el, &el_elnum); |
|
333 + if (el_elt == 0 |
|
334 + || (base_elt && base_elt != el_elt)) |
|
335 + return 0; |
|
336 + base_elt = el_elt; |
|
337 + total_elnum += el_elnum; |
|
338 + if (total_elnum > 8) |
|
339 + return 0; |
|
340 + el++; |
|
341 + } |
|
342 + *elnum = total_elnum; |
|
343 + return base_elt; |
|
344 + } |
|
345 + |
|
346 + default: |
|
347 + return 0; |
|
348 + } |
|
349 +} |
|
350 +#endif |
|
351 + |
|
352 + |
|
353 /* ffi_prep_args64 is called by the assembly routine once stack space |
|
354 has been allocated for the function's arguments. |
|
355 |
|
356 @@ -423,6 +474,7 @@ ffi_prep_args64 (extended_cif *ecif, uns |
|
357 unsigned long *ul; |
|
358 float *f; |
|
359 double *d; |
|
360 + size_t p; |
|
361 } valp; |
|
362 |
|
363 /* 'stacktop' points at the previous backchain pointer. */ |
|
364 @@ -438,9 +490,9 @@ ffi_prep_args64 (extended_cif *ecif, uns |
|
365 /* 'fpr_base' points at the space for fpr3, and grows upwards as |
|
366 we use FPR registers. */ |
|
367 valp fpr_base; |
|
368 - int fparg_count; |
|
369 + unsigned int fparg_count; |
|
370 |
|
371 - int i, words; |
|
372 + unsigned int i, words, nargs, nfixedargs; |
|
373 ffi_type **ptr; |
|
374 double double_tmp; |
|
375 union { |
|
376 @@ -457,11 +509,18 @@ ffi_prep_args64 (extended_cif *ecif, uns |
|
377 double **d; |
|
378 } p_argv; |
|
379 unsigned long gprvalue; |
|
380 +#ifdef __STRUCT_PARM_ALIGN__ |
|
381 + unsigned long align; |
|
382 +#endif |
|
383 |
|
384 stacktop.c = (char *) stack + bytes; |
|
385 gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64; |
|
386 gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64; |
|
387 +#if _CALL_ELF == 2 |
|
388 + rest.ul = stack + 4 + NUM_GPR_ARG_REGISTERS64; |
|
389 +#else |
|
390 rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64; |
|
391 +#endif |
|
392 fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64; |
|
393 fparg_count = 0; |
|
394 next_arg.ul = gpr_base.ul; |
|
395 @@ -477,30 +536,36 @@ ffi_prep_args64 (extended_cif *ecif, uns |
|
396 |
|
397 /* Now for the arguments. */ |
|
398 p_argv.v = ecif->avalue; |
|
399 - for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; |
|
400 - i > 0; |
|
401 - i--, ptr++, p_argv.v++) |
|
402 + nargs = ecif->cif->nargs; |
|
403 + nfixedargs = ecif->cif->nfixedargs; |
|
404 + for (ptr = ecif->cif->arg_types, i = 0; |
|
405 + i < nargs; |
|
406 + i++, ptr++, p_argv.v++) |
|
407 { |
|
408 + unsigned int elt, elnum; |
|
409 + |
|
410 switch ((*ptr)->type) |
|
411 { |
|
412 case FFI_TYPE_FLOAT: |
|
413 double_tmp = **p_argv.f; |
|
414 - *next_arg.f = (float) double_tmp; |
|
415 + if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) |
|
416 + *fpr_base.d++ = double_tmp; |
|
417 + else |
|
418 + *next_arg.f = (float) double_tmp; |
|
419 if (++next_arg.ul == gpr_end.ul) |
|
420 next_arg.ul = rest.ul; |
|
421 - if (fparg_count < NUM_FPR_ARG_REGISTERS64) |
|
422 - *fpr_base.d++ = double_tmp; |
|
423 fparg_count++; |
|
424 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); |
|
425 break; |
|
426 |
|
427 case FFI_TYPE_DOUBLE: |
|
428 double_tmp = **p_argv.d; |
|
429 - *next_arg.d = double_tmp; |
|
430 + if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) |
|
431 + *fpr_base.d++ = double_tmp; |
|
432 + else |
|
433 + *next_arg.d = double_tmp; |
|
434 if (++next_arg.ul == gpr_end.ul) |
|
435 next_arg.ul = rest.ul; |
|
436 - if (fparg_count < NUM_FPR_ARG_REGISTERS64) |
|
437 - *fpr_base.d++ = double_tmp; |
|
438 fparg_count++; |
|
439 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); |
|
440 break; |
|
441 @@ -508,18 +573,20 @@ ffi_prep_args64 (extended_cif *ecif, uns |
|
442 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
443 case FFI_TYPE_LONGDOUBLE: |
|
444 double_tmp = (*p_argv.d)[0]; |
|
445 - *next_arg.d = double_tmp; |
|
446 + if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) |
|
447 + *fpr_base.d++ = double_tmp; |
|
448 + else |
|
449 + *next_arg.d = double_tmp; |
|
450 if (++next_arg.ul == gpr_end.ul) |
|
451 next_arg.ul = rest.ul; |
|
452 - if (fparg_count < NUM_FPR_ARG_REGISTERS64) |
|
453 - *fpr_base.d++ = double_tmp; |
|
454 fparg_count++; |
|
455 double_tmp = (*p_argv.d)[1]; |
|
456 - *next_arg.d = double_tmp; |
|
457 + if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) |
|
458 + *fpr_base.d++ = double_tmp; |
|
459 + else |
|
460 + *next_arg.d = double_tmp; |
|
461 if (++next_arg.ul == gpr_end.ul) |
|
462 next_arg.ul = rest.ul; |
|
463 - if (fparg_count < NUM_FPR_ARG_REGISTERS64) |
|
464 - *fpr_base.d++ = double_tmp; |
|
465 fparg_count++; |
|
466 FFI_ASSERT (__LDBL_MANT_DIG__ == 106); |
|
467 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); |
|
468 @@ -527,27 +594,86 @@ ffi_prep_args64 (extended_cif *ecif, uns |
|
469 #endif |
|
470 |
|
471 case FFI_TYPE_STRUCT: |
|
472 - words = ((*ptr)->size + 7) / 8; |
|
473 - if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) |
|
474 +#ifdef __STRUCT_PARM_ALIGN__ |
|
475 + align = (*ptr)->alignment; |
|
476 + if (align > __STRUCT_PARM_ALIGN__) |
|
477 + align = __STRUCT_PARM_ALIGN__; |
|
478 + if (align > 1) |
|
479 + next_arg.p = ALIGN (next_arg.p, align); |
|
480 +#endif |
|
481 + elt = 0; |
|
482 +#if _CALL_ELF == 2 |
|
483 + elt = discover_homogeneous_aggregate (*ptr, &elnum); |
|
484 +#endif |
|
485 + if (elt) |
|
486 { |
|
487 - size_t first = gpr_end.c - next_arg.c; |
|
488 - memcpy (next_arg.c, *p_argv.c, first); |
|
489 - memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first); |
|
490 - next_arg.c = rest.c + words * 8 - first; |
|
491 + union { |
|
492 + void *v; |
|
493 + float *f; |
|
494 + double *d; |
|
495 + } arg; |
|
496 + |
|
497 + arg.v = *p_argv.v; |
|
498 + if (elt == FFI_TYPE_FLOAT) |
|
499 + { |
|
500 + do |
|
501 + { |
|
502 + double_tmp = *arg.f++; |
|
503 + if (fparg_count < NUM_FPR_ARG_REGISTERS64 |
|
504 + && i < nfixedargs) |
|
505 + *fpr_base.d++ = double_tmp; |
|
506 + else |
|
507 + *next_arg.f = (float) double_tmp; |
|
508 + if (++next_arg.f == gpr_end.f) |
|
509 + next_arg.f = rest.f; |
|
510 + fparg_count++; |
|
511 + } |
|
512 + while (--elnum != 0); |
|
513 + if ((next_arg.p & 3) != 0) |
|
514 + { |
|
515 + if (++next_arg.f == gpr_end.f) |
|
516 + next_arg.f = rest.f; |
|
517 + } |
|
518 + } |
|
519 + else |
|
520 + do |
|
521 + { |
|
522 + double_tmp = *arg.d++; |
|
523 + if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) |
|
524 + *fpr_base.d++ = double_tmp; |
|
525 + else |
|
526 + *next_arg.d = double_tmp; |
|
527 + if (++next_arg.d == gpr_end.d) |
|
528 + next_arg.d = rest.d; |
|
529 + fparg_count++; |
|
530 + } |
|
531 + while (--elnum != 0); |
|
532 } |
|
533 else |
|
534 { |
|
535 - char *where = next_arg.c; |
|
536 - |
|
537 - /* Structures with size less than eight bytes are passed |
|
538 - left-padded. */ |
|
539 - if ((*ptr)->size < 8) |
|
540 - where += 8 - (*ptr)->size; |
|
541 + words = ((*ptr)->size + 7) / 8; |
|
542 + if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) |
|
543 + { |
|
544 + size_t first = gpr_end.c - next_arg.c; |
|
545 + memcpy (next_arg.c, *p_argv.c, first); |
|
546 + memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first); |
|
547 + next_arg.c = rest.c + words * 8 - first; |
|
548 + } |
|
549 + else |
|
550 + { |
|
551 + char *where = next_arg.c; |
|
552 |
|
553 - memcpy (where, *p_argv.c, (*ptr)->size); |
|
554 - next_arg.ul += words; |
|
555 - if (next_arg.ul == gpr_end.ul) |
|
556 - next_arg.ul = rest.ul; |
|
557 +#ifndef __LITTLE_ENDIAN__ |
|
558 + /* Structures with size less than eight bytes are passed |
|
559 + left-padded. */ |
|
560 + if ((*ptr)->size < 8) |
|
561 + where += 8 - (*ptr)->size; |
|
562 +#endif |
|
563 + memcpy (where, *p_argv.c, (*ptr)->size); |
|
564 + next_arg.ul += words; |
|
565 + if (next_arg.ul == gpr_end.ul) |
|
566 + next_arg.ul = rest.ul; |
|
567 + } |
|
568 } |
|
569 break; |
|
570 |
|
571 @@ -591,27 +717,22 @@ ffi_prep_args64 (extended_cif *ecif, uns |
|
572 |
|
573 |
|
574 /* Perform machine dependent cif processing */ |
|
575 -ffi_status |
|
576 -ffi_prep_cif_machdep (ffi_cif *cif) |
|
577 +static ffi_status |
|
578 +ffi_prep_cif_machdep_core (ffi_cif *cif) |
|
579 { |
|
580 /* All this is for the SYSV and LINUX64 ABI. */ |
|
581 - int i; |
|
582 ffi_type **ptr; |
|
583 unsigned bytes; |
|
584 - int fparg_count = 0, intarg_count = 0; |
|
585 - unsigned flags = 0; |
|
586 + unsigned i, fparg_count = 0, intarg_count = 0; |
|
587 + unsigned flags = cif->flags; |
|
588 unsigned struct_copy_size = 0; |
|
589 unsigned type = cif->rtype->type; |
|
590 unsigned size = cif->rtype->size; |
|
591 |
|
592 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
593 - NUM_FPR_ARG_REGISTERS = 0; |
|
594 - |
|
595 + /* The machine-independent calculation of cif->bytes doesn't work |
|
596 + for us. Redo the calculation. */ |
|
597 if (cif->abi != FFI_LINUX64) |
|
598 { |
|
599 - /* All the machine-independent calculation of cif->bytes will be wrong. |
|
600 - Redo the calculation for SYSV. */ |
|
601 - |
|
602 /* Space for the frame pointer, callee's LR, and the asm's temp regs. */ |
|
603 bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int); |
|
604 |
|
605 @@ -621,13 +742,20 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
606 else |
|
607 { |
|
608 /* 64-bit ABI. */ |
|
609 +#if _CALL_ELF == 2 |
|
610 + /* Space for backchain, CR, LR, TOC and the asm's temp regs. */ |
|
611 + bytes = (4 + ASM_NEEDS_REGISTERS64) * sizeof (long); |
|
612 |
|
613 + /* Space for the general registers. */ |
|
614 + bytes += NUM_GPR_ARG_REGISTERS64 * sizeof (long); |
|
615 +#else |
|
616 /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp |
|
617 regs. */ |
|
618 bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long); |
|
619 |
|
620 /* Space for the mandatory parm save area and general registers. */ |
|
621 bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long); |
|
622 +#endif |
|
623 } |
|
624 |
|
625 /* Return value handling. The rules for SYSV are as follows: |
|
626 @@ -646,13 +774,30 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
627 - Single/double FP values in fpr1, long double in fpr1,fpr2. |
|
628 - soft-float float/doubles are treated as UINT32/UINT64 respectivley. |
|
629 - soft-float long doubles are returned in gpr3-gpr6. */ |
|
630 + /* First translate for softfloat/nonlinux */ |
|
631 + if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
632 + { |
|
633 + if (type == FFI_TYPE_FLOAT) |
|
634 + type = FFI_TYPE_UINT32; |
|
635 + if (type == FFI_TYPE_DOUBLE) |
|
636 + type = FFI_TYPE_UINT64; |
|
637 + if (type == FFI_TYPE_LONGDOUBLE) |
|
638 + type = FFI_TYPE_UINT128; |
|
639 + } |
|
640 + else if (cif->abi != FFI_LINUX |
|
641 + && cif->abi != FFI_LINUX64) |
|
642 + { |
|
643 +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
644 + if (type == FFI_TYPE_LONGDOUBLE) |
|
645 + type = FFI_TYPE_STRUCT; |
|
646 +#endif |
|
647 + } |
|
648 + |
|
649 switch (type) |
|
650 { |
|
651 +#ifndef __NO_FPRS__ |
|
652 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
653 case FFI_TYPE_LONGDOUBLE: |
|
654 - if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64 |
|
655 - && cif->abi != FFI_LINUX_SOFT_FLOAT) |
|
656 - goto byref; |
|
657 flags |= FLAG_RETURNS_128BITS; |
|
658 /* Fall through. */ |
|
659 #endif |
|
660 @@ -660,47 +805,52 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
661 flags |= FLAG_RETURNS_64BITS; |
|
662 /* Fall through. */ |
|
663 case FFI_TYPE_FLOAT: |
|
664 - /* With FFI_LINUX_SOFT_FLOAT no fp registers are used. */ |
|
665 - if (cif->abi != FFI_LINUX_SOFT_FLOAT) |
|
666 - flags |= FLAG_RETURNS_FP; |
|
667 + flags |= FLAG_RETURNS_FP; |
|
668 break; |
|
669 +#endif |
|
670 |
|
671 + case FFI_TYPE_UINT128: |
|
672 + flags |= FLAG_RETURNS_128BITS; |
|
673 + /* Fall through. */ |
|
674 case FFI_TYPE_UINT64: |
|
675 case FFI_TYPE_SINT64: |
|
676 flags |= FLAG_RETURNS_64BITS; |
|
677 break; |
|
678 |
|
679 case FFI_TYPE_STRUCT: |
|
680 - if (cif->abi == FFI_SYSV) |
|
681 + /* |
|
682 + * The final SYSV ABI says that structures smaller or equal 8 bytes |
|
683 + * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them |
|
684 + * in memory. |
|
685 + * |
|
686 + * NOTE: The assembly code can safely assume that it just needs to |
|
687 + * store both r3 and r4 into a 8-byte word-aligned buffer, as |
|
688 + * we allocate a temporary buffer in ffi_call() if this flag is |
|
689 + * set. |
|
690 + */ |
|
691 + if (cif->abi == FFI_SYSV && size <= 8) |
|
692 { |
|
693 - /* The final SYSV ABI says that structures smaller or equal 8 bytes |
|
694 - are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them |
|
695 - in memory. */ |
|
696 - |
|
697 - /* Treat structs with size <= 8 bytes. */ |
|
698 - if (size <= 8) |
|
699 + flags |= FLAG_RETURNS_SMST; |
|
700 + break; |
|
701 + } |
|
702 +#if _CALL_ELF == 2 |
|
703 + if (cif->abi == FFI_LINUX64) |
|
704 + { |
|
705 + unsigned int elt, elnum; |
|
706 + elt = discover_homogeneous_aggregate (cif->rtype, &elnum); |
|
707 + if (elt) |
|
708 + { |
|
709 + if (elt == FFI_TYPE_DOUBLE) |
|
710 + flags |= FLAG_RETURNS_64BITS; |
|
711 + flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST; |
|
712 + break; |
|
713 + } |
|
714 + if (size <= 16) |
|
715 { |
|
716 flags |= FLAG_RETURNS_SMST; |
|
717 - /* These structs are returned in r3. We pack the type and the |
|
718 - precalculated shift value (needed in the sysv.S) into flags. |
|
719 - The same applies for the structs returned in r3/r4. */ |
|
720 - if (size <= 4) |
|
721 - { |
|
722 - flags |= FLAG_SYSV_SMST_R3; |
|
723 - flags |= 8 * (4 - size) << 8; |
|
724 - break; |
|
725 - } |
|
726 - /* These structs are returned in r3 and r4. See above. */ |
|
727 - if (size <= 8) |
|
728 - { |
|
729 - flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4; |
|
730 - flags |= 8 * (8 - size) << 8; |
|
731 - break; |
|
732 - } |
|
733 + break; |
|
734 } |
|
735 } |
|
736 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
737 - byref: |
|
738 #endif |
|
739 intarg_count++; |
|
740 flags |= FLAG_RETVAL_REFERENCE; |
|
741 @@ -722,39 +872,36 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
742 Stuff on the stack needs to keep proper alignment. */ |
|
743 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) |
|
744 { |
|
745 - switch ((*ptr)->type) |
|
746 - { |
|
747 + unsigned short typenum = (*ptr)->type; |
|
748 + |
|
749 + /* We may need to handle some values depending on ABI */ |
|
750 + if (cif->abi == FFI_LINUX_SOFT_FLOAT) { |
|
751 + if (typenum == FFI_TYPE_FLOAT) |
|
752 + typenum = FFI_TYPE_UINT32; |
|
753 + if (typenum == FFI_TYPE_DOUBLE) |
|
754 + typenum = FFI_TYPE_UINT64; |
|
755 + if (typenum == FFI_TYPE_LONGDOUBLE) |
|
756 + typenum = FFI_TYPE_UINT128; |
|
757 + } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) { |
|
758 +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
759 + if (typenum == FFI_TYPE_LONGDOUBLE) |
|
760 + typenum = FFI_TYPE_STRUCT; |
|
761 +#endif |
|
762 + } |
|
763 + |
|
764 + switch (typenum) { |
|
765 +#ifndef __NO_FPRS__ |
|
766 case FFI_TYPE_FLOAT: |
|
767 - /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */ |
|
768 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
769 - goto soft_float_cif; |
|
770 fparg_count++; |
|
771 /* floating singles are not 8-aligned on stack */ |
|
772 break; |
|
773 |
|
774 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
775 case FFI_TYPE_LONGDOUBLE: |
|
776 - if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT) |
|
777 - goto do_struct; |
|
778 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
779 - { |
|
780 - if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3 |
|
781 - || intarg_count < NUM_GPR_ARG_REGISTERS) |
|
782 - /* A long double in FFI_LINUX_SOFT_FLOAT can use only |
|
783 - a set of four consecutive gprs. If we have not enough, |
|
784 - we have to adjust the intarg_count value. */ |
|
785 - intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count; |
|
786 - intarg_count += 4; |
|
787 - break; |
|
788 - } |
|
789 - else |
|
790 - fparg_count++; |
|
791 + fparg_count++; |
|
792 /* Fall thru */ |
|
793 #endif |
|
794 case FFI_TYPE_DOUBLE: |
|
795 - /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */ |
|
796 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
797 - goto soft_double_cif; |
|
798 fparg_count++; |
|
799 /* If this FP arg is going on the stack, it must be |
|
800 8-byte-aligned. */ |
|
801 @@ -763,10 +910,21 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
802 && intarg_count % 2 != 0) |
|
803 intarg_count++; |
|
804 break; |
|
805 +#endif |
|
806 + case FFI_TYPE_UINT128: |
|
807 + /* |
|
808 + * A long double in FFI_LINUX_SOFT_FLOAT can use only a set |
|
809 + * of four consecutive gprs. If we do not have enough, we |
|
810 + * have to adjust the intarg_count value. |
|
811 + */ |
|
812 + if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3 |
|
813 + && intarg_count < NUM_GPR_ARG_REGISTERS) |
|
814 + intarg_count = NUM_GPR_ARG_REGISTERS; |
|
815 + intarg_count += 4; |
|
816 + break; |
|
817 |
|
818 case FFI_TYPE_UINT64: |
|
819 case FFI_TYPE_SINT64: |
|
820 - soft_double_cif: |
|
821 /* 'long long' arguments are passed as two words, but |
|
822 either both words must fit in registers or both go |
|
823 on the stack. If they go on the stack, they must |
|
824 @@ -783,9 +941,6 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
825 break; |
|
826 |
|
827 case FFI_TYPE_STRUCT: |
|
828 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
829 - do_struct: |
|
830 -#endif |
|
831 /* We must allocate space for a copy of these to enforce |
|
832 pass-by-value. Pad the space up to a multiple of 16 |
|
833 bytes (the maximum alignment required for anything under |
|
834 @@ -793,50 +948,100 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
835 struct_copy_size += ((*ptr)->size + 15) & ~0xF; |
|
836 /* Fall through (allocate space for the pointer). */ |
|
837 |
|
838 - default: |
|
839 - soft_float_cif: |
|
840 + case FFI_TYPE_POINTER: |
|
841 + case FFI_TYPE_INT: |
|
842 + case FFI_TYPE_UINT32: |
|
843 + case FFI_TYPE_SINT32: |
|
844 + case FFI_TYPE_UINT16: |
|
845 + case FFI_TYPE_SINT16: |
|
846 + case FFI_TYPE_UINT8: |
|
847 + case FFI_TYPE_SINT8: |
|
848 /* Everything else is passed as a 4-byte word in a GPR, either |
|
849 the object itself or a pointer to it. */ |
|
850 intarg_count++; |
|
851 break; |
|
852 + default: |
|
853 + FFI_ASSERT (0); |
|
854 } |
|
855 } |
|
856 else |
|
857 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) |
|
858 { |
|
859 + unsigned int elt, elnum; |
|
860 +#ifdef __STRUCT_PARM_ALIGN__ |
|
861 + unsigned int align; |
|
862 +#endif |
|
863 + |
|
864 switch ((*ptr)->type) |
|
865 { |
|
866 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
867 case FFI_TYPE_LONGDOUBLE: |
|
868 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
869 - intarg_count += 4; |
|
870 - else |
|
871 - { |
|
872 - fparg_count += 2; |
|
873 - intarg_count += 2; |
|
874 - } |
|
875 + fparg_count += 2; |
|
876 + intarg_count += 2; |
|
877 + if (fparg_count > NUM_FPR_ARG_REGISTERS) |
|
878 + flags |= FLAG_ARG_NEEDS_PSAVE; |
|
879 break; |
|
880 #endif |
|
881 case FFI_TYPE_FLOAT: |
|
882 case FFI_TYPE_DOUBLE: |
|
883 fparg_count++; |
|
884 intarg_count++; |
|
885 + if (fparg_count > NUM_FPR_ARG_REGISTERS) |
|
886 + flags |= FLAG_ARG_NEEDS_PSAVE; |
|
887 break; |
|
888 |
|
889 case FFI_TYPE_STRUCT: |
|
890 +#ifdef __STRUCT_PARM_ALIGN__ |
|
891 + align = (*ptr)->alignment; |
|
892 + if (align > __STRUCT_PARM_ALIGN__) |
|
893 + align = __STRUCT_PARM_ALIGN__; |
|
894 + align = align / 8; |
|
895 + if (align > 1) |
|
896 + intarg_count = ALIGN (intarg_count, align); |
|
897 +#endif |
|
898 intarg_count += ((*ptr)->size + 7) / 8; |
|
899 + elt = 0; |
|
900 +#if _CALL_ELF == 2 |
|
901 + elt = discover_homogeneous_aggregate (*ptr, &elnum); |
|
902 +#endif |
|
903 + if (elt) |
|
904 + { |
|
905 + fparg_count += elnum; |
|
906 + if (fparg_count > NUM_FPR_ARG_REGISTERS) |
|
907 + flags |= FLAG_ARG_NEEDS_PSAVE; |
|
908 + } |
|
909 + else |
|
910 + { |
|
911 + if (intarg_count > NUM_GPR_ARG_REGISTERS) |
|
912 + flags |= FLAG_ARG_NEEDS_PSAVE; |
|
913 + } |
|
914 break; |
|
915 |
|
916 - default: |
|
917 + case FFI_TYPE_POINTER: |
|
918 + case FFI_TYPE_UINT64: |
|
919 + case FFI_TYPE_SINT64: |
|
920 + case FFI_TYPE_INT: |
|
921 + case FFI_TYPE_UINT32: |
|
922 + case FFI_TYPE_SINT32: |
|
923 + case FFI_TYPE_UINT16: |
|
924 + case FFI_TYPE_SINT16: |
|
925 + case FFI_TYPE_UINT8: |
|
926 + case FFI_TYPE_SINT8: |
|
927 /* Everything else is passed as a 8-byte word in a GPR, either |
|
928 the object itself or a pointer to it. */ |
|
929 intarg_count++; |
|
930 + if (intarg_count > NUM_GPR_ARG_REGISTERS) |
|
931 + flags |= FLAG_ARG_NEEDS_PSAVE; |
|
932 break; |
|
933 + default: |
|
934 + FFI_ASSERT (0); |
|
935 } |
|
936 } |
|
937 |
|
938 +#ifndef __NO_FPRS__ |
|
939 if (fparg_count != 0) |
|
940 flags |= FLAG_FP_ARGUMENTS; |
|
941 +#endif |
|
942 if (intarg_count > 4) |
|
943 flags |= FLAG_4_GPR_ARGUMENTS; |
|
944 if (struct_copy_size != 0) |
|
945 @@ -844,25 +1049,36 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
946 |
|
947 if (cif->abi != FFI_LINUX64) |
|
948 { |
|
949 +#ifndef __NO_FPRS__ |
|
950 /* Space for the FPR registers, if needed. */ |
|
951 if (fparg_count != 0) |
|
952 bytes += NUM_FPR_ARG_REGISTERS * sizeof (double); |
|
953 +#endif |
|
954 |
|
955 /* Stack space. */ |
|
956 if (intarg_count > NUM_GPR_ARG_REGISTERS) |
|
957 bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int); |
|
958 +#ifndef __NO_FPRS__ |
|
959 if (fparg_count > NUM_FPR_ARG_REGISTERS) |
|
960 bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double); |
|
961 +#endif |
|
962 } |
|
963 else |
|
964 { |
|
965 +#ifndef __NO_FPRS__ |
|
966 /* Space for the FPR registers, if needed. */ |
|
967 if (fparg_count != 0) |
|
968 bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double); |
|
969 +#endif |
|
970 |
|
971 /* Stack space. */ |
|
972 +#if _CALL_ELF == 2 |
|
973 + if ((flags & FLAG_ARG_NEEDS_PSAVE) != 0) |
|
974 + bytes += intarg_count * sizeof (long); |
|
975 +#else |
|
976 if (intarg_count > NUM_GPR_ARG_REGISTERS64) |
|
977 bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long); |
|
978 +#endif |
|
979 } |
|
980 |
|
981 /* The stack space allocated needs to be a multiple of 16 bytes. */ |
|
982 @@ -877,6 +1093,26 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
983 return FFI_OK; |
|
984 } |
|
985 |
|
986 +ffi_status |
|
987 +ffi_prep_cif_machdep (ffi_cif *cif) |
|
988 +{ |
|
989 + cif->nfixedargs = cif->nargs; |
|
990 + return ffi_prep_cif_machdep_core (cif); |
|
991 +} |
|
992 + |
|
993 +ffi_status |
|
994 +ffi_prep_cif_machdep_var (ffi_cif *cif, |
|
995 + unsigned int nfixedargs, |
|
996 + unsigned int ntotalargs MAYBE_UNUSED) |
|
997 +{ |
|
998 + cif->nfixedargs = nfixedargs; |
|
999 +#if _CALL_ELF == 2 |
|
1000 + if (cif->abi == FFI_LINUX64) |
|
1001 + cif->flags |= FLAG_ARG_NEEDS_PSAVE; |
|
1002 +#endif |
|
1003 + return ffi_prep_cif_machdep_core (cif); |
|
1004 +} |
|
1005 + |
|
1006 extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *, |
|
1007 void (*fn)(void)); |
|
1008 extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, |
|
1009 @@ -886,28 +1122,39 @@ extern void FFI_HIDDEN ffi_call_LINUX64( |
|
1010 void |
|
1011 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) |
|
1012 { |
|
1013 + /* |
|
1014 + * The final SYSV ABI says that structures smaller or equal 8 bytes |
|
1015 + * are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them |
|
1016 + * in memory. |
|
1017 + * |
|
1018 + * We bounce-buffer SYSV small struct return values so that sysv.S |
|
1019 + * can write r3 and r4 to memory without worrying about struct size. |
|
1020 + * |
|
1021 + * For ELFv2 ABI, use a bounce buffer for homogeneous structs too, |
|
1022 + * for similar reasons. |
|
1023 + */ |
|
1024 + unsigned long smst_buffer[8]; |
|
1025 extended_cif ecif; |
|
1026 |
|
1027 ecif.cif = cif; |
|
1028 ecif.avalue = avalue; |
|
1029 |
|
1030 - /* If the return value is a struct and we don't have a return */ |
|
1031 - /* value address then we need to make one */ |
|
1032 - |
|
1033 - if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT)) |
|
1034 - { |
|
1035 - ecif.rvalue = alloca(cif->rtype->size); |
|
1036 - } |
|
1037 - else |
|
1038 - ecif.rvalue = rvalue; |
|
1039 - |
|
1040 + ecif.rvalue = rvalue; |
|
1041 + if ((cif->flags & FLAG_RETURNS_SMST) != 0) |
|
1042 + ecif.rvalue = smst_buffer; |
|
1043 + /* Ensure that we have a valid struct return value. |
|
1044 + FIXME: Isn't this just papering over a user problem? */ |
|
1045 + else if (!rvalue && cif->rtype->type == FFI_TYPE_STRUCT) |
|
1046 + ecif.rvalue = alloca (cif->rtype->size); |
|
1047 |
|
1048 switch (cif->abi) |
|
1049 { |
|
1050 #ifndef POWERPC64 |
|
1051 +# ifndef __NO_FPRS__ |
|
1052 case FFI_SYSV: |
|
1053 case FFI_GCC_SYSV: |
|
1054 case FFI_LINUX: |
|
1055 +# endif |
|
1056 case FFI_LINUX_SOFT_FLOAT: |
|
1057 ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn); |
|
1058 break; |
|
1059 @@ -920,10 +1167,29 @@ ffi_call(ffi_cif *cif, void (*fn)(void), |
|
1060 FFI_ASSERT (0); |
|
1061 break; |
|
1062 } |
|
1063 + |
|
1064 + /* Check for a bounce-buffered return value */ |
|
1065 + if (rvalue && ecif.rvalue == smst_buffer) |
|
1066 + { |
|
1067 + unsigned int rsize = cif->rtype->size; |
|
1068 +#ifndef __LITTLE_ENDIAN__ |
|
1069 + /* The SYSV ABI returns a structure of up to 4 bytes in size |
|
1070 + left-padded in r3. */ |
|
1071 + if (cif->abi == FFI_SYSV && rsize <= 4) |
|
1072 + memcpy (rvalue, (char *) smst_buffer + 4 - rsize, rsize); |
|
1073 + /* The SYSV ABI returns a structure of up to 8 bytes in size |
|
1074 + left-padded in r3/r4, and the ELFv2 ABI similarly returns a |
|
1075 + structure of up to 8 bytes in size left-padded in r3. */ |
|
1076 + else if (rsize <= 8) |
|
1077 + memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize); |
|
1078 + else |
|
1079 +#endif |
|
1080 + memcpy (rvalue, smst_buffer, rsize); |
|
1081 + } |
|
1082 } |
|
1083 |
|
1084 |
|
1085 -#ifndef POWERPC64 |
|
1086 +#if !defined POWERPC64 || _CALL_ELF == 2 |
|
1087 #define MIN_CACHE_LINE_SIZE 8 |
|
1088 |
|
1089 static void |
|
1090 @@ -947,16 +1213,38 @@ ffi_prep_closure_loc (ffi_closure *closu |
|
1091 void *codeloc) |
|
1092 { |
|
1093 #ifdef POWERPC64 |
|
1094 +# if _CALL_ELF == 2 |
|
1095 + unsigned int *tramp = (unsigned int *) &closure->tramp[0]; |
|
1096 + |
|
1097 + if (cif->abi != FFI_LINUX64) |
|
1098 + return FFI_BAD_ABI; |
|
1099 + |
|
1100 + tramp[0] = 0xe96c0018; /* 0: ld 11,2f-0b(12) */ |
|
1101 + tramp[1] = 0xe98c0010; /* ld 12,1f-0b(12) */ |
|
1102 + tramp[2] = 0x7d8903a6; /* mtctr 12 */ |
|
1103 + tramp[3] = 0x4e800420; /* bctr */ |
|
1104 + /* 1: .quad function_addr */ |
|
1105 + /* 2: .quad context */ |
|
1106 + *(void **) &tramp[4] = (void *) ffi_closure_LINUX64; |
|
1107 + *(void **) &tramp[6] = codeloc; |
|
1108 + flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); |
|
1109 +# else |
|
1110 void **tramp = (void **) &closure->tramp[0]; |
|
1111 |
|
1112 - FFI_ASSERT (cif->abi == FFI_LINUX64); |
|
1113 + if (cif->abi != FFI_LINUX64) |
|
1114 + return FFI_BAD_ABI; |
|
1115 /* Copy function address and TOC from ffi_closure_LINUX64. */ |
|
1116 memcpy (tramp, (char *) ffi_closure_LINUX64, 16); |
|
1117 tramp[2] = codeloc; |
|
1118 +# endif |
|
1119 #else |
|
1120 unsigned int *tramp; |
|
1121 |
|
1122 - FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV); |
|
1123 + if (! (cif->abi == FFI_GCC_SYSV |
|
1124 + || cif->abi == FFI_SYSV |
|
1125 + || cif->abi == FFI_LINUX |
|
1126 + || cif->abi == FFI_LINUX_SOFT_FLOAT)) |
|
1127 + return FFI_BAD_ABI; |
|
1128 |
|
1129 tramp = (unsigned int *) &closure->tramp[0]; |
|
1130 tramp[0] = 0x7c0802a6; /* mflr r0 */ |
|
1131 @@ -1011,32 +1299,38 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1132 void ** avalue; |
|
1133 ffi_type ** arg_types; |
|
1134 long i, avn; |
|
1135 - long nf; /* number of floating registers already used */ |
|
1136 - long ng; /* number of general registers already used */ |
|
1137 - ffi_cif * cif; |
|
1138 - double temp; |
|
1139 - unsigned size; |
|
1140 +#ifndef __NO_FPRS__ |
|
1141 + long nf = 0; /* number of floating registers already used */ |
|
1142 +#endif |
|
1143 + long ng = 0; /* number of general registers already used */ |
|
1144 + |
|
1145 + ffi_cif *cif = closure->cif; |
|
1146 + unsigned size = cif->rtype->size; |
|
1147 + unsigned short rtypenum = cif->rtype->type; |
|
1148 |
|
1149 - cif = closure->cif; |
|
1150 avalue = alloca (cif->nargs * sizeof (void *)); |
|
1151 - size = cif->rtype->size; |
|
1152 |
|
1153 - nf = 0; |
|
1154 - ng = 0; |
|
1155 + /* First translate for softfloat/nonlinux */ |
|
1156 + if (cif->abi == FFI_LINUX_SOFT_FLOAT) { |
|
1157 + if (rtypenum == FFI_TYPE_FLOAT) |
|
1158 + rtypenum = FFI_TYPE_UINT32; |
|
1159 + if (rtypenum == FFI_TYPE_DOUBLE) |
|
1160 + rtypenum = FFI_TYPE_UINT64; |
|
1161 + if (rtypenum == FFI_TYPE_LONGDOUBLE) |
|
1162 + rtypenum = FFI_TYPE_UINT128; |
|
1163 + } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) { |
|
1164 +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1165 + if (rtypenum == FFI_TYPE_LONGDOUBLE) |
|
1166 + rtypenum = FFI_TYPE_STRUCT; |
|
1167 +#endif |
|
1168 + } |
|
1169 + |
|
1170 |
|
1171 /* Copy the caller's structure return value address so that the closure |
|
1172 returns the data directly to the caller. |
|
1173 For FFI_SYSV the result is passed in r3/r4 if the struct size is less |
|
1174 or equal 8 bytes. */ |
|
1175 - |
|
1176 - if ((cif->rtype->type == FFI_TYPE_STRUCT |
|
1177 - && !((cif->abi == FFI_SYSV) && (size <= 8))) |
|
1178 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1179 - || (cif->rtype->type == FFI_TYPE_LONGDOUBLE |
|
1180 - && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT) |
|
1181 -#endif |
|
1182 - ) |
|
1183 - { |
|
1184 + if (rtypenum == FFI_TYPE_STRUCT && ((cif->abi != FFI_SYSV) || (size > 8))) { |
|
1185 rvalue = (void *) *pgr; |
|
1186 ng++; |
|
1187 pgr++; |
|
1188 @@ -1047,12 +1341,112 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1189 arg_types = cif->arg_types; |
|
1190 |
|
1191 /* Grab the addresses of the arguments from the stack frame. */ |
|
1192 - while (i < avn) |
|
1193 - { |
|
1194 - switch (arg_types[i]->type) |
|
1195 - { |
|
1196 + while (i < avn) { |
|
1197 + unsigned short typenum = arg_types[i]->type; |
|
1198 + |
|
1199 + /* We may need to handle some values depending on ABI */ |
|
1200 + if (cif->abi == FFI_LINUX_SOFT_FLOAT) { |
|
1201 + if (typenum == FFI_TYPE_FLOAT) |
|
1202 + typenum = FFI_TYPE_UINT32; |
|
1203 + if (typenum == FFI_TYPE_DOUBLE) |
|
1204 + typenum = FFI_TYPE_UINT64; |
|
1205 + if (typenum == FFI_TYPE_LONGDOUBLE) |
|
1206 + typenum = FFI_TYPE_UINT128; |
|
1207 + } else if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64) { |
|
1208 +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1209 + if (typenum == FFI_TYPE_LONGDOUBLE) |
|
1210 + typenum = FFI_TYPE_STRUCT; |
|
1211 +#endif |
|
1212 + } |
|
1213 + |
|
1214 + switch (typenum) { |
|
1215 +#ifndef __NO_FPRS__ |
|
1216 + case FFI_TYPE_FLOAT: |
|
1217 + /* unfortunately float values are stored as doubles |
|
1218 + * in the ffi_closure_SYSV code (since we don't check |
|
1219 + * the type in that routine). |
|
1220 + */ |
|
1221 + |
|
1222 + /* there are 8 64bit floating point registers */ |
|
1223 + |
|
1224 + if (nf < 8) |
|
1225 + { |
|
1226 + double temp = pfr->d; |
|
1227 + pfr->f = (float) temp; |
|
1228 + avalue[i] = pfr; |
|
1229 + nf++; |
|
1230 + pfr++; |
|
1231 + } |
|
1232 + else |
|
1233 + { |
|
1234 + /* FIXME? here we are really changing the values |
|
1235 + * stored in the original calling routines outgoing |
|
1236 + * parameter stack. This is probably a really |
|
1237 + * naughty thing to do but... |
|
1238 + */ |
|
1239 + avalue[i] = pst; |
|
1240 + pst += 1; |
|
1241 + } |
|
1242 + break; |
|
1243 + |
|
1244 + case FFI_TYPE_DOUBLE: |
|
1245 + /* On the outgoing stack all values are aligned to 8 */ |
|
1246 + /* there are 8 64bit floating point registers */ |
|
1247 + |
|
1248 + if (nf < 8) |
|
1249 + { |
|
1250 + avalue[i] = pfr; |
|
1251 + nf++; |
|
1252 + pfr++; |
|
1253 + } |
|
1254 + else |
|
1255 + { |
|
1256 + if (((long) pst) & 4) |
|
1257 + pst++; |
|
1258 + avalue[i] = pst; |
|
1259 + pst += 2; |
|
1260 + } |
|
1261 + break; |
|
1262 + |
|
1263 +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1264 + case FFI_TYPE_LONGDOUBLE: |
|
1265 + if (nf < 7) |
|
1266 + { |
|
1267 + avalue[i] = pfr; |
|
1268 + pfr += 2; |
|
1269 + nf += 2; |
|
1270 + } |
|
1271 + else |
|
1272 + { |
|
1273 + if (((long) pst) & 4) |
|
1274 + pst++; |
|
1275 + avalue[i] = pst; |
|
1276 + pst += 4; |
|
1277 + nf = 8; |
|
1278 + } |
|
1279 + break; |
|
1280 +#endif |
|
1281 +#endif /* have FPRS */ |
|
1282 + |
|
1283 + case FFI_TYPE_UINT128: |
|
1284 + /* |
|
1285 + * Test if for the whole long double, 4 gprs are available. |
|
1286 + * otherwise the stuff ends up on the stack. |
|
1287 + */ |
|
1288 + if (ng < 5) { |
|
1289 + avalue[i] = pgr; |
|
1290 + pgr += 4; |
|
1291 + ng += 4; |
|
1292 + } else { |
|
1293 + avalue[i] = pst; |
|
1294 + pst += 4; |
|
1295 + ng = 8+4; |
|
1296 + } |
|
1297 + break; |
|
1298 + |
|
1299 case FFI_TYPE_SINT8: |
|
1300 case FFI_TYPE_UINT8: |
|
1301 +#ifndef __LITTLE_ENDIAN__ |
|
1302 /* there are 8 gpr registers used to pass values */ |
|
1303 if (ng < 8) |
|
1304 { |
|
1305 @@ -1066,9 +1460,11 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1306 pst++; |
|
1307 } |
|
1308 break; |
|
1309 +#endif |
|
1310 |
|
1311 case FFI_TYPE_SINT16: |
|
1312 case FFI_TYPE_UINT16: |
|
1313 +#ifndef __LITTLE_ENDIAN__ |
|
1314 /* there are 8 gpr registers used to pass values */ |
|
1315 if (ng < 8) |
|
1316 { |
|
1317 @@ -1082,11 +1478,11 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1318 pst++; |
|
1319 } |
|
1320 break; |
|
1321 +#endif |
|
1322 |
|
1323 case FFI_TYPE_SINT32: |
|
1324 case FFI_TYPE_UINT32: |
|
1325 case FFI_TYPE_POINTER: |
|
1326 - soft_float_closure: |
|
1327 /* there are 8 gpr registers used to pass values */ |
|
1328 if (ng < 8) |
|
1329 { |
|
1330 @@ -1102,9 +1498,6 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1331 break; |
|
1332 |
|
1333 case FFI_TYPE_STRUCT: |
|
1334 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1335 - do_struct: |
|
1336 -#endif |
|
1337 /* Structs are passed by reference. The address will appear in a |
|
1338 gpr if it is one of the first 8 arguments. */ |
|
1339 if (ng < 8) |
|
1340 @@ -1122,7 +1515,6 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1341 |
|
1342 case FFI_TYPE_SINT64: |
|
1343 case FFI_TYPE_UINT64: |
|
1344 - soft_double_closure: |
|
1345 /* passing long long ints are complex, they must |
|
1346 * be passed in suitable register pairs such as |
|
1347 * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10) |
|
1348 @@ -1154,99 +1546,8 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1349 } |
|
1350 break; |
|
1351 |
|
1352 - case FFI_TYPE_FLOAT: |
|
1353 - /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32. */ |
|
1354 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
1355 - goto soft_float_closure; |
|
1356 - /* unfortunately float values are stored as doubles |
|
1357 - * in the ffi_closure_SYSV code (since we don't check |
|
1358 - * the type in that routine). |
|
1359 - */ |
|
1360 - |
|
1361 - /* there are 8 64bit floating point registers */ |
|
1362 - |
|
1363 - if (nf < 8) |
|
1364 - { |
|
1365 - temp = pfr->d; |
|
1366 - pfr->f = (float) temp; |
|
1367 - avalue[i] = pfr; |
|
1368 - nf++; |
|
1369 - pfr++; |
|
1370 - } |
|
1371 - else |
|
1372 - { |
|
1373 - /* FIXME? here we are really changing the values |
|
1374 - * stored in the original calling routines outgoing |
|
1375 - * parameter stack. This is probably a really |
|
1376 - * naughty thing to do but... |
|
1377 - */ |
|
1378 - avalue[i] = pst; |
|
1379 - pst += 1; |
|
1380 - } |
|
1381 - break; |
|
1382 - |
|
1383 - case FFI_TYPE_DOUBLE: |
|
1384 - /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64. */ |
|
1385 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
1386 - goto soft_double_closure; |
|
1387 - /* On the outgoing stack all values are aligned to 8 */ |
|
1388 - /* there are 8 64bit floating point registers */ |
|
1389 - |
|
1390 - if (nf < 8) |
|
1391 - { |
|
1392 - avalue[i] = pfr; |
|
1393 - nf++; |
|
1394 - pfr++; |
|
1395 - } |
|
1396 - else |
|
1397 - { |
|
1398 - if (((long) pst) & 4) |
|
1399 - pst++; |
|
1400 - avalue[i] = pst; |
|
1401 - pst += 2; |
|
1402 - } |
|
1403 - break; |
|
1404 - |
|
1405 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1406 - case FFI_TYPE_LONGDOUBLE: |
|
1407 - if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT) |
|
1408 - goto do_struct; |
|
1409 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
1410 - { /* Test if for the whole long double, 4 gprs are available. |
|
1411 - otherwise the stuff ends up on the stack. */ |
|
1412 - if (ng < 5) |
|
1413 - { |
|
1414 - avalue[i] = pgr; |
|
1415 - pgr += 4; |
|
1416 - ng += 4; |
|
1417 - } |
|
1418 - else |
|
1419 - { |
|
1420 - avalue[i] = pst; |
|
1421 - pst += 4; |
|
1422 - ng = 8; |
|
1423 - } |
|
1424 - break; |
|
1425 - } |
|
1426 - if (nf < 7) |
|
1427 - { |
|
1428 - avalue[i] = pfr; |
|
1429 - pfr += 2; |
|
1430 - nf += 2; |
|
1431 - } |
|
1432 - else |
|
1433 - { |
|
1434 - if (((long) pst) & 4) |
|
1435 - pst++; |
|
1436 - avalue[i] = pst; |
|
1437 - pst += 4; |
|
1438 - nf = 8; |
|
1439 - } |
|
1440 - break; |
|
1441 -#endif |
|
1442 - |
|
1443 default: |
|
1444 - FFI_ASSERT (0); |
|
1445 + FFI_ASSERT (0); |
|
1446 } |
|
1447 |
|
1448 i++; |
|
1449 @@ -1263,39 +1564,9 @@ ffi_closure_helper_SYSV (ffi_closure *cl |
|
1450 already used and we never have a struct with size zero. That is the reason |
|
1451 for the subtraction of 1. See the comment in ffitarget.h about ordering. |
|
1452 */ |
|
1453 - if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT |
|
1454 - && size <= 8) |
|
1455 + if (cif->abi == FFI_SYSV && rtypenum == FFI_TYPE_STRUCT && size <= 8) |
|
1456 return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size; |
|
1457 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1458 - else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE |
|
1459 - && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT) |
|
1460 - return FFI_TYPE_STRUCT; |
|
1461 -#endif |
|
1462 - /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32 |
|
1463 - respectivley UINT64. */ |
|
1464 - if (cif->abi == FFI_LINUX_SOFT_FLOAT) |
|
1465 - { |
|
1466 - switch (cif->rtype->type) |
|
1467 - { |
|
1468 - case FFI_TYPE_FLOAT: |
|
1469 - return FFI_TYPE_UINT32; |
|
1470 - break; |
|
1471 - case FFI_TYPE_DOUBLE: |
|
1472 - return FFI_TYPE_UINT64; |
|
1473 - break; |
|
1474 -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1475 - case FFI_TYPE_LONGDOUBLE: |
|
1476 - return FFI_TYPE_UINT128; |
|
1477 - break; |
|
1478 -#endif |
|
1479 - default: |
|
1480 - return cif->rtype->type; |
|
1481 - } |
|
1482 - } |
|
1483 - else |
|
1484 - { |
|
1485 - return cif->rtype->type; |
|
1486 - } |
|
1487 + return rtypenum; |
|
1488 } |
|
1489 |
|
1490 int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *, |
|
1491 @@ -1312,16 +1583,20 @@ ffi_closure_helper_LINUX64 (ffi_closure |
|
1492 |
|
1493 void **avalue; |
|
1494 ffi_type **arg_types; |
|
1495 - long i, avn; |
|
1496 + unsigned long i, avn, nfixedargs; |
|
1497 ffi_cif *cif; |
|
1498 ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; |
|
1499 +#ifdef __STRUCT_PARM_ALIGN__ |
|
1500 + unsigned long align; |
|
1501 +#endif |
|
1502 |
|
1503 cif = closure->cif; |
|
1504 avalue = alloca (cif->nargs * sizeof (void *)); |
|
1505 |
|
1506 - /* Copy the caller's structure return value address so that the closure |
|
1507 - returns the data directly to the caller. */ |
|
1508 - if (cif->rtype->type == FFI_TYPE_STRUCT) |
|
1509 + /* Copy the caller's structure return value address so that the |
|
1510 + closure returns the data directly to the caller. */ |
|
1511 + if (cif->rtype->type == FFI_TYPE_STRUCT |
|
1512 + && (cif->flags & FLAG_RETURNS_SMST) == 0) |
|
1513 { |
|
1514 rvalue = (void *) *pst; |
|
1515 pst++; |
|
1516 @@ -1329,30 +1604,39 @@ ffi_closure_helper_LINUX64 (ffi_closure |
|
1517 |
|
1518 i = 0; |
|
1519 avn = cif->nargs; |
|
1520 + nfixedargs = cif->nfixedargs; |
|
1521 arg_types = cif->arg_types; |
|
1522 |
|
1523 /* Grab the addresses of the arguments from the stack frame. */ |
|
1524 while (i < avn) |
|
1525 { |
|
1526 + unsigned int elt, elnum; |
|
1527 + |
|
1528 switch (arg_types[i]->type) |
|
1529 { |
|
1530 case FFI_TYPE_SINT8: |
|
1531 case FFI_TYPE_UINT8: |
|
1532 +#ifndef __LITTLE_ENDIAN__ |
|
1533 avalue[i] = (char *) pst + 7; |
|
1534 pst++; |
|
1535 break; |
|
1536 +#endif |
|
1537 |
|
1538 case FFI_TYPE_SINT16: |
|
1539 case FFI_TYPE_UINT16: |
|
1540 +#ifndef __LITTLE_ENDIAN__ |
|
1541 avalue[i] = (char *) pst + 6; |
|
1542 pst++; |
|
1543 break; |
|
1544 +#endif |
|
1545 |
|
1546 case FFI_TYPE_SINT32: |
|
1547 case FFI_TYPE_UINT32: |
|
1548 +#ifndef __LITTLE_ENDIAN__ |
|
1549 avalue[i] = (char *) pst + 4; |
|
1550 pst++; |
|
1551 break; |
|
1552 +#endif |
|
1553 |
|
1554 case FFI_TYPE_SINT64: |
|
1555 case FFI_TYPE_UINT64: |
|
1556 @@ -1362,12 +1646,82 @@ ffi_closure_helper_LINUX64 (ffi_closure |
|
1557 break; |
|
1558 |
|
1559 case FFI_TYPE_STRUCT: |
|
1560 - /* Structures with size less than eight bytes are passed |
|
1561 - left-padded. */ |
|
1562 - if (arg_types[i]->size < 8) |
|
1563 - avalue[i] = (char *) pst + 8 - arg_types[i]->size; |
|
1564 +#ifdef __STRUCT_PARM_ALIGN__ |
|
1565 + align = arg_types[i]->alignment; |
|
1566 + if (align > __STRUCT_PARM_ALIGN__) |
|
1567 + align = __STRUCT_PARM_ALIGN__; |
|
1568 + if (align > 1) |
|
1569 + pst = (unsigned long *) ALIGN ((size_t) pst, align); |
|
1570 +#endif |
|
1571 + elt = 0; |
|
1572 +#if _CALL_ELF == 2 |
|
1573 + elt = discover_homogeneous_aggregate (arg_types[i], &elnum); |
|
1574 +#endif |
|
1575 + if (elt) |
|
1576 + { |
|
1577 + union { |
|
1578 + void *v; |
|
1579 + unsigned long *ul; |
|
1580 + float *f; |
|
1581 + double *d; |
|
1582 + size_t p; |
|
1583 + } to, from; |
|
1584 + |
|
1585 + /* Repackage the aggregate from its parts. The |
|
1586 + aggregate size is not greater than the space taken by |
|
1587 + the registers so store back to the register/parameter |
|
1588 + save arrays. */ |
|
1589 + if (pfr + elnum <= end_pfr) |
|
1590 + to.v = pfr; |
|
1591 + else |
|
1592 + to.v = pst; |
|
1593 + |
|
1594 + avalue[i] = to.v; |
|
1595 + from.ul = pst; |
|
1596 + if (elt == FFI_TYPE_FLOAT) |
|
1597 + { |
|
1598 + do |
|
1599 + { |
|
1600 + if (pfr < end_pfr && i < nfixedargs) |
|
1601 + { |
|
1602 + *to.f = (float) pfr->d; |
|
1603 + pfr++; |
|
1604 + } |
|
1605 + else |
|
1606 + *to.f = *from.f; |
|
1607 + to.f++; |
|
1608 + from.f++; |
|
1609 + } |
|
1610 + while (--elnum != 0); |
|
1611 + } |
|
1612 + else |
|
1613 + { |
|
1614 + do |
|
1615 + { |
|
1616 + if (pfr < end_pfr && i < nfixedargs) |
|
1617 + { |
|
1618 + *to.d = pfr->d; |
|
1619 + pfr++; |
|
1620 + } |
|
1621 + else |
|
1622 + *to.d = *from.d; |
|
1623 + to.d++; |
|
1624 + from.d++; |
|
1625 + } |
|
1626 + while (--elnum != 0); |
|
1627 + } |
|
1628 + } |
|
1629 else |
|
1630 - avalue[i] = pst; |
|
1631 + { |
|
1632 +#ifndef __LITTLE_ENDIAN__ |
|
1633 + /* Structures with size less than eight bytes are passed |
|
1634 + left-padded. */ |
|
1635 + if (arg_types[i]->size < 8) |
|
1636 + avalue[i] = (char *) pst + 8 - arg_types[i]->size; |
|
1637 + else |
|
1638 +#endif |
|
1639 + avalue[i] = pst; |
|
1640 + } |
|
1641 pst += (arg_types[i]->size + 7) / 8; |
|
1642 break; |
|
1643 |
|
1644 @@ -1379,7 +1733,7 @@ ffi_closure_helper_LINUX64 (ffi_closure |
|
1645 |
|
1646 /* there are 13 64bit floating point registers */ |
|
1647 |
|
1648 - if (pfr < end_pfr) |
|
1649 + if (pfr < end_pfr && i < nfixedargs) |
|
1650 { |
|
1651 double temp = pfr->d; |
|
1652 pfr->f = (float) temp; |
|
1653 @@ -1395,7 +1749,7 @@ ffi_closure_helper_LINUX64 (ffi_closure |
|
1654 /* On the outgoing stack all values are aligned to 8 */ |
|
1655 /* there are 13 64bit floating point registers */ |
|
1656 |
|
1657 - if (pfr < end_pfr) |
|
1658 + if (pfr < end_pfr && i < nfixedargs) |
|
1659 { |
|
1660 avalue[i] = pfr; |
|
1661 pfr++; |
|
1662 @@ -1407,14 +1761,14 @@ ffi_closure_helper_LINUX64 (ffi_closure |
|
1663 |
|
1664 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1665 case FFI_TYPE_LONGDOUBLE: |
|
1666 - if (pfr + 1 < end_pfr) |
|
1667 + if (pfr + 1 < end_pfr && i + 1 < nfixedargs) |
|
1668 { |
|
1669 avalue[i] = pfr; |
|
1670 pfr += 2; |
|
1671 } |
|
1672 else |
|
1673 { |
|
1674 - if (pfr < end_pfr) |
|
1675 + if (pfr < end_pfr && i < nfixedargs) |
|
1676 { |
|
1677 /* Passed partly in f13 and partly on the stack. |
|
1678 Move it all to the stack. */ |
|
1679 @@ -1438,5 +1792,14 @@ ffi_closure_helper_LINUX64 (ffi_closure |
|
1680 (closure->fun) (cif, rvalue, avalue, closure->user_data); |
|
1681 |
|
1682 /* Tell ffi_closure_LINUX64 how to perform return type promotions. */ |
|
1683 + if ((cif->flags & FLAG_RETURNS_SMST) != 0) |
|
1684 + { |
|
1685 + if ((cif->flags & FLAG_RETURNS_FP) == 0) |
|
1686 + return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1; |
|
1687 + else if ((cif->flags & FLAG_RETURNS_64BITS) != 0) |
|
1688 + return FFI_V2_TYPE_DOUBLE_HOMOG; |
|
1689 + else |
|
1690 + return FFI_V2_TYPE_FLOAT_HOMOG; |
|
1691 + } |
|
1692 return cif->rtype->type; |
|
1693 } |
|
1694 --- mozilla/js/src/ctypes/libffi/src/powerpc/ffi_darwin.c 2013-10-24 09:56:51.846587814 +0200 |
|
1695 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/ffi_darwin.c 2013-11-29 17:23:26.000000000 +0100 |
|
1696 @@ -3,7 +3,7 @@ |
|
1697 |
|
1698 Copyright (C) 1998 Geoffrey Keating |
|
1699 Copyright (C) 2001 John Hornkvist |
|
1700 - Copyright (C) 2002, 2006, 2007, 2009 Free Software Foundation, Inc. |
|
1701 + Copyright (C) 2002, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. |
|
1702 |
|
1703 FFI support for Darwin and AIX. |
|
1704 |
|
1705 @@ -35,11 +35,17 @@ |
|
1706 extern void ffi_closure_ASM (void); |
|
1707 |
|
1708 enum { |
|
1709 - /* The assembly depends on these exact flags. */ |
|
1710 - FLAG_RETURNS_NOTHING = 1 << (31-30), /* These go in cr7 */ |
|
1711 - FLAG_RETURNS_FP = 1 << (31-29), |
|
1712 - FLAG_RETURNS_64BITS = 1 << (31-28), |
|
1713 - FLAG_RETURNS_128BITS = 1 << (31-31), |
|
1714 + /* The assembly depends on these exact flags. |
|
1715 + For Darwin64 (when FLAG_RETURNS_STRUCT is set): |
|
1716 + FLAG_RETURNS_FP indicates that the structure embeds FP data. |
|
1717 + FLAG_RETURNS_128BITS signals a special struct size that is not |
|
1718 + expanded for float content. */ |
|
1719 + FLAG_RETURNS_128BITS = 1 << (31-31), /* These go in cr7 */ |
|
1720 + FLAG_RETURNS_NOTHING = 1 << (31-30), |
|
1721 + FLAG_RETURNS_FP = 1 << (31-29), |
|
1722 + FLAG_RETURNS_64BITS = 1 << (31-28), |
|
1723 + |
|
1724 + FLAG_RETURNS_STRUCT = 1 << (31-27), /* This goes in cr6 */ |
|
1725 |
|
1726 FLAG_ARG_NEEDS_COPY = 1 << (31- 7), |
|
1727 FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ |
|
1728 @@ -50,43 +56,61 @@ enum { |
|
1729 /* About the DARWIN ABI. */ |
|
1730 enum { |
|
1731 NUM_GPR_ARG_REGISTERS = 8, |
|
1732 - NUM_FPR_ARG_REGISTERS = 13 |
|
1733 + NUM_FPR_ARG_REGISTERS = 13, |
|
1734 + LINKAGE_AREA_GPRS = 6 |
|
1735 }; |
|
1736 -enum { ASM_NEEDS_REGISTERS = 4 }; |
|
1737 + |
|
1738 +enum { ASM_NEEDS_REGISTERS = 4 }; /* r28-r31 */ |
|
1739 |
|
1740 /* ffi_prep_args is called by the assembly routine once stack space |
|
1741 has been allocated for the function's arguments. |
|
1742 + |
|
1743 + m32/m64 |
|
1744 |
|
1745 The stack layout we want looks like this: |
|
1746 |
|
1747 | Return address from ffi_call_DARWIN | higher addresses |
|
1748 |--------------------------------------------| |
|
1749 - | Previous backchain pointer 4 | stack pointer here |
|
1750 + | Previous backchain pointer 4/8 | stack pointer here |
|
1751 |--------------------------------------------|<+ <<< on entry to |
|
1752 - | Saved r28-r31 4*4 | | ffi_call_DARWIN |
|
1753 + | ASM_NEEDS_REGISTERS=r28-r31 4*(4/8) | | ffi_call_DARWIN |
|
1754 |--------------------------------------------| | |
|
1755 - | Parameters (at least 8*4=32) | | |
|
1756 + | When we have any FP activity... the | | |
|
1757 + | FPRs occupy NUM_FPR_ARG_REGISTERS slots | | |
|
1758 + | here fp13 .. fp1 from high to low addr. | | |
|
1759 + ~ ~ ~ |
|
1760 + | Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS |
|
1761 |--------------------------------------------| | |
|
1762 - | Space for GPR2 4 | | |
|
1763 + | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | |
|
1764 |--------------------------------------------| | stack | |
|
1765 - | Reserved 2*4 | | grows | |
|
1766 + | Reserved 2*4/8 | | grows | |
|
1767 |--------------------------------------------| | down V |
|
1768 - | Space for callee's LR 4 | | |
|
1769 + | Space for callee's LR 4/8 | | |
|
1770 |--------------------------------------------| | lower addresses |
|
1771 - | Saved CR 4 | | |
|
1772 + | Saved CR [low word for m64] 4/8 | | |
|
1773 |--------------------------------------------| | stack pointer here |
|
1774 - | Current backchain pointer 4 |-/ during |
|
1775 + | Current backchain pointer 4/8 |-/ during |
|
1776 |--------------------------------------------| <<< ffi_call_DARWIN |
|
1777 |
|
1778 */ |
|
1779 |
|
1780 +#if defined(POWERPC_DARWIN64) |
|
1781 +static void |
|
1782 +darwin64_pass_struct_by_value |
|
1783 + (ffi_type *, char *, unsigned, unsigned *, double **, unsigned long **); |
|
1784 +#endif |
|
1785 + |
|
1786 +/* This depends on GPR_SIZE = sizeof (unsigned long) */ |
|
1787 + |
|
1788 void |
|
1789 ffi_prep_args (extended_cif *ecif, unsigned long *const stack) |
|
1790 { |
|
1791 const unsigned bytes = ecif->cif->bytes; |
|
1792 const unsigned flags = ecif->cif->flags; |
|
1793 const unsigned nargs = ecif->cif->nargs; |
|
1794 +#if !defined(POWERPC_DARWIN64) |
|
1795 const ffi_abi abi = ecif->cif->abi; |
|
1796 +#endif |
|
1797 |
|
1798 /* 'stacktop' points at the previous backchain pointer. */ |
|
1799 unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long)); |
|
1800 @@ -94,18 +118,19 @@ ffi_prep_args (extended_cif *ecif, unsig |
|
1801 /* 'fpr_base' points at the space for fpr1, and grows upwards as |
|
1802 we use FPR registers. */ |
|
1803 double *fpr_base = (double *) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS; |
|
1804 - int fparg_count = 0; |
|
1805 - |
|
1806 + int gp_count = 0, fparg_count = 0; |
|
1807 |
|
1808 /* 'next_arg' grows up as we put parameters in it. */ |
|
1809 - unsigned long *next_arg = stack + 6; /* 6 reserved positions. */ |
|
1810 + unsigned long *next_arg = stack + LINKAGE_AREA_GPRS; /* 6 reserved positions. */ |
|
1811 |
|
1812 int i; |
|
1813 double double_tmp; |
|
1814 void **p_argv = ecif->avalue; |
|
1815 unsigned long gprvalue; |
|
1816 ffi_type** ptr = ecif->cif->arg_types; |
|
1817 +#if !defined(POWERPC_DARWIN64) |
|
1818 char *dest_cpy; |
|
1819 +#endif |
|
1820 unsigned size_al = 0; |
|
1821 |
|
1822 /* Check that everything starts aligned properly. */ |
|
1823 @@ -130,25 +155,30 @@ ffi_prep_args (extended_cif *ecif, unsig |
|
1824 the size of the floating-point parameter are skipped. */ |
|
1825 case FFI_TYPE_FLOAT: |
|
1826 double_tmp = *(float *) *p_argv; |
|
1827 - if (fparg_count >= NUM_FPR_ARG_REGISTERS) |
|
1828 - *(double *)next_arg = double_tmp; |
|
1829 - else |
|
1830 + if (fparg_count < NUM_FPR_ARG_REGISTERS) |
|
1831 *fpr_base++ = double_tmp; |
|
1832 +#if defined(POWERPC_DARWIN) |
|
1833 + *(float *)next_arg = *(float *) *p_argv; |
|
1834 +#else |
|
1835 + *(double *)next_arg = double_tmp; |
|
1836 +#endif |
|
1837 next_arg++; |
|
1838 + gp_count++; |
|
1839 fparg_count++; |
|
1840 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); |
|
1841 break; |
|
1842 |
|
1843 case FFI_TYPE_DOUBLE: |
|
1844 double_tmp = *(double *) *p_argv; |
|
1845 - if (fparg_count >= NUM_FPR_ARG_REGISTERS) |
|
1846 - *(double *)next_arg = double_tmp; |
|
1847 - else |
|
1848 + if (fparg_count < NUM_FPR_ARG_REGISTERS) |
|
1849 *fpr_base++ = double_tmp; |
|
1850 + *(double *)next_arg = double_tmp; |
|
1851 #ifdef POWERPC64 |
|
1852 next_arg++; |
|
1853 + gp_count++; |
|
1854 #else |
|
1855 next_arg += 2; |
|
1856 + gp_count += 2; |
|
1857 #endif |
|
1858 fparg_count++; |
|
1859 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); |
|
1860 @@ -157,30 +187,41 @@ ffi_prep_args (extended_cif *ecif, unsig |
|
1861 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
1862 |
|
1863 case FFI_TYPE_LONGDOUBLE: |
|
1864 -#ifdef POWERPC64 |
|
1865 +# if defined(POWERPC64) && !defined(POWERPC_DARWIN64) |
|
1866 + /* ??? This will exceed the regs count when the value starts at fp13 |
|
1867 + and it will not put the extra bit on the stack. */ |
|
1868 if (fparg_count < NUM_FPR_ARG_REGISTERS) |
|
1869 *(long double *) fpr_base++ = *(long double *) *p_argv; |
|
1870 else |
|
1871 *(long double *) next_arg = *(long double *) *p_argv; |
|
1872 next_arg += 2; |
|
1873 fparg_count += 2; |
|
1874 -#else |
|
1875 +# else |
|
1876 double_tmp = ((double *) *p_argv)[0]; |
|
1877 if (fparg_count < NUM_FPR_ARG_REGISTERS) |
|
1878 *fpr_base++ = double_tmp; |
|
1879 - else |
|
1880 - *(double *) next_arg = double_tmp; |
|
1881 + *(double *) next_arg = double_tmp; |
|
1882 +# if defined(POWERPC_DARWIN64) |
|
1883 + next_arg++; |
|
1884 + gp_count++; |
|
1885 +# else |
|
1886 next_arg += 2; |
|
1887 + gp_count += 2; |
|
1888 +# endif |
|
1889 fparg_count++; |
|
1890 - |
|
1891 double_tmp = ((double *) *p_argv)[1]; |
|
1892 if (fparg_count < NUM_FPR_ARG_REGISTERS) |
|
1893 *fpr_base++ = double_tmp; |
|
1894 - else |
|
1895 - *(double *) next_arg = double_tmp; |
|
1896 + *(double *) next_arg = double_tmp; |
|
1897 +# if defined(POWERPC_DARWIN64) |
|
1898 + next_arg++; |
|
1899 + gp_count++; |
|
1900 +# else |
|
1901 next_arg += 2; |
|
1902 + gp_count += 2; |
|
1903 +# endif |
|
1904 fparg_count++; |
|
1905 -#endif |
|
1906 +# endif |
|
1907 FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); |
|
1908 break; |
|
1909 #endif |
|
1910 @@ -192,6 +233,7 @@ ffi_prep_args (extended_cif *ecif, unsig |
|
1911 #else |
|
1912 *(long long *) next_arg = *(long long *) *p_argv; |
|
1913 next_arg += 2; |
|
1914 + gp_count += 2; |
|
1915 #endif |
|
1916 break; |
|
1917 case FFI_TYPE_POINTER: |
|
1918 @@ -211,32 +253,35 @@ ffi_prep_args (extended_cif *ecif, unsig |
|
1919 goto putgpr; |
|
1920 |
|
1921 case FFI_TYPE_STRUCT: |
|
1922 -#ifdef POWERPC64 |
|
1923 - dest_cpy = (char *) next_arg; |
|
1924 size_al = (*ptr)->size; |
|
1925 - if ((*ptr)->elements[0]->type == 3) |
|
1926 +#if defined(POWERPC_DARWIN64) |
|
1927 + next_arg = (unsigned long *)ALIGN((char *)next_arg, (*ptr)->alignment); |
|
1928 + darwin64_pass_struct_by_value (*ptr, (char *) *p_argv, |
|
1929 + (unsigned) size_al, |
|
1930 + (unsigned int *) &fparg_count, |
|
1931 + &fpr_base, &next_arg); |
|
1932 +#else |
|
1933 + dest_cpy = (char *) next_arg; |
|
1934 + |
|
1935 + /* If the first member of the struct is a double, then include enough |
|
1936 + padding in the struct size to align it to double-word. */ |
|
1937 + if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) |
|
1938 size_al = ALIGN((*ptr)->size, 8); |
|
1939 - if (size_al < 3 && abi == FFI_DARWIN) |
|
1940 - dest_cpy += 4 - size_al; |
|
1941 |
|
1942 +# if defined(POWERPC64) |
|
1943 + FFI_ASSERT (abi != FFI_DARWIN); |
|
1944 memcpy ((char *) dest_cpy, (char *) *p_argv, size_al); |
|
1945 next_arg += (size_al + 7) / 8; |
|
1946 -#else |
|
1947 - dest_cpy = (char *) next_arg; |
|
1948 - |
|
1949 +# else |
|
1950 /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, |
|
1951 SI 4 bytes) are aligned as if they were those modes. |
|
1952 Structures with 3 byte in size are padded upwards. */ |
|
1953 - size_al = (*ptr)->size; |
|
1954 - /* If the first member of the struct is a double, then align |
|
1955 - the struct to double-word. */ |
|
1956 - if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) |
|
1957 - size_al = ALIGN((*ptr)->size, 8); |
|
1958 if (size_al < 3 && abi == FFI_DARWIN) |
|
1959 dest_cpy += 4 - size_al; |
|
1960 |
|
1961 memcpy((char *) dest_cpy, (char *) *p_argv, size_al); |
|
1962 next_arg += (size_al + 3) / 4; |
|
1963 +# endif |
|
1964 #endif |
|
1965 break; |
|
1966 |
|
1967 @@ -249,6 +294,7 @@ ffi_prep_args (extended_cif *ecif, unsig |
|
1968 gprvalue = *(unsigned int *) *p_argv; |
|
1969 putgpr: |
|
1970 *next_arg++ = gprvalue; |
|
1971 + gp_count++; |
|
1972 break; |
|
1973 default: |
|
1974 break; |
|
1975 @@ -262,8 +308,269 @@ ffi_prep_args (extended_cif *ecif, unsig |
|
1976 //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); |
|
1977 } |
|
1978 |
|
1979 +#if defined(POWERPC_DARWIN64) |
|
1980 + |
|
1981 +/* See if we can put some of the struct into fprs. |
|
1982 + This should not be called for structures of size 16 bytes, since these are not |
|
1983 + broken out this way. */ |
|
1984 +static void |
|
1985 +darwin64_scan_struct_for_floats (ffi_type *s, unsigned *nfpr) |
|
1986 +{ |
|
1987 + int i; |
|
1988 + |
|
1989 + FFI_ASSERT (s->type == FFI_TYPE_STRUCT) |
|
1990 + |
|
1991 + for (i = 0; s->elements[i] != NULL; i++) |
|
1992 + { |
|
1993 + ffi_type *p = s->elements[i]; |
|
1994 + switch (p->type) |
|
1995 + { |
|
1996 + case FFI_TYPE_STRUCT: |
|
1997 + darwin64_scan_struct_for_floats (p, nfpr); |
|
1998 + break; |
|
1999 + case FFI_TYPE_LONGDOUBLE: |
|
2000 + (*nfpr) += 2; |
|
2001 + break; |
|
2002 + case FFI_TYPE_DOUBLE: |
|
2003 + case FFI_TYPE_FLOAT: |
|
2004 + (*nfpr) += 1; |
|
2005 + break; |
|
2006 + default: |
|
2007 + break; |
|
2008 + } |
|
2009 + } |
|
2010 +} |
|
2011 + |
|
2012 +static int |
|
2013 +darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr) |
|
2014 +{ |
|
2015 + unsigned struct_offset=0, i; |
|
2016 + |
|
2017 + for (i = 0; s->elements[i] != NULL; i++) |
|
2018 + { |
|
2019 + char *item_base; |
|
2020 + ffi_type *p = s->elements[i]; |
|
2021 + /* Find the start of this item (0 for the first one). */ |
|
2022 + if (i > 0) |
|
2023 + struct_offset = ALIGN(struct_offset, p->alignment); |
|
2024 + |
|
2025 + item_base = src + struct_offset; |
|
2026 + |
|
2027 + switch (p->type) |
|
2028 + { |
|
2029 + case FFI_TYPE_STRUCT: |
|
2030 + if (darwin64_struct_size_exceeds_gprs_p (p, item_base, nfpr)) |
|
2031 + return 1; |
|
2032 + break; |
|
2033 + case FFI_TYPE_LONGDOUBLE: |
|
2034 + if (*nfpr >= NUM_FPR_ARG_REGISTERS) |
|
2035 + return 1; |
|
2036 + (*nfpr) += 1; |
|
2037 + item_base += 8; |
|
2038 + /* FALL THROUGH */ |
|
2039 + case FFI_TYPE_DOUBLE: |
|
2040 + if (*nfpr >= NUM_FPR_ARG_REGISTERS) |
|
2041 + return 1; |
|
2042 + (*nfpr) += 1; |
|
2043 + break; |
|
2044 + case FFI_TYPE_FLOAT: |
|
2045 + if (*nfpr >= NUM_FPR_ARG_REGISTERS) |
|
2046 + return 1; |
|
2047 + (*nfpr) += 1; |
|
2048 + break; |
|
2049 + default: |
|
2050 + /* If we try and place any item, that is non-float, once we've |
|
2051 + exceeded the 8 GPR mark, then we can't fit the struct. */ |
|
2052 + if ((unsigned long)item_base >= 8*8) |
|
2053 + return 1; |
|
2054 + break; |
|
2055 + } |
|
2056 + /* now count the size of what we just used. */ |
|
2057 + struct_offset += p->size; |
|
2058 + } |
|
2059 + return 0; |
|
2060 +} |
|
2061 + |
|
2062 +/* Can this struct be returned by value? */ |
|
2063 +int |
|
2064 +darwin64_struct_ret_by_value_p (ffi_type *s) |
|
2065 +{ |
|
2066 + unsigned nfp = 0; |
|
2067 + |
|
2068 + FFI_ASSERT (s && s->type == FFI_TYPE_STRUCT); |
|
2069 + |
|
2070 + /* The largest structure we can return is 8long + 13 doubles. */ |
|
2071 + if (s->size > 168) |
|
2072 + return 0; |
|
2073 + |
|
2074 + /* We can't pass more than 13 floats. */ |
|
2075 + darwin64_scan_struct_for_floats (s, &nfp); |
|
2076 + if (nfp > 13) |
|
2077 + return 0; |
|
2078 + |
|
2079 + /* If there are not too many floats, and the struct is |
|
2080 + small enough to accommodate in the GPRs, then it must be OK. */ |
|
2081 + if (s->size <= 64) |
|
2082 + return 1; |
|
2083 + |
|
2084 + /* Well, we have to look harder. */ |
|
2085 + nfp = 0; |
|
2086 + if (darwin64_struct_size_exceeds_gprs_p (s, NULL, &nfp)) |
|
2087 + return 0; |
|
2088 + |
|
2089 + return 1; |
|
2090 +} |
|
2091 + |
|
2092 +void |
|
2093 +darwin64_pass_struct_floats (ffi_type *s, char *src, |
|
2094 + unsigned *nfpr, double **fprs) |
|
2095 +{ |
|
2096 + int i; |
|
2097 + double *fpr_base = *fprs; |
|
2098 + unsigned struct_offset = 0; |
|
2099 + |
|
2100 + /* We don't assume anything about the alignment of the source. */ |
|
2101 + for (i = 0; s->elements[i] != NULL; i++) |
|
2102 + { |
|
2103 + char *item_base; |
|
2104 + ffi_type *p = s->elements[i]; |
|
2105 + /* Find the start of this item (0 for the first one). */ |
|
2106 + if (i > 0) |
|
2107 + struct_offset = ALIGN(struct_offset, p->alignment); |
|
2108 + item_base = src + struct_offset; |
|
2109 + |
|
2110 + switch (p->type) |
|
2111 + { |
|
2112 + case FFI_TYPE_STRUCT: |
|
2113 + darwin64_pass_struct_floats (p, item_base, nfpr, |
|
2114 + &fpr_base); |
|
2115 + break; |
|
2116 + case FFI_TYPE_LONGDOUBLE: |
|
2117 + if (*nfpr < NUM_FPR_ARG_REGISTERS) |
|
2118 + *fpr_base++ = *(double *)item_base; |
|
2119 + (*nfpr) += 1; |
|
2120 + item_base += 8; |
|
2121 + /* FALL THROUGH */ |
|
2122 + case FFI_TYPE_DOUBLE: |
|
2123 + if (*nfpr < NUM_FPR_ARG_REGISTERS) |
|
2124 + *fpr_base++ = *(double *)item_base; |
|
2125 + (*nfpr) += 1; |
|
2126 + break; |
|
2127 + case FFI_TYPE_FLOAT: |
|
2128 + if (*nfpr < NUM_FPR_ARG_REGISTERS) |
|
2129 + *fpr_base++ = (double) *(float *)item_base; |
|
2130 + (*nfpr) += 1; |
|
2131 + break; |
|
2132 + default: |
|
2133 + break; |
|
2134 + } |
|
2135 + /* now count the size of what we just used. */ |
|
2136 + struct_offset += p->size; |
|
2137 + } |
|
2138 + /* Update the scores. */ |
|
2139 + *fprs = fpr_base; |
|
2140 +} |
|
2141 + |
|
2142 +/* Darwin64 special rules. |
|
2143 + Break out a struct into params and float registers. */ |
|
2144 +static void |
|
2145 +darwin64_pass_struct_by_value (ffi_type *s, char *src, unsigned size, |
|
2146 + unsigned *nfpr, double **fprs, unsigned long **arg) |
|
2147 +{ |
|
2148 + unsigned long *next_arg = *arg; |
|
2149 + char *dest_cpy = (char *)next_arg; |
|
2150 + |
|
2151 + FFI_ASSERT (s->type == FFI_TYPE_STRUCT) |
|
2152 + |
|
2153 + if (!size) |
|
2154 + return; |
|
2155 + |
|
2156 + /* First... special cases. */ |
|
2157 + if (size < 3 |
|
2158 + || (size == 4 |
|
2159 + && s->elements[0] |
|
2160 + && s->elements[0]->type != FFI_TYPE_FLOAT)) |
|
2161 + { |
|
2162 + /* Must be at least one GPR, padding is unspecified in value, |
|
2163 + let's make it zero. */ |
|
2164 + *next_arg = 0UL; |
|
2165 + dest_cpy += 8 - size; |
|
2166 + memcpy ((char *) dest_cpy, src, size); |
|
2167 + next_arg++; |
|
2168 + } |
|
2169 + else if (size == 16) |
|
2170 + { |
|
2171 + memcpy ((char *) dest_cpy, src, size); |
|
2172 + next_arg += 2; |
|
2173 + } |
|
2174 + else |
|
2175 + { |
|
2176 + /* now the general case, we consider embedded floats. */ |
|
2177 + memcpy ((char *) dest_cpy, src, size); |
|
2178 + darwin64_pass_struct_floats (s, src, nfpr, fprs); |
|
2179 + next_arg += (size+7)/8; |
|
2180 + } |
|
2181 + |
|
2182 + *arg = next_arg; |
|
2183 +} |
|
2184 + |
|
2185 +double * |
|
2186 +darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned *nf) |
|
2187 +{ |
|
2188 + int i; |
|
2189 + unsigned struct_offset = 0; |
|
2190 + |
|
2191 + /* We don't assume anything about the alignment of the source. */ |
|
2192 + for (i = 0; s->elements[i] != NULL; i++) |
|
2193 + { |
|
2194 + char *item_base; |
|
2195 + ffi_type *p = s->elements[i]; |
|
2196 + /* Find the start of this item (0 for the first one). */ |
|
2197 + if (i > 0) |
|
2198 + struct_offset = ALIGN(struct_offset, p->alignment); |
|
2199 + item_base = dest + struct_offset; |
|
2200 + |
|
2201 + switch (p->type) |
|
2202 + { |
|
2203 + case FFI_TYPE_STRUCT: |
|
2204 + fprs = darwin64_struct_floats_to_mem (p, item_base, fprs, nf); |
|
2205 + break; |
|
2206 + case FFI_TYPE_LONGDOUBLE: |
|
2207 + if (*nf < NUM_FPR_ARG_REGISTERS) |
|
2208 + { |
|
2209 + *(double *)item_base = *fprs++ ; |
|
2210 + (*nf) += 1; |
|
2211 + } |
|
2212 + item_base += 8; |
|
2213 + /* FALL THROUGH */ |
|
2214 + case FFI_TYPE_DOUBLE: |
|
2215 + if (*nf < NUM_FPR_ARG_REGISTERS) |
|
2216 + { |
|
2217 + *(double *)item_base = *fprs++ ; |
|
2218 + (*nf) += 1; |
|
2219 + } |
|
2220 + break; |
|
2221 + case FFI_TYPE_FLOAT: |
|
2222 + if (*nf < NUM_FPR_ARG_REGISTERS) |
|
2223 + { |
|
2224 + *(float *)item_base = (float) *fprs++ ; |
|
2225 + (*nf) += 1; |
|
2226 + } |
|
2227 + break; |
|
2228 + default: |
|
2229 + break; |
|
2230 + } |
|
2231 + /* now count the size of what we just used. */ |
|
2232 + struct_offset += p->size; |
|
2233 + } |
|
2234 + return fprs; |
|
2235 +} |
|
2236 + |
|
2237 +#endif |
|
2238 + |
|
2239 /* Adjust the size of S to be correct for Darwin. |
|
2240 - On Darwin, the first field of a structure has natural alignment. */ |
|
2241 + On Darwin m32, the first field of a structure has natural alignment. |
|
2242 + On Darwin m64, all fields have natural alignment. */ |
|
2243 |
|
2244 static void |
|
2245 darwin_adjust_aggregate_sizes (ffi_type *s) |
|
2246 @@ -280,22 +587,29 @@ darwin_adjust_aggregate_sizes (ffi_type |
|
2247 int align; |
|
2248 |
|
2249 p = s->elements[i]; |
|
2250 - darwin_adjust_aggregate_sizes (p); |
|
2251 - if (i == 0 |
|
2252 - && (p->type == FFI_TYPE_UINT64 |
|
2253 - || p->type == FFI_TYPE_SINT64 |
|
2254 - || p->type == FFI_TYPE_DOUBLE |
|
2255 - || p->alignment == 8)) |
|
2256 - align = 8; |
|
2257 + if (p->type == FFI_TYPE_STRUCT) |
|
2258 + darwin_adjust_aggregate_sizes (p); |
|
2259 +#if defined(POWERPC_DARWIN64) |
|
2260 + /* Natural alignment for all items. */ |
|
2261 + align = p->alignment; |
|
2262 +#else |
|
2263 + /* Natrual alignment for the first item... */ |
|
2264 + if (i == 0) |
|
2265 + align = p->alignment; |
|
2266 else if (p->alignment == 16 || p->alignment < 4) |
|
2267 + /* .. subsequent items with vector or align < 4 have natural align. */ |
|
2268 align = p->alignment; |
|
2269 else |
|
2270 + /* .. or align is 4. */ |
|
2271 align = 4; |
|
2272 +#endif |
|
2273 + /* Pad, if necessary, before adding the current item. */ |
|
2274 s->size = ALIGN(s->size, align) + p->size; |
|
2275 } |
|
2276 |
|
2277 s->size = ALIGN(s->size, s->alignment); |
|
2278 |
|
2279 + /* This should not be necessary on m64, but harmless. */ |
|
2280 if (s->elements[0]->type == FFI_TYPE_UINT64 |
|
2281 || s->elements[0]->type == FFI_TYPE_SINT64 |
|
2282 || s->elements[0]->type == FFI_TYPE_DOUBLE |
|
2283 @@ -347,7 +661,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
2284 unsigned i; |
|
2285 ffi_type **ptr; |
|
2286 unsigned bytes; |
|
2287 - int fparg_count = 0, intarg_count = 0; |
|
2288 + unsigned fparg_count = 0, intarg_count = 0; |
|
2289 unsigned flags = 0; |
|
2290 unsigned size_al = 0; |
|
2291 |
|
2292 @@ -372,16 +686,25 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
2293 /* Space for the frame pointer, callee's LR, CR, etc, and for |
|
2294 the asm's temp regs. */ |
|
2295 |
|
2296 - bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); |
|
2297 + bytes = (LINKAGE_AREA_GPRS + ASM_NEEDS_REGISTERS) * sizeof(unsigned long); |
|
2298 |
|
2299 - /* Return value handling. The rules are as follows: |
|
2300 + /* Return value handling. |
|
2301 + The rules m32 are as follows: |
|
2302 - 32-bit (or less) integer values are returned in gpr3; |
|
2303 - - Structures of size <= 4 bytes also returned in gpr3; |
|
2304 - - 64-bit integer values and structures between 5 and 8 bytes are returned |
|
2305 - in gpr3 and gpr4; |
|
2306 + - structures of size <= 4 bytes also returned in gpr3; |
|
2307 + - 64-bit integer values [??? and structures between 5 and 8 bytes] are |
|
2308 + returned in gpr3 and gpr4; |
|
2309 - Single/double FP values are returned in fpr1; |
|
2310 - Long double FP (if not equivalent to double) values are returned in |
|
2311 fpr1 and fpr2; |
|
2312 + m64: |
|
2313 + - 64-bit or smaller integral values are returned in GPR3 |
|
2314 + - Single/double FP values are returned in fpr1; |
|
2315 + - Long double FP values are returned in fpr1 and fpr2; |
|
2316 + m64 Structures: |
|
2317 + - If the structure could be accommodated in registers were it to be the |
|
2318 + first argument to a routine, then it is returned in those registers. |
|
2319 + m32/m64 structures otherwise: |
|
2320 - Larger structures values are allocated space and a pointer is passed |
|
2321 as the first argument. */ |
|
2322 switch (cif->rtype->type) |
|
2323 @@ -410,9 +733,42 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
2324 break; |
|
2325 |
|
2326 case FFI_TYPE_STRUCT: |
|
2327 +#if defined(POWERPC_DARWIN64) |
|
2328 + { |
|
2329 + /* Can we fit the struct into regs? */ |
|
2330 + if (darwin64_struct_ret_by_value_p (cif->rtype)) |
|
2331 + { |
|
2332 + unsigned nfpr = 0; |
|
2333 + flags |= FLAG_RETURNS_STRUCT; |
|
2334 + if (cif->rtype->size != 16) |
|
2335 + darwin64_scan_struct_for_floats (cif->rtype, &nfpr) ; |
|
2336 + else |
|
2337 + flags |= FLAG_RETURNS_128BITS; |
|
2338 + /* Will be 0 for 16byte struct. */ |
|
2339 + if (nfpr) |
|
2340 + flags |= FLAG_RETURNS_FP; |
|
2341 + } |
|
2342 + else /* By ref. */ |
|
2343 + { |
|
2344 + flags |= FLAG_RETVAL_REFERENCE; |
|
2345 + flags |= FLAG_RETURNS_NOTHING; |
|
2346 + intarg_count++; |
|
2347 + } |
|
2348 + } |
|
2349 +#elif defined(DARWIN_PPC) |
|
2350 + if (cif->rtype->size <= 4) |
|
2351 + flags |= FLAG_RETURNS_STRUCT; |
|
2352 + else /* else by reference. */ |
|
2353 + { |
|
2354 + flags |= FLAG_RETVAL_REFERENCE; |
|
2355 + flags |= FLAG_RETURNS_NOTHING; |
|
2356 + intarg_count++; |
|
2357 + } |
|
2358 +#else /* assume we pass by ref. */ |
|
2359 flags |= FLAG_RETVAL_REFERENCE; |
|
2360 flags |= FLAG_RETURNS_NOTHING; |
|
2361 intarg_count++; |
|
2362 +#endif |
|
2363 break; |
|
2364 case FFI_TYPE_VOID: |
|
2365 flags |= FLAG_RETURNS_NOTHING; |
|
2366 @@ -425,57 +781,83 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
2367 |
|
2368 /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the |
|
2369 first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest |
|
2370 - goes on the stack. Structures are passed as a pointer to a copy of |
|
2371 - the structure. Stuff on the stack needs to keep proper alignment. */ |
|
2372 + goes on the stack. |
|
2373 + ??? Structures are passed as a pointer to a copy of the structure. |
|
2374 + Stuff on the stack needs to keep proper alignment. |
|
2375 + For m64 the count is effectively of half-GPRs. */ |
|
2376 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) |
|
2377 { |
|
2378 + unsigned align_words; |
|
2379 switch ((*ptr)->type) |
|
2380 { |
|
2381 case FFI_TYPE_FLOAT: |
|
2382 case FFI_TYPE_DOUBLE: |
|
2383 fparg_count++; |
|
2384 +#if !defined(POWERPC_DARWIN64) |
|
2385 /* If this FP arg is going on the stack, it must be |
|
2386 8-byte-aligned. */ |
|
2387 if (fparg_count > NUM_FPR_ARG_REGISTERS |
|
2388 - && intarg_count%2 != 0) |
|
2389 + && (intarg_count & 0x01) != 0) |
|
2390 intarg_count++; |
|
2391 +#endif |
|
2392 break; |
|
2393 |
|
2394 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE |
|
2395 - |
|
2396 case FFI_TYPE_LONGDOUBLE: |
|
2397 fparg_count += 2; |
|
2398 /* If this FP arg is going on the stack, it must be |
|
2399 - 8-byte-aligned. */ |
|
2400 - if (fparg_count > NUM_FPR_ARG_REGISTERS |
|
2401 - && intarg_count%2 != 0) |
|
2402 - intarg_count++; |
|
2403 - intarg_count +=2; |
|
2404 + 16-byte-aligned. */ |
|
2405 + if (fparg_count >= NUM_FPR_ARG_REGISTERS) |
|
2406 +#if defined (POWERPC64) |
|
2407 + intarg_count = ALIGN(intarg_count, 2); |
|
2408 +#else |
|
2409 + intarg_count = ALIGN(intarg_count, 4); |
|
2410 +#endif |
|
2411 break; |
|
2412 #endif |
|
2413 |
|
2414 case FFI_TYPE_UINT64: |
|
2415 case FFI_TYPE_SINT64: |
|
2416 +#if defined(POWERPC64) |
|
2417 + intarg_count++; |
|
2418 +#else |
|
2419 /* 'long long' arguments are passed as two words, but |
|
2420 either both words must fit in registers or both go |
|
2421 on the stack. If they go on the stack, they must |
|
2422 be 8-byte-aligned. */ |
|
2423 if (intarg_count == NUM_GPR_ARG_REGISTERS-1 |
|
2424 - || (intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count%2 != 0)) |
|
2425 + || (intarg_count >= NUM_GPR_ARG_REGISTERS |
|
2426 + && (intarg_count & 0x01) != 0)) |
|
2427 intarg_count++; |
|
2428 intarg_count += 2; |
|
2429 +#endif |
|
2430 break; |
|
2431 |
|
2432 case FFI_TYPE_STRUCT: |
|
2433 size_al = (*ptr)->size; |
|
2434 +#if defined(POWERPC_DARWIN64) |
|
2435 + align_words = (*ptr)->alignment >> 3; |
|
2436 + if (align_words) |
|
2437 + intarg_count = ALIGN(intarg_count, align_words); |
|
2438 + /* Base size of the struct. */ |
|
2439 + intarg_count += (size_al + 7) / 8; |
|
2440 + /* If 16 bytes then don't worry about floats. */ |
|
2441 + if (size_al != 16) |
|
2442 + /* Scan through for floats to be placed in regs. */ |
|
2443 + darwin64_scan_struct_for_floats (*ptr, &fparg_count) ; |
|
2444 +#else |
|
2445 + align_words = (*ptr)->alignment >> 2; |
|
2446 + if (align_words) |
|
2447 + intarg_count = ALIGN(intarg_count, align_words); |
|
2448 /* If the first member of the struct is a double, then align |
|
2449 - the struct to double-word. */ |
|
2450 + the struct to double-word. |
|
2451 if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) |
|
2452 - size_al = ALIGN((*ptr)->size, 8); |
|
2453 -#ifdef POWERPC64 |
|
2454 + size_al = ALIGN((*ptr)->size, 8); */ |
|
2455 +# ifdef POWERPC64 |
|
2456 intarg_count += (size_al + 7) / 8; |
|
2457 -#else |
|
2458 +# else |
|
2459 intarg_count += (size_al + 3) / 4; |
|
2460 +# endif |
|
2461 #endif |
|
2462 break; |
|
2463 |
|
2464 @@ -490,9 +872,18 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
2465 if (fparg_count != 0) |
|
2466 flags |= FLAG_FP_ARGUMENTS; |
|
2467 |
|
2468 +#if defined(POWERPC_DARWIN64) |
|
2469 + /* Space to image the FPR registers, if needed - which includes when they might be |
|
2470 + used in a struct return. */ |
|
2471 + if (fparg_count != 0 |
|
2472 + || ((flags & FLAG_RETURNS_STRUCT) |
|
2473 + && (flags & FLAG_RETURNS_FP))) |
|
2474 + bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); |
|
2475 +#else |
|
2476 /* Space for the FPR registers, if needed. */ |
|
2477 if (fparg_count != 0) |
|
2478 bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); |
|
2479 +#endif |
|
2480 |
|
2481 /* Stack space. */ |
|
2482 #ifdef POWERPC64 |
|
2483 @@ -506,7 +897,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
2484 bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); |
|
2485 |
|
2486 /* The stack space allocated needs to be a multiple of 16 bytes. */ |
|
2487 - bytes = (bytes + 15) & ~0xF; |
|
2488 + bytes = ALIGN(bytes, 16) ; |
|
2489 |
|
2490 cif->flags = flags; |
|
2491 cif->bytes = bytes; |
|
2492 @@ -516,8 +907,9 @@ ffi_prep_cif_machdep (ffi_cif *cif) |
|
2493 |
|
2494 extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *, |
|
2495 void (*fn)(void), void (*fn2)(void)); |
|
2496 + |
|
2497 extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *, |
|
2498 - void (*fn)(void), void (*fn2)(void)); |
|
2499 + void (*fn)(void), void (*fn2)(void), ffi_type*); |
|
2500 |
|
2501 void |
|
2502 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) |
|
2503 @@ -546,7 +938,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void) |
|
2504 break; |
|
2505 case FFI_DARWIN: |
|
2506 ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn, |
|
2507 - FFI_FN(ffi_prep_args)); |
|
2508 + FFI_FN(ffi_prep_args), cif->rtype); |
|
2509 break; |
|
2510 default: |
|
2511 FFI_ASSERT(0); |
|
2512 @@ -566,58 +958,48 @@ typedef struct aix_fd_struct { |
|
2513 } aix_fd; |
|
2514 |
|
2515 /* here I'd like to add the stack frame layout we use in darwin_closure.S |
|
2516 - and aix_clsoure.S |
|
2517 + and aix_closure.S |
|
2518 + |
|
2519 + m32/m64 |
|
2520 |
|
2521 - SP previous -> +---------------------------------------+ <--- child frame |
|
2522 - | back chain to caller 4 | |
|
2523 - +---------------------------------------+ 4 |
|
2524 - | saved CR 4 | |
|
2525 - +---------------------------------------+ 8 |
|
2526 - | saved LR 4 | |
|
2527 - +---------------------------------------+ 12 |
|
2528 - | reserved for compilers 4 | |
|
2529 - +---------------------------------------+ 16 |
|
2530 - | reserved for binders 4 | |
|
2531 - +---------------------------------------+ 20 |
|
2532 - | saved TOC pointer 4 | |
|
2533 - +---------------------------------------+ 24 |
|
2534 - | always reserved 8*4=32 (previous GPRs)| |
|
2535 - | according to the linkage convention | |
|
2536 - | from AIX | |
|
2537 - +---------------------------------------+ 56 |
|
2538 - | our FPR area 13*8=104 | |
|
2539 - | f1 | |
|
2540 - | . | |
|
2541 - | f13 | |
|
2542 - +---------------------------------------+ 160 |
|
2543 - | result area 8 | |
|
2544 - +---------------------------------------+ 168 |
|
2545 - | alignement to the next multiple of 16 | |
|
2546 -SP current --> +---------------------------------------+ 176 <- parent frame |
|
2547 - | back chain to caller 4 | |
|
2548 - +---------------------------------------+ 180 |
|
2549 - | saved CR 4 | |
|
2550 - +---------------------------------------+ 184 |
|
2551 - | saved LR 4 | |
|
2552 - +---------------------------------------+ 188 |
|
2553 - | reserved for compilers 4 | |
|
2554 - +---------------------------------------+ 192 |
|
2555 - | reserved for binders 4 | |
|
2556 - +---------------------------------------+ 196 |
|
2557 - | saved TOC pointer 4 | |
|
2558 - +---------------------------------------+ 200 |
|
2559 - | always reserved 8*4=32 we store our | |
|
2560 - | GPRs here | |
|
2561 - | r3 | |
|
2562 - | . | |
|
2563 - | r10 | |
|
2564 - +---------------------------------------+ 232 |
|
2565 - | overflow part | |
|
2566 - +---------------------------------------+ xxx |
|
2567 - | ???? | |
|
2568 - +---------------------------------------+ xxx |
|
2569 + The stack layout looks like this: |
|
2570 + |
|
2571 + | Additional params... | | Higher address |
|
2572 + ~ ~ ~ |
|
2573 + | Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS |
|
2574 + |--------------------------------------------| | |
|
2575 + | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | |
|
2576 + |--------------------------------------------| | |
|
2577 + | Reserved 2*4/8 | | |
|
2578 + |--------------------------------------------| | |
|
2579 + | Space for callee's LR 4/8 | | |
|
2580 + |--------------------------------------------| | |
|
2581 + | Saved CR [low word for m64] 4/8 | | |
|
2582 + |--------------------------------------------| | |
|
2583 + | Current backchain pointer 4/8 |-/ Parent's frame. |
|
2584 + |--------------------------------------------| <+ <<< on entry to ffi_closure_ASM |
|
2585 + | Result Bytes 16 | | |
|
2586 + |--------------------------------------------| | |
|
2587 + ~ padding to 16-byte alignment ~ ~ |
|
2588 + |--------------------------------------------| | |
|
2589 + | NUM_FPR_ARG_REGISTERS slots | | |
|
2590 + | here fp13 .. fp1 13*8 | | |
|
2591 + |--------------------------------------------| | |
|
2592 + | R3..R10 8*4/8=32/64 | | NUM_GPR_ARG_REGISTERS |
|
2593 + |--------------------------------------------| | |
|
2594 + | TOC=R2 (AIX) Reserved (Darwin) 4/8 | | |
|
2595 + |--------------------------------------------| | stack | |
|
2596 + | Reserved [compiler,binder] 2*4/8 | | grows | |
|
2597 + |--------------------------------------------| | down V |
|
2598 + | Space for callee's LR 4/8 | | |
|
2599 + |--------------------------------------------| | lower addresses |
|
2600 + | Saved CR [low word for m64] 4/8 | | |
|
2601 + |--------------------------------------------| | stack pointer here |
|
2602 + | Current backchain pointer 4/8 |-/ during |
|
2603 + |--------------------------------------------| <<< ffi_closure_ASM. |
|
2604 |
|
2605 */ |
|
2606 + |
|
2607 ffi_status |
|
2608 ffi_prep_closure_loc (ffi_closure* closure, |
|
2609 ffi_cif* cif, |
|
2610 @@ -631,30 +1013,44 @@ ffi_prep_closure_loc (ffi_closure* closu |
|
2611 |
|
2612 switch (cif->abi) |
|
2613 { |
|
2614 - case FFI_DARWIN: |
|
2615 + case FFI_DARWIN: |
|
2616 |
|
2617 - FFI_ASSERT (cif->abi == FFI_DARWIN); |
|
2618 + FFI_ASSERT (cif->abi == FFI_DARWIN); |
|
2619 |
|
2620 - tramp = (unsigned int *) &closure->tramp[0]; |
|
2621 - tramp[0] = 0x7c0802a6; /* mflr r0 */ |
|
2622 - tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */ |
|
2623 - tramp[4] = 0x7d6802a6; /* mflr r11 */ |
|
2624 - tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */ |
|
2625 - tramp[6] = 0x7c0803a6; /* mtlr r0 */ |
|
2626 - tramp[7] = 0x7d8903a6; /* mtctr r12 */ |
|
2627 - tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */ |
|
2628 - tramp[9] = 0x4e800420; /* bctr */ |
|
2629 - tramp[2] = (unsigned long) ffi_closure_ASM; /* function */ |
|
2630 - tramp[3] = (unsigned long) codeloc; /* context */ |
|
2631 + tramp = (unsigned int *) &closure->tramp[0]; |
|
2632 +#if defined(POWERPC_DARWIN64) |
|
2633 + tramp[0] = 0x7c0802a6; /* mflr r0 */ |
|
2634 + tramp[1] = 0x429f0015; /* bcl- 20,4*cr7+so, +0x18 (L1) */ |
|
2635 + /* We put the addresses here. */ |
|
2636 + tramp[6] = 0x7d6802a6; /*L1: mflr r11 */ |
|
2637 + tramp[7] = 0xe98b0000; /* ld r12,0(r11) function address */ |
|
2638 + tramp[8] = 0x7c0803a6; /* mtlr r0 */ |
|
2639 + tramp[9] = 0x7d8903a6; /* mtctr r12 */ |
|
2640 + tramp[10] = 0xe96b0008; /* lwz r11,8(r11) static chain */ |
|
2641 + tramp[11] = 0x4e800420; /* bctr */ |
|
2642 |
|
2643 - closure->cif = cif; |
|
2644 - closure->fun = fun; |
|
2645 - closure->user_data = user_data; |
|
2646 + *((unsigned long *)&tramp[2]) = (unsigned long) ffi_closure_ASM; /* function */ |
|
2647 + *((unsigned long *)&tramp[4]) = (unsigned long) codeloc; /* context */ |
|
2648 +#else |
|
2649 + tramp[0] = 0x7c0802a6; /* mflr r0 */ |
|
2650 + tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */ |
|
2651 + tramp[4] = 0x7d6802a6; /* mflr r11 */ |
|
2652 + tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */ |
|
2653 + tramp[6] = 0x7c0803a6; /* mtlr r0 */ |
|
2654 + tramp[7] = 0x7d8903a6; /* mtctr r12 */ |
|
2655 + tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */ |
|
2656 + tramp[9] = 0x4e800420; /* bctr */ |
|
2657 + tramp[2] = (unsigned long) ffi_closure_ASM; /* function */ |
|
2658 + tramp[3] = (unsigned long) codeloc; /* context */ |
|
2659 +#endif |
|
2660 + closure->cif = cif; |
|
2661 + closure->fun = fun; |
|
2662 + closure->user_data = user_data; |
|
2663 |
|
2664 - /* Flush the icache. Only necessary on Darwin. */ |
|
2665 - flush_range(codeloc, FFI_TRAMPOLINE_SIZE); |
|
2666 + /* Flush the icache. Only necessary on Darwin. */ |
|
2667 + flush_range(codeloc, FFI_TRAMPOLINE_SIZE); |
|
2668 |
|
2669 - break; |
|
2670 + break; |
|
2671 |
|
2672 case FFI_AIX: |
|
2673 |
|
2674 @@ -669,10 +1065,10 @@ ffi_prep_closure_loc (ffi_closure* closu |
|
2675 closure->cif = cif; |
|
2676 closure->fun = fun; |
|
2677 closure->user_data = user_data; |
|
2678 + break; |
|
2679 |
|
2680 default: |
|
2681 - |
|
2682 - FFI_ASSERT(0); |
|
2683 + return FFI_BAD_ABI; |
|
2684 break; |
|
2685 } |
|
2686 return FFI_OK; |
|
2687 @@ -708,7 +1104,7 @@ typedef union |
|
2688 double d; |
|
2689 } ffi_dblfl; |
|
2690 |
|
2691 -int |
|
2692 +ffi_type * |
|
2693 ffi_closure_helper_DARWIN (ffi_closure *, void *, |
|
2694 unsigned long *, ffi_dblfl *); |
|
2695 |
|
2696 @@ -719,7 +1115,7 @@ ffi_closure_helper_DARWIN (ffi_closure * |
|
2697 up space for a return value, ffi_closure_ASM invokes the |
|
2698 following helper function to do most of the work. */ |
|
2699 |
|
2700 -int |
|
2701 +ffi_type * |
|
2702 ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, |
|
2703 unsigned long *pgr, ffi_dblfl *pfr) |
|
2704 { |
|
2705 @@ -741,16 +1137,32 @@ ffi_closure_helper_DARWIN (ffi_closure * |
|
2706 ffi_cif * cif; |
|
2707 ffi_dblfl * end_pfr = pfr + NUM_FPR_ARG_REGISTERS; |
|
2708 unsigned size_al; |
|
2709 +#if defined(POWERPC_DARWIN64) |
|
2710 + unsigned fpsused = 0; |
|
2711 +#endif |
|
2712 |
|
2713 cif = closure->cif; |
|
2714 avalue = alloca (cif->nargs * sizeof(void *)); |
|
2715 |
|
2716 - /* Copy the caller's structure return value address so that the closure |
|
2717 - returns the data directly to the caller. */ |
|
2718 if (cif->rtype->type == FFI_TYPE_STRUCT) |
|
2719 { |
|
2720 +#if defined(POWERPC_DARWIN64) |
|
2721 + if (!darwin64_struct_ret_by_value_p (cif->rtype)) |
|
2722 + { |
|
2723 + /* Won't fit into the regs - return by ref. */ |
|
2724 + rvalue = (void *) *pgr; |
|
2725 + pgr++; |
|
2726 + } |
|
2727 +#elif defined(DARWIN_PPC) |
|
2728 + if (cif->rtype->size > 4) |
|
2729 + { |
|
2730 + rvalue = (void *) *pgr; |
|
2731 + pgr++; |
|
2732 + } |
|
2733 +#else /* assume we return by ref. */ |
|
2734 rvalue = (void *) *pgr; |
|
2735 pgr++; |
|
2736 +#endif |
|
2737 } |
|
2738 |
|
2739 i = 0; |
|
2740 @@ -764,7 +1176,7 @@ ffi_closure_helper_DARWIN (ffi_closure * |
|
2741 { |
|
2742 case FFI_TYPE_SINT8: |
|
2743 case FFI_TYPE_UINT8: |
|
2744 -#ifdef POWERPC64 |
|
2745 +#if defined(POWERPC64) |
|
2746 avalue[i] = (char *) pgr + 7; |
|
2747 #else |
|
2748 avalue[i] = (char *) pgr + 3; |
|
2749 @@ -774,7 +1186,7 @@ ffi_closure_helper_DARWIN (ffi_closure * |
|
2750 |
|
2751 case FFI_TYPE_SINT16: |
|
2752 case FFI_TYPE_UINT16: |
|
2753 -#ifdef POWERPC64 |
|
2754 +#if defined(POWERPC64) |
|
2755 avalue[i] = (char *) pgr + 6; |
|
2756 #else |
|
2757 avalue[i] = (char *) pgr + 2; |
|
2758 @@ -784,7 +1196,7 @@ ffi_closure_helper_DARWIN (ffi_closure * |
|
2759 |
|
2760 case FFI_TYPE_SINT32: |
|
2761 case FFI_TYPE_UINT32: |
|
2762 -#ifdef POWERPC64 |
|
2763 +#if defined(POWERPC64) |
|
2764 avalue[i] = (char *) pgr + 4; |
|
2765 #else |
|
2766 case FFI_TYPE_POINTER: |
|
2767 @@ -794,34 +1206,53 @@ ffi_closure_helper_DARWIN (ffi_closure * |
|
2768 break; |
|
2769 |
|
2770 case FFI_TYPE_STRUCT: |
|
2771 -#ifdef POWERPC64 |
|
2772 size_al = arg_types[i]->size; |
|
2773 - if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) |
|
2774 - size_al = ALIGN (arg_types[i]->size, 8); |
|
2775 - if (size_al < 3 && cif->abi == FFI_DARWIN) |
|
2776 - avalue[i] = (char *) pgr + 8 - size_al; |
|
2777 - else |
|
2778 - avalue[i] = pgr; |
|
2779 +#if defined(POWERPC_DARWIN64) |
|
2780 + pgr = (unsigned long *)ALIGN((char *)pgr, arg_types[i]->alignment); |
|
2781 + if (size_al < 3 || size_al == 4) |
|
2782 + { |
|
2783 + avalue[i] = ((char *)pgr)+8-size_al; |
|
2784 + if (arg_types[i]->elements[0]->type == FFI_TYPE_FLOAT |
|
2785 + && fpsused < NUM_FPR_ARG_REGISTERS) |
|
2786 + { |
|
2787 + *(float *)pgr = (float) *(double *)pfr; |
|
2788 + pfr++; |
|
2789 + fpsused++; |
|
2790 + } |
|
2791 + } |
|
2792 + else |
|
2793 + { |
|
2794 + if (size_al != 16) |
|
2795 + pfr = (ffi_dblfl *) |
|
2796 + darwin64_struct_floats_to_mem (arg_types[i], (char *)pgr, |
|
2797 + (double *)pfr, &fpsused); |
|
2798 + avalue[i] = pgr; |
|
2799 + } |
|
2800 pgr += (size_al + 7) / 8; |
|
2801 #else |
|
2802 - /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, |
|
2803 - SI 4 bytes) are aligned as if they were those modes. */ |
|
2804 - size_al = arg_types[i]->size; |
|
2805 /* If the first member of the struct is a double, then align |
|
2806 the struct to double-word. */ |
|
2807 if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) |
|
2808 size_al = ALIGN(arg_types[i]->size, 8); |
|
2809 +# if defined(POWERPC64) |
|
2810 + FFI_ASSERT (cif->abi != FFI_DARWIN); |
|
2811 + avalue[i] = pgr; |
|
2812 + pgr += (size_al + 7) / 8; |
|
2813 +# else |
|
2814 + /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, |
|
2815 + SI 4 bytes) are aligned as if they were those modes. */ |
|
2816 if (size_al < 3 && cif->abi == FFI_DARWIN) |
|
2817 avalue[i] = (char*) pgr + 4 - size_al; |
|
2818 else |
|
2819 avalue[i] = pgr; |
|
2820 pgr += (size_al + 3) / 4; |
|
2821 +# endif |
|
2822 #endif |
|
2823 break; |
|
2824 |
|
2825 case FFI_TYPE_SINT64: |
|
2826 case FFI_TYPE_UINT64: |
|
2827 -#ifdef POWERPC64 |
|
2828 +#if defined(POWERPC64) |
|
2829 case FFI_TYPE_POINTER: |
|
2830 avalue[i] = pgr; |
|
2831 pgr++; |
|
2832 @@ -924,5 +1355,5 @@ ffi_closure_helper_DARWIN (ffi_closure * |
|
2833 (closure->fun) (cif, rvalue, avalue, closure->user_data); |
|
2834 |
|
2835 /* Tell ffi_closure_ASM to perform return type promotions. */ |
|
2836 - return cif->rtype->type; |
|
2837 + return cif->rtype; |
|
2838 } |
|
2839 --- mozilla/js/src/ctypes/libffi/src/powerpc/ffitarget.h 2013-10-24 09:56:51.847587813 +0200 |
|
2840 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/ffitarget.h 2013-11-29 17:23:26.000000000 +0100 |
|
2841 @@ -1,6 +1,8 @@ |
|
2842 /* -----------------------------------------------------------------*-C-*- |
|
2843 - ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. |
|
2844 - Copyright (C) 2007, 2008 Free Software Foundation, Inc |
|
2845 + ffitarget.h - Copyright (c) 2012 Anthony Green |
|
2846 + Copyright (C) 2007, 2008, 2010 Free Software Foundation, Inc |
|
2847 + Copyright (c) 1996-2003 Red Hat, Inc. |
|
2848 + |
|
2849 Target configuration macros for PowerPC. |
|
2850 |
|
2851 Permission is hereby granted, free of charge, to any person obtaining |
|
2852 @@ -28,16 +30,23 @@ |
|
2853 #ifndef LIBFFI_TARGET_H |
|
2854 #define LIBFFI_TARGET_H |
|
2855 |
|
2856 +#ifndef LIBFFI_H |
|
2857 +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." |
|
2858 +#endif |
|
2859 + |
|
2860 /* ---- System specific configurations ----------------------------------- */ |
|
2861 |
|
2862 #if defined (POWERPC) && defined (__powerpc64__) /* linux64 */ |
|
2863 #ifndef POWERPC64 |
|
2864 #define POWERPC64 |
|
2865 #endif |
|
2866 -#elif defined (POWERPC_DARWIN) && defined (__ppc64__) /* Darwin */ |
|
2867 +#elif defined (POWERPC_DARWIN) && defined (__ppc64__) /* Darwin64 */ |
|
2868 #ifndef POWERPC64 |
|
2869 #define POWERPC64 |
|
2870 #endif |
|
2871 +#ifndef POWERPC_DARWIN64 |
|
2872 +#define POWERPC_DARWIN64 |
|
2873 +#endif |
|
2874 #elif defined (POWERPC_AIX) && defined (__64BIT__) /* AIX64 */ |
|
2875 #ifndef POWERPC64 |
|
2876 #define POWERPC64 |
|
2877 @@ -57,18 +66,14 @@ typedef enum ffi_abi { |
|
2878 FFI_LINUX64, |
|
2879 FFI_LINUX, |
|
2880 FFI_LINUX_SOFT_FLOAT, |
|
2881 -# ifdef POWERPC64 |
|
2882 +# if defined(POWERPC64) |
|
2883 FFI_DEFAULT_ABI = FFI_LINUX64, |
|
2884 -# else |
|
2885 -# if (!defined(__NO_FPRS__) && (__LDBL_MANT_DIG__ == 106)) |
|
2886 - FFI_DEFAULT_ABI = FFI_LINUX, |
|
2887 -# else |
|
2888 -# ifdef __NO_FPRS__ |
|
2889 +# elif defined(__NO_FPRS__) |
|
2890 FFI_DEFAULT_ABI = FFI_LINUX_SOFT_FLOAT, |
|
2891 -# else |
|
2892 +# elif (__LDBL_MANT_DIG__ == 106) |
|
2893 + FFI_DEFAULT_ABI = FFI_LINUX, |
|
2894 +# else |
|
2895 FFI_DEFAULT_ABI = FFI_GCC_SYSV, |
|
2896 -# endif |
|
2897 -# endif |
|
2898 # endif |
|
2899 #endif |
|
2900 |
|
2901 @@ -101,6 +106,10 @@ typedef enum ffi_abi { |
|
2902 |
|
2903 #define FFI_CLOSURES 1 |
|
2904 #define FFI_NATIVE_RAW_API 0 |
|
2905 +#if defined (POWERPC) || defined (POWERPC_FREEBSD) |
|
2906 +# define FFI_TARGET_SPECIFIC_VARIADIC 1 |
|
2907 +# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs |
|
2908 +#endif |
|
2909 |
|
2910 /* For additional types like the below, take care about the order in |
|
2911 ppc_closures.S. They must follow after the FFI_TYPE_LAST. */ |
|
2912 @@ -113,10 +122,23 @@ typedef enum ffi_abi { |
|
2913 defined in ffi.c, to determine the exact return type and its size. */ |
|
2914 #define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2) |
|
2915 |
|
2916 -#if defined(POWERPC64) || defined(POWERPC_AIX) |
|
2917 -#define FFI_TRAMPOLINE_SIZE 24 |
|
2918 -#else /* POWERPC || POWERPC_AIX */ |
|
2919 -#define FFI_TRAMPOLINE_SIZE 40 |
|
2920 +/* Used by ELFv2 for homogenous structure returns. */ |
|
2921 +#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_TYPE_LAST + 1) |
|
2922 +#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_TYPE_LAST + 2) |
|
2923 +#define FFI_V2_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 3) |
|
2924 + |
|
2925 +#if _CALL_ELF == 2 |
|
2926 +# define FFI_TRAMPOLINE_SIZE 32 |
|
2927 +#else |
|
2928 +# if defined(POWERPC64) || defined(POWERPC_AIX) |
|
2929 +# if defined(POWERPC_DARWIN64) |
|
2930 +# define FFI_TRAMPOLINE_SIZE 48 |
|
2931 +# else |
|
2932 +# define FFI_TRAMPOLINE_SIZE 24 |
|
2933 +# endif |
|
2934 +# else /* POWERPC || POWERPC_AIX */ |
|
2935 +# define FFI_TRAMPOLINE_SIZE 40 |
|
2936 +# endif |
|
2937 #endif |
|
2938 |
|
2939 #ifndef LIBFFI_ASM |
|
2940 --- mozilla/js/src/ctypes/libffi/src/powerpc/linux64_closure.S 2013-10-24 09:56:51.847587813 +0200 |
|
2941 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/linux64_closure.S 2013-11-29 17:23:26.000000000 +0100 |
|
2942 @@ -32,66 +32,127 @@ |
|
2943 |
|
2944 #ifdef __powerpc64__ |
|
2945 FFI_HIDDEN (ffi_closure_LINUX64) |
|
2946 - FFI_HIDDEN (.ffi_closure_LINUX64) |
|
2947 - .globl ffi_closure_LINUX64, .ffi_closure_LINUX64 |
|
2948 + .globl ffi_closure_LINUX64 |
|
2949 +# if _CALL_ELF == 2 |
|
2950 + .text |
|
2951 +ffi_closure_LINUX64: |
|
2952 + addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha |
|
2953 + addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l |
|
2954 + .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64 |
|
2955 +# else |
|
2956 .section ".opd","aw" |
|
2957 .align 3 |
|
2958 ffi_closure_LINUX64: |
|
2959 +# ifdef _CALL_LINUX |
|
2960 + .quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0 |
|
2961 + .type ffi_closure_LINUX64,@function |
|
2962 + .text |
|
2963 +.L.ffi_closure_LINUX64: |
|
2964 +# else |
|
2965 + FFI_HIDDEN (.ffi_closure_LINUX64) |
|
2966 + .globl .ffi_closure_LINUX64 |
|
2967 .quad .ffi_closure_LINUX64,.TOC.@tocbase,0 |
|
2968 .size ffi_closure_LINUX64,24 |
|
2969 .type .ffi_closure_LINUX64,@function |
|
2970 .text |
|
2971 .ffi_closure_LINUX64: |
|
2972 +# endif |
|
2973 +# endif |
|
2974 + |
|
2975 +# if _CALL_ELF == 2 |
|
2976 +# 32 byte special reg save area + 64 byte parm save area and retval |
|
2977 +# + 13*8 fpr save area + round to 16 |
|
2978 +# define STACKFRAME 208 |
|
2979 +# define PARMSAVE 32 |
|
2980 +# No parameter save area is needed for the call to ffi_closure_helper_LINUX64, |
|
2981 +# so return value can start there. |
|
2982 +# define RETVAL PARMSAVE |
|
2983 +# else |
|
2984 +# 48 bytes special reg save area + 64 bytes parm save area |
|
2985 +# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16 |
|
2986 +# define STACKFRAME 240 |
|
2987 +# define PARMSAVE 48 |
|
2988 +# define RETVAL PARMSAVE+64 |
|
2989 +# endif |
|
2990 + |
|
2991 .LFB1: |
|
2992 - # save general regs into parm save area |
|
2993 - std %r3, 48(%r1) |
|
2994 - std %r4, 56(%r1) |
|
2995 - std %r5, 64(%r1) |
|
2996 - std %r6, 72(%r1) |
|
2997 +# if _CALL_ELF == 2 |
|
2998 + ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif |
|
2999 + mflr %r0 |
|
3000 + lwz %r12, 28(%r12) # cif->flags |
|
3001 + mtcrf 0x40, %r12 |
|
3002 + addi %r12, %r1, PARMSAVE |
|
3003 + bt 7, .Lparmsave |
|
3004 + # Our caller has not allocated a parameter save area. |
|
3005 + # We need to allocate one here and use it to pass gprs to |
|
3006 + # ffi_closure_helper_LINUX64. The return value area will do. |
|
3007 + addi %r12, %r1, -STACKFRAME+RETVAL |
|
3008 +.Lparmsave: |
|
3009 + std %r0, 16(%r1) |
|
3010 + # Save general regs into parm save area |
|
3011 + std %r3, 0(%r12) |
|
3012 + std %r4, 8(%r12) |
|
3013 + std %r5, 16(%r12) |
|
3014 + std %r6, 24(%r12) |
|
3015 + std %r7, 32(%r12) |
|
3016 + std %r8, 40(%r12) |
|
3017 + std %r9, 48(%r12) |
|
3018 + std %r10, 56(%r12) |
|
3019 + |
|
3020 + # load up the pointer to the parm save area |
|
3021 + mr %r5, %r12 |
|
3022 +# else |
|
3023 mflr %r0 |
|
3024 + # Save general regs into parm save area |
|
3025 + # This is the parameter save area set up by our caller. |
|
3026 + std %r3, PARMSAVE+0(%r1) |
|
3027 + std %r4, PARMSAVE+8(%r1) |
|
3028 + std %r5, PARMSAVE+16(%r1) |
|
3029 + std %r6, PARMSAVE+24(%r1) |
|
3030 + std %r7, PARMSAVE+32(%r1) |
|
3031 + std %r8, PARMSAVE+40(%r1) |
|
3032 + std %r9, PARMSAVE+48(%r1) |
|
3033 + std %r10, PARMSAVE+56(%r1) |
|
3034 |
|
3035 - std %r7, 80(%r1) |
|
3036 - std %r8, 88(%r1) |
|
3037 - std %r9, 96(%r1) |
|
3038 - std %r10, 104(%r1) |
|
3039 std %r0, 16(%r1) |
|
3040 |
|
3041 - # mandatory 48 bytes special reg save area + 64 bytes parm save area |
|
3042 - # + 16 bytes retval area + 13*8 bytes fpr save area + round to 16 |
|
3043 - stdu %r1, -240(%r1) |
|
3044 -.LCFI0: |
|
3045 + # load up the pointer to the parm save area |
|
3046 + addi %r5, %r1, PARMSAVE |
|
3047 +# endif |
|
3048 |
|
3049 # next save fpr 1 to fpr 13 |
|
3050 - stfd %f1, 128+(0*8)(%r1) |
|
3051 - stfd %f2, 128+(1*8)(%r1) |
|
3052 - stfd %f3, 128+(2*8)(%r1) |
|
3053 - stfd %f4, 128+(3*8)(%r1) |
|
3054 - stfd %f5, 128+(4*8)(%r1) |
|
3055 - stfd %f6, 128+(5*8)(%r1) |
|
3056 - stfd %f7, 128+(6*8)(%r1) |
|
3057 - stfd %f8, 128+(7*8)(%r1) |
|
3058 - stfd %f9, 128+(8*8)(%r1) |
|
3059 - stfd %f10, 128+(9*8)(%r1) |
|
3060 - stfd %f11, 128+(10*8)(%r1) |
|
3061 - stfd %f12, 128+(11*8)(%r1) |
|
3062 - stfd %f13, 128+(12*8)(%r1) |
|
3063 + stfd %f1, -104+(0*8)(%r1) |
|
3064 + stfd %f2, -104+(1*8)(%r1) |
|
3065 + stfd %f3, -104+(2*8)(%r1) |
|
3066 + stfd %f4, -104+(3*8)(%r1) |
|
3067 + stfd %f5, -104+(4*8)(%r1) |
|
3068 + stfd %f6, -104+(5*8)(%r1) |
|
3069 + stfd %f7, -104+(6*8)(%r1) |
|
3070 + stfd %f8, -104+(7*8)(%r1) |
|
3071 + stfd %f9, -104+(8*8)(%r1) |
|
3072 + stfd %f10, -104+(9*8)(%r1) |
|
3073 + stfd %f11, -104+(10*8)(%r1) |
|
3074 + stfd %f12, -104+(11*8)(%r1) |
|
3075 + stfd %f13, -104+(12*8)(%r1) |
|
3076 |
|
3077 - # set up registers for the routine that actually does the work |
|
3078 - # get the context pointer from the trampoline |
|
3079 - mr %r3, %r11 |
|
3080 + # load up the pointer to the saved fpr registers */ |
|
3081 + addi %r6, %r1, -104 |
|
3082 |
|
3083 - # now load up the pointer to the result storage |
|
3084 - addi %r4, %r1, 112 |
|
3085 + # load up the pointer to the result storage |
|
3086 + addi %r4, %r1, -STACKFRAME+RETVAL |
|
3087 |
|
3088 - # now load up the pointer to the parameter save area |
|
3089 - # in the previous frame |
|
3090 - addi %r5, %r1, 240 + 48 |
|
3091 + stdu %r1, -STACKFRAME(%r1) |
|
3092 +.LCFI0: |
|
3093 |
|
3094 - # now load up the pointer to the saved fpr registers */ |
|
3095 - addi %r6, %r1, 128 |
|
3096 + # get the context pointer from the trampoline |
|
3097 + mr %r3, %r11 |
|
3098 |
|
3099 # make the call |
|
3100 +# if defined _CALL_LINUX || _CALL_ELF == 2 |
|
3101 + bl ffi_closure_helper_LINUX64 |
|
3102 +# else |
|
3103 bl .ffi_closure_helper_LINUX64 |
|
3104 +# endif |
|
3105 .Lret: |
|
3106 |
|
3107 # now r3 contains the return type |
|
3108 @@ -100,10 +161,12 @@ ffi_closure_LINUX64: |
|
3109 |
|
3110 # look up the proper starting point in table |
|
3111 # by using return type as offset |
|
3112 + ld %r0, STACKFRAME+16(%r1) |
|
3113 + cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT |
|
3114 + bge .Lsmall |
|
3115 mflr %r4 # move address of .Lret to r4 |
|
3116 sldi %r3, %r3, 4 # now multiply return type by 16 |
|
3117 addi %r4, %r4, .Lret_type0 - .Lret |
|
3118 - ld %r0, 240+16(%r1) |
|
3119 add %r3, %r3, %r4 # add contents of table to table address |
|
3120 mtctr %r3 |
|
3121 bctr # jump to it |
|
3122 @@ -116,85 +179,175 @@ ffi_closure_LINUX64: |
|
3123 .Lret_type0: |
|
3124 # case FFI_TYPE_VOID |
|
3125 mtlr %r0 |
|
3126 - addi %r1, %r1, 240 |
|
3127 + addi %r1, %r1, STACKFRAME |
|
3128 blr |
|
3129 nop |
|
3130 # case FFI_TYPE_INT |
|
3131 - lwa %r3, 112+4(%r1) |
|
3132 +# ifdef __LITTLE_ENDIAN__ |
|
3133 + lwa %r3, RETVAL+0(%r1) |
|
3134 +# else |
|
3135 + lwa %r3, RETVAL+4(%r1) |
|
3136 +# endif |
|
3137 mtlr %r0 |
|
3138 - addi %r1, %r1, 240 |
|
3139 + addi %r1, %r1, STACKFRAME |
|
3140 blr |
|
3141 # case FFI_TYPE_FLOAT |
|
3142 - lfs %f1, 112+0(%r1) |
|
3143 + lfs %f1, RETVAL+0(%r1) |
|
3144 mtlr %r0 |
|
3145 - addi %r1, %r1, 240 |
|
3146 + addi %r1, %r1, STACKFRAME |
|
3147 blr |
|
3148 # case FFI_TYPE_DOUBLE |
|
3149 - lfd %f1, 112+0(%r1) |
|
3150 + lfd %f1, RETVAL+0(%r1) |
|
3151 mtlr %r0 |
|
3152 - addi %r1, %r1, 240 |
|
3153 + addi %r1, %r1, STACKFRAME |
|
3154 blr |
|
3155 # case FFI_TYPE_LONGDOUBLE |
|
3156 - lfd %f1, 112+0(%r1) |
|
3157 + lfd %f1, RETVAL+0(%r1) |
|
3158 mtlr %r0 |
|
3159 - lfd %f2, 112+8(%r1) |
|
3160 + lfd %f2, RETVAL+8(%r1) |
|
3161 b .Lfinish |
|
3162 # case FFI_TYPE_UINT8 |
|
3163 - lbz %r3, 112+7(%r1) |
|
3164 +# ifdef __LITTLE_ENDIAN__ |
|
3165 + lbz %r3, RETVAL+0(%r1) |
|
3166 +# else |
|
3167 + lbz %r3, RETVAL+7(%r1) |
|
3168 +# endif |
|
3169 mtlr %r0 |
|
3170 - addi %r1, %r1, 240 |
|
3171 + addi %r1, %r1, STACKFRAME |
|
3172 blr |
|
3173 # case FFI_TYPE_SINT8 |
|
3174 - lbz %r3, 112+7(%r1) |
|
3175 +# ifdef __LITTLE_ENDIAN__ |
|
3176 + lbz %r3, RETVAL+0(%r1) |
|
3177 +# else |
|
3178 + lbz %r3, RETVAL+7(%r1) |
|
3179 +# endif |
|
3180 extsb %r3,%r3 |
|
3181 mtlr %r0 |
|
3182 b .Lfinish |
|
3183 # case FFI_TYPE_UINT16 |
|
3184 - lhz %r3, 112+6(%r1) |
|
3185 +# ifdef __LITTLE_ENDIAN__ |
|
3186 + lhz %r3, RETVAL+0(%r1) |
|
3187 +# else |
|
3188 + lhz %r3, RETVAL+6(%r1) |
|
3189 +# endif |
|
3190 mtlr %r0 |
|
3191 .Lfinish: |
|
3192 - addi %r1, %r1, 240 |
|
3193 + addi %r1, %r1, STACKFRAME |
|
3194 blr |
|
3195 # case FFI_TYPE_SINT16 |
|
3196 - lha %r3, 112+6(%r1) |
|
3197 +# ifdef __LITTLE_ENDIAN__ |
|
3198 + lha %r3, RETVAL+0(%r1) |
|
3199 +# else |
|
3200 + lha %r3, RETVAL+6(%r1) |
|
3201 +# endif |
|
3202 mtlr %r0 |
|
3203 - addi %r1, %r1, 240 |
|
3204 + addi %r1, %r1, STACKFRAME |
|
3205 blr |
|
3206 # case FFI_TYPE_UINT32 |
|
3207 - lwz %r3, 112+4(%r1) |
|
3208 +# ifdef __LITTLE_ENDIAN__ |
|
3209 + lwz %r3, RETVAL+0(%r1) |
|
3210 +# else |
|
3211 + lwz %r3, RETVAL+4(%r1) |
|
3212 +# endif |
|
3213 mtlr %r0 |
|
3214 - addi %r1, %r1, 240 |
|
3215 + addi %r1, %r1, STACKFRAME |
|
3216 blr |
|
3217 # case FFI_TYPE_SINT32 |
|
3218 - lwa %r3, 112+4(%r1) |
|
3219 +# ifdef __LITTLE_ENDIAN__ |
|
3220 + lwa %r3, RETVAL+0(%r1) |
|
3221 +# else |
|
3222 + lwa %r3, RETVAL+4(%r1) |
|
3223 +# endif |
|
3224 mtlr %r0 |
|
3225 - addi %r1, %r1, 240 |
|
3226 + addi %r1, %r1, STACKFRAME |
|
3227 blr |
|
3228 # case FFI_TYPE_UINT64 |
|
3229 - ld %r3, 112+0(%r1) |
|
3230 + ld %r3, RETVAL+0(%r1) |
|
3231 mtlr %r0 |
|
3232 - addi %r1, %r1, 240 |
|
3233 + addi %r1, %r1, STACKFRAME |
|
3234 blr |
|
3235 # case FFI_TYPE_SINT64 |
|
3236 - ld %r3, 112+0(%r1) |
|
3237 + ld %r3, RETVAL+0(%r1) |
|
3238 mtlr %r0 |
|
3239 - addi %r1, %r1, 240 |
|
3240 + addi %r1, %r1, STACKFRAME |
|
3241 blr |
|
3242 # case FFI_TYPE_STRUCT |
|
3243 mtlr %r0 |
|
3244 - addi %r1, %r1, 240 |
|
3245 + addi %r1, %r1, STACKFRAME |
|
3246 blr |
|
3247 nop |
|
3248 # case FFI_TYPE_POINTER |
|
3249 - ld %r3, 112+0(%r1) |
|
3250 + ld %r3, RETVAL+0(%r1) |
|
3251 mtlr %r0 |
|
3252 - addi %r1, %r1, 240 |
|
3253 + addi %r1, %r1, STACKFRAME |
|
3254 + blr |
|
3255 +# case FFI_V2_TYPE_FLOAT_HOMOG |
|
3256 + lfs %f1, RETVAL+0(%r1) |
|
3257 + lfs %f2, RETVAL+4(%r1) |
|
3258 + lfs %f3, RETVAL+8(%r1) |
|
3259 + b .Lmorefloat |
|
3260 +# case FFI_V2_TYPE_DOUBLE_HOMOG |
|
3261 + lfd %f1, RETVAL+0(%r1) |
|
3262 + lfd %f2, RETVAL+8(%r1) |
|
3263 + lfd %f3, RETVAL+16(%r1) |
|
3264 + lfd %f4, RETVAL+24(%r1) |
|
3265 + mtlr %r0 |
|
3266 + lfd %f5, RETVAL+32(%r1) |
|
3267 + lfd %f6, RETVAL+40(%r1) |
|
3268 + lfd %f7, RETVAL+48(%r1) |
|
3269 + lfd %f8, RETVAL+56(%r1) |
|
3270 + addi %r1, %r1, STACKFRAME |
|
3271 + blr |
|
3272 +.Lmorefloat: |
|
3273 + lfs %f4, RETVAL+12(%r1) |
|
3274 + mtlr %r0 |
|
3275 + lfs %f5, RETVAL+16(%r1) |
|
3276 + lfs %f6, RETVAL+20(%r1) |
|
3277 + lfs %f7, RETVAL+24(%r1) |
|
3278 + lfs %f8, RETVAL+28(%r1) |
|
3279 + addi %r1, %r1, STACKFRAME |
|
3280 + blr |
|
3281 +.Lsmall: |
|
3282 +# ifdef __LITTLE_ENDIAN__ |
|
3283 + ld %r3,RETVAL+0(%r1) |
|
3284 + mtlr %r0 |
|
3285 + ld %r4,RETVAL+8(%r1) |
|
3286 + addi %r1, %r1, STACKFRAME |
|
3287 + blr |
|
3288 +# else |
|
3289 + # A struct smaller than a dword is returned in the low bits of r3 |
|
3290 + # ie. right justified. Larger structs are passed left justified |
|
3291 + # in r3 and r4. The return value area on the stack will have |
|
3292 + # the structs as they are usually stored in memory. |
|
3293 + cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes? |
|
3294 + neg %r5, %r3 |
|
3295 + ld %r3,RETVAL+0(%r1) |
|
3296 + blt .Lsmalldown |
|
3297 + mtlr %r0 |
|
3298 + ld %r4,RETVAL+8(%r1) |
|
3299 + addi %r1, %r1, STACKFRAME |
|
3300 + blr |
|
3301 +.Lsmalldown: |
|
3302 + addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7 |
|
3303 + mtlr %r0 |
|
3304 + sldi %r5, %r5, 3 |
|
3305 + addi %r1, %r1, STACKFRAME |
|
3306 + srd %r3, %r3, %r5 |
|
3307 blr |
|
3308 -# esac |
|
3309 +# endif |
|
3310 + |
|
3311 .LFE1: |
|
3312 .long 0 |
|
3313 .byte 0,12,0,1,128,0,0,0 |
|
3314 +# if _CALL_ELF == 2 |
|
3315 + .size ffi_closure_LINUX64,.-ffi_closure_LINUX64 |
|
3316 +# else |
|
3317 +# ifdef _CALL_LINUX |
|
3318 + .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64 |
|
3319 +# else |
|
3320 .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64 |
|
3321 +# endif |
|
3322 +# endif |
|
3323 |
|
3324 .section .eh_frame,EH_FRAME_FLAGS,@progbits |
|
3325 .Lframe1: |
|
3326 @@ -223,14 +376,14 @@ ffi_closure_LINUX64: |
|
3327 .byte 0x2 # DW_CFA_advance_loc1 |
|
3328 .byte .LCFI0-.LFB1 |
|
3329 .byte 0xe # DW_CFA_def_cfa_offset |
|
3330 - .uleb128 240 |
|
3331 + .uleb128 STACKFRAME |
|
3332 .byte 0x11 # DW_CFA_offset_extended_sf |
|
3333 .uleb128 0x41 |
|
3334 .sleb128 -2 |
|
3335 .align 3 |
|
3336 .LEFDE1: |
|
3337 -#endif |
|
3338 |
|
3339 -#if defined __ELF__ && defined __linux__ |
|
3340 +# if defined __ELF__ && defined __linux__ |
|
3341 .section .note.GNU-stack,"",@progbits |
|
3342 +# endif |
|
3343 #endif |
|
3344 --- mozilla/js/src/ctypes/libffi/src/powerpc/linux64.S 2013-10-24 09:56:51.847587813 +0200 |
|
3345 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/linux64.S 2013-11-29 17:23:26.000000000 +0100 |
|
3346 @@ -30,16 +30,33 @@ |
|
3347 #include <ffi.h> |
|
3348 |
|
3349 #ifdef __powerpc64__ |
|
3350 - .hidden ffi_call_LINUX64, .ffi_call_LINUX64 |
|
3351 - .globl ffi_call_LINUX64, .ffi_call_LINUX64 |
|
3352 + .hidden ffi_call_LINUX64 |
|
3353 + .globl ffi_call_LINUX64 |
|
3354 +# if _CALL_ELF == 2 |
|
3355 + .text |
|
3356 +ffi_call_LINUX64: |
|
3357 + addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha |
|
3358 + addi %r2, %r2, .TOC.-ffi_call_LINUX64@l |
|
3359 + .localentry ffi_call_LINUX64, . - ffi_call_LINUX64 |
|
3360 +# else |
|
3361 .section ".opd","aw" |
|
3362 .align 3 |
|
3363 ffi_call_LINUX64: |
|
3364 +# ifdef _CALL_LINUX |
|
3365 + .quad .L.ffi_call_LINUX64,.TOC.@tocbase,0 |
|
3366 + .type ffi_call_LINUX64,@function |
|
3367 + .text |
|
3368 +.L.ffi_call_LINUX64: |
|
3369 +# else |
|
3370 + .hidden .ffi_call_LINUX64 |
|
3371 + .globl .ffi_call_LINUX64 |
|
3372 .quad .ffi_call_LINUX64,.TOC.@tocbase,0 |
|
3373 .size ffi_call_LINUX64,24 |
|
3374 .type .ffi_call_LINUX64,@function |
|
3375 .text |
|
3376 .ffi_call_LINUX64: |
|
3377 +# endif |
|
3378 +# endif |
|
3379 .LFB1: |
|
3380 mflr %r0 |
|
3381 std %r28, -32(%r1) |
|
3382 @@ -54,22 +71,35 @@ ffi_call_LINUX64: |
|
3383 mr %r31, %r5 /* flags, */ |
|
3384 mr %r30, %r6 /* rvalue, */ |
|
3385 mr %r29, %r7 /* function address. */ |
|
3386 +/* Save toc pointer, not for the ffi_prep_args64 call, but for the later |
|
3387 + bctrl function call. */ |
|
3388 +# if _CALL_ELF == 2 |
|
3389 + std %r2, 24(%r1) |
|
3390 +# else |
|
3391 std %r2, 40(%r1) |
|
3392 +# endif |
|
3393 |
|
3394 /* Call ffi_prep_args64. */ |
|
3395 mr %r4, %r1 |
|
3396 +# if defined _CALL_LINUX || _CALL_ELF == 2 |
|
3397 + bl ffi_prep_args64 |
|
3398 +# else |
|
3399 bl .ffi_prep_args64 |
|
3400 +# endif |
|
3401 |
|
3402 - ld %r0, 0(%r29) |
|
3403 +# if _CALL_ELF == 2 |
|
3404 + mr %r12, %r29 |
|
3405 +# else |
|
3406 + ld %r12, 0(%r29) |
|
3407 ld %r2, 8(%r29) |
|
3408 ld %r11, 16(%r29) |
|
3409 - |
|
3410 +# endif |
|
3411 /* Now do the call. */ |
|
3412 /* Set up cr1 with bits 4-7 of the flags. */ |
|
3413 mtcrf 0x40, %r31 |
|
3414 |
|
3415 /* Get the address to call into CTR. */ |
|
3416 - mtctr %r0 |
|
3417 + mtctr %r12 |
|
3418 /* Load all those argument registers. */ |
|
3419 ld %r3, -32-(8*8)(%r28) |
|
3420 ld %r4, -32-(7*8)(%r28) |
|
3421 @@ -104,12 +134,17 @@ ffi_call_LINUX64: |
|
3422 |
|
3423 /* This must follow the call immediately, the unwinder |
|
3424 uses this to find out if r2 has been saved or not. */ |
|
3425 +# if _CALL_ELF == 2 |
|
3426 + ld %r2, 24(%r1) |
|
3427 +# else |
|
3428 ld %r2, 40(%r1) |
|
3429 +# endif |
|
3430 |
|
3431 /* Now, deal with the return value. */ |
|
3432 mtcrf 0x01, %r31 |
|
3433 - bt- 30, .Ldone_return_value |
|
3434 - bt- 29, .Lfp_return_value |
|
3435 + bt 31, .Lstruct_return_value |
|
3436 + bt 30, .Ldone_return_value |
|
3437 + bt 29, .Lfp_return_value |
|
3438 std %r3, 0(%r30) |
|
3439 /* Fall through... */ |
|
3440 |
|
3441 @@ -117,7 +152,7 @@ ffi_call_LINUX64: |
|
3442 /* Restore the registers we used and return. */ |
|
3443 mr %r1, %r28 |
|
3444 ld %r0, 16(%r28) |
|
3445 - ld %r28, -32(%r1) |
|
3446 + ld %r28, -32(%r28) |
|
3447 mtlr %r0 |
|
3448 ld %r29, -24(%r1) |
|
3449 ld %r30, -16(%r1) |
|
3450 @@ -134,10 +169,48 @@ ffi_call_LINUX64: |
|
3451 .Lfloat_return_value: |
|
3452 stfs %f1, 0(%r30) |
|
3453 b .Ldone_return_value |
|
3454 + |
|
3455 +.Lstruct_return_value: |
|
3456 + bf 29, .Lsmall_struct |
|
3457 + bf 28, .Lfloat_homog_return_value |
|
3458 + stfd %f1, 0(%r30) |
|
3459 + stfd %f2, 8(%r30) |
|
3460 + stfd %f3, 16(%r30) |
|
3461 + stfd %f4, 24(%r30) |
|
3462 + stfd %f5, 32(%r30) |
|
3463 + stfd %f6, 40(%r30) |
|
3464 + stfd %f7, 48(%r30) |
|
3465 + stfd %f8, 56(%r30) |
|
3466 + b .Ldone_return_value |
|
3467 + |
|
3468 +.Lfloat_homog_return_value: |
|
3469 + stfs %f1, 0(%r30) |
|
3470 + stfs %f2, 4(%r30) |
|
3471 + stfs %f3, 8(%r30) |
|
3472 + stfs %f4, 12(%r30) |
|
3473 + stfs %f5, 16(%r30) |
|
3474 + stfs %f6, 20(%r30) |
|
3475 + stfs %f7, 24(%r30) |
|
3476 + stfs %f8, 28(%r30) |
|
3477 + b .Ldone_return_value |
|
3478 + |
|
3479 +.Lsmall_struct: |
|
3480 + std %r3, 0(%r30) |
|
3481 + std %r4, 8(%r30) |
|
3482 + b .Ldone_return_value |
|
3483 + |
|
3484 .LFE1: |
|
3485 .long 0 |
|
3486 .byte 0,12,0,1,128,4,0,0 |
|
3487 +# if _CALL_ELF == 2 |
|
3488 + .size ffi_call_LINUX64,.-ffi_call_LINUX64 |
|
3489 +# else |
|
3490 +# ifdef _CALL_LINUX |
|
3491 + .size ffi_call_LINUX64,.-.L.ffi_call_LINUX64 |
|
3492 +# else |
|
3493 .size .ffi_call_LINUX64,.-.ffi_call_LINUX64 |
|
3494 +# endif |
|
3495 +# endif |
|
3496 |
|
3497 .section .eh_frame,EH_FRAME_FLAGS,@progbits |
|
3498 .Lframe1: |
|
3499 @@ -180,8 +253,8 @@ ffi_call_LINUX64: |
|
3500 .uleb128 0x4 |
|
3501 .align 3 |
|
3502 .LEFDE1: |
|
3503 -#endif |
|
3504 |
|
3505 -#if defined __ELF__ && defined __linux__ |
|
3506 +# if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 |
|
3507 .section .note.GNU-stack,"",@progbits |
|
3508 +# endif |
|
3509 #endif |
|
3510 --- mozilla/js/src/ctypes/libffi/src/powerpc/ppc_closure.S 2013-10-24 09:56:51.847587813 +0200 |
|
3511 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/ppc_closure.S 2013-11-29 17:23:26.000000000 +0100 |
|
3512 @@ -122,43 +122,78 @@ ENTRY(ffi_closure_SYSV) |
|
3513 blr |
|
3514 |
|
3515 # case FFI_TYPE_FLOAT |
|
3516 +#ifndef __NO_FPRS__ |
|
3517 lfs %f1,112+0(%r1) |
|
3518 mtlr %r0 |
|
3519 addi %r1,%r1,144 |
|
3520 +#else |
|
3521 + nop |
|
3522 + nop |
|
3523 + nop |
|
3524 +#endif |
|
3525 blr |
|
3526 |
|
3527 # case FFI_TYPE_DOUBLE |
|
3528 +#ifndef __NO_FPRS__ |
|
3529 lfd %f1,112+0(%r1) |
|
3530 mtlr %r0 |
|
3531 addi %r1,%r1,144 |
|
3532 +#else |
|
3533 + nop |
|
3534 + nop |
|
3535 + nop |
|
3536 +#endif |
|
3537 blr |
|
3538 |
|
3539 # case FFI_TYPE_LONGDOUBLE |
|
3540 +#ifndef __NO_FPRS__ |
|
3541 lfd %f1,112+0(%r1) |
|
3542 lfd %f2,112+8(%r1) |
|
3543 mtlr %r0 |
|
3544 b .Lfinish |
|
3545 +#else |
|
3546 + nop |
|
3547 + nop |
|
3548 + nop |
|
3549 + blr |
|
3550 +#endif |
|
3551 |
|
3552 # case FFI_TYPE_UINT8 |
|
3553 +#ifdef __LITTLE_ENDIAN__ |
|
3554 + lbz %r3,112+0(%r1) |
|
3555 +#else |
|
3556 lbz %r3,112+3(%r1) |
|
3557 +#endif |
|
3558 mtlr %r0 |
|
3559 addi %r1,%r1,144 |
|
3560 blr |
|
3561 |
|
3562 # case FFI_TYPE_SINT8 |
|
3563 +#ifdef __LITTLE_ENDIAN__ |
|
3564 + lbz %r3,112+0(%r1) |
|
3565 +#else |
|
3566 lbz %r3,112+3(%r1) |
|
3567 +#endif |
|
3568 extsb %r3,%r3 |
|
3569 mtlr %r0 |
|
3570 b .Lfinish |
|
3571 |
|
3572 # case FFI_TYPE_UINT16 |
|
3573 +#ifdef __LITTLE_ENDIAN__ |
|
3574 + lhz %r3,112+0(%r1) |
|
3575 +#else |
|
3576 lhz %r3,112+2(%r1) |
|
3577 +#endif |
|
3578 mtlr %r0 |
|
3579 addi %r1,%r1,144 |
|
3580 blr |
|
3581 |
|
3582 # case FFI_TYPE_SINT16 |
|
3583 +#ifdef __LITTLE_ENDIAN__ |
|
3584 + lha %r3,112+0(%r1) |
|
3585 +#else |
|
3586 lha %r3,112+2(%r1) |
|
3587 +#endif |
|
3588 mtlr %r0 |
|
3589 addi %r1,%r1,144 |
|
3590 blr |
|
3591 @@ -203,7 +238,7 @@ ENTRY(ffi_closure_SYSV) |
|
3592 lwz %r3,112+0(%r1) |
|
3593 lwz %r4,112+4(%r1) |
|
3594 lwz %r5,112+8(%r1) |
|
3595 - bl .Luint128 |
|
3596 + b .Luint128 |
|
3597 |
|
3598 # The return types below are only used when the ABI type is FFI_SYSV. |
|
3599 # case FFI_SYSV_TYPE_SMALL_STRUCT + 1. One byte struct. |
|
3600 @@ -220,9 +255,15 @@ ENTRY(ffi_closure_SYSV) |
|
3601 |
|
3602 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct. |
|
3603 lwz %r3,112+0(%r1) |
|
3604 +#ifdef __LITTLE_ENDIAN__ |
|
3605 + mtlr %r0 |
|
3606 + addi %r1,%r1,144 |
|
3607 + blr |
|
3608 +#else |
|
3609 srwi %r3,%r3,8 |
|
3610 mtlr %r0 |
|
3611 b .Lfinish |
|
3612 +#endif |
|
3613 |
|
3614 # case FFI_SYSV_TYPE_SMALL_STRUCT + 4. Four byte struct. |
|
3615 lwz %r3,112+0(%r1) |
|
3616 @@ -233,20 +274,35 @@ ENTRY(ffi_closure_SYSV) |
|
3617 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct. |
|
3618 lwz %r3,112+0(%r1) |
|
3619 lwz %r4,112+4(%r1) |
|
3620 +#ifdef __LITTLE_ENDIAN__ |
|
3621 + mtlr %r0 |
|
3622 + b .Lfinish |
|
3623 +#else |
|
3624 li %r5,24 |
|
3625 b .Lstruct567 |
|
3626 +#endif |
|
3627 |
|
3628 # case FFI_SYSV_TYPE_SMALL_STRUCT + 6. Six byte struct. |
|
3629 lwz %r3,112+0(%r1) |
|
3630 lwz %r4,112+4(%r1) |
|
3631 +#ifdef __LITTLE_ENDIAN__ |
|
3632 + mtlr %r0 |
|
3633 + b .Lfinish |
|
3634 +#else |
|
3635 li %r5,16 |
|
3636 b .Lstruct567 |
|
3637 +#endif |
|
3638 |
|
3639 # case FFI_SYSV_TYPE_SMALL_STRUCT + 7. Seven byte struct. |
|
3640 lwz %r3,112+0(%r1) |
|
3641 lwz %r4,112+4(%r1) |
|
3642 +#ifdef __LITTLE_ENDIAN__ |
|
3643 + mtlr %r0 |
|
3644 + b .Lfinish |
|
3645 +#else |
|
3646 li %r5,8 |
|
3647 b .Lstruct567 |
|
3648 +#endif |
|
3649 |
|
3650 # case FFI_SYSV_TYPE_SMALL_STRUCT + 8. Eight byte struct. |
|
3651 lwz %r3,112+0(%r1) |
|
3652 @@ -254,6 +310,7 @@ ENTRY(ffi_closure_SYSV) |
|
3653 mtlr %r0 |
|
3654 b .Lfinish |
|
3655 |
|
3656 +#ifndef __LITTLE_ENDIAN__ |
|
3657 .Lstruct567: |
|
3658 subfic %r6,%r5,32 |
|
3659 srw %r4,%r4,%r5 |
|
3660 @@ -263,6 +320,7 @@ ENTRY(ffi_closure_SYSV) |
|
3661 mtlr %r0 |
|
3662 addi %r1,%r1,144 |
|
3663 blr |
|
3664 +#endif |
|
3665 |
|
3666 .Luint128: |
|
3667 lwz %r6,112+12(%r1) |
|
3668 --- mozilla/js/src/ctypes/libffi/src/powerpc/sysv.S 2013-10-24 09:56:51.848587813 +0200 |
|
3669 +++ /suse/dvaleev/obs/openSUSE:Factory:PowerLE/libffi48/gcc-4.8-ibmr205465/libffi/src/powerpc/sysv.S 2013-11-29 17:23:26.000000000 +0100 |
|
3670 @@ -83,6 +83,7 @@ ENTRY(ffi_call_SYSV) |
|
3671 nop |
|
3672 1: |
|
3673 |
|
3674 +#ifndef __NO_FPRS__ |
|
3675 /* Load all the FP registers. */ |
|
3676 bf- 6,2f |
|
3677 lfd %f1,-16-(8*4)-(8*8)(%r28) |
|
3678 @@ -94,6 +95,7 @@ ENTRY(ffi_call_SYSV) |
|
3679 lfd %f6,-16-(8*4)-(3*8)(%r28) |
|
3680 lfd %f7,-16-(8*4)-(2*8)(%r28) |
|
3681 lfd %f8,-16-(8*4)-(1*8)(%r28) |
|
3682 +#endif |
|
3683 2: |
|
3684 |
|
3685 /* Make the call. */ |
|
3686 @@ -103,7 +105,9 @@ ENTRY(ffi_call_SYSV) |
|
3687 mtcrf 0x01,%r31 /* cr7 */ |
|
3688 bt- 31,L(small_struct_return_value) |
|
3689 bt- 30,L(done_return_value) |
|
3690 +#ifndef __NO_FPRS__ |
|
3691 bt- 29,L(fp_return_value) |
|
3692 +#endif |
|
3693 stw %r3,0(%r30) |
|
3694 bf+ 28,L(done_return_value) |
|
3695 stw %r4,4(%r30) |
|
3696 @@ -124,6 +128,7 @@ L(done_return_value): |
|
3697 lwz %r1,0(%r1) |
|
3698 blr |
|
3699 |
|
3700 +#ifndef __NO_FPRS__ |
|
3701 L(fp_return_value): |
|
3702 bf 28,L(float_return_value) |
|
3703 stfd %f1,0(%r30) |
|
3704 @@ -134,21 +139,17 @@ L(fp_return_value): |
|
3705 L(float_return_value): |
|
3706 stfs %f1,0(%r30) |
|
3707 b L(done_return_value) |
|
3708 +#endif |
|
3709 |
|
3710 L(small_struct_return_value): |
|
3711 - extrwi %r6,%r31,2,19 /* number of bytes padding = shift/8 */ |
|
3712 - mtcrf 0x02,%r31 /* copy flags to cr[24:27] (cr6) */ |
|
3713 - extrwi %r5,%r31,5,19 /* r5 <- number of bits of padding */ |
|
3714 - subfic %r6,%r6,4 /* r6 <- number of useful bytes in r3 */ |
|
3715 - bf- 25,L(done_return_value) /* struct in r3 ? if not, done. */ |
|
3716 -/* smst_one_register: */ |
|
3717 - slw %r3,%r3,%r5 /* Left-justify value in r3 */ |
|
3718 - mtxer %r6 /* move byte count to XER ... */ |
|
3719 - stswx %r3,0,%r30 /* ... and store that many bytes */ |
|
3720 - bf+ 26,L(done_return_value) /* struct in r3:r4 ? */ |
|
3721 - add %r6,%r6,%r30 /* adjust pointer */ |
|
3722 - stswi %r4,%r6,4 /* store last four bytes */ |
|
3723 - b L(done_return_value) |
|
3724 + /* |
|
3725 + * The C code always allocates a properly-aligned 8-byte bounce |
|
3726 + * buffer to make this assembly code very simple. Just write out |
|
3727 + * r3 and r4 to the buffer to allow the C code to handle the rest. |
|
3728 + */ |
|
3729 + stw %r3, 0(%r30) |
|
3730 + stw %r4, 4(%r30) |
|
3731 + b L(done_return_value) |
|
3732 |
|
3733 .LFE1: |
|
3734 END(ffi_call_SYSV) |