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