Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / ctypes / libffi / src / powerpc / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 1998 Geoffrey Keating
3    Copyright (C) 2007, 2008 Free Software Foundation, Inc
4    Copyright (C) 2008 Red Hat, Inc
5
6    PowerPC Foreign Function Interface
7
8    Permission is hereby granted, free of charge, to any person obtaining
9    a copy of this software and associated documentation files (the
10    ``Software''), to deal in the Software without restriction, including
11    without limitation the rights to use, copy, modify, merge, publish,
12    distribute, sublicense, and/or sell copies of the Software, and to
13    permit persons to whom the Software is furnished to do so, subject to
14    the following conditions:
15
16    The above copyright notice and this permission notice shall be included
17    in all copies or substantial portions of the Software.
18
19    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
20    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
23    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25    OTHER DEALINGS IN THE SOFTWARE.
26    ----------------------------------------------------------------------- */
27
28 #include <ffi.h>
29 #include <ffi_common.h>
30
31 #include <stdlib.h>
32 #include <stdio.h>
33
34
35 extern void ffi_closure_SYSV (void);
36 extern void FFI_HIDDEN ffi_closure_LINUX64 (void);
37
38 enum {
39   /* The assembly depends on these exact flags.  */
40   FLAG_RETURNS_SMST     = 1 << (31-31), /* Used for FFI_SYSV small structs.  */
41   FLAG_RETURNS_NOTHING  = 1 << (31-30), /* These go in cr7 */
42   FLAG_RETURNS_FP       = 1 << (31-29),
43   FLAG_RETURNS_64BITS   = 1 << (31-28),
44
45   FLAG_RETURNS_128BITS  = 1 << (31-27), /* cr6  */
46   FLAG_SYSV_SMST_R4     = 1 << (31-26), /* use r4 for FFI_SYSV 8 byte
47                                            structs.  */
48   FLAG_SYSV_SMST_R3     = 1 << (31-25), /* use r3 for FFI_SYSV 4 byte
49                                            structs.  */
50   /* Bits (31-24) through (31-19) store shift value for SMST */
51
52   FLAG_ARG_NEEDS_COPY   = 1 << (31- 7),
53   FLAG_FP_ARGUMENTS     = 1 << (31- 6), /* cr1.eq; specified by ABI */
54   FLAG_4_GPR_ARGUMENTS  = 1 << (31- 5),
55   FLAG_RETVAL_REFERENCE = 1 << (31- 4)
56 };
57
58 /* About the SYSV ABI.  */
59 unsigned int NUM_GPR_ARG_REGISTERS = 8;
60 #ifndef __NO_FPRS__
61 unsigned int NUM_FPR_ARG_REGISTERS = 8;
62 #else
63 unsigned int NUM_FPR_ARG_REGISTERS = 0;
64 #endif
65
66 enum { ASM_NEEDS_REGISTERS = 4 };
67
68 /* ffi_prep_args_SYSV is called by the assembly routine once stack space
69    has been allocated for the function's arguments.
70
71    The stack layout we want looks like this:
72
73    |   Return address from ffi_call_SYSV 4bytes |       higher addresses
74    |--------------------------------------------|
75    |   Previous backchain pointer       4       |       stack pointer here
76    |--------------------------------------------|<+ <<< on entry to
77    |   Saved r28-r31                    4*4     | |     ffi_call_SYSV
78    |--------------------------------------------| |
79    |   GPR registers r3-r10             8*4     | |     ffi_call_SYSV
80    |--------------------------------------------| |
81    |   FPR registers f1-f8 (optional)   8*8     | |
82    |--------------------------------------------| |     stack   |
83    |   Space for copied structures              | |     grows   |
84    |--------------------------------------------| |     down    V
85    |   Parameters that didn't fit in registers  | |
86    |--------------------------------------------| |     lower addresses
87    |   Space for callee's LR            4       | |
88    |--------------------------------------------| |     stack pointer here
89    |   Current backchain pointer        4       |-/     during
90    |--------------------------------------------|   <<< ffi_call_SYSV
91
92 */
93
94 void
95 ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack)
96 {
97   const unsigned bytes = ecif->cif->bytes;
98   const unsigned flags = ecif->cif->flags;
99
100   typedef union {
101     char *c;
102     unsigned *u;
103     long long *ll;
104     float *f;
105     double *d;
106   } valp;
107
108   /* 'stacktop' points at the previous backchain pointer.  */
109   valp stacktop;
110
111   /* 'gpr_base' points at the space for gpr3, and grows upwards as
112      we use GPR registers.  */
113   valp gpr_base;
114   int intarg_count;
115
116   /* 'fpr_base' points at the space for fpr1, and grows upwards as
117      we use FPR registers.  */
118   valp fpr_base;
119   int fparg_count;
120
121   /* 'copy_space' grows down as we put structures in it.  It should
122      stay 16-byte aligned.  */
123   valp copy_space;
124
125   /* 'next_arg' grows up as we put parameters in it.  */
126   valp next_arg;
127
128   int i, ii MAYBE_UNUSED;
129   ffi_type **ptr;
130   double double_tmp;
131   union {
132     void **v;
133     char **c;
134     signed char **sc;
135     unsigned char **uc;
136     signed short **ss;
137     unsigned short **us;
138     unsigned int **ui;
139     long long **ll;
140     float **f;
141     double **d;
142   } p_argv;
143   size_t struct_copy_size;
144   unsigned gprvalue;
145
146   if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
147     NUM_FPR_ARG_REGISTERS = 0;
148
149   stacktop.c = (char *) stack + bytes;
150   gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS;
151   intarg_count = 0;
152   fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS;
153   fparg_count = 0;
154   copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c);
155   next_arg.u = stack + 2;
156
157   /* Check that everything starts aligned properly.  */
158   FFI_ASSERT (((unsigned) (char *) stack & 0xF) == 0);
159   FFI_ASSERT (((unsigned) copy_space.c & 0xF) == 0);
160   FFI_ASSERT (((unsigned) stacktop.c & 0xF) == 0);
161   FFI_ASSERT ((bytes & 0xF) == 0);
162   FFI_ASSERT (copy_space.c >= next_arg.c);
163
164   /* Deal with return values that are actually pass-by-reference.  */
165   if (flags & FLAG_RETVAL_REFERENCE)
166     {
167       *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue;
168       intarg_count++;
169     }
170
171   /* Now for the arguments.  */
172   p_argv.v = ecif->avalue;
173   for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
174        i > 0;
175        i--, ptr++, p_argv.v++)
176     {
177       switch ((*ptr)->type)
178         {
179         case FFI_TYPE_FLOAT:
180           /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
181           if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
182             goto soft_float_prep;
183           double_tmp = **p_argv.f;
184           if (fparg_count >= NUM_FPR_ARG_REGISTERS)
185             {
186               *next_arg.f = (float) double_tmp;
187               next_arg.u += 1;
188               intarg_count++;
189             }
190           else
191             *fpr_base.d++ = double_tmp;
192           fparg_count++;
193           FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
194           break;
195
196         case FFI_TYPE_DOUBLE:
197           /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
198           if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
199             goto soft_double_prep;
200           double_tmp = **p_argv.d;
201
202           if (fparg_count >= NUM_FPR_ARG_REGISTERS)
203             {
204               if (intarg_count >= NUM_GPR_ARG_REGISTERS
205                   && intarg_count % 2 != 0)
206                 {
207                   intarg_count++;
208                   next_arg.u++;
209                 }
210               *next_arg.d = double_tmp;
211               next_arg.u += 2;
212             }
213           else
214             *fpr_base.d++ = double_tmp;
215           fparg_count++;
216           FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
217           break;
218
219 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
220         case FFI_TYPE_LONGDOUBLE:
221           if ((ecif->cif->abi != FFI_LINUX)
222                 && (ecif->cif->abi != FFI_LINUX_SOFT_FLOAT))
223             goto do_struct;
224           /* The soft float ABI for long doubles works like this,
225              a long double is passed in four consecutive gprs if available.
226              A maximum of 2 long doubles can be passed in gprs.
227              If we do not have 4 gprs left, the long double is passed on the
228              stack, 4-byte aligned.  */
229           if (ecif->cif->abi == FFI_LINUX_SOFT_FLOAT)
230             {
231               unsigned int int_tmp = (*p_argv.ui)[0];
232               if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3)
233                 {
234                   if (intarg_count < NUM_GPR_ARG_REGISTERS)
235                     intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
236                   *next_arg.u = int_tmp;
237                   next_arg.u++;
238                   for (ii = 1; ii < 4; ii++)
239                     {
240                       int_tmp = (*p_argv.ui)[ii];
241                       *next_arg.u = int_tmp;
242                       next_arg.u++;
243                     }
244                 }
245               else
246                 {
247                   *gpr_base.u++ = int_tmp;
248                   for (ii = 1; ii < 4; ii++)
249                     {
250                       int_tmp = (*p_argv.ui)[ii];
251                       *gpr_base.u++ = int_tmp;
252                     }
253                 }
254               intarg_count +=4;
255             }
256           else
257             {
258               double_tmp = (*p_argv.d)[0];
259
260               if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1)
261                 {
262                   if (intarg_count >= NUM_GPR_ARG_REGISTERS
263                       && intarg_count % 2 != 0)
264                     {
265                       intarg_count++;
266                       next_arg.u++;
267                     }
268                   *next_arg.d = double_tmp;
269                   next_arg.u += 2;
270                   double_tmp = (*p_argv.d)[1];
271                   *next_arg.d = double_tmp;
272                   next_arg.u += 2;
273                 }
274               else
275                 {
276                   *fpr_base.d++ = double_tmp;
277                   double_tmp = (*p_argv.d)[1];
278                   *fpr_base.d++ = double_tmp;
279                 }
280
281               fparg_count += 2;
282               FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
283             }
284           break;
285 #endif
286
287         case FFI_TYPE_UINT64:
288         case FFI_TYPE_SINT64:
289         soft_double_prep:
290           if (intarg_count == NUM_GPR_ARG_REGISTERS-1)
291             intarg_count++;
292           if (intarg_count >= NUM_GPR_ARG_REGISTERS)
293             {
294               if (intarg_count % 2 != 0)
295                 {
296                   intarg_count++;
297                   next_arg.u++;
298                 }
299               *next_arg.ll = **p_argv.ll;
300               next_arg.u += 2;
301             }
302           else
303             {
304               /* whoops: abi states only certain register pairs
305                * can be used for passing long long int
306                * specifically (r3,r4), (r5,r6), (r7,r8),
307                * (r9,r10) and if next arg is long long but
308                * not correct starting register of pair then skip
309                * until the proper starting register
310                */
311               if (intarg_count % 2 != 0)
312                 {
313                   intarg_count ++;
314                   gpr_base.u++;
315                 }
316               *gpr_base.ll++ = **p_argv.ll;
317             }
318           intarg_count += 2;
319           break;
320
321         case FFI_TYPE_STRUCT:
322 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
323         do_struct:
324 #endif
325           struct_copy_size = ((*ptr)->size + 15) & ~0xF;
326           copy_space.c -= struct_copy_size;
327           memcpy (copy_space.c, *p_argv.c, (*ptr)->size);
328
329           gprvalue = (unsigned long) copy_space.c;
330
331           FFI_ASSERT (copy_space.c > next_arg.c);
332           FFI_ASSERT (flags & FLAG_ARG_NEEDS_COPY);
333           goto putgpr;
334
335         case FFI_TYPE_UINT8:
336           gprvalue = **p_argv.uc;
337           goto putgpr;
338         case FFI_TYPE_SINT8:
339           gprvalue = **p_argv.sc;
340           goto putgpr;
341         case FFI_TYPE_UINT16:
342           gprvalue = **p_argv.us;
343           goto putgpr;
344         case FFI_TYPE_SINT16:
345           gprvalue = **p_argv.ss;
346           goto putgpr;
347
348         case FFI_TYPE_INT:
349         case FFI_TYPE_UINT32:
350         case FFI_TYPE_SINT32:
351         case FFI_TYPE_POINTER:
352         soft_float_prep:
353
354           gprvalue = **p_argv.ui;
355
356         putgpr:
357           if (intarg_count >= NUM_GPR_ARG_REGISTERS)
358             *next_arg.u++ = gprvalue;
359           else
360             *gpr_base.u++ = gprvalue;
361           intarg_count++;
362           break;
363         }
364     }
365
366   /* Check that we didn't overrun the stack...  */
367   FFI_ASSERT (copy_space.c >= next_arg.c);
368   FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS);
369   FFI_ASSERT (fpr_base.u
370               <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS);
371   FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
372 }
373
374 /* About the LINUX64 ABI.  */
375 enum {
376   NUM_GPR_ARG_REGISTERS64 = 8,
377   NUM_FPR_ARG_REGISTERS64 = 13
378 };
379 enum { ASM_NEEDS_REGISTERS64 = 4 };
380
381 /* ffi_prep_args64 is called by the assembly routine once stack space
382    has been allocated for the function's arguments.
383
384    The stack layout we want looks like this:
385
386    |   Ret addr from ffi_call_LINUX64   8bytes  |       higher addresses
387    |--------------------------------------------|
388    |   CR save area                     8bytes  |
389    |--------------------------------------------|
390    |   Previous backchain pointer       8       |       stack pointer here
391    |--------------------------------------------|<+ <<< on entry to
392    |   Saved r28-r31                    4*8     | |     ffi_call_LINUX64
393    |--------------------------------------------| |
394    |   GPR registers r3-r10             8*8     | |
395    |--------------------------------------------| |
396    |   FPR registers f1-f13 (optional)  13*8    | |
397    |--------------------------------------------| |
398    |   Parameter save area                      | |
399    |--------------------------------------------| |
400    |   TOC save area                    8       | |
401    |--------------------------------------------| |     stack   |
402    |   Linker doubleword                8       | |     grows   |
403    |--------------------------------------------| |     down    V
404    |   Compiler doubleword              8       | |
405    |--------------------------------------------| |     lower addresses
406    |   Space for callee's LR            8       | |
407    |--------------------------------------------| |
408    |   CR save area                     8       | |
409    |--------------------------------------------| |     stack pointer here
410    |   Current backchain pointer        8       |-/     during
411    |--------------------------------------------|   <<< ffi_call_LINUX64
412
413 */
414
415 void FFI_HIDDEN
416 ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
417 {
418   const unsigned long bytes = ecif->cif->bytes;
419   const unsigned long flags = ecif->cif->flags;
420
421   typedef union {
422     char *c;
423     unsigned long *ul;
424     float *f;
425     double *d;
426   } valp;
427
428   /* 'stacktop' points at the previous backchain pointer.  */
429   valp stacktop;
430
431   /* 'next_arg' points at the space for gpr3, and grows upwards as
432      we use GPR registers, then continues at rest.  */
433   valp gpr_base;
434   valp gpr_end;
435   valp rest;
436   valp next_arg;
437
438   /* 'fpr_base' points at the space for fpr3, and grows upwards as
439      we use FPR registers.  */
440   valp fpr_base;
441   int fparg_count;
442
443   int i, words;
444   ffi_type **ptr;
445   double double_tmp;
446   union {
447     void **v;
448     char **c;
449     signed char **sc;
450     unsigned char **uc;
451     signed short **ss;
452     unsigned short **us;
453     signed int **si;
454     unsigned int **ui;
455     unsigned long **ul;
456     float **f;
457     double **d;
458   } p_argv;
459   unsigned long gprvalue;
460
461   stacktop.c = (char *) stack + bytes;
462   gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
463   gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
464   rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
465   fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
466   fparg_count = 0;
467   next_arg.ul = gpr_base.ul;
468
469   /* Check that everything starts aligned properly.  */
470   FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
471   FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
472   FFI_ASSERT ((bytes & 0xF) == 0);
473
474   /* Deal with return values that are actually pass-by-reference.  */
475   if (flags & FLAG_RETVAL_REFERENCE)
476     *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
477
478   /* Now for the arguments.  */
479   p_argv.v = ecif->avalue;
480   for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs;
481        i > 0;
482        i--, ptr++, p_argv.v++)
483     {
484       switch ((*ptr)->type)
485         {
486         case FFI_TYPE_FLOAT:
487           double_tmp = **p_argv.f;
488           *next_arg.f = (float) double_tmp;
489           if (++next_arg.ul == gpr_end.ul)
490             next_arg.ul = rest.ul;
491           if (fparg_count < NUM_FPR_ARG_REGISTERS64)
492             *fpr_base.d++ = double_tmp;
493           fparg_count++;
494           FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
495           break;
496
497         case FFI_TYPE_DOUBLE:
498           double_tmp = **p_argv.d;
499           *next_arg.d = double_tmp;
500           if (++next_arg.ul == gpr_end.ul)
501             next_arg.ul = rest.ul;
502           if (fparg_count < NUM_FPR_ARG_REGISTERS64)
503             *fpr_base.d++ = double_tmp;
504           fparg_count++;
505           FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
506           break;
507
508 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
509         case FFI_TYPE_LONGDOUBLE:
510           double_tmp = (*p_argv.d)[0];
511           *next_arg.d = double_tmp;
512           if (++next_arg.ul == gpr_end.ul)
513             next_arg.ul = rest.ul;
514           if (fparg_count < NUM_FPR_ARG_REGISTERS64)
515             *fpr_base.d++ = double_tmp;
516           fparg_count++;
517           double_tmp = (*p_argv.d)[1];
518           *next_arg.d = double_tmp;
519           if (++next_arg.ul == gpr_end.ul)
520             next_arg.ul = rest.ul;
521           if (fparg_count < NUM_FPR_ARG_REGISTERS64)
522             *fpr_base.d++ = double_tmp;
523           fparg_count++;
524           FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
525           FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
526           break;
527 #endif
528
529         case FFI_TYPE_STRUCT:
530           words = ((*ptr)->size + 7) / 8;
531           if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
532             {
533               size_t first = gpr_end.c - next_arg.c;
534               memcpy (next_arg.c, *p_argv.c, first);
535               memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
536               next_arg.c = rest.c + words * 8 - first;
537             }
538           else
539             {
540               char *where = next_arg.c;
541
542               /* Structures with size less than eight bytes are passed
543                  left-padded.  */
544               if ((*ptr)->size < 8)
545                 where += 8 - (*ptr)->size;
546
547               memcpy (where, *p_argv.c, (*ptr)->size);
548               next_arg.ul += words;
549               if (next_arg.ul == gpr_end.ul)
550                 next_arg.ul = rest.ul;
551             }
552           break;
553
554         case FFI_TYPE_UINT8:
555           gprvalue = **p_argv.uc;
556           goto putgpr;
557         case FFI_TYPE_SINT8:
558           gprvalue = **p_argv.sc;
559           goto putgpr;
560         case FFI_TYPE_UINT16:
561           gprvalue = **p_argv.us;
562           goto putgpr;
563         case FFI_TYPE_SINT16:
564           gprvalue = **p_argv.ss;
565           goto putgpr;
566         case FFI_TYPE_UINT32:
567           gprvalue = **p_argv.ui;
568           goto putgpr;
569         case FFI_TYPE_INT:
570         case FFI_TYPE_SINT32:
571           gprvalue = **p_argv.si;
572           goto putgpr;
573
574         case FFI_TYPE_UINT64:
575         case FFI_TYPE_SINT64:
576         case FFI_TYPE_POINTER:
577           gprvalue = **p_argv.ul;
578         putgpr:
579           *next_arg.ul++ = gprvalue;
580           if (next_arg.ul == gpr_end.ul)
581             next_arg.ul = rest.ul;
582           break;
583         }
584     }
585
586   FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
587               || (next_arg.ul >= gpr_base.ul
588                   && next_arg.ul <= gpr_base.ul + 4));
589 }
590
591
592
593 /* Perform machine dependent cif processing */
594 ffi_status
595 ffi_prep_cif_machdep (ffi_cif *cif)
596 {
597   /* All this is for the SYSV and LINUX64 ABI.  */
598   int i;
599   ffi_type **ptr;
600   unsigned bytes;
601   int fparg_count = 0, intarg_count = 0;
602   unsigned flags = 0;
603   unsigned struct_copy_size = 0;
604   unsigned type = cif->rtype->type;
605   unsigned size = cif->rtype->size;
606
607   if (cif->abi == FFI_LINUX_SOFT_FLOAT)
608     NUM_FPR_ARG_REGISTERS = 0;
609
610   if (cif->abi != FFI_LINUX64)
611     {
612       /* All the machine-independent calculation of cif->bytes will be wrong.
613          Redo the calculation for SYSV.  */
614
615       /* Space for the frame pointer, callee's LR, and the asm's temp regs.  */
616       bytes = (2 + ASM_NEEDS_REGISTERS) * sizeof (int);
617
618       /* Space for the GPR registers.  */
619       bytes += NUM_GPR_ARG_REGISTERS * sizeof (int);
620     }
621   else
622     {
623       /* 64-bit ABI.  */
624
625       /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
626          regs.  */
627       bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
628
629       /* Space for the mandatory parm save area and general registers.  */
630       bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
631     }
632
633   /* Return value handling.  The rules for SYSV are as follows:
634      - 32-bit (or less) integer values are returned in gpr3;
635      - Structures of size <= 4 bytes also returned in gpr3;
636      - 64-bit integer values and structures between 5 and 8 bytes are returned
637      in gpr3 and gpr4;
638      - Single/double FP values are returned in fpr1;
639      - Larger structures are allocated space and a pointer is passed as
640      the first argument.
641      - long doubles (if not equivalent to double) are returned in
642      fpr1,fpr2 for Linux and as for large structs for SysV.
643      For LINUX64:
644      - integer values in gpr3;
645      - Structures/Unions by reference;
646      - Single/double FP values in fpr1, long double in fpr1,fpr2.
647      - soft-float float/doubles are treated as UINT32/UINT64 respectivley.
648      - soft-float long doubles are returned in gpr3-gpr6.  */
649   switch (type)
650     {
651 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
652     case FFI_TYPE_LONGDOUBLE:
653       if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX64
654         && cif->abi != FFI_LINUX_SOFT_FLOAT)
655         goto byref;
656       flags |= FLAG_RETURNS_128BITS;
657       /* Fall through.  */
658 #endif
659     case FFI_TYPE_DOUBLE:
660       flags |= FLAG_RETURNS_64BITS;
661       /* Fall through.  */
662     case FFI_TYPE_FLOAT:
663       /* With FFI_LINUX_SOFT_FLOAT no fp registers are used.  */
664       if (cif->abi != FFI_LINUX_SOFT_FLOAT)
665         flags |= FLAG_RETURNS_FP;
666       break;
667
668     case FFI_TYPE_UINT64:
669     case FFI_TYPE_SINT64:
670       flags |= FLAG_RETURNS_64BITS;
671       break;
672
673     case FFI_TYPE_STRUCT:
674       if (cif->abi == FFI_SYSV)
675         {
676           /* The final SYSV ABI says that structures smaller or equal 8 bytes
677              are returned in r3/r4. The FFI_GCC_SYSV ABI instead returns them
678              in memory.  */
679
680           /* Treat structs with size <= 8 bytes.  */
681           if (size <= 8)
682             {
683               flags |= FLAG_RETURNS_SMST;
684               /* These structs are returned in r3. We pack the type and the
685                  precalculated shift value (needed in the sysv.S) into flags.
686                  The same applies for the structs returned in r3/r4.  */
687               if (size <= 4)
688                 {
689                   flags |= FLAG_SYSV_SMST_R3;
690                   flags |= 8 * (4 - size) << 8;
691                   break;
692                 }
693               /* These structs are returned in r3 and r4. See above.   */
694               if  (size <= 8)
695                 {
696                   flags |= FLAG_SYSV_SMST_R3 | FLAG_SYSV_SMST_R4;
697                   flags |= 8 * (8 - size) << 8;
698                   break;
699                 }
700             }
701         }
702 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
703     byref:
704 #endif
705       intarg_count++;
706       flags |= FLAG_RETVAL_REFERENCE;
707       /* Fall through.  */
708     case FFI_TYPE_VOID:
709       flags |= FLAG_RETURNS_NOTHING;
710       break;
711
712     default:
713       /* Returns 32-bit integer, or similar.  Nothing to do here.  */
714       break;
715     }
716
717   if (cif->abi != FFI_LINUX64)
718     /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
719        first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
720        goes on the stack.  Structures and long doubles (if not equivalent
721        to double) are passed as a pointer to a copy of the structure.
722        Stuff on the stack needs to keep proper alignment.  */
723     for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
724       {
725         switch ((*ptr)->type)
726           {
727           case FFI_TYPE_FLOAT:
728             /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
729             if (cif->abi == FFI_LINUX_SOFT_FLOAT)
730               goto soft_float_cif;
731             fparg_count++;
732             /* floating singles are not 8-aligned on stack */
733             break;
734
735 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
736           case FFI_TYPE_LONGDOUBLE:
737             if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
738               goto do_struct;
739             if (cif->abi == FFI_LINUX_SOFT_FLOAT)
740               {
741                 if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3
742                   || intarg_count < NUM_GPR_ARG_REGISTERS)
743                   /* A long double in FFI_LINUX_SOFT_FLOAT can use only
744                      a set of four consecutive gprs. If we have not enough,
745                      we have to adjust the intarg_count value.  */
746                   intarg_count += NUM_GPR_ARG_REGISTERS - intarg_count;
747                 intarg_count += 4;
748                 break;
749               }
750             else
751               fparg_count++;
752             /* Fall thru */
753 #endif
754           case FFI_TYPE_DOUBLE:
755             /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
756             if (cif->abi == FFI_LINUX_SOFT_FLOAT)
757               goto soft_double_cif;
758             fparg_count++;
759             /* If this FP arg is going on the stack, it must be
760                8-byte-aligned.  */
761             if (fparg_count > NUM_FPR_ARG_REGISTERS
762                 && intarg_count >= NUM_GPR_ARG_REGISTERS
763                 && intarg_count % 2 != 0)
764               intarg_count++;
765             break;
766
767           case FFI_TYPE_UINT64:
768           case FFI_TYPE_SINT64:
769           soft_double_cif:
770             /* 'long long' arguments are passed as two words, but
771                either both words must fit in registers or both go
772                on the stack.  If they go on the stack, they must
773                be 8-byte-aligned.
774
775                Also, only certain register pairs can be used for
776                passing long long int -- specifically (r3,r4), (r5,r6),
777                (r7,r8), (r9,r10).
778             */
779             if (intarg_count == NUM_GPR_ARG_REGISTERS-1
780                 || intarg_count % 2 != 0)
781               intarg_count++;
782             intarg_count += 2;
783             break;
784
785           case FFI_TYPE_STRUCT:
786 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
787           do_struct:
788 #endif
789             /* We must allocate space for a copy of these to enforce
790                pass-by-value.  Pad the space up to a multiple of 16
791                bytes (the maximum alignment required for anything under
792                the SYSV ABI).  */
793             struct_copy_size += ((*ptr)->size + 15) & ~0xF;
794             /* Fall through (allocate space for the pointer).  */
795
796           default:
797           soft_float_cif:
798             /* Everything else is passed as a 4-byte word in a GPR, either
799                the object itself or a pointer to it.  */
800             intarg_count++;
801             break;
802           }
803       }
804   else
805     for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
806       {
807         switch ((*ptr)->type)
808           {
809 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
810           case FFI_TYPE_LONGDOUBLE:
811             if (cif->abi == FFI_LINUX_SOFT_FLOAT)
812               intarg_count += 4;
813             else
814               {
815                 fparg_count += 2;
816                 intarg_count += 2;
817               }
818             break;
819 #endif
820           case FFI_TYPE_FLOAT:
821           case FFI_TYPE_DOUBLE:
822             fparg_count++;
823             intarg_count++;
824             break;
825
826           case FFI_TYPE_STRUCT:
827             intarg_count += ((*ptr)->size + 7) / 8;
828             break;
829
830           default:
831             /* Everything else is passed as a 8-byte word in a GPR, either
832                the object itself or a pointer to it.  */
833             intarg_count++;
834             break;
835           }
836       }
837
838   if (fparg_count != 0)
839     flags |= FLAG_FP_ARGUMENTS;
840   if (intarg_count > 4)
841     flags |= FLAG_4_GPR_ARGUMENTS;
842   if (struct_copy_size != 0)
843     flags |= FLAG_ARG_NEEDS_COPY;
844
845   if (cif->abi != FFI_LINUX64)
846     {
847       /* Space for the FPR registers, if needed.  */
848       if (fparg_count != 0)
849         bytes += NUM_FPR_ARG_REGISTERS * sizeof (double);
850
851       /* Stack space.  */
852       if (intarg_count > NUM_GPR_ARG_REGISTERS)
853         bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int);
854       if (fparg_count > NUM_FPR_ARG_REGISTERS)
855         bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double);
856     }
857   else
858     {
859       /* Space for the FPR registers, if needed.  */
860       if (fparg_count != 0)
861         bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
862
863       /* Stack space.  */
864       if (intarg_count > NUM_GPR_ARG_REGISTERS64)
865         bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
866     }
867
868   /* The stack space allocated needs to be a multiple of 16 bytes.  */
869   bytes = (bytes + 15) & ~0xF;
870
871   /* Add in the space for the copied structures.  */
872   bytes += struct_copy_size;
873
874   cif->flags = flags;
875   cif->bytes = bytes;
876
877   return FFI_OK;
878 }
879
880 extern void ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *,
881                           void (*fn)(void));
882 extern void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long,
883                                         unsigned long, unsigned long *,
884                                         void (*fn)(void));
885
886 void
887 ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
888 {
889   extended_cif ecif;
890
891   ecif.cif = cif;
892   ecif.avalue = avalue;
893
894   /* If the return value is a struct and we don't have a return */
895   /* value address then we need to make one                     */
896
897   if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
898     {
899       ecif.rvalue = alloca(cif->rtype->size);
900     }
901   else
902     ecif.rvalue = rvalue;
903
904
905   switch (cif->abi)
906     {
907 #ifndef POWERPC64
908     case FFI_SYSV:
909     case FFI_GCC_SYSV:
910     case FFI_LINUX:
911     case FFI_LINUX_SOFT_FLOAT:
912       ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn);
913       break;
914 #else
915     case FFI_LINUX64:
916       ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn);
917       break;
918 #endif
919     default:
920       FFI_ASSERT (0);
921       break;
922     }
923 }
924
925
926 #ifndef POWERPC64
927 #define MIN_CACHE_LINE_SIZE 8
928
929 static void
930 flush_icache (char *wraddr, char *xaddr, int size)
931 {
932   int i;
933   for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
934     __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
935                       : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
936   __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
937                     : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
938                     : "memory");
939 }
940 #endif
941
942 ffi_status
943 ffi_prep_closure_loc (ffi_closure *closure,
944                       ffi_cif *cif,
945                       void (*fun) (ffi_cif *, void *, void **, void *),
946                       void *user_data,
947                       void *codeloc)
948 {
949 #ifdef POWERPC64
950   void **tramp = (void **) &closure->tramp[0];
951
952   FFI_ASSERT (cif->abi == FFI_LINUX64);
953   /* Copy function address and TOC from ffi_closure_LINUX64.  */
954   memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
955   tramp[2] = codeloc;
956 #else
957   unsigned int *tramp;
958
959   FFI_ASSERT (cif->abi == FFI_GCC_SYSV || cif->abi == FFI_SYSV);
960
961   tramp = (unsigned int *) &closure->tramp[0];
962   tramp[0] = 0x7c0802a6;  /*   mflr    r0 */
963   tramp[1] = 0x4800000d;  /*   bl      10 <trampoline_initial+0x10> */
964   tramp[4] = 0x7d6802a6;  /*   mflr    r11 */
965   tramp[5] = 0x7c0803a6;  /*   mtlr    r0 */
966   tramp[6] = 0x800b0000;  /*   lwz     r0,0(r11) */
967   tramp[7] = 0x816b0004;  /*   lwz     r11,4(r11) */
968   tramp[8] = 0x7c0903a6;  /*   mtctr   r0 */
969   tramp[9] = 0x4e800420;  /*   bctr */
970   *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
971   *(void **) &tramp[3] = codeloc;                   /* context */
972
973   /* Flush the icache.  */
974   flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
975 #endif
976
977   closure->cif = cif;
978   closure->fun = fun;
979   closure->user_data = user_data;
980
981   return FFI_OK;
982 }
983
984 typedef union
985 {
986   float f;
987   double d;
988 } ffi_dblfl;
989
990 int ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *,
991                              ffi_dblfl *, unsigned long *);
992
993 /* Basically the trampoline invokes ffi_closure_SYSV, and on
994  * entry, r11 holds the address of the closure.
995  * After storing the registers that could possibly contain
996  * parameters to be passed into the stack frame and setting
997  * up space for a return value, ffi_closure_SYSV invokes the
998  * following helper function to do most of the work
999  */
1000
1001 int
1002 ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
1003                          unsigned long *pgr, ffi_dblfl *pfr,
1004                          unsigned long *pst)
1005 {
1006   /* rvalue is the pointer to space for return value in closure assembly */
1007   /* pgr is the pointer to where r3-r10 are stored in ffi_closure_SYSV */
1008   /* pfr is the pointer to where f1-f8 are stored in ffi_closure_SYSV  */
1009   /* pst is the pointer to outgoing parameter stack in original caller */
1010
1011   void **          avalue;
1012   ffi_type **      arg_types;
1013   long             i, avn;
1014   long             nf;   /* number of floating registers already used */
1015   long             ng;   /* number of general registers already used */
1016   ffi_cif *        cif;
1017   double           temp;
1018   unsigned         size;
1019
1020   cif = closure->cif;
1021   avalue = alloca (cif->nargs * sizeof (void *));
1022   size = cif->rtype->size;
1023
1024   nf = 0;
1025   ng = 0;
1026
1027   /* Copy the caller's structure return value address so that the closure
1028      returns the data directly to the caller.
1029      For FFI_SYSV the result is passed in r3/r4 if the struct size is less
1030      or equal 8 bytes.  */
1031
1032   if ((cif->rtype->type == FFI_TYPE_STRUCT
1033        && !((cif->abi == FFI_SYSV) && (size <= 8)))
1034 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1035       || (cif->rtype->type == FFI_TYPE_LONGDOUBLE
1036           && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1037 #endif
1038       )
1039     {
1040       rvalue = (void *) *pgr;
1041       ng++;
1042       pgr++;
1043     }
1044
1045   i = 0;
1046   avn = cif->nargs;
1047   arg_types = cif->arg_types;
1048
1049   /* Grab the addresses of the arguments from the stack frame.  */
1050   while (i < avn)
1051     {
1052       switch (arg_types[i]->type)
1053         {
1054         case FFI_TYPE_SINT8:
1055         case FFI_TYPE_UINT8:
1056           /* there are 8 gpr registers used to pass values */
1057           if (ng < 8)
1058             {
1059               avalue[i] = (char *) pgr + 3;
1060               ng++;
1061               pgr++;
1062             }
1063           else
1064             {
1065               avalue[i] = (char *) pst + 3;
1066               pst++;
1067             }
1068           break;
1069
1070         case FFI_TYPE_SINT16:
1071         case FFI_TYPE_UINT16:
1072           /* there are 8 gpr registers used to pass values */
1073           if (ng < 8)
1074             {
1075               avalue[i] = (char *) pgr + 2;
1076               ng++;
1077               pgr++;
1078             }
1079           else
1080             {
1081               avalue[i] = (char *) pst + 2;
1082               pst++;
1083             }
1084           break;
1085
1086         case FFI_TYPE_SINT32:
1087         case FFI_TYPE_UINT32:
1088         case FFI_TYPE_POINTER:
1089         soft_float_closure:
1090           /* there are 8 gpr registers used to pass values */
1091           if (ng < 8)
1092             {
1093               avalue[i] = pgr;
1094               ng++;
1095               pgr++;
1096             }
1097           else
1098             {
1099               avalue[i] = pst;
1100               pst++;
1101             }
1102           break;
1103
1104         case FFI_TYPE_STRUCT:
1105 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1106         do_struct:
1107 #endif
1108           /* Structs are passed by reference. The address will appear in a
1109              gpr if it is one of the first 8 arguments.  */
1110           if (ng < 8)
1111             {
1112               avalue[i] = (void *) *pgr;
1113               ng++;
1114               pgr++;
1115             }
1116           else
1117             {
1118               avalue[i] = (void *) *pst;
1119               pst++;
1120             }
1121           break;
1122
1123         case FFI_TYPE_SINT64:
1124         case FFI_TYPE_UINT64:
1125         soft_double_closure:
1126           /* passing long long ints are complex, they must
1127            * be passed in suitable register pairs such as
1128            * (r3,r4) or (r5,r6) or (r6,r7), or (r7,r8) or (r9,r10)
1129            * and if the entire pair aren't available then the outgoing
1130            * parameter stack is used for both but an alignment of 8
1131            * must will be kept.  So we must either look in pgr
1132            * or pst to find the correct address for this type
1133            * of parameter.
1134            */
1135           if (ng < 7)
1136             {
1137               if (ng & 0x01)
1138                 {
1139                   /* skip r4, r6, r8 as starting points */
1140                   ng++;
1141                   pgr++;
1142                 }
1143               avalue[i] = pgr;
1144               ng += 2;
1145               pgr += 2;
1146             }
1147           else
1148             {
1149               if (((long) pst) & 4)
1150                 pst++;
1151               avalue[i] = pst;
1152               pst += 2;
1153               ng = 8;
1154             }
1155           break;
1156
1157         case FFI_TYPE_FLOAT:
1158           /* With FFI_LINUX_SOFT_FLOAT floats are handled like UINT32.  */
1159           if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1160             goto soft_float_closure;
1161           /* unfortunately float values are stored as doubles
1162            * in the ffi_closure_SYSV code (since we don't check
1163            * the type in that routine).
1164            */
1165
1166           /* there are 8 64bit floating point registers */
1167
1168           if (nf < 8)
1169             {
1170               temp = pfr->d;
1171               pfr->f = (float) temp;
1172               avalue[i] = pfr;
1173               nf++;
1174               pfr++;
1175             }
1176           else
1177             {
1178               /* FIXME? here we are really changing the values
1179                * stored in the original calling routines outgoing
1180                * parameter stack.  This is probably a really
1181                * naughty thing to do but...
1182                */
1183               avalue[i] = pst;
1184               pst += 1;
1185             }
1186           break;
1187
1188         case FFI_TYPE_DOUBLE:
1189           /* With FFI_LINUX_SOFT_FLOAT doubles are handled like UINT64.  */
1190           if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1191             goto soft_double_closure;
1192           /* On the outgoing stack all values are aligned to 8 */
1193           /* there are 8 64bit floating point registers */
1194
1195           if (nf < 8)
1196             {
1197               avalue[i] = pfr;
1198               nf++;
1199               pfr++;
1200             }
1201           else
1202             {
1203               if (((long) pst) & 4)
1204                 pst++;
1205               avalue[i] = pst;
1206               pst += 2;
1207             }
1208           break;
1209
1210 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1211         case FFI_TYPE_LONGDOUBLE:
1212           if (cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1213             goto do_struct;
1214           if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1215             { /* Test if for the whole long double, 4 gprs are available.
1216                  otherwise the stuff ends up on the stack.  */
1217               if (ng < 5)
1218                 {
1219                   avalue[i] = pgr;
1220                   pgr += 4;
1221                   ng += 4;
1222                 }
1223               else
1224                 {
1225                   avalue[i] = pst;
1226                   pst += 4;
1227                   ng = 8;
1228                 }
1229               break;
1230             }
1231           if (nf < 7)
1232             {
1233               avalue[i] = pfr;
1234               pfr += 2;
1235               nf += 2;
1236             }
1237           else
1238             {
1239               if (((long) pst) & 4)
1240                 pst++;
1241               avalue[i] = pst;
1242               pst += 4;
1243               nf = 8;
1244             }
1245           break;
1246 #endif
1247
1248         default:
1249           FFI_ASSERT (0);
1250         }
1251
1252       i++;
1253     }
1254
1255
1256   (closure->fun) (cif, rvalue, avalue, closure->user_data);
1257
1258   /* Tell ffi_closure_SYSV how to perform return type promotions.
1259      Because the FFI_SYSV ABI returns the structures <= 8 bytes in r3/r4
1260      we have to tell ffi_closure_SYSV how to treat them. We combine the base
1261      type FFI_SYSV_TYPE_SMALL_STRUCT - 1  with the size of the struct.
1262      So a one byte struct gets the return type 16. Return type 1 to 15 are
1263      already used and we never have a struct with size zero. That is the reason
1264      for the subtraction of 1. See the comment in ffitarget.h about ordering.
1265   */
1266   if (cif->abi == FFI_SYSV && cif->rtype->type == FFI_TYPE_STRUCT
1267       && size <= 8)
1268     return (FFI_SYSV_TYPE_SMALL_STRUCT - 1) + size;
1269 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1270   else if (cif->rtype->type == FFI_TYPE_LONGDOUBLE
1271            && cif->abi != FFI_LINUX && cif->abi != FFI_LINUX_SOFT_FLOAT)
1272     return FFI_TYPE_STRUCT;
1273 #endif
1274   /* With FFI_LINUX_SOFT_FLOAT floats and doubles are handled like UINT32
1275      respectivley UINT64.  */
1276   if (cif->abi == FFI_LINUX_SOFT_FLOAT)
1277     {
1278       switch (cif->rtype->type)
1279         {
1280         case FFI_TYPE_FLOAT:
1281           return FFI_TYPE_UINT32;
1282           break;
1283         case FFI_TYPE_DOUBLE:
1284           return FFI_TYPE_UINT64;
1285           break;
1286 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1287         case FFI_TYPE_LONGDOUBLE:
1288           return FFI_TYPE_UINT128;
1289           break;
1290 #endif
1291         default:
1292           return cif->rtype->type;
1293         }
1294     }
1295   else
1296     {
1297       return cif->rtype->type;
1298     }
1299 }
1300
1301 int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *,
1302                                            unsigned long *, ffi_dblfl *);
1303
1304 int FFI_HIDDEN
1305 ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
1306                             unsigned long *pst, ffi_dblfl *pfr)
1307 {
1308   /* rvalue is the pointer to space for return value in closure assembly */
1309   /* pst is the pointer to parameter save area
1310      (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
1311   /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
1312
1313   void **avalue;
1314   ffi_type **arg_types;
1315   long i, avn;
1316   ffi_cif *cif;
1317   ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
1318
1319   cif = closure->cif;
1320   avalue = alloca (cif->nargs * sizeof (void *));
1321
1322   /* Copy the caller's structure return value address so that the closure
1323      returns the data directly to the caller.  */
1324   if (cif->rtype->type == FFI_TYPE_STRUCT)
1325     {
1326       rvalue = (void *) *pst;
1327       pst++;
1328     }
1329
1330   i = 0;
1331   avn = cif->nargs;
1332   arg_types = cif->arg_types;
1333
1334   /* Grab the addresses of the arguments from the stack frame.  */
1335   while (i < avn)
1336     {
1337       switch (arg_types[i]->type)
1338         {
1339         case FFI_TYPE_SINT8:
1340         case FFI_TYPE_UINT8:
1341           avalue[i] = (char *) pst + 7;
1342           pst++;
1343           break;
1344
1345         case FFI_TYPE_SINT16:
1346         case FFI_TYPE_UINT16:
1347           avalue[i] = (char *) pst + 6;
1348           pst++;
1349           break;
1350
1351         case FFI_TYPE_SINT32:
1352         case FFI_TYPE_UINT32:
1353           avalue[i] = (char *) pst + 4;
1354           pst++;
1355           break;
1356
1357         case FFI_TYPE_SINT64:
1358         case FFI_TYPE_UINT64:
1359         case FFI_TYPE_POINTER:
1360           avalue[i] = pst;
1361           pst++;
1362           break;
1363
1364         case FFI_TYPE_STRUCT:
1365           /* Structures with size less than eight bytes are passed
1366              left-padded.  */
1367           if (arg_types[i]->size < 8)
1368             avalue[i] = (char *) pst + 8 - arg_types[i]->size;
1369           else
1370             avalue[i] = pst;
1371           pst += (arg_types[i]->size + 7) / 8;
1372           break;
1373
1374         case FFI_TYPE_FLOAT:
1375           /* unfortunately float values are stored as doubles
1376            * in the ffi_closure_LINUX64 code (since we don't check
1377            * the type in that routine).
1378            */
1379
1380           /* there are 13 64bit floating point registers */
1381
1382           if (pfr < end_pfr)
1383             {
1384               double temp = pfr->d;
1385               pfr->f = (float) temp;
1386               avalue[i] = pfr;
1387               pfr++;
1388             }
1389           else
1390             avalue[i] = pst;
1391           pst++;
1392           break;
1393
1394         case FFI_TYPE_DOUBLE:
1395           /* On the outgoing stack all values are aligned to 8 */
1396           /* there are 13 64bit floating point registers */
1397
1398           if (pfr < end_pfr)
1399             {
1400               avalue[i] = pfr;
1401               pfr++;
1402             }
1403           else
1404             avalue[i] = pst;
1405           pst++;
1406           break;
1407
1408 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
1409         case FFI_TYPE_LONGDOUBLE:
1410           if (pfr + 1 < end_pfr)
1411             {
1412               avalue[i] = pfr;
1413               pfr += 2;
1414             }
1415           else
1416             {
1417               if (pfr < end_pfr)
1418                 {
1419                   /* Passed partly in f13 and partly on the stack.
1420                      Move it all to the stack.  */
1421                   *pst = *(unsigned long *) pfr;
1422                   pfr++;
1423                 }
1424               avalue[i] = pst;
1425             }
1426           pst += 2;
1427           break;
1428 #endif
1429
1430         default:
1431           FFI_ASSERT (0);
1432         }
1433
1434       i++;
1435     }
1436
1437
1438   (closure->fun) (cif, rvalue, avalue, closure->user_data);
1439
1440   /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
1441   return cif->rtype->type;
1442 }