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