Ruby: ext/fiddle/libffi-3.2.1/src/powerpc/ffi_sysv.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

ffi_sysv.c
Go to the documentation of this file.
1/* -----------------------------------------------------------------------
2 ffi_sysv.c - Copyright (C) 2013 IBM
3 Copyright (C) 2011 Anthony Green
4 Copyright (C) 2011 Kyle Moffett
5 Copyright (C) 2008 Red Hat, Inc
6 Copyright (C) 2007, 2008 Free Software Foundation, Inc
7 Copyright (c) 1998 Geoffrey Keating
8
9 PowerPC Foreign Function Interface
10
11 Permission is hereby granted, free of charge, to any person obtaining
12 a copy of this software and associated documentation files (the
13 ``Software''), to deal in the Software without restriction, including
14 without limitation the rights to use, copy, modify, merge, publish,
15 distribute, sublicense, and/or sell copies of the Software, and to
16 permit persons to whom the Software is furnished to do so, subject to
17 the following conditions:
18
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
29 ----------------------------------------------------------------------- */
30
31#include "ffi.h"
32
33#ifndef POWERPC64
34#include "ffi_common.h"
35#include "ffi_powerpc.h"
36
37
38/* About the SYSV ABI. */
39#define ASM_NEEDS_REGISTERS 4
40#define NUM_GPR_ARG_REGISTERS 8
41#define NUM_FPR_ARG_REGISTERS 8
42
43
44#if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
45/* Adjust size of ffi_type_longdouble. */
46void FFI_HIDDEN
47 ffi_prep_types_sysv (ffi_abi abi)
48{
49 if ((abi & (FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128)) == FFI_SYSV)
50 {
51 ffi_type_longdouble.size = 8;
52 ffi_type_longdouble.alignment = 8;
53 }
54 else
55 {
56 ffi_type_longdouble.size = 16;
57 ffi_type_longdouble.alignment = 16;
58 }
59}
60#endif
61
62/* Transform long double, double and float to other types as per abi. */
63static int
64translate_float (int abi, int type)
65{
66#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
67 if (type == FFI_TYPE_LONGDOUBLE
68 && (abi & FFI_SYSV_LONG_DOUBLE_128) == 0)
69 type = FFI_TYPE_DOUBLE;
70#endif
71 if ((abi & FFI_SYSV_SOFT_FLOAT) != 0)
72 {
73 if (type == FFI_TYPE_FLOAT)
74 type = FFI_TYPE_UINT32;
75 else if (type == FFI_TYPE_DOUBLE)
76 type = FFI_TYPE_UINT64;
77#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
78 else if (type == FFI_TYPE_LONGDOUBLE)
79 type = FFI_TYPE_UINT128;
80 }
81 else if ((abi & FFI_SYSV_IBM_LONG_DOUBLE) == 0)
82 {
83 if (type == FFI_TYPE_LONGDOUBLE)
84 type = FFI_TYPE_STRUCT;
85#endif
86 }
87 return type;
88}
89
90/* Perform machine dependent cif processing */
91static ffi_status
92ffi_prep_cif_sysv_core (ffi_cif *cif)
93{
94 ffi_type **ptr;
95 unsigned bytes;
96 unsigned i, fparg_count = 0, intarg_count = 0;
97 unsigned flags = cif->flags;
98 unsigned struct_copy_size = 0;
99 unsigned type = cif->rtype->type;
100 unsigned size = cif->rtype->size;
101
102 /* The machine-independent calculation of cif->bytes doesn't work
103 for us. Redo the calculation. */
104
105 /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
106 bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
107
108 /* Space for the GPR registers. */
109 bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
110
111 /* Return value handling. The rules for SYSV are as follows:
112 - 32-bit (or less) integer values are returned in gpr3;
113 - Structures of size <= 4 bytes also returned in gpr3;
114 - 64-bit integer values and structures between 5 and 8 bytes are returned
115 in gpr3 and gpr4;
116 - Larger structures are allocated space and a pointer is passed as
117 the first argument.
118 - Single/double FP values are returned in fpr1;
119 - long doubles (if not equivalent to double) are returned in
120 fpr1,fpr2 for Linux and as for large structs for SysV. */
121
122 type = translate_float (cif->abi, type);
123
124 switch (type)
125 {
126#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
127 case FFI_TYPE_LONGDOUBLE:
128 flags |= FLAG_RETURNS_128BITS;
129 /* Fall through. */
130#endif
131 case FFI_TYPE_DOUBLE:
132 flags |= FLAG_RETURNS_64BITS;
133 /* Fall through. */
134 case FFI_TYPE_FLOAT:
135 flags |= FLAG_RETURNS_FP;
136#ifdef __NO_FPRS__
137 return FFI_BAD_ABI;
138#endif
139 break;
140
141 case FFI_TYPE_UINT128:
142 flags |= FLAG_RETURNS_128BITS;
143 /* Fall through. */
144 case FFI_TYPE_UINT64:
145 case FFI_TYPE_SINT64:
146 flags |= FLAG_RETURNS_64BITS;
147 break;
148
149 case FFI_TYPE_STRUCT:
150 /* The final SYSV ABI says that structures smaller or equal 8 bytes
151 are returned in r3/r4. A draft ABI used by linux instead
152 returns them in memory. */
153 if ((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
154 {
155 flags |= FLAG_RETURNS_SMST;
156 break;
157 }
158 intarg_count++;
159 flags |= FLAG_RETVAL_REFERENCE;
160 /* Fall through. */
161 case FFI_TYPE_VOID:
162 flags |= FLAG_RETURNS_NOTHING;
163 break;
164
165 default:
166 /* Returns 32-bit integer, or similar. Nothing to do here. */
167 break;
168 }
169
170 /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
171 first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
172 goes on the stack. Structures and long doubles (if not equivalent
173 to double) are passed as a pointer to a copy of the structure.
174 Stuff on the stack needs to keep proper alignment. */
175 for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
176 {
177 unsigned short typenum = (*ptr)->type;
178
179 typenum = translate_float (cif->abi, typenum);
180
181 switch (typenum)
182 {
183#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
184 case FFI_TYPE_LONGDOUBLE:
185 fparg_count++;
186 /* Fall thru */
187#endif
188 case FFI_TYPE_DOUBLE:
189 fparg_count++;
190 /* If this FP arg is going on the stack, it must be
191 8-byte-aligned. */
192 if (fparg_count > NUM_FPR_ARG_REGISTERS
193 && intarg_count >= NUM_GPR_ARG_REGISTERS
194 && intarg_count % 2 != 0)
195 intarg_count++;
196#ifdef __NO_FPRS__
197 return FFI_BAD_ABI;
198#endif
199 break;
200
201 case FFI_TYPE_FLOAT:
202 fparg_count++;
203#ifdef __NO_FPRS__
204 return FFI_BAD_ABI;
205#endif
206 break;
207
208 case FFI_TYPE_UINT128:
209 /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
210 of four consecutive gprs. If we do not have enough, we
211 have to adjust the intarg_count value. */
212 if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
213 && intarg_count < NUM_GPR_ARG_REGISTERS)
214 intarg_count = NUM_GPR_ARG_REGISTERS;
215 intarg_count += 4;
216 break;
217
218 case FFI_TYPE_UINT64:
219 case FFI_TYPE_SINT64:
220 /* 'long long' arguments are passed as two words, but
221 either both words must fit in registers or both go
222 on the stack. If they go on the stack, they must
223 be 8-byte-aligned.
224
225 Also, only certain register pairs can be used for
226 passing long long int -- specifically (r3,r4), (r5,r6),
227 (r7,r8), (r9,r10). */
228 if (intarg_count == NUM_GPR_ARG_REGISTERS-1
229 || intarg_count % 2 != 0)
230 intarg_count++;
231 intarg_count += 2;
232 break;
233
234 case FFI_TYPE_STRUCT:
235 /* We must allocate space for a copy of these to enforce
236 pass-by-value. Pad the space up to a multiple of 16
237 bytes (the maximum alignment required for anything under
238 the SYSV ABI). */
239 struct_copy_size += ((*ptr)->size + 15) & ~0xF;
240 /* Fall through (allocate space for the pointer). */
241
242 case FFI_TYPE_POINTER:
243 case FFI_TYPE_INT:
244 case FFI_TYPE_UINT32:
245 case FFI_TYPE_SINT32:
246 case FFI_TYPE_UINT16:
247 case FFI_TYPE_SINT16:
248 case FFI_TYPE_UINT8:
249 case FFI_TYPE_SINT8:
250 /* Everything else is passed as a 4-byte word in a GPR, either
251 the object itself or a pointer to it. */
252 intarg_count++;
253 break;
254
255 default:
256 FFI_ASSERT (0);
257 }
258 }
259
260 if (fparg_count != 0)
261 flags |= FLAG_FP_ARGUMENTS;
262 if (intarg_count > 4)
263 flags |= FLAG_4_GPR_ARGUMENTS;
264 if (struct_copy_size != 0)
265 flags |= FLAG_ARG_NEEDS_COPY;
266
267 /* Space for the FPR registers, if needed. */
268 if (fparg_count != 0)
269 bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
270
271 /* Stack space. */
272 if (intarg_count > NUM_GPR_ARG_REGISTERS)
273 bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
274 if (fparg_count > NUM_FPR_ARG_REGISTERS)
275 bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
276
277 /* The stack space allocated needs to be a multiple of 16 bytes. */
278 bytes = (bytes + 15) & ~0xF;
279
280 /* Add in the space for the copied structures. */
281 bytes += struct_copy_size;
282
283 cif->flags = flags;
284 cif->bytes = bytes;
285
286 return FFI_OK;
287}
288
289ffi_status FFI_HIDDEN
290 ffi_prep_cif_sysv (ffi_cif *cif)
291{
292 if ((cif->abi & FFI_SYSV) == 0)
293 {
294 /* This call is from old code. Translate to new ABI values. */
295 cif->flags |= FLAG_COMPAT;
296 switch (cif->abi)
297 {
298 default:
299 return FFI_BAD_ABI;
300
301 case FFI_COMPAT_SYSV:
302 cif->abi = FFI_SYSV | FFI_SYSV_STRUCT_RET | FFI_SYSV_LONG_DOUBLE_128;
303 break;
304
305 case FFI_COMPAT_GCC_SYSV:
306 cif->abi = FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128;
307 break;
308
309 case FFI_COMPAT_LINUX:
310 cif->abi = (FFI_SYSV | FFI_SYSV_IBM_LONG_DOUBLE
311 | FFI_SYSV_LONG_DOUBLE_128);
312 break;
313
314 case FFI_COMPAT_LINUX_SOFT_FLOAT:
315 cif->abi = (FFI_SYSV | FFI_SYSV_SOFT_FLOAT | FFI_SYSV_IBM_LONG_DOUBLE
316 | FFI_SYSV_LONG_DOUBLE_128);
317 break;
318 }
319 }
320 return ffi_prep_cif_sysv_core (cif);
321}
322
323/* ffi_prep_args_SYSV is called by the assembly routine once stack space
324 has been allocated for the function's arguments.
325
326 The stack layout we want looks like this:
327
328 | Return address from ffi_call_SYSV 4bytes | higher addresses
329 |--------------------------------------------|
330 | Previous backchain pointer 4 | stack pointer here
331 |--------------------------------------------|<+ <<< on entry to
332 | Saved r28-r31 4*4 | | ffi_call_SYSV
333 |--------------------------------------------| |
334 | GPR registers r3-r10 8*4 | | ffi_call_SYSV
335 |--------------------------------------------| |
336 | FPR registers f1-f8 (optional) 8*8 | |
337 |--------------------------------------------| | stack |
338 | Space for copied structures | | grows |
339 |--------------------------------------------| | down V
340 | Parameters that didn't fit in registers | |
341 |--------------------------------------------| | lower addresses
342 | Space for callee's LR 4 | |
343 |--------------------------------------------| | stack pointer here
344 | Current backchain pointer 4 |-/ during
345 |--------------------------------------------| <<< ffi_call_SYSV
346
347*/
348
349void FFI_HIDDEN
350ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
351{
352 const unsigned bytes = ecif->cif->bytes;
353 const unsigned flags = ecif->cif->flags;
354
355 typedef union
356 {
357 char *c;
358 unsigned *u;
359 long long *ll;
360 float *f;
361 double *d;
362 } valp;
363
364 /* 'stacktop' points at the previous backchain pointer. */
365 valp stacktop;
366
367 /* 'gpr_base' points at the space for gpr3, and grows upwards as
368 we use GPR registers. */
369 valp gpr_base;
370 int intarg_count;
371
372#ifndef __NO_FPRS__
373 /* 'fpr_base' points at the space for fpr1, and grows upwards as
374 we use FPR registers. */
375 valp fpr_base;
376 int fparg_count;
377#endif
378
379 /* 'copy_space' grows down as we put structures in it. It should
380 stay 16-byte aligned. */
381 valp copy_space;
382
383 /* 'next_arg' grows up as we put parameters in it. */
384 valp next_arg;
385
386 int i;
387 ffi_type **ptr;
388#ifndef __NO_FPRS__
389 double double_tmp;
390#endif
391 union
392 {
393 void **v;
394 char **c;
395 signed char **sc;
396 unsigned char **uc;
397 signed short **ss;
398 unsigned short **us;
399 unsigned int **ui;
400 long long **ll;
401 float **f;
402 double **d;
403 } p_argv;
404 size_t struct_copy_size;
405 unsigned gprvalue;
406
407 stacktop.c = (char *) stack + bytes;
408 gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
409 intarg_count = 0;
410#ifndef __NO_FPRS__
411 fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
412 fparg_count = 0;
413 copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
414#else
415 copy_space.c = gpr_base.c;
416#endif
417 next_arg.u = stack + 2;
418
419 /* Check that everything starts aligned properly. */
420 FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
421 FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0);
422 FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
423 FFI_ASSERT ((bytes & 0xF) == 0);
424 FFI_ASSERT (copy_space.c >= next_arg.c);
425
426 /* Deal with return values that are actually pass-by-reference. */
427 if (flags & FLAG_RETVAL_REFERENCE)
428 {
429 *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
430 intarg_count++;
431 }
432
433 /* Now for the arguments. */
434 p_argv.v = ecif->avalue;
435 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
436 i > 0;
437 i--, ptr++, p_argv.v++)
438 {
439 unsigned int typenum = (*ptr)->type;
440
441 typenum = translate_float (ecif->cif->abi, typenum);
442
443 /* Now test the translated value */
444 switch (typenum)
445 {
446#ifndef __NO_FPRS__
447# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
448 case FFI_TYPE_LONGDOUBLE:
449 double_tmp = (*p_argv.d)[0];
450
451 if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
452 {
453 if (intarg_count >= NUM_GPR_ARG_REGISTERS
454 && intarg_count % 2 != 0)
455 {
456 intarg_count++;
457 next_arg.u++;
458 }
459 *next_arg.d = double_tmp;
460 next_arg.u += 2;
461 double_tmp = (*p_argv.d)[1];
462 *next_arg.d = double_tmp;
463 next_arg.u += 2;
464 }
465 else
466 {
467 *fpr_base.d++ = double_tmp;
468 double_tmp = (*p_argv.d)[1];
469 *fpr_base.d++ = double_tmp;
470 }
471
472 fparg_count += 2;
473 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
474 break;
475# endif
476 case FFI_TYPE_DOUBLE:
477 double_tmp = **p_argv.d;
478
479 if (fparg_count >= NUM_FPR_ARG_REGISTERS)
480 {
481 if (intarg_count >= NUM_GPR_ARG_REGISTERS
482 && intarg_count % 2 != 0)
483 {
484 intarg_count++;
485 next_arg.u++;
486 }
487 *next_arg.d = double_tmp;
488 next_arg.u += 2;
489 }
490 else
491 *fpr_base.d++ = double_tmp;
492 fparg_count++;
493 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
494 break;
495
496 case FFI_TYPE_FLOAT:
497 double_tmp = **p_argv.f;
498 if (fparg_count >= NUM_FPR_ARG_REGISTERS)
499 {
500 *next_arg.f = (float) double_tmp;
501 next_arg.u += 1;
502 intarg_count++;
503 }
504 else
505 *fpr_base.d++ = double_tmp;
506 fparg_count++;
507 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
508 break;
509#endif /* have FPRs */
510
511 case FFI_TYPE_UINT128:
512 /* The soft float ABI for long doubles works like this, a long double
513 is passed in four consecutive GPRs if available. A maximum of 2
514 long doubles can be passed in gprs. If we do not have 4 GPRs
515 left, the long double is passed on the stack, 4-byte aligned. */
516 {
517 unsigned int int_tmp;
518 unsigned int ii;
519 if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
520 {
521 if (intarg_count < NUM_GPR_ARG_REGISTERS)
522 intarg_count = NUM_GPR_ARG_REGISTERS;
523 for (ii = 0; ii < 4; ii++)
524 {
525 int_tmp = (*p_argv.ui)[ii];
526 *next_arg.u++ = int_tmp;
527 }
528 }
529 else
530 {
531 for (ii = 0; ii < 4; ii++)
532 {
533 int_tmp = (*p_argv.ui)[ii];
534 *gpr_base.u++ = int_tmp;
535 }
536 }
537 intarg_count += 4;
538 break;
539 }
540
541 case FFI_TYPE_UINT64:
542 case FFI_TYPE_SINT64:
543 if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
544 intarg_count++;
545 if (intarg_count >= NUM_GPR_ARG_REGISTERS)
546 {
547 if (intarg_count % 2 != 0)
548 {
549 intarg_count++;
550 next_arg.u++;
551 }
552 *next_arg.ll = **p_argv.ll;
553 next_arg.u += 2;
554 }
555 else
556 {
557 /* The abi states only certain register pairs can be
558 used for passing long long int specifically (r3,r4),
559 (r5,r6), (r7,r8), (r9,r10). If next arg is long long
560 but not correct starting register of pair then skip
561 until the proper starting register. */
562 if (intarg_count % 2 != 0)
563 {
564 intarg_count ++;
565 gpr_base.u++;
566 }
567 *gpr_base.ll++ = **p_argv.ll;
568 }
569 intarg_count += 2;
570 break;
571
572 case FFI_TYPE_STRUCT:
573 struct_copy_size = ((*ptr)->size + 15) & ~0xF;
574 copy_space.c -= struct_copy_size;
575 memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
576
577 gprvalue = (unsigned long) copy_space.c;
578
579 FFI_ASSERT (copy_space.c > next_arg.c);
580 FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
581 goto putgpr;
582
583 case FFI_TYPE_UINT8:
584 gprvalue = **p_argv.uc;
585 goto putgpr;
586 case FFI_TYPE_SINT8:
587 gprvalue = **p_argv.sc;
588 goto putgpr;
589 case FFI_TYPE_UINT16:
590 gprvalue = **p_argv.us;
591 goto putgpr;
592 case FFI_TYPE_SINT16:
593 gprvalue = **p_argv.ss;
594 goto putgpr;
595
596 case FFI_TYPE_INT:
597 case FFI_TYPE_UINT32:
598 case FFI_TYPE_SINT32:
599 case FFI_TYPE_POINTER:
600
601 gprvalue = **p_argv.ui;
602
603 putgpr:
604 if (intarg_count >= NUM_GPR_ARG_REGISTERS)
605 *next_arg.u++ = gprvalue;
606 else
607 *gpr_base.u++ = gprvalue;
608 intarg_count++;
609 break;
610 }
611 }
612
613 /* Check that we didn't overrun the stack... */
614 FFI_ASSERT (copy_space.c >= next_arg.c);
615 FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
616 /* The assert below is testing that the number of integer arguments agrees
617 with the number found in ffi_prep_cif_machdep(). However, intarg_count
618 is incremented whenever we place an FP arg on the stack, so account for
619 that before our assert test. */
620#ifndef __NO_FPRS__
621 if (fparg_count > NUM_FPR_ARG_REGISTERS)
622 intarg_count -= fparg_count - NUM_FPR_ARG_REGISTERS;
623 FFI_ASSERT (fpr_base.u
624 <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
625#endif
626 FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
627}
628
629#define MIN_CACHE_LINE_SIZE 8
630
631static void
632flush_icache (char *wraddr, char *xaddr, int size)
633{
634 int i;
635 for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
636 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
637 : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
638 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
639 : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
640 : "memory");
641}
642
643ffi_status FFI_HIDDEN
644ffi_prep_closure_loc_sysv (ffi_closure *closure,
645 ffi_cif *cif,
646 void (*fun) (ffi_cif *, void *, void **, void *),
647 void *user_data,
648 void *codeloc)
649{
650 unsigned int *tramp;
651
652 if (cif->abi < FFI_SYSV || cif->abi >= FFI_LAST_ABI)
653 return FFI_BAD_ABI;
654
655 tramp = (unsigned int *) &closure->tramp[0];
656 tramp[0] = 0x7c0802a6; /* mflr r0 */
657 tramp[1] = 0x4800000d; /* bl 10 <trampoline_initial+0x10> */
658 tramp[4] = 0x7d6802a6; /* mflr r11 */
659 tramp[5] = 0x7c0803a6; /* mtlr r0 */
660 tramp[6] = 0x800b0000; /* lwz r0,0(r11) */
661 tramp[7] = 0x816b0004; /* lwz r11,4(r11) */
662 tramp[8] = 0x7c0903a6; /* mtctr r0 */
663 tramp[9] = 0x4e800420; /* bctr */
664 *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
665 *(void **) &tramp[3] = codeloc; /* context */
666
667 /* Flush the icache. */
668 flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
669
670 closure->cif = cif;
671 closure->fun = fun;
672 closure->user_data = user_data;
673
674 return FFI_OK;
675}
676
677/* Basically the trampoline invokes ffi_closure_SYSV, and on
678 entry, r11 holds the address of the closure.
679 After storing the registers that could possibly contain
680 parameters to be passed into the stack frame and setting
681 up space for a return value, ffi_closure_SYSV invokes the
682 following helper function to do most of the work. */
683
684int
685 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
686 unsigned long *pgr, ffi_dblfl *pfr,
687 unsigned long *pst)
688{
689 /* rvalue is the pointer to space for return value in closure assembly */
690 /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
691 /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
692 /* pst is the pointer to outgoing parameter stack in original caller */
693
694 void ** avalue;
695 ffi_type ** arg_types;
696 long i, avn;
697#ifndef __NO_FPRS__
698 long nf = 0; /* number of floating registers already used */
699#endif
700 long ng = 0; /* number of general registers already used */
701
702 ffi_cif *cif = closure->cif;
703 unsigned size = cif->rtype->size;
704 unsigned short rtypenum = cif->rtype->type;
705
706 avalue = alloca (cif->nargs * sizeof (void *));
707
708 /* First translate for softfloat/nonlinux */
709 rtypenum = translate_float (cif->abi, rtypenum);
710
711 /* Copy the caller's structure return value address so that the closure
712 returns the data directly to the caller.
713 For FFI_SYSV the result is passed in r3/r4 if the struct size is less
714 or equal 8 bytes. */
715 if (rtypenum == FFI_TYPE_STRUCT
716 && !((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8))
717 {
718 rvalue = (void *) *pgr;
719 ng++;
720 pgr++;
721 }
722
723 i = 0;
724 avn = cif->nargs;
725 arg_types = cif->arg_types;
726
727 /* Grab the addresses of the arguments from the stack frame. */
728 while (i < avn) {
729 unsigned short typenum = arg_types[i]->type;
730
731 /* We may need to handle some values depending on ABI. */
732 typenum = translate_float (cif->abi, typenum);
733
734 switch (typenum)
735 {
736#ifndef __NO_FPRS__
737 case FFI_TYPE_FLOAT:
738 /* Unfortunately float values are stored as doubles
739 in the ffi_closure_SYSV code (since we don't check
740 the type in that routine). */
741 if (nf < NUM_FPR_ARG_REGISTERS)
742 {
743 /* FIXME? here we are really changing the values
744 stored in the original calling routines outgoing
745 parameter stack. This is probably a really
746 naughty thing to do but... */
747 double temp = pfr->d;
748 pfr->f = (float) temp;
749 avalue[i] = pfr;
750 nf++;
751 pfr++;
752 }
753 else
754 {
755 avalue[i] = pst;
756 pst += 1;
757 }
758 break;
759
760 case FFI_TYPE_DOUBLE:
761 if (nf < NUM_FPR_ARG_REGISTERS)
762 {
763 avalue[i] = pfr;
764 nf++;
765 pfr++;
766 }
767 else
768 {
769 if (((long) pst) & 4)
770 pst++;
771 avalue[i] = pst;
772 pst += 2;
773 }
774 break;
775
776# if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
777 case FFI_TYPE_LONGDOUBLE:
778 if (nf < NUM_FPR_ARG_REGISTERS - 1)
779 {
780 avalue[i] = pfr;
781 pfr += 2;
782 nf += 2;
783 }
784 else
785 {
786 if (((long) pst) & 4)
787 pst++;
788 avalue[i] = pst;
789 pst += 4;
790 nf = 8;
791 }
792 break;
793# endif
794#endif
795
796 case FFI_TYPE_UINT128:
797 /* Test if for the whole long double, 4 gprs are available.
798 otherwise the stuff ends up on the stack. */
799 if (ng < NUM_GPR_ARG_REGISTERS - 3)
800 {
801 avalue[i] = pgr;
802 pgr += 4;
803 ng += 4;
804 }
805 else
806 {
807 avalue[i] = pst;
808 pst += 4;
809 ng = 8+4;
810 }
811 break;
812
813 case FFI_TYPE_SINT8:
814 case FFI_TYPE_UINT8:
815#ifndef __LITTLE_ENDIAN__
816 if (ng < NUM_GPR_ARG_REGISTERS)
817 {
818 avalue[i] = (char *) pgr + 3;
819 ng++;
820 pgr++;
821 }
822 else
823 {
824 avalue[i] = (char *) pst + 3;
825 pst++;
826 }
827 break;
828#endif
829
830 case FFI_TYPE_SINT16:
831 case FFI_TYPE_UINT16:
832#ifndef __LITTLE_ENDIAN__
833 if (ng < NUM_GPR_ARG_REGISTERS)
834 {
835 avalue[i] = (char *) pgr + 2;
836 ng++;
837 pgr++;
838 }
839 else
840 {
841 avalue[i] = (char *) pst + 2;
842 pst++;
843 }
844 break;
845#endif
846
847 case FFI_TYPE_SINT32:
848 case FFI_TYPE_UINT32:
849 case FFI_TYPE_POINTER:
850 if (ng < NUM_GPR_ARG_REGISTERS)
851 {
852 avalue[i] = pgr;
853 ng++;
854 pgr++;
855 }
856 else
857 {
858 avalue[i] = pst;
859 pst++;
860 }
861 break;
862
863 case FFI_TYPE_STRUCT:
864 /* Structs are passed by reference. The address will appear in a
865 gpr if it is one of the first 8 arguments. */
866 if (ng < NUM_GPR_ARG_REGISTERS)
867 {
868 avalue[i] = (void *) *pgr;
869 ng++;
870 pgr++;
871 }
872 else
873 {
874 avalue[i] = (void *) *pst;
875 pst++;
876 }
877 break;
878
879 case FFI_TYPE_SINT64:
880 case FFI_TYPE_UINT64:
881 /* Passing long long ints are complex, they must
882 be passed in suitable register pairs such as
883 (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
884 and if the entire pair aren't available then the outgoing
885 parameter stack is used for both but an alignment of 8
886 must will be kept. So we must either look in pgr
887 or pst to find the correct address for this type
888 of parameter. */
889 if (ng < NUM_GPR_ARG_REGISTERS - 1)
890 {
891 if (ng & 1)
892 {
893 /* skip r4, r6, r8 as starting points */
894 ng++;
895 pgr++;
896 }
897 avalue[i] = pgr;
898 ng += 2;
899 pgr += 2;
900 }
901 else
902 {
903 if (((long) pst) & 4)
904 pst++;
905 avalue[i] = pst;
906 pst += 2;
907 ng = NUM_GPR_ARG_REGISTERS;
908 }
909 break;
910
911 default:
912 FFI_ASSERT (0);
913 }
914
915 i++;
916 }
917
918 (closure->fun) (cif, rvalue, avalue, closure->user_data);
919
920 /* Tell ffi_closure_SYSV how to perform return type promotions.
921 Because the FFI_SYSV ABI returns the structures <= 8 bytes in
922 r3/r4 we have to tell ffi_closure_SYSV how to treat them. We
923 combine the base type FFI_SYSV_TYPE_SMALL_STRUCT with the size of
924 the struct less one. We never have a struct with size zero.
925 See the comment in ffitarget.h about ordering. */
926 if (rtypenum == FFI_TYPE_STRUCT
927 && (cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
928 return FFI_SYSV_TYPE_SMALL_STRUCT - 1 + size;
929 return rtypenum;
930}
931#endif
FFI_TRAMPOLINE_SIZE
#define FFI_TRAMPOLINE_SIZE
Definition: ffitarget.h:45
ffi_abi
ffi_abi
Definition: ffitarget.h:34
FFI_SYSV
@ FFI_SYSV
Definition: ffitarget.h:36
FFI_LAST_ABI
@ FFI_LAST_ABI
Definition: ffitarget.h:37
FFI_TYPE_LONGDOUBLE
#define FFI_TYPE_LONGDOUBLE
Definition: ffi.c:40
ptr
struct RIMemo * ptr
Definition: debug.c:88
ffi_common.h
alloca
#define alloca
Definition: ffi_common.h:27
FFI_ASSERT
#define FFI_ASSERT(x)
Definition: ffi_common.h:72
memcpy
#define memcpy(d, s, n)
Definition: ffi_common.h:55
FLAG_RETURNS_64BITS
@ FLAG_RETURNS_64BITS
Definition: ffi_darwin.c:46
FLAG_ARG_NEEDS_COPY
@ FLAG_ARG_NEEDS_COPY
Definition: ffi_darwin.c:50
FLAG_RETVAL_REFERENCE
@ FLAG_RETVAL_REFERENCE
Definition: ffi_darwin.c:53
FLAG_FP_ARGUMENTS
@ FLAG_FP_ARGUMENTS
Definition: ffi_darwin.c:51
FLAG_RETURNS_NOTHING
@ FLAG_RETURNS_NOTHING
Definition: ffi_darwin.c:44
FLAG_RETURNS_128BITS
@ FLAG_RETURNS_128BITS
Definition: ffi_darwin.c:43
FLAG_RETURNS_FP
@ FLAG_RETURNS_FP
Definition: ffi_darwin.c:45
FLAG_4_GPR_ARGUMENTS
@ FLAG_4_GPR_ARGUMENTS
Definition: ffi_darwin.c:52
ffi_powerpc.h
ffi_prep_types_sysv
void FFI_HIDDEN ffi_prep_types_sysv(ffi_abi)
FLAG_COMPAT
@ FLAG_COMPAT
Definition: ffi_powerpc.h:42
FLAG_RETURNS_SMST
@ FLAG_RETURNS_SMST
Definition: ffi_powerpc.h:34
ffi_closure_helper_SYSV
int ffi_closure_helper_SYSV(ffi_closure *closure, void *rvalue, unsigned long *pgr, ffi_dblfl *pfr, unsigned long *pst)
Definition: ffi_sysv.c:685
ASM_NEEDS_REGISTERS
#define ASM_NEEDS_REGISTERS
Definition: ffi_sysv.c:39
MIN_CACHE_LINE_SIZE
#define MIN_CACHE_LINE_SIZE
Definition: ffi_sysv.c:629
ffi_prep_cif_sysv
ffi_status FFI_HIDDEN ffi_prep_cif_sysv(ffi_cif *cif)
Definition: ffi_sysv.c:290
NUM_GPR_ARG_REGISTERS
#define NUM_GPR_ARG_REGISTERS
Definition: ffi_sysv.c:40
ffi_prep_closure_loc_sysv
ffi_status FFI_HIDDEN ffi_prep_closure_loc_sysv(ffi_closure *closure, ffi_cif *cif, void(*fun)(ffi_cif *, void *, void **, void *), void *user_data, void *codeloc)
Definition: ffi_sysv.c:644
NUM_FPR_ARG_REGISTERS
#define NUM_FPR_ARG_REGISTERS
Definition: ffi_sysv.c:41
ffi_prep_args_SYSV
void FFI_HIDDEN ffi_prep_args_SYSV(extended_cif *ecif, unsigned *const stack)
Definition: ffi_sysv.c:350
FFI_HIDDEN
#define FFI_HIDDEN
Definition: fficonfig.h:27
size
voidpf void uLong size
Definition: ioapi.h:138
long
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
int
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
ffi_closure_SYSV
void ffi_closure_SYSV(void)
Definition: ffi.c:53
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
FFI_SYSV_TYPE_SMALL_STRUCT
#define FFI_SYSV_TYPE_SMALL_STRUCT
Definition: ffitarget.h:152
FFI_TYPE_UINT128
#define FFI_TYPE_UINT128
Definition: ffitarget.h:149
FFI_SYSV_LONG_DOUBLE_128
@ FFI_SYSV_LONG_DOUBLE_128
Definition: ffitarget.h:112
FFI_COMPAT_LINUX
@ FFI_COMPAT_LINUX
Definition: ffitarget.h:82
FFI_SYSV_IBM_LONG_DOUBLE
@ FFI_SYSV_IBM_LONG_DOUBLE
Definition: ffitarget.h:111
FFI_SYSV_SOFT_FLOAT
@ FFI_SYSV_SOFT_FLOAT
Definition: ffitarget.h:109
FFI_SYSV_STRUCT_RET
@ FFI_SYSV_STRUCT_RET
Definition: ffitarget.h:110
FFI_COMPAT_GCC_SYSV
@ FFI_COMPAT_GCC_SYSV
Definition: ffitarget.h:80
FFI_COMPAT_SYSV
@ FFI_COMPAT_SYSV
Definition: ffitarget.h:79
FFI_COMPAT_LINUX_SOFT_FLOAT
@ FFI_COMPAT_LINUX_SOFT_FLOAT
Definition: ffitarget.h:83
f
#define f
RIMemo::flags
VALUE flags
Definition: debug.c:33
extended_cif
Definition: ffi_common.h:87
extended_cif::rvalue
void * rvalue
Definition: ffi_common.h:89
extended_cif::cif
ffi_cif * cif
Definition: ffi_common.h:88
extended_cif::avalue
void ** avalue
Definition: ffi_common.h:90
ffi_dblfl
Definition: ffi_darwin.c:1102
ffi_dblfl::d
double d
Definition: ffi_darwin.c:1104
ffi_dblfl::f
float f
Definition: ffi_darwin.c:1103