OSDN Git Service

Merge "Add default code reviewers into OWNERS"
[android-x86/external-libffi.git] / src / powerpc / ffi_linux64.c
1 /* -----------------------------------------------------------------------
2    ffi_linux64.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 #ifdef POWERPC64
34 #include "ffi_common.h"
35 #include "ffi_powerpc.h"
36
37
38 /* About the LINUX64 ABI.  */
39 enum {
40   NUM_GPR_ARG_REGISTERS64 = 8,
41   NUM_FPR_ARG_REGISTERS64 = 13
42 };
43 enum { ASM_NEEDS_REGISTERS64 = 4 };
44
45
46 #if HAVE_LONG_DOUBLE_VARIANT && FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
47 /* Adjust size of ffi_type_longdouble.  */
48 void FFI_HIDDEN
49 ffi_prep_types_linux64 (ffi_abi abi)
50 {
51   if ((abi & (FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128)) == FFI_LINUX)
52     {
53       ffi_type_longdouble.size = 8;
54       ffi_type_longdouble.alignment = 8;
55     }
56   else
57     {
58       ffi_type_longdouble.size = 16;
59       ffi_type_longdouble.alignment = 16;
60     }
61 }
62 #endif
63
64
65 #if _CALL_ELF == 2
66 static unsigned int
67 discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
68 {
69   switch (t->type)
70     {
71     case FFI_TYPE_FLOAT:
72     case FFI_TYPE_DOUBLE:
73       *elnum = 1;
74       return (int) t->type;
75
76     case FFI_TYPE_STRUCT:;
77       {
78         unsigned int base_elt = 0, total_elnum = 0;
79         ffi_type **el = t->elements;
80         while (*el)
81           {
82             unsigned int el_elt, el_elnum = 0;
83             el_elt = discover_homogeneous_aggregate (*el, &el_elnum);
84             if (el_elt == 0
85                 || (base_elt && base_elt != el_elt))
86               return 0;
87             base_elt = el_elt;
88             total_elnum += el_elnum;
89             if (total_elnum > 8)
90               return 0;
91             el++;
92           }
93         *elnum = total_elnum;
94         return base_elt;
95       }
96
97     default:
98       return 0;
99     }
100 }
101 #endif
102
103
104 /* Perform machine dependent cif processing */
105 static ffi_status
106 ffi_prep_cif_linux64_core (ffi_cif *cif)
107 {
108   ffi_type **ptr;
109   unsigned bytes;
110   unsigned i, fparg_count = 0, intarg_count = 0;
111   unsigned flags = cif->flags;
112 #if _CALL_ELF == 2
113   unsigned int elt, elnum;
114 #endif
115
116 #if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE
117   /* If compiled without long double support..  */
118   if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
119     return FFI_BAD_ABI;
120 #endif
121
122   /* The machine-independent calculation of cif->bytes doesn't work
123      for us.  Redo the calculation.  */
124 #if _CALL_ELF == 2
125   /* Space for backchain, CR, LR, TOC and the asm's temp regs.  */
126   bytes = (4 + ASM_NEEDS_REGISTERS64) * sizeof (long);
127
128   /* Space for the general registers.  */
129   bytes += NUM_GPR_ARG_REGISTERS64 * sizeof (long);
130 #else
131   /* Space for backchain, CR, LR, cc/ld doubleword, TOC and the asm's temp
132      regs.  */
133   bytes = (6 + ASM_NEEDS_REGISTERS64) * sizeof (long);
134
135   /* Space for the mandatory parm save area and general registers.  */
136   bytes += 2 * NUM_GPR_ARG_REGISTERS64 * sizeof (long);
137 #endif
138
139   /* Return value handling.  */
140   switch (cif->rtype->type)
141     {
142 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
143     case FFI_TYPE_LONGDOUBLE:
144       if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
145         flags |= FLAG_RETURNS_128BITS;
146       /* Fall through.  */
147 #endif
148     case FFI_TYPE_DOUBLE:
149       flags |= FLAG_RETURNS_64BITS;
150       /* Fall through.  */
151     case FFI_TYPE_FLOAT:
152       flags |= FLAG_RETURNS_FP;
153       break;
154
155     case FFI_TYPE_UINT128:
156       flags |= FLAG_RETURNS_128BITS;
157       /* Fall through.  */
158     case FFI_TYPE_UINT64:
159     case FFI_TYPE_SINT64:
160       flags |= FLAG_RETURNS_64BITS;
161       break;
162
163     case FFI_TYPE_STRUCT:
164 #if _CALL_ELF == 2
165       elt = discover_homogeneous_aggregate (cif->rtype, &elnum);
166       if (elt)
167         {
168           if (elt == FFI_TYPE_DOUBLE)
169             flags |= FLAG_RETURNS_64BITS;
170           flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST;
171           break;
172         }
173       if (cif->rtype->size <= 16)
174         {
175           flags |= FLAG_RETURNS_SMST;
176           break;
177         }
178 #endif
179       intarg_count++;
180       flags |= FLAG_RETVAL_REFERENCE;
181       /* Fall through.  */
182     case FFI_TYPE_VOID:
183       flags |= FLAG_RETURNS_NOTHING;
184       break;
185
186     default:
187       /* Returns 32-bit integer, or similar.  Nothing to do here.  */
188       break;
189     }
190
191   for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
192     {
193       unsigned int align;
194
195       switch ((*ptr)->type)
196         {
197 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
198         case FFI_TYPE_LONGDOUBLE:
199           if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
200             {
201               fparg_count++;
202               intarg_count++;
203             }
204           /* Fall through.  */
205 #endif
206         case FFI_TYPE_DOUBLE:
207         case FFI_TYPE_FLOAT:
208           fparg_count++;
209           intarg_count++;
210           if (fparg_count > NUM_FPR_ARG_REGISTERS64)
211             flags |= FLAG_ARG_NEEDS_PSAVE;
212           break;
213
214         case FFI_TYPE_STRUCT:
215           if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
216             {
217               align = (*ptr)->alignment;
218               if (align > 16)
219                 align = 16;
220               align = align / 8;
221               if (align > 1)
222                 intarg_count = ALIGN (intarg_count, align);
223             }
224           intarg_count += ((*ptr)->size + 7) / 8;
225 #if _CALL_ELF == 2
226           elt = discover_homogeneous_aggregate (*ptr, &elnum);
227           if (elt)
228             {
229               fparg_count += elnum;
230               if (fparg_count > NUM_FPR_ARG_REGISTERS64)
231                 flags |= FLAG_ARG_NEEDS_PSAVE;
232             }
233           else
234 #endif
235             {
236               if (intarg_count > NUM_GPR_ARG_REGISTERS64)
237                 flags |= FLAG_ARG_NEEDS_PSAVE;
238             }
239           break;
240
241         case FFI_TYPE_POINTER:
242         case FFI_TYPE_UINT64:
243         case FFI_TYPE_SINT64:
244         case FFI_TYPE_INT:
245         case FFI_TYPE_UINT32:
246         case FFI_TYPE_SINT32:
247         case FFI_TYPE_UINT16:
248         case FFI_TYPE_SINT16:
249         case FFI_TYPE_UINT8:
250         case FFI_TYPE_SINT8:
251           /* Everything else is passed as a 8-byte word in a GPR, either
252              the object itself or a pointer to it.  */
253           intarg_count++;
254           if (intarg_count > NUM_GPR_ARG_REGISTERS64)
255             flags |= FLAG_ARG_NEEDS_PSAVE;
256           break;
257         default:
258           FFI_ASSERT (0);
259         }
260     }
261
262   if (fparg_count != 0)
263     flags |= FLAG_FP_ARGUMENTS;
264   if (intarg_count > 4)
265     flags |= FLAG_4_GPR_ARGUMENTS;
266
267   /* Space for the FPR registers, if needed.  */
268   if (fparg_count != 0)
269     bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double);
270
271   /* Stack space.  */
272 #if _CALL_ELF == 2
273   if ((flags & FLAG_ARG_NEEDS_PSAVE) != 0)
274     bytes += intarg_count * sizeof (long);
275 #else
276   if (intarg_count > NUM_GPR_ARG_REGISTERS64)
277     bytes += (intarg_count - NUM_GPR_ARG_REGISTERS64) * sizeof (long);
278 #endif
279
280   /* The stack space allocated needs to be a multiple of 16 bytes.  */
281   bytes = (bytes + 15) & ~0xF;
282
283   cif->flags = flags;
284   cif->bytes = bytes;
285
286   return FFI_OK;
287 }
288
289 ffi_status FFI_HIDDEN
290 ffi_prep_cif_linux64 (ffi_cif *cif)
291 {
292   if ((cif->abi & FFI_LINUX) != 0)
293     cif->nfixedargs = cif->nargs;
294 #if _CALL_ELF != 2
295   else if (cif->abi == FFI_COMPAT_LINUX64)
296     {
297       /* This call is from old code.  Don't touch cif->nfixedargs
298          since old code will be using a smaller cif.  */
299       cif->flags |= FLAG_COMPAT;
300       /* Translate to new abi value.  */
301       cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128;
302     }
303 #endif
304   else
305     return FFI_BAD_ABI;
306   return ffi_prep_cif_linux64_core (cif);
307 }
308
309 ffi_status FFI_HIDDEN
310 ffi_prep_cif_linux64_var (ffi_cif *cif,
311                           unsigned int nfixedargs,
312                           unsigned int ntotalargs MAYBE_UNUSED)
313 {
314   if ((cif->abi & FFI_LINUX) != 0)
315     cif->nfixedargs = nfixedargs;
316 #if _CALL_ELF != 2
317   else if (cif->abi == FFI_COMPAT_LINUX64)
318     {
319       /* This call is from old code.  Don't touch cif->nfixedargs
320          since old code will be using a smaller cif.  */
321       cif->flags |= FLAG_COMPAT;
322       /* Translate to new abi value.  */
323       cif->abi = FFI_LINUX | FFI_LINUX_LONG_DOUBLE_128;
324     }
325 #endif
326   else
327     return FFI_BAD_ABI;
328 #if _CALL_ELF == 2
329   cif->flags |= FLAG_ARG_NEEDS_PSAVE;
330 #endif
331   return ffi_prep_cif_linux64_core (cif);
332 }
333
334
335 /* ffi_prep_args64 is called by the assembly routine once stack space
336    has been allocated for the function's arguments.
337
338    The stack layout we want looks like this:
339
340    |   Ret addr from ffi_call_LINUX64   8bytes  |       higher addresses
341    |--------------------------------------------|
342    |   CR save area                     8bytes  |
343    |--------------------------------------------|
344    |   Previous backchain pointer       8       |       stack pointer here
345    |--------------------------------------------|<+ <<< on entry to
346    |   Saved r28-r31                    4*8     | |     ffi_call_LINUX64
347    |--------------------------------------------| |
348    |   GPR registers r3-r10             8*8     | |
349    |--------------------------------------------| |
350    |   FPR registers f1-f13 (optional)  13*8    | |
351    |--------------------------------------------| |
352    |   Parameter save area                      | |
353    |--------------------------------------------| |
354    |   TOC save area                    8       | |
355    |--------------------------------------------| |     stack   |
356    |   Linker doubleword                8       | |     grows   |
357    |--------------------------------------------| |     down    V
358    |   Compiler doubleword              8       | |
359    |--------------------------------------------| |     lower addresses
360    |   Space for callee's LR            8       | |
361    |--------------------------------------------| |
362    |   CR save area                     8       | |
363    |--------------------------------------------| |     stack pointer here
364    |   Current backchain pointer        8       |-/     during
365    |--------------------------------------------|   <<< ffi_call_LINUX64
366
367 */
368
369 void FFI_HIDDEN
370 ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
371 {
372   const unsigned long bytes = ecif->cif->bytes;
373   const unsigned long flags = ecif->cif->flags;
374
375   typedef union
376   {
377     char *c;
378     unsigned long *ul;
379     float *f;
380     double *d;
381     size_t p;
382   } valp;
383
384   /* 'stacktop' points at the previous backchain pointer.  */
385   valp stacktop;
386
387   /* 'next_arg' points at the space for gpr3, and grows upwards as
388      we use GPR registers, then continues at rest.  */
389   valp gpr_base;
390   valp gpr_end;
391   valp rest;
392   valp next_arg;
393
394   /* 'fpr_base' points at the space for fpr3, and grows upwards as
395      we use FPR registers.  */
396   valp fpr_base;
397   unsigned int fparg_count;
398
399   unsigned int i, words, nargs, nfixedargs;
400   ffi_type **ptr;
401   double double_tmp;
402   union
403   {
404     void **v;
405     char **c;
406     signed char **sc;
407     unsigned char **uc;
408     signed short **ss;
409     unsigned short **us;
410     signed int **si;
411     unsigned int **ui;
412     unsigned long **ul;
413     float **f;
414     double **d;
415   } p_argv;
416   unsigned long gprvalue;
417   unsigned long align;
418
419   stacktop.c = (char *) stack + bytes;
420   gpr_base.ul = stacktop.ul - ASM_NEEDS_REGISTERS64 - NUM_GPR_ARG_REGISTERS64;
421   gpr_end.ul = gpr_base.ul + NUM_GPR_ARG_REGISTERS64;
422 #if _CALL_ELF == 2
423   rest.ul = stack + 4 + NUM_GPR_ARG_REGISTERS64;
424 #else
425   rest.ul = stack + 6 + NUM_GPR_ARG_REGISTERS64;
426 #endif
427   fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64;
428   fparg_count = 0;
429   next_arg.ul = gpr_base.ul;
430
431   /* Check that everything starts aligned properly.  */
432   FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0);
433   FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0);
434   FFI_ASSERT ((bytes & 0xF) == 0);
435
436   /* Deal with return values that are actually pass-by-reference.  */
437   if (flags & FLAG_RETVAL_REFERENCE)
438     *next_arg.ul++ = (unsigned long) (char *) ecif->rvalue;
439
440   /* Now for the arguments.  */
441   p_argv.v = ecif->avalue;
442   nargs = ecif->cif->nargs;
443 #if _CALL_ELF != 2
444   nfixedargs = (unsigned) -1;
445   if ((flags & FLAG_COMPAT) == 0)
446 #endif
447     nfixedargs = ecif->cif->nfixedargs;
448   for (ptr = ecif->cif->arg_types, i = 0;
449        i < nargs;
450        i++, ptr++, p_argv.v++)
451     {
452 #if _CALL_ELF == 2
453       unsigned int elt, elnum;
454 #endif
455
456       switch ((*ptr)->type)
457         {
458 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
459         case FFI_TYPE_LONGDOUBLE:
460           if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
461             {
462               double_tmp = (*p_argv.d)[0];
463               if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
464                 {
465                   *fpr_base.d++ = double_tmp;
466 # if _CALL_ELF != 2
467                   if ((flags & FLAG_COMPAT) != 0)
468                     *next_arg.d = double_tmp;
469 # endif
470                 }
471               else
472                 *next_arg.d = double_tmp;
473               if (++next_arg.ul == gpr_end.ul)
474                 next_arg.ul = rest.ul;
475               fparg_count++;
476               double_tmp = (*p_argv.d)[1];
477               if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
478                 {
479                   *fpr_base.d++ = double_tmp;
480 # if _CALL_ELF != 2
481                   if ((flags & FLAG_COMPAT) != 0)
482                     *next_arg.d = double_tmp;
483 # endif
484                 }
485               else
486                 *next_arg.d = double_tmp;
487               if (++next_arg.ul == gpr_end.ul)
488                 next_arg.ul = rest.ul;
489               fparg_count++;
490               FFI_ASSERT (__LDBL_MANT_DIG__ == 106);
491               FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
492               break;
493             }
494           /* Fall through.  */
495 #endif
496         case FFI_TYPE_DOUBLE:
497           double_tmp = **p_argv.d;
498           if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
499             {
500               *fpr_base.d++ = double_tmp;
501 #if _CALL_ELF != 2
502               if ((flags & FLAG_COMPAT) != 0)
503                 *next_arg.d = double_tmp;
504 #endif
505             }
506           else
507             *next_arg.d = double_tmp;
508           if (++next_arg.ul == gpr_end.ul)
509             next_arg.ul = rest.ul;
510           fparg_count++;
511           FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
512           break;
513
514         case FFI_TYPE_FLOAT:
515           double_tmp = **p_argv.f;
516           if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
517             {
518               *fpr_base.d++ = double_tmp;
519 #if _CALL_ELF != 2
520               if ((flags & FLAG_COMPAT) != 0)
521                 *next_arg.f = (float) double_tmp;
522 #endif
523             }
524           else
525             *next_arg.f = (float) double_tmp;
526           if (++next_arg.ul == gpr_end.ul)
527             next_arg.ul = rest.ul;
528           fparg_count++;
529           FFI_ASSERT (flags & FLAG_FP_ARGUMENTS);
530           break;
531
532         case FFI_TYPE_STRUCT:
533           if ((ecif->cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
534             {
535               align = (*ptr)->alignment;
536               if (align > 16)
537                 align = 16;
538               if (align > 1)
539                 next_arg.p = ALIGN (next_arg.p, align);
540             }
541 #if _CALL_ELF == 2
542           elt = discover_homogeneous_aggregate (*ptr, &elnum);
543           if (elt)
544             {
545               union {
546                 void *v;
547                 float *f;
548                 double *d;
549               } arg;
550
551               arg.v = *p_argv.v;
552               if (elt == FFI_TYPE_FLOAT)
553                 {
554                   do
555                     {
556                       double_tmp = *arg.f++;
557                       if (fparg_count < NUM_FPR_ARG_REGISTERS64
558                           && i < nfixedargs)
559                         *fpr_base.d++ = double_tmp;
560                       else
561                         *next_arg.f = (float) double_tmp;
562                       if (++next_arg.f == gpr_end.f)
563                         next_arg.f = rest.f;
564                       fparg_count++;
565                     }
566                   while (--elnum != 0);
567                   if ((next_arg.p & 3) != 0)
568                     {
569                       if (++next_arg.f == gpr_end.f)
570                         next_arg.f = rest.f;
571                     }
572                 }
573               else
574                 do
575                   {
576                     double_tmp = *arg.d++;
577                     if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
578                       *fpr_base.d++ = double_tmp;
579                     else
580                       *next_arg.d = double_tmp;
581                     if (++next_arg.d == gpr_end.d)
582                       next_arg.d = rest.d;
583                     fparg_count++;
584                   }
585                 while (--elnum != 0);
586             }
587           else
588 #endif
589             {
590               words = ((*ptr)->size + 7) / 8;
591               if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul)
592                 {
593                   size_t first = gpr_end.c - next_arg.c;
594                   memcpy (next_arg.c, *p_argv.c, first);
595                   memcpy (rest.c, *p_argv.c + first, (*ptr)->size - first);
596                   next_arg.c = rest.c + words * 8 - first;
597                 }
598               else
599                 {
600                   char *where = next_arg.c;
601
602 #ifndef __LITTLE_ENDIAN__
603                   /* Structures with size less than eight bytes are passed
604                      left-padded.  */
605                   if ((*ptr)->size < 8)
606                     where += 8 - (*ptr)->size;
607 #endif
608                   memcpy (where, *p_argv.c, (*ptr)->size);
609                   next_arg.ul += words;
610                   if (next_arg.ul == gpr_end.ul)
611                     next_arg.ul = rest.ul;
612                 }
613             }
614           break;
615
616         case FFI_TYPE_UINT8:
617           gprvalue = **p_argv.uc;
618           goto putgpr;
619         case FFI_TYPE_SINT8:
620           gprvalue = **p_argv.sc;
621           goto putgpr;
622         case FFI_TYPE_UINT16:
623           gprvalue = **p_argv.us;
624           goto putgpr;
625         case FFI_TYPE_SINT16:
626           gprvalue = **p_argv.ss;
627           goto putgpr;
628         case FFI_TYPE_UINT32:
629           gprvalue = **p_argv.ui;
630           goto putgpr;
631         case FFI_TYPE_INT:
632         case FFI_TYPE_SINT32:
633           gprvalue = **p_argv.si;
634           goto putgpr;
635
636         case FFI_TYPE_UINT64:
637         case FFI_TYPE_SINT64:
638         case FFI_TYPE_POINTER:
639           gprvalue = **p_argv.ul;
640         putgpr:
641           *next_arg.ul++ = gprvalue;
642           if (next_arg.ul == gpr_end.ul)
643             next_arg.ul = rest.ul;
644           break;
645         }
646     }
647
648   FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS
649               || (next_arg.ul >= gpr_base.ul
650                   && next_arg.ul <= gpr_base.ul + 4));
651 }
652
653
654 #if _CALL_ELF == 2
655 #define MIN_CACHE_LINE_SIZE 8
656
657 static void
658 flush_icache (char *wraddr, char *xaddr, int size)
659 {
660   int i;
661   for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
662     __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
663                       : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
664   __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
665                     : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
666                     : "memory");
667 }
668 #endif
669
670 ffi_status
671 ffi_prep_closure_loc_linux64 (ffi_closure *closure,
672                               ffi_cif *cif,
673                               void (*fun) (ffi_cif *, void *, void **, void *),
674                               void *user_data,
675                               void *codeloc)
676 {
677 #if _CALL_ELF == 2
678   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
679
680   if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
681     return FFI_BAD_ABI;
682
683   tramp[0] = 0xe96c0018;        /* 0:   ld      11,2f-0b(12)    */
684   tramp[1] = 0xe98c0010;        /*      ld      12,1f-0b(12)    */
685   tramp[2] = 0x7d8903a6;        /*      mtctr   12              */
686   tramp[3] = 0x4e800420;        /*      bctr                    */
687                                 /* 1:   .quad   function_addr   */
688                                 /* 2:   .quad   context         */
689   *(void **) &tramp[4] = (void *) ffi_closure_LINUX64;
690   *(void **) &tramp[6] = codeloc;
691   flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE);
692 #else
693   void **tramp = (void **) &closure->tramp[0];
694
695   if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI)
696     return FFI_BAD_ABI;
697
698   /* Copy function address and TOC from ffi_closure_LINUX64.  */
699   memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
700   tramp[2] = tramp[1];
701   tramp[1] = codeloc;
702 #endif
703
704   closure->cif = cif;
705   closure->fun = fun;
706   closure->user_data = user_data;
707
708   return FFI_OK;
709 }
710
711
712 int FFI_HIDDEN
713 ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue,
714                             unsigned long *pst, ffi_dblfl *pfr)
715 {
716   /* rvalue is the pointer to space for return value in closure assembly */
717   /* pst is the pointer to parameter save area
718      (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */
719   /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */
720
721   void **avalue;
722   ffi_type **arg_types;
723   unsigned long i, avn, nfixedargs;
724   ffi_cif *cif;
725   ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64;
726   unsigned long align;
727
728   cif = closure->cif;
729   avalue = alloca (cif->nargs * sizeof (void *));
730
731   /* Copy the caller's structure return value address so that the
732      closure returns the data directly to the caller.  */
733   if (cif->rtype->type == FFI_TYPE_STRUCT
734       && (cif->flags & FLAG_RETURNS_SMST) == 0)
735     {
736       rvalue = (void *) *pst;
737       pst++;
738     }
739
740   i = 0;
741   avn = cif->nargs;
742 #if _CALL_ELF != 2
743   nfixedargs = (unsigned) -1;
744   if ((cif->flags & FLAG_COMPAT) == 0)
745 #endif
746     nfixedargs = cif->nfixedargs;
747   arg_types = cif->arg_types;
748
749   /* Grab the addresses of the arguments from the stack frame.  */
750   while (i < avn)
751     {
752       unsigned int elt, elnum;
753
754       switch (arg_types[i]->type)
755         {
756         case FFI_TYPE_SINT8:
757         case FFI_TYPE_UINT8:
758 #ifndef __LITTLE_ENDIAN__
759           avalue[i] = (char *) pst + 7;
760           pst++;
761           break;
762 #endif
763
764         case FFI_TYPE_SINT16:
765         case FFI_TYPE_UINT16:
766 #ifndef __LITTLE_ENDIAN__
767           avalue[i] = (char *) pst + 6;
768           pst++;
769           break;
770 #endif
771
772         case FFI_TYPE_SINT32:
773         case FFI_TYPE_UINT32:
774 #ifndef __LITTLE_ENDIAN__
775           avalue[i] = (char *) pst + 4;
776           pst++;
777           break;
778 #endif
779
780         case FFI_TYPE_SINT64:
781         case FFI_TYPE_UINT64:
782         case FFI_TYPE_POINTER:
783           avalue[i] = pst;
784           pst++;
785           break;
786
787         case FFI_TYPE_STRUCT:
788           if ((cif->abi & FFI_LINUX_STRUCT_ALIGN) != 0)
789             {
790               align = arg_types[i]->alignment;
791               if (align > 16)
792                 align = 16;
793               if (align > 1)
794                 pst = (unsigned long *) ALIGN ((size_t) pst, align);
795             }
796           elt = 0;
797 #if _CALL_ELF == 2
798           elt = discover_homogeneous_aggregate (arg_types[i], &elnum);
799 #endif
800           if (elt)
801             {
802               union {
803                 void *v;
804                 unsigned long *ul;
805                 float *f;
806                 double *d;
807                 size_t p;
808               } to, from;
809
810               /* Repackage the aggregate from its parts.  The
811                  aggregate size is not greater than the space taken by
812                  the registers so store back to the register/parameter
813                  save arrays.  */
814               if (pfr + elnum <= end_pfr)
815                 to.v = pfr;
816               else
817                 to.v = pst;
818
819               avalue[i] = to.v;
820               from.ul = pst;
821               if (elt == FFI_TYPE_FLOAT)
822                 {
823                   do
824                     {
825                       if (pfr < end_pfr && i < nfixedargs)
826                         {
827                           *to.f = (float) pfr->d;
828                           pfr++;
829                         }
830                       else
831                         *to.f = *from.f;
832                       to.f++;
833                       from.f++;
834                     }
835                   while (--elnum != 0);
836                 }
837               else
838                 {
839                   do
840                     {
841                       if (pfr < end_pfr && i < nfixedargs)
842                         {
843                           *to.d = pfr->d;
844                           pfr++;
845                         }
846                       else
847                         *to.d = *from.d;
848                       to.d++;
849                       from.d++;
850                     }
851                   while (--elnum != 0);
852                 }
853             }
854           else
855             {
856 #ifndef __LITTLE_ENDIAN__
857               /* Structures with size less than eight bytes are passed
858                  left-padded.  */
859               if (arg_types[i]->size < 8)
860                 avalue[i] = (char *) pst + 8 - arg_types[i]->size;
861               else
862 #endif
863                 avalue[i] = pst;
864             }
865           pst += (arg_types[i]->size + 7) / 8;
866           break;
867
868 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
869         case FFI_TYPE_LONGDOUBLE:
870           if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0)
871             {
872               if (pfr + 1 < end_pfr && i + 1 < nfixedargs)
873                 {
874                   avalue[i] = pfr;
875                   pfr += 2;
876                 }
877               else
878                 {
879                   if (pfr < end_pfr && i < nfixedargs)
880                     {
881                       /* Passed partly in f13 and partly on the stack.
882                          Move it all to the stack.  */
883                       *pst = *(unsigned long *) pfr;
884                       pfr++;
885                     }
886                   avalue[i] = pst;
887                 }
888               pst += 2;
889               break;
890             }
891           /* Fall through.  */
892 #endif
893         case FFI_TYPE_DOUBLE:
894           /* On the outgoing stack all values are aligned to 8 */
895           /* there are 13 64bit floating point registers */
896
897           if (pfr < end_pfr && i < nfixedargs)
898             {
899               avalue[i] = pfr;
900               pfr++;
901             }
902           else
903             avalue[i] = pst;
904           pst++;
905           break;
906
907         case FFI_TYPE_FLOAT:
908           if (pfr < end_pfr && i < nfixedargs)
909             {
910               /* Float values are stored as doubles in the
911                  ffi_closure_LINUX64 code.  Fix them here.  */
912               pfr->f = (float) pfr->d;
913               avalue[i] = pfr;
914               pfr++;
915             }
916           else
917             avalue[i] = pst;
918           pst++;
919           break;
920
921         default:
922           FFI_ASSERT (0);
923         }
924
925       i++;
926     }
927
928
929   (closure->fun) (cif, rvalue, avalue, closure->user_data);
930
931   /* Tell ffi_closure_LINUX64 how to perform return type promotions.  */
932   if ((cif->flags & FLAG_RETURNS_SMST) != 0)
933     {
934       if ((cif->flags & FLAG_RETURNS_FP) == 0)
935         return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1;
936       else if ((cif->flags & FLAG_RETURNS_64BITS) != 0)
937         return FFI_V2_TYPE_DOUBLE_HOMOG;
938       else
939         return FFI_V2_TYPE_FLOAT_HOMOG;
940     }
941   return cif->rtype->type;
942 }
943 #endif