Daily bump.
[official-gcc.git] / libffi / src / powerpc / ffi_sysv.c
blob4078e7511629dd25eb18c74a800ba82db3c43340
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
9 PowerPC Foreign Function Interface
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:
19 The above copyright notice and this permission notice shall be included
20 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
31 #include "ffi.h"
33 #ifndef POWERPC64
34 #include "ffi_common.h"
35 #include "ffi_powerpc.h"
38 /* About the SYSV ABI. */
39 #define ASM_NEEDS_REGISTERS 6
40 #define NUM_GPR_ARG_REGISTERS 8
41 #define NUM_FPR_ARG_REGISTERS 8
44 #if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
45 /* Adjust size of ffi_type_longdouble. */
46 void FFI_HIDDEN
47 ffi_prep_types_sysv (ffi_abi abi)
49 if ((abi & (FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128)) == FFI_SYSV)
51 ffi_type_longdouble.size = 8;
52 ffi_type_longdouble.alignment = 8;
54 else
56 ffi_type_longdouble.size = 16;
57 ffi_type_longdouble.alignment = 16;
60 #endif
62 /* Transform long double, double and float to other types as per abi. */
63 static int
64 translate_float (int abi, int type)
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)
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;
81 else if ((abi & FFI_SYSV_IBM_LONG_DOUBLE) == 0)
83 if (type == FFI_TYPE_LONGDOUBLE)
84 type = FFI_TYPE_STRUCT;
85 #endif
87 return type;
90 /* Perform machine dependent cif processing */
91 static ffi_status
92 ffi_prep_cif_sysv_core (ffi_cif *cif)
94 ffi_type **ptr;
95 unsigned bytes;
96 unsigned i, fpr_count = 0, gpr_count = 0, stack_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;
102 /* The machine-independent calculation of cif->bytes doesn't work
103 for us. Redo the calculation. */
105 /* Space for the frame pointer, callee's LR, and the asm's temp regs. */
106 bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
108 /* Space for the GPR registers. */
109 bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
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. */
122 type = translate_float (cif->abi, type);
124 switch (type)
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;
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;
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)
155 flags |= FLAG_RETURNS_SMST;
156 break;
158 gpr_count++;
159 flags |= FLAG_RETVAL_REFERENCE;
160 /* Fall through. */
161 case FFI_TYPE_VOID:
162 flags |= FLAG_RETURNS_NOTHING;
163 break;
165 default:
166 /* Returns 32-bit integer, or similar. Nothing to do here. */
167 break;
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++)
177 unsigned short typenum = (*ptr)->type;
179 typenum = translate_float (cif->abi, typenum);
181 switch (typenum)
183 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
184 case FFI_TYPE_LONGDOUBLE:
185 if (fpr_count >= NUM_FPR_ARG_REGISTERS - 1)
187 fpr_count = NUM_FPR_ARG_REGISTERS;
188 /* 8-byte align long doubles. */
189 stack_count += stack_count & 1;
190 stack_count += 4;
192 else
193 fpr_count += 2;
194 #ifdef __NO_FPRS__
195 return FFI_BAD_ABI;
196 #endif
197 break;
198 #endif
200 case FFI_TYPE_DOUBLE:
201 if (fpr_count >= NUM_FPR_ARG_REGISTERS)
203 /* 8-byte align doubles. */
204 stack_count += stack_count & 1;
205 stack_count += 2;
207 else
208 fpr_count += 1;
209 #ifdef __NO_FPRS__
210 return FFI_BAD_ABI;
211 #endif
212 break;
214 case FFI_TYPE_FLOAT:
215 if (fpr_count >= NUM_FPR_ARG_REGISTERS)
216 /* Yes, we don't follow the ABI, but neither does gcc. */
217 stack_count += 1;
218 else
219 fpr_count += 1;
220 #ifdef __NO_FPRS__
221 return FFI_BAD_ABI;
222 #endif
223 break;
225 case FFI_TYPE_UINT128:
226 /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set
227 of four consecutive gprs. If we do not have enough, we
228 have to adjust the gpr_count value. */
229 if (gpr_count >= NUM_GPR_ARG_REGISTERS - 3)
230 gpr_count = NUM_GPR_ARG_REGISTERS;
231 if (gpr_count >= NUM_GPR_ARG_REGISTERS)
232 stack_count += 4;
233 else
234 gpr_count += 4;
235 break;
237 case FFI_TYPE_UINT64:
238 case FFI_TYPE_SINT64:
239 /* 'long long' arguments are passed as two words, but
240 either both words must fit in registers or both go
241 on the stack. If they go on the stack, they must
242 be 8-byte-aligned.
244 Also, only certain register pairs can be used for
245 passing long long int -- specifically (r3,r4), (r5,r6),
246 (r7,r8), (r9,r10). */
247 gpr_count += gpr_count & 1;
248 if (gpr_count >= NUM_GPR_ARG_REGISTERS)
250 stack_count += stack_count & 1;
251 stack_count += 2;
253 else
254 gpr_count += 2;
255 break;
257 case FFI_TYPE_STRUCT:
258 /* We must allocate space for a copy of these to enforce
259 pass-by-value. Pad the space up to a multiple of 16
260 bytes (the maximum alignment required for anything under
261 the SYSV ABI). */
262 struct_copy_size += ((*ptr)->size + 15) & ~0xF;
263 /* Fall through (allocate space for the pointer). */
265 case FFI_TYPE_POINTER:
266 case FFI_TYPE_INT:
267 case FFI_TYPE_UINT32:
268 case FFI_TYPE_SINT32:
269 case FFI_TYPE_UINT16:
270 case FFI_TYPE_SINT16:
271 case FFI_TYPE_UINT8:
272 case FFI_TYPE_SINT8:
273 /* Everything else is passed as a 4-byte word in a GPR, either
274 the object itself or a pointer to it. */
275 if (gpr_count >= NUM_GPR_ARG_REGISTERS)
276 stack_count += 1;
277 else
278 gpr_count += 1;
279 break;
281 default:
282 FFI_ASSERT (0);
286 if (fpr_count != 0)
287 flags |= FLAG_FP_ARGUMENTS;
288 if (gpr_count > 4)
289 flags |= FLAG_4_GPR_ARGUMENTS;
290 if (struct_copy_size != 0)
291 flags |= FLAG_ARG_NEEDS_COPY;
293 /* Space for the FPR registers, if needed. */
294 if (fpr_count != 0)
295 bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
297 /* Stack space. */
298 bytes += stack_count * sizeof (int);
300 /* The stack space allocated needs to be a multiple of 16 bytes. */
301 bytes = (bytes + 15) & ~0xF;
303 /* Add in the space for the copied structures. */
304 bytes += struct_copy_size;
306 cif->flags = flags;
307 cif->bytes = bytes;
309 return FFI_OK;
312 ffi_status FFI_HIDDEN
313 ffi_prep_cif_sysv (ffi_cif *cif)
315 if ((cif->abi & FFI_SYSV) == 0)
317 /* This call is from old code. Translate to new ABI values. */
318 cif->flags |= FLAG_COMPAT;
319 switch (cif->abi)
321 default:
322 return FFI_BAD_ABI;
324 case FFI_COMPAT_SYSV:
325 cif->abi = FFI_SYSV | FFI_SYSV_STRUCT_RET | FFI_SYSV_LONG_DOUBLE_128;
326 break;
328 case FFI_COMPAT_GCC_SYSV:
329 cif->abi = FFI_SYSV | FFI_SYSV_LONG_DOUBLE_128;
330 break;
332 case FFI_COMPAT_LINUX:
333 cif->abi = (FFI_SYSV | FFI_SYSV_IBM_LONG_DOUBLE
334 | FFI_SYSV_LONG_DOUBLE_128);
335 break;
337 case FFI_COMPAT_LINUX_SOFT_FLOAT:
338 cif->abi = (FFI_SYSV | FFI_SYSV_SOFT_FLOAT | FFI_SYSV_IBM_LONG_DOUBLE
339 | FFI_SYSV_LONG_DOUBLE_128);
340 break;
343 return ffi_prep_cif_sysv_core (cif);
346 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
347 has been allocated for the function's arguments.
349 The stack layout we want looks like this:
351 | Return address from ffi_call_SYSV 4bytes | higher addresses
352 |--------------------------------------------|
353 | Previous backchain pointer 4 | stack pointer here
354 |--------------------------------------------|<+ <<< on entry to
355 | Saved r28-r31 4*4 | | ffi_call_SYSV
356 |--------------------------------------------| |
357 | GPR registers r3-r10 8*4 | | ffi_call_SYSV
358 |--------------------------------------------| |
359 | FPR registers f1-f8 (optional) 8*8 | |
360 |--------------------------------------------| | stack |
361 | Space for copied structures | | grows |
362 |--------------------------------------------| | down V
363 | Parameters that didn't fit in registers | |
364 |--------------------------------------------| | lower addresses
365 | Space for callee's LR 4 | |
366 |--------------------------------------------| | stack pointer here
367 | Current backchain pointer 4 |-/ during
368 |--------------------------------------------| <<< ffi_call_SYSV
372 void FFI_HIDDEN
373 ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
375 const unsigned bytes = ecif->cif->bytes;
376 const unsigned flags = ecif->cif->flags;
378 typedef union
380 char *c;
381 unsigned *u;
382 long long *ll;
383 float *f;
384 double *d;
385 } valp;
387 /* 'stacktop' points at the previous backchain pointer. */
388 valp stacktop;
390 /* 'gpr_base' points at the space for gpr3, and grows upwards as
391 we use GPR registers. */
392 valp gpr_base;
393 valp gpr_end;
395 #ifndef __NO_FPRS__
396 /* 'fpr_base' points at the space for fpr1, and grows upwards as
397 we use FPR registers. */
398 valp fpr_base;
399 valp fpr_end;
400 #endif
402 /* 'copy_space' grows down as we put structures in it. It should
403 stay 16-byte aligned. */
404 valp copy_space;
406 /* 'next_arg' grows up as we put parameters in it. */
407 valp next_arg;
409 int i;
410 ffi_type **ptr;
411 #ifndef __NO_FPRS__
412 double double_tmp;
413 #endif
414 union
416 void **v;
417 char **c;
418 signed char **sc;
419 unsigned char **uc;
420 signed short **ss;
421 unsigned short **us;
422 unsigned int **ui;
423 long long **ll;
424 float **f;
425 double **d;
426 } p_argv;
427 size_t struct_copy_size;
428 unsigned gprvalue;
430 stacktop.c = (char *) stack + bytes;
431 gpr_end.u = stacktop.u - ASM_NEEDS_REGISTERS;
432 gpr_base.u = gpr_end.u - NUM_GPR_ARG_REGISTERS;
433 #ifndef __NO_FPRS__
434 fpr_end.d = gpr_base.d;
435 fpr_base.d = fpr_end.d - NUM_FPR_ARG_REGISTERS;
436 copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
437 #else
438 copy_space.c = gpr_base.c;
439 #endif
440 next_arg.u = stack + 2;
442 /* Check that everything starts aligned properly. */
443 FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
444 FFI_ASSERT (((unsigned long) copy_space.c & 0xF) == 0);
445 FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
446 FFI_ASSERT ((bytes & 0xF) == 0);
447 FFI_ASSERT (copy_space.c >= next_arg.c);
449 /* Deal with return values that are actually pass-by-reference. */
450 if (flags & FLAG_RETVAL_REFERENCE)
451 *gpr_base.u++ = (unsigned) (char *) ecif->rvalue;
453 /* Now for the arguments. */
454 p_argv.v = ecif->avalue;
455 for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
456 i > 0;
457 i--, ptr++, p_argv.v++)
459 unsigned int typenum = (*ptr)->type;
461 typenum = translate_float (ecif->cif->abi, typenum);
463 /* Now test the translated value */
464 switch (typenum)
466 #ifndef __NO_FPRS__
467 # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
468 case FFI_TYPE_LONGDOUBLE:
469 double_tmp = (*p_argv.d)[0];
471 if (fpr_base.d >= fpr_end.d - 1)
473 fpr_base.d = fpr_end.d;
474 if (((next_arg.u - stack) & 1) != 0)
475 next_arg.u += 1;
476 *next_arg.d = double_tmp;
477 next_arg.u += 2;
478 double_tmp = (*p_argv.d)[1];
479 *next_arg.d = double_tmp;
480 next_arg.u += 2;
482 else
484 *fpr_base.d++ = double_tmp;
485 double_tmp = (*p_argv.d)[1];
486 *fpr_base.d++ = double_tmp;
488 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
489 break;
490 # endif
491 case FFI_TYPE_DOUBLE:
492 double_tmp = **p_argv.d;
494 if (fpr_base.d >= fpr_end.d)
496 if (((next_arg.u - stack) & 1) != 0)
497 next_arg.u += 1;
498 *next_arg.d = double_tmp;
499 next_arg.u += 2;
501 else
502 *fpr_base.d++ = double_tmp;
503 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
504 break;
506 case FFI_TYPE_FLOAT:
507 double_tmp = **p_argv.f;
508 if (fpr_base.d >= fpr_end.d)
510 *next_arg.f = (float) double_tmp;
511 next_arg.u += 1;
513 else
514 *fpr_base.d++ = double_tmp;
515 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
516 break;
517 #endif /* have FPRs */
519 case FFI_TYPE_UINT128:
520 /* The soft float ABI for long doubles works like this, a long double
521 is passed in four consecutive GPRs if available. A maximum of 2
522 long doubles can be passed in gprs. If we do not have 4 GPRs
523 left, the long double is passed on the stack, 4-byte aligned. */
524 if (gpr_base.u >= gpr_end.u - 3)
526 unsigned int ii;
527 gpr_base.u = gpr_end.u;
528 for (ii = 0; ii < 4; ii++)
530 unsigned int int_tmp = (*p_argv.ui)[ii];
531 *next_arg.u++ = int_tmp;
534 else
536 unsigned int ii;
537 for (ii = 0; ii < 4; ii++)
539 unsigned int int_tmp = (*p_argv.ui)[ii];
540 *gpr_base.u++ = int_tmp;
543 break;
545 case FFI_TYPE_UINT64:
546 case FFI_TYPE_SINT64:
547 if (gpr_base.u >= gpr_end.u - 1)
549 gpr_base.u = gpr_end.u;
550 if (((next_arg.u - stack) & 1) != 0)
551 next_arg.u++;
552 *next_arg.ll = **p_argv.ll;
553 next_arg.u += 2;
555 else
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 (((gpr_end.u - gpr_base.u) & 1) != 0)
563 gpr_base.u++;
564 *gpr_base.ll++ = **p_argv.ll;
566 break;
568 case FFI_TYPE_STRUCT:
569 struct_copy_size = ((*ptr)->size + 15) & ~0xF;
570 copy_space.c -= struct_copy_size;
571 memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
573 gprvalue = (unsigned long) copy_space.c;
575 FFI_ASSERT (copy_space.c > next_arg.c);
576 FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
577 goto putgpr;
579 case FFI_TYPE_UINT8:
580 gprvalue = **p_argv.uc;
581 goto putgpr;
582 case FFI_TYPE_SINT8:
583 gprvalue = **p_argv.sc;
584 goto putgpr;
585 case FFI_TYPE_UINT16:
586 gprvalue = **p_argv.us;
587 goto putgpr;
588 case FFI_TYPE_SINT16:
589 gprvalue = **p_argv.ss;
590 goto putgpr;
592 case FFI_TYPE_INT:
593 case FFI_TYPE_UINT32:
594 case FFI_TYPE_SINT32:
595 case FFI_TYPE_POINTER:
597 gprvalue = **p_argv.ui;
599 putgpr:
600 if (gpr_base.u >= gpr_end.u)
601 *next_arg.u++ = gprvalue;
602 else
603 *gpr_base.u++ = gprvalue;
604 break;
608 /* Check that we didn't overrun the stack... */
609 FFI_ASSERT (copy_space.c >= next_arg.c);
610 FFI_ASSERT (gpr_base.u <= gpr_end.u);
611 #ifndef __NO_FPRS__
612 FFI_ASSERT (fpr_base.u <= fpr_end.u);
613 #endif
614 FFI_ASSERT (((flags & FLAG_4_GPR_ARGUMENTS) != 0)
615 == (gpr_end.u - gpr_base.u < 4));
618 #define MIN_CACHE_LINE_SIZE 8
620 static void
621 flush_icache (char *wraddr, char *xaddr, int size)
623 int i;
624 for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
625 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
626 : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
627 __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
628 : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
629 : "memory");
632 ffi_status FFI_HIDDEN
633 ffi_prep_closure_loc_sysv (ffi_closure *closure,
634 ffi_cif *cif,
635 void (*fun) (ffi_cif *, void *, void **, void *),
636 void *user_data,
637 void *codeloc)
639 unsigned int *tramp;
641 if (cif->abi < FFI_SYSV || cif->abi >= FFI_LAST_ABI)
642 return FFI_BAD_ABI;
644 tramp = (unsigned int *) &closure->tramp[0];
645 tramp[0] = 0x7c0802a6; /* mflr r0 */
646 tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */
647 tramp[2] = 0x7d6802a6; /* mflr r11 */
648 tramp[3] = 0x7c0803a6; /* mtlr r0 */
649 tramp[4] = 0x800b0018; /* lwz r0,24(r11) */
650 tramp[5] = 0x816b001c; /* lwz r11,28(r11) */
651 tramp[6] = 0x7c0903a6; /* mtctr r0 */
652 tramp[7] = 0x4e800420; /* bctr */
653 *(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */
654 *(void **) &tramp[9] = codeloc; /* context */
656 /* Flush the icache. */
657 flush_icache ((char *)tramp, (char *)codeloc, 8 * 4);
659 closure->cif = cif;
660 closure->fun = fun;
661 closure->user_data = user_data;
663 return FFI_OK;
666 /* Basically the trampoline invokes ffi_closure_SYSV, and on
667 entry, r11 holds the address of the closure.
668 After storing the registers that could possibly contain
669 parameters to be passed into the stack frame and setting
670 up space for a return value, ffi_closure_SYSV invokes the
671 following helper function to do most of the work. */
674 ffi_closure_helper_SYSV (ffi_cif *cif,
675 void (*fun) (ffi_cif *, void *, void **, void *),
676 void *user_data,
677 void *rvalue,
678 unsigned long *pgr,
679 ffi_dblfl *pfr,
680 unsigned long *pst)
682 /* rvalue is the pointer to space for return value in closure assembly */
683 /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
684 /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV */
685 /* pst is the pointer to outgoing parameter stack in original caller */
687 void ** avalue;
688 ffi_type ** arg_types;
689 long i, avn;
690 #ifndef __NO_FPRS__
691 long nf = 0; /* number of floating registers already used */
692 #endif
693 long ng = 0; /* number of general registers already used */
695 unsigned size = cif->rtype->size;
696 unsigned short rtypenum = cif->rtype->type;
698 avalue = alloca (cif->nargs * sizeof (void *));
700 /* First translate for softfloat/nonlinux */
701 rtypenum = translate_float (cif->abi, rtypenum);
703 /* Copy the caller's structure return value address so that the closure
704 returns the data directly to the caller.
705 For FFI_SYSV the result is passed in r3/r4 if the struct size is less
706 or equal 8 bytes. */
707 if (rtypenum == FFI_TYPE_STRUCT
708 && !((cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8))
710 rvalue = (void *) *pgr;
711 ng++;
712 pgr++;
715 i = 0;
716 avn = cif->nargs;
717 arg_types = cif->arg_types;
719 /* Grab the addresses of the arguments from the stack frame. */
720 while (i < avn) {
721 unsigned short typenum = arg_types[i]->type;
723 /* We may need to handle some values depending on ABI. */
724 typenum = translate_float (cif->abi, typenum);
726 switch (typenum)
728 #ifndef __NO_FPRS__
729 case FFI_TYPE_FLOAT:
730 /* Unfortunately float values are stored as doubles
731 in the ffi_closure_SYSV code (since we don't check
732 the type in that routine). */
733 if (nf < NUM_FPR_ARG_REGISTERS)
735 /* FIXME? here we are really changing the values
736 stored in the original calling routines outgoing
737 parameter stack. This is probably a really
738 naughty thing to do but... */
739 double temp = pfr->d;
740 pfr->f = (float) temp;
741 avalue[i] = pfr;
742 nf++;
743 pfr++;
745 else
747 avalue[i] = pst;
748 pst += 1;
750 break;
752 case FFI_TYPE_DOUBLE:
753 if (nf < NUM_FPR_ARG_REGISTERS)
755 avalue[i] = pfr;
756 nf++;
757 pfr++;
759 else
761 if (((long) pst) & 4)
762 pst++;
763 avalue[i] = pst;
764 pst += 2;
766 break;
768 # if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
769 case FFI_TYPE_LONGDOUBLE:
770 if (nf < NUM_FPR_ARG_REGISTERS - 1)
772 avalue[i] = pfr;
773 pfr += 2;
774 nf += 2;
776 else
778 if (((long) pst) & 4)
779 pst++;
780 avalue[i] = pst;
781 pst += 4;
782 nf = 8;
784 break;
785 # endif
786 #endif
788 case FFI_TYPE_UINT128:
789 /* Test if for the whole long double, 4 gprs are available.
790 otherwise the stuff ends up on the stack. */
791 if (ng < NUM_GPR_ARG_REGISTERS - 3)
793 avalue[i] = pgr;
794 pgr += 4;
795 ng += 4;
797 else
799 avalue[i] = pst;
800 pst += 4;
801 ng = 8+4;
803 break;
805 case FFI_TYPE_SINT8:
806 case FFI_TYPE_UINT8:
807 #ifndef __LITTLE_ENDIAN__
808 if (ng < NUM_GPR_ARG_REGISTERS)
810 avalue[i] = (char *) pgr + 3;
811 ng++;
812 pgr++;
814 else
816 avalue[i] = (char *) pst + 3;
817 pst++;
819 break;
820 #endif
822 case FFI_TYPE_SINT16:
823 case FFI_TYPE_UINT16:
824 #ifndef __LITTLE_ENDIAN__
825 if (ng < NUM_GPR_ARG_REGISTERS)
827 avalue[i] = (char *) pgr + 2;
828 ng++;
829 pgr++;
831 else
833 avalue[i] = (char *) pst + 2;
834 pst++;
836 break;
837 #endif
839 case FFI_TYPE_SINT32:
840 case FFI_TYPE_UINT32:
841 case FFI_TYPE_POINTER:
842 if (ng < NUM_GPR_ARG_REGISTERS)
844 avalue[i] = pgr;
845 ng++;
846 pgr++;
848 else
850 avalue[i] = pst;
851 pst++;
853 break;
855 case FFI_TYPE_STRUCT:
856 /* Structs are passed by reference. The address will appear in a
857 gpr if it is one of the first 8 arguments. */
858 if (ng < NUM_GPR_ARG_REGISTERS)
860 avalue[i] = (void *) *pgr;
861 ng++;
862 pgr++;
864 else
866 avalue[i] = (void *) *pst;
867 pst++;
869 break;
871 case FFI_TYPE_SINT64:
872 case FFI_TYPE_UINT64:
873 /* Passing long long ints are complex, they must
874 be passed in suitable register pairs such as
875 (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
876 and if the entire pair aren't available then the outgoing
877 parameter stack is used for both but an alignment of 8
878 must will be kept. So we must either look in pgr
879 or pst to find the correct address for this type
880 of parameter. */
881 if (ng < NUM_GPR_ARG_REGISTERS - 1)
883 if (ng & 1)
885 /* skip r4, r6, r8 as starting points */
886 ng++;
887 pgr++;
889 avalue[i] = pgr;
890 ng += 2;
891 pgr += 2;
893 else
895 if (((long) pst) & 4)
896 pst++;
897 avalue[i] = pst;
898 pst += 2;
899 ng = NUM_GPR_ARG_REGISTERS;
901 break;
903 default:
904 FFI_ASSERT (0);
907 i++;
910 (*fun) (cif, rvalue, avalue, user_data);
912 /* Tell ffi_closure_SYSV how to perform return type promotions.
913 Because the FFI_SYSV ABI returns the structures <= 8 bytes in
914 r3/r4 we have to tell ffi_closure_SYSV how to treat them. We
915 combine the base type FFI_SYSV_TYPE_SMALL_STRUCT with the size of
916 the struct less one. We never have a struct with size zero.
917 See the comment in ffitarget.h about ordering. */
918 if (rtypenum == FFI_TYPE_STRUCT
919 && (cif->abi & FFI_SYSV_STRUCT_RET) != 0 && size <= 8)
920 return FFI_SYSV_TYPE_SMALL_STRUCT - 1 + size;
921 return rtypenum;
923 #endif