Static tramp v5 (#624)
[platform/upstream/libffi.git] / src / arm / ffi.c
1 /* -----------------------------------------------------------------------
2    ffi.c - Copyright (c) 2011 Timothy Wall
3            Copyright (c) 2011 Plausible Labs Cooperative, Inc.
4            Copyright (c) 2011 Anthony Green
5            Copyright (c) 2011 Free Software Foundation
6            Copyright (c) 1998, 2008, 2011  Red Hat, Inc.
7
8    ARM Foreign Function Interface
9
10    Permission is hereby granted, free of charge, to any person obtaining
11    a copy of this software and associated documentation files (the
12    ``Software''), to deal in the Software without restriction, including
13    without limitation the rights to use, copy, modify, merge, publish,
14    distribute, sublicense, and/or sell copies of the Software, and to
15    permit persons to whom the Software is furnished to do so, subject to
16    the following conditions:
17
18    The above copyright notice and this permission notice shall be included
19    in all copies or substantial portions of the Software.
20
21    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28    DEALINGS IN THE SOFTWARE.
29    ----------------------------------------------------------------------- */
30
31 #if defined(__arm__) || defined(_M_ARM)
32 #include <fficonfig.h>
33 #include <ffi.h>
34 #include <ffi_common.h>
35 #include <stdint.h>
36 #include <stdlib.h>
37 #include <tramp.h>
38 #include "internal.h"
39
40 #if defined(_MSC_VER) && defined(_M_ARM)
41 #define WIN32_LEAN_AND_MEAN
42 #include <windows.h>
43 #endif
44
45 #if FFI_EXEC_TRAMPOLINE_TABLE
46
47 #ifdef __MACH__
48 #include <mach/machine/vm_param.h>
49 #endif
50
51 #else
52 #ifndef _M_ARM
53 extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN;
54 #else
55 extern unsigned int ffi_arm_trampoline[3] FFI_HIDDEN;
56 #endif
57 #endif
58
59 #if defined(__FreeBSD__) && defined(__arm__)
60 #include <sys/types.h>
61 #include <machine/sysarch.h>
62 #endif
63
64 /* Forward declares. */
65 static int vfp_type_p (const ffi_type *);
66 static void layout_vfp_args (ffi_cif *);
67
68 static void *
69 ffi_align (ffi_type *ty, void *p)
70 {
71   /* Align if necessary */
72   size_t alignment;
73 #ifdef _WIN32_WCE
74   alignment = 4;
75 #else
76   alignment = ty->alignment;
77   if (alignment < 4)
78     alignment = 4;
79 #endif
80   return (void *) FFI_ALIGN (p, alignment);
81 }
82
83 static size_t
84 ffi_put_arg (ffi_type *ty, void *src, void *dst)
85 {
86   size_t z = ty->size;
87
88   switch (ty->type)
89     {
90     case FFI_TYPE_SINT8:
91       *(UINT32 *)dst = *(SINT8 *)src;
92       break;
93     case FFI_TYPE_UINT8:
94       *(UINT32 *)dst = *(UINT8 *)src;
95       break;
96     case FFI_TYPE_SINT16:
97       *(UINT32 *)dst = *(SINT16 *)src;
98       break;
99     case FFI_TYPE_UINT16:
100       *(UINT32 *)dst = *(UINT16 *)src;
101       break;
102
103     case FFI_TYPE_INT:
104     case FFI_TYPE_SINT32:
105     case FFI_TYPE_UINT32:
106     case FFI_TYPE_POINTER:
107 #ifndef _MSC_VER
108     case FFI_TYPE_FLOAT:
109 #endif
110       *(UINT32 *)dst = *(UINT32 *)src;
111       break;
112
113 #ifdef _MSC_VER
114     // casting a float* to a UINT32* doesn't work on Windows
115     case FFI_TYPE_FLOAT:
116         *(uintptr_t *)dst = 0;
117         *(float *)dst = *(float *)src;
118         break;
119 #endif
120
121     case FFI_TYPE_SINT64:
122     case FFI_TYPE_UINT64:
123     case FFI_TYPE_DOUBLE:
124       *(UINT64 *)dst = *(UINT64 *)src;
125       break;
126
127     case FFI_TYPE_STRUCT:
128     case FFI_TYPE_COMPLEX:
129       memcpy (dst, src, z);
130       break;
131
132     default:
133       abort();
134     }
135
136   return FFI_ALIGN (z, 4);
137 }
138
139 /* ffi_prep_args is called once stack space has been allocated
140    for the function's arguments.
141
142    The vfp_space parameter is the load area for VFP regs, the return
143    value is cif->vfp_used (word bitset of VFP regs used for passing
144    arguments). These are only used for the VFP hard-float ABI.
145 */
146 static void
147 ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue,
148                     void **avalue, char *argp)
149 {
150   ffi_type **arg_types = cif->arg_types;
151   int i, n;
152
153   if (flags == ARM_TYPE_STRUCT)
154     {
155       *(void **) argp = rvalue;
156       argp += 4;
157     }
158
159   for (i = 0, n = cif->nargs; i < n; i++)
160     {
161       ffi_type *ty = arg_types[i];
162       argp = ffi_align (ty, argp);
163       argp += ffi_put_arg (ty, avalue[i], argp);
164     }
165 }
166
167 static void
168 ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
169                    void **avalue, char *stack, char *vfp_space)
170 {
171   ffi_type **arg_types = cif->arg_types;
172   int i, n, vi = 0;
173   char *argp, *regp, *eo_regp;
174   char stack_used = 0;
175   char done_with_regs = 0;
176
177   /* The first 4 words on the stack are used for values
178      passed in core registers.  */
179   regp = stack;
180   eo_regp = argp = regp + 16;
181
182   /* If the function returns an FFI_TYPE_STRUCT in memory,
183      that address is passed in r0 to the function.  */
184   if (flags == ARM_TYPE_STRUCT)
185     {
186       *(void **) regp = rvalue;
187       regp += 4;
188     }
189
190   for (i = 0, n = cif->nargs; i < n; i++)
191     {
192       ffi_type *ty = arg_types[i];
193       void *a = avalue[i];
194       int is_vfp_type = vfp_type_p (ty);
195
196       /* Allocated in VFP registers. */
197       if (vi < cif->vfp_nargs && is_vfp_type)
198         {
199           char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4;
200           ffi_put_arg (ty, a, vfp_slot);
201           continue;
202         }
203       /* Try allocating in core registers. */
204       else if (!done_with_regs && !is_vfp_type)
205         {
206           char *tregp = ffi_align (ty, regp);
207           size_t size = ty->size;
208           size = (size < 4) ? 4 : size; // pad
209           /* Check if there is space left in the aligned register
210              area to place the argument.  */
211           if (tregp + size <= eo_regp)
212             {
213               regp = tregp + ffi_put_arg (ty, a, tregp);
214               done_with_regs = (regp == argp);
215               // ensure we did not write into the stack area
216               FFI_ASSERT (regp <= argp);
217               continue;
218             }
219           /* In case there are no arguments in the stack area yet,
220              the argument is passed in the remaining core registers
221              and on the stack.  */
222           else if (!stack_used)
223             {
224               stack_used = 1;
225               done_with_regs = 1;
226               argp = tregp + ffi_put_arg (ty, a, tregp);
227               FFI_ASSERT (eo_regp < argp);
228               continue;
229             }
230         }
231       /* Base case, arguments are passed on the stack */
232       stack_used = 1;
233       argp = ffi_align (ty, argp);
234       argp += ffi_put_arg (ty, a, argp);
235     }
236 }
237
238 /* Perform machine dependent cif processing */
239 ffi_status FFI_HIDDEN
240 ffi_prep_cif_machdep (ffi_cif *cif)
241 {
242   int flags = 0, cabi = cif->abi;
243   size_t bytes = cif->bytes;
244
245   /* Map out the register placements of VFP register args.  The VFP
246      hard-float calling conventions are slightly more sophisticated
247      than the base calling conventions, so we do it here instead of
248      in ffi_prep_args(). */
249   if (cabi == FFI_VFP)
250     layout_vfp_args (cif);
251
252   /* Set the return type flag */
253   switch (cif->rtype->type)
254     {
255     case FFI_TYPE_VOID:
256       flags = ARM_TYPE_VOID;
257       break;
258
259     case FFI_TYPE_INT:
260     case FFI_TYPE_UINT8:
261     case FFI_TYPE_SINT8:
262     case FFI_TYPE_UINT16:
263     case FFI_TYPE_SINT16:
264     case FFI_TYPE_UINT32:
265     case FFI_TYPE_SINT32:
266     case FFI_TYPE_POINTER:
267       flags = ARM_TYPE_INT;
268       break;
269
270     case FFI_TYPE_SINT64:
271     case FFI_TYPE_UINT64:
272       flags = ARM_TYPE_INT64;
273       break;
274
275     case FFI_TYPE_FLOAT:
276       flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT);
277       break;
278     case FFI_TYPE_DOUBLE:
279       flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64);
280       break;
281
282     case FFI_TYPE_STRUCT:
283     case FFI_TYPE_COMPLEX:
284       if (cabi == FFI_VFP)
285         {
286           int h = vfp_type_p (cif->rtype);
287
288           flags = ARM_TYPE_VFP_N;
289           if (h == 0x100 + FFI_TYPE_FLOAT)
290             flags = ARM_TYPE_VFP_S;
291           if (h == 0x100 + FFI_TYPE_DOUBLE)
292             flags = ARM_TYPE_VFP_D;
293           if (h != 0)
294               break;
295         }
296
297       /* A Composite Type not larger than 4 bytes is returned in r0.
298          A Composite Type larger than 4 bytes, or whose size cannot
299          be determined statically ... is stored in memory at an
300          address passed [in r0].  */
301       if (cif->rtype->size <= 4)
302         flags = ARM_TYPE_INT;
303       else
304         {
305           flags = ARM_TYPE_STRUCT;
306           bytes += 4;
307         }
308       break;
309
310     default:
311       abort();
312     }
313
314   /* Round the stack up to a multiple of 8 bytes.  This isn't needed
315      everywhere, but it is on some platforms, and it doesn't harm anything
316      when it isn't needed.  */
317   bytes = FFI_ALIGN (bytes, 8);
318
319   /* Minimum stack space is the 4 register arguments that we pop.  */
320   if (bytes < 4*4)
321     bytes = 4*4;
322
323   cif->bytes = bytes;
324   cif->flags = flags;
325
326   return FFI_OK;
327 }
328
329 /* Perform machine dependent cif processing for variadic calls */
330 ffi_status FFI_HIDDEN
331 ffi_prep_cif_machdep_var (ffi_cif * cif,
332                           unsigned int nfixedargs, unsigned int ntotalargs)
333 {
334   /* VFP variadic calls actually use the SYSV ABI */
335   if (cif->abi == FFI_VFP)
336     cif->abi = FFI_SYSV;
337
338   return ffi_prep_cif_machdep (cif);
339 }
340
341 /* Prototypes for assembly functions, in sysv.S.  */
342
343 struct call_frame
344 {
345   void *fp;
346   void *lr;
347   void *rvalue;
348   int flags;
349   void *closure;
350 };
351
352 extern void ffi_call_SYSV (void *stack, struct call_frame *,
353                            void (*fn) (void)) FFI_HIDDEN;
354 extern void ffi_call_VFP (void *vfp_space, struct call_frame *,
355                            void (*fn) (void), unsigned vfp_used) FFI_HIDDEN;
356
357 static void
358 ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue,
359               void **avalue, void *closure)
360 {
361   int flags = cif->flags;
362   ffi_type *rtype = cif->rtype;
363   size_t bytes, rsize, vfp_size;
364   char *stack, *vfp_space, *new_rvalue;
365   struct call_frame *frame;
366
367   rsize = 0;
368   if (rvalue == NULL)
369     {
370       /* If the return value is a struct and we don't have a return
371          value address then we need to make one.  Otherwise the return
372          value is in registers and we can ignore them.  */
373       if (flags == ARM_TYPE_STRUCT)
374         rsize = rtype->size;
375       else
376         flags = ARM_TYPE_VOID;
377     }
378   else if (flags == ARM_TYPE_VFP_N)
379     {
380       /* Largest case is double x 4. */
381       rsize = 32;
382     }
383   else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT)
384     rsize = 4;
385
386   /* Largest case.  */
387   vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0);
388
389   bytes = cif->bytes;
390   stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize);
391
392   vfp_space = NULL;
393   if (vfp_size)
394     {
395       vfp_space = stack;
396       stack += vfp_size;
397     }
398
399   frame = (struct call_frame *)(stack + bytes);
400
401   new_rvalue = rvalue;
402   if (rsize)
403     new_rvalue = (void *)(frame + 1);
404
405   frame->rvalue = new_rvalue;
406   frame->flags = flags;
407   frame->closure = closure;
408
409   if (vfp_space)
410     {
411       ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space);
412       ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used);
413     }
414   else
415     {
416       ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack);
417       ffi_call_SYSV (stack, frame, fn);
418     }
419
420   if (rvalue && rvalue != new_rvalue)
421     memcpy (rvalue, new_rvalue, rtype->size);
422 }
423
424 void
425 ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
426 {
427   ffi_call_int (cif, fn, rvalue, avalue, NULL);
428 }
429
430 #ifdef FFI_GO_CLOSURES
431 void
432 ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue,
433              void **avalue, void *closure)
434 {
435   ffi_call_int (cif, fn, rvalue, avalue, closure);
436 }
437 #endif
438
439 static void *
440 ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue,
441                              char *argp, void **avalue)
442 {
443   ffi_type **arg_types = cif->arg_types;
444   int i, n;
445
446   if (cif->flags == ARM_TYPE_STRUCT)
447     {
448       rvalue = *(void **) argp;
449       argp += 4;
450     }
451   else
452     {
453       if (cif->rtype->size && cif->rtype->size < 4)
454         *(uint32_t *) rvalue = 0;
455     }
456
457   for (i = 0, n = cif->nargs; i < n; i++)
458     {
459       ffi_type *ty = arg_types[i];
460       size_t z = ty->size;
461
462       argp = ffi_align (ty, argp);
463       avalue[i] = (void *) argp;
464       argp += z;
465     }
466
467   return rvalue;
468 }
469
470 static void *
471 ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack,
472                             char *vfp_space, void **avalue)
473 {
474   ffi_type **arg_types = cif->arg_types;
475   int i, n, vi = 0;
476   char *argp, *regp, *eo_regp;
477   char done_with_regs = 0;
478   char stack_used = 0;
479
480   regp = stack;
481   eo_regp = argp = regp + 16;
482
483   if (cif->flags == ARM_TYPE_STRUCT)
484     {
485       rvalue = *(void **) regp;
486       regp += 4;
487     }
488
489   for (i = 0, n = cif->nargs; i < n; i++)
490     {
491       ffi_type *ty = arg_types[i];
492       int is_vfp_type = vfp_type_p (ty);
493       size_t z = ty->size;
494
495       if (vi < cif->vfp_nargs && is_vfp_type)
496         {
497           avalue[i] = vfp_space + cif->vfp_args[vi++] * 4;
498           continue;
499         }
500       else if (!done_with_regs && !is_vfp_type)
501         {
502           char *tregp = ffi_align (ty, regp);
503
504           z = (z < 4) ? 4 : z;  // pad
505
506           /* If the arguments either fits into the registers or uses registers
507              and stack, while we haven't read other things from the stack */
508           if (tregp + z <= eo_regp || !stack_used)
509             {
510               /* Because we're little endian, this is what it turns into.  */
511               avalue[i] = (void *) tregp;
512               regp = tregp + z;
513
514               /* If we read past the last core register, make sure we
515                  have not read from the stack before and continue
516                  reading after regp.  */
517               if (regp > eo_regp)
518                 {
519                   FFI_ASSERT (!stack_used);
520                   argp = regp;
521                 }
522               if (regp >= eo_regp)
523                 {
524                   done_with_regs = 1;
525                   stack_used = 1;
526                 }
527               continue;
528             }
529         }
530
531       stack_used = 1;
532       argp = ffi_align (ty, argp);
533       avalue[i] = (void *) argp;
534       argp += z;
535     }
536
537   return rvalue;
538 }
539
540 struct closure_frame
541 {
542   char vfp_space[8*8] __attribute__((aligned(8)));
543   char result[8*4];
544   char argp[];
545 };
546
547 int FFI_HIDDEN
548 ffi_closure_inner_SYSV (ffi_cif *cif,
549                         void (*fun) (ffi_cif *, void *, void **, void *),
550                         void *user_data,
551                         struct closure_frame *frame)
552 {
553   void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
554   void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result,
555                                               frame->argp, avalue);
556   fun (cif, rvalue, avalue, user_data);
557   return cif->flags;
558 }
559
560 int FFI_HIDDEN
561 ffi_closure_inner_VFP (ffi_cif *cif,
562                        void (*fun) (ffi_cif *, void *, void **, void *),
563                        void *user_data,
564                        struct closure_frame *frame)
565 {
566   void **avalue = (void **) alloca (cif->nargs * sizeof (void *));
567   void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp,
568                                              frame->vfp_space, avalue);
569   fun (cif, rvalue, avalue, user_data);
570   return cif->flags;
571 }
572
573 void ffi_closure_SYSV (void) FFI_HIDDEN;
574 void ffi_closure_VFP (void) FFI_HIDDEN;
575 #if defined(FFI_EXEC_STATIC_TRAMP)
576 void ffi_closure_SYSV_alt (void) FFI_HIDDEN;
577 void ffi_closure_VFP_alt (void) FFI_HIDDEN;
578 #endif
579
580 #ifdef FFI_GO_CLOSURES
581 void ffi_go_closure_SYSV (void) FFI_HIDDEN;
582 void ffi_go_closure_VFP (void) FFI_HIDDEN;
583 #endif
584
585 /* the cif must already be prep'ed */
586
587 #if defined(__FreeBSD__) && defined(__arm__)
588 #define __clear_cache(start, end) do { \
589                 struct arm_sync_icache_args ua;                 \
590                                                                 \
591                 ua.addr = (uintptr_t)(start);                   \
592                 ua.len = (char *)(end) - (char *)start;         \
593                 sysarch(ARM_SYNC_ICACHE, &ua);                  \
594         } while (0);
595 #endif
596
597 ffi_status
598 ffi_prep_closure_loc (ffi_closure * closure,
599                       ffi_cif * cif,
600                       void (*fun) (ffi_cif *, void *, void **, void *),
601                       void *user_data, void *codeloc)
602 {
603   void (*closure_func) (void) = ffi_closure_SYSV;
604
605   if (cif->abi == FFI_VFP)
606     {
607       /* We only need take the vfp path if there are vfp arguments.  */
608       if (cif->vfp_used)
609         closure_func = ffi_closure_VFP;
610     }
611   else if (cif->abi != FFI_SYSV)
612     return FFI_BAD_ABI;
613
614 #if FFI_EXEC_TRAMPOLINE_TABLE
615   void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE);
616   config[0] = closure;
617   config[1] = closure_func;
618 #else
619
620 #if defined(FFI_EXEC_STATIC_TRAMP)
621   if (ffi_tramp_is_present(closure))
622     {
623       /* Initialize the static trampoline's parameters. */
624       if (closure_func == ffi_closure_SYSV)
625         closure_func = ffi_closure_SYSV_alt;
626       else
627         closure_func = ffi_closure_VFP_alt;
628       ffi_tramp_set_parms (closure->ftramp, closure_func, closure);
629       goto out;
630     }
631 #endif
632
633   /* Initialize the dynamic trampoline. */
634 #ifndef _M_ARM
635   memcpy(closure->tramp, ffi_arm_trampoline, 8);
636 #else
637   // cast away function type so MSVC doesn't set the lower bit of the function pointer
638   memcpy(closure->tramp, (void*)((uintptr_t)ffi_arm_trampoline & 0xFFFFFFFE), FFI_TRAMPOLINE_CLOSURE_OFFSET);
639 #endif
640
641 #if defined (__QNX__)
642   msync(closure->tramp, 8, 0x1000000);  /* clear data map */
643   msync(codeloc, 8, 0x1000000); /* clear insn map */
644 #elif defined(_MSC_VER)
645   FlushInstructionCache(GetCurrentProcess(), closure->tramp, FFI_TRAMPOLINE_SIZE);
646 #else
647   __clear_cache(closure->tramp, closure->tramp + 8);    /* clear data map */
648   __clear_cache(codeloc, codeloc + 8);                  /* clear insn map */
649 #endif
650 #ifdef _M_ARM
651   *(void(**)(void))(closure->tramp + FFI_TRAMPOLINE_CLOSURE_FUNCTION) = closure_func;
652 #else
653   *(void (**)(void))(closure->tramp + 8) = closure_func;
654 #endif
655 out:
656 #endif
657
658   closure->cif = cif;
659   closure->fun = fun;
660   closure->user_data = user_data;
661
662   return FFI_OK;
663 }
664
665 #ifdef FFI_GO_CLOSURES
666 ffi_status
667 ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif,
668                      void (*fun) (ffi_cif *, void *, void **, void *))
669 {
670   void (*closure_func) (void) = ffi_go_closure_SYSV;
671
672   if (cif->abi == FFI_VFP)
673     {
674       /* We only need take the vfp path if there are vfp arguments.  */
675       if (cif->vfp_used)
676         closure_func = ffi_go_closure_VFP;
677     }
678   else if (cif->abi != FFI_SYSV)
679     return FFI_BAD_ABI;
680
681   closure->tramp = closure_func;
682   closure->cif = cif;
683   closure->fun = fun;
684
685   return FFI_OK;
686 }
687 #endif
688
689 /* Below are routines for VFP hard-float support. */
690
691 /* A subroutine of vfp_type_p.  Given a structure type, return the type code
692    of the first non-structure element.  Recurse for structure elements.
693    Return -1 if the structure is in fact empty, i.e. no nested elements.  */
694
695 static int
696 is_hfa0 (const ffi_type *ty)
697 {
698   ffi_type **elements = ty->elements;
699   int i, ret = -1;
700
701   if (elements != NULL)
702     for (i = 0; elements[i]; ++i)
703       {
704         ret = elements[i]->type;
705         if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX)
706           {
707             ret = is_hfa0 (elements[i]);
708             if (ret < 0)
709               continue;
710           }
711         break;
712       }
713
714   return ret;
715 }
716
717 /* A subroutine of vfp_type_p.  Given a structure type, return true if all
718    of the non-structure elements are the same as CANDIDATE.  */
719
720 static int
721 is_hfa1 (const ffi_type *ty, int candidate)
722 {
723   ffi_type **elements = ty->elements;
724   int i;
725
726   if (elements != NULL)
727     for (i = 0; elements[i]; ++i)
728       {
729         int t = elements[i]->type;
730         if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
731           {
732             if (!is_hfa1 (elements[i], candidate))
733               return 0;
734           }
735         else if (t != candidate)
736           return 0;
737       }
738
739   return 1;
740 }
741
742 /* Determine if TY is an homogenous floating point aggregate (HFA).
743    That is, a structure consisting of 1 to 4 members of all the same type,
744    where that type is a floating point scalar.
745
746    Returns non-zero iff TY is an HFA.  The result is an encoded value where
747    bits 0-7 contain the type code, and bits 8-10 contain the element count.  */
748
749 static int
750 vfp_type_p (const ffi_type *ty)
751 {
752   ffi_type **elements;
753   int candidate, i;
754   size_t size, ele_count;
755
756   /* Quickest tests first.  */
757   candidate = ty->type;
758   switch (ty->type)
759     {
760     default:
761       return 0;
762     case FFI_TYPE_FLOAT:
763     case FFI_TYPE_DOUBLE:
764       ele_count = 1;
765       goto done;
766     case FFI_TYPE_COMPLEX:
767       candidate = ty->elements[0]->type;
768       if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE)
769         return 0;
770       ele_count = 2;
771       goto done;
772     case FFI_TYPE_STRUCT:
773       break;
774     }
775
776   /* No HFA types are smaller than 4 bytes, or larger than 32 bytes.  */
777   size = ty->size;
778   if (size < 4 || size > 32)
779     return 0;
780
781   /* Find the type of the first non-structure member.  */
782   elements = ty->elements;
783   candidate = elements[0]->type;
784   if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX)
785     {
786       for (i = 0; ; ++i)
787         {
788           candidate = is_hfa0 (elements[i]);
789           if (candidate >= 0)
790             break;
791         }
792     }
793
794   /* If the first member is not a floating point type, it's not an HFA.
795      Also quickly re-check the size of the structure.  */
796   switch (candidate)
797     {
798     case FFI_TYPE_FLOAT:
799       ele_count = size / sizeof(float);
800       if (size != ele_count * sizeof(float))
801         return 0;
802       break;
803     case FFI_TYPE_DOUBLE:
804       ele_count = size / sizeof(double);
805       if (size != ele_count * sizeof(double))
806         return 0;
807       break;
808     default:
809       return 0;
810     }
811   if (ele_count > 4)
812     return 0;
813
814   /* Finally, make sure that all scalar elements are the same type.  */
815   for (i = 0; elements[i]; ++i)
816     {
817       int t = elements[i]->type;
818       if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX)
819         {
820           if (!is_hfa1 (elements[i], candidate))
821             return 0;
822         }
823       else if (t != candidate)
824         return 0;
825     }
826
827   /* All tests succeeded.  Encode the result.  */
828  done:
829   return (ele_count << 8) | candidate;
830 }
831
832 static int
833 place_vfp_arg (ffi_cif *cif, int h)
834 {
835   unsigned short reg = cif->vfp_reg_free;
836   int align = 1, nregs = h >> 8;
837
838   if ((h & 0xff) == FFI_TYPE_DOUBLE)
839     align = 2, nregs *= 2;
840
841   /* Align register number. */
842   if ((reg & 1) && align == 2)
843     reg++;
844
845   while (reg + nregs <= 16)
846     {
847       int s, new_used = 0;
848       for (s = reg; s < reg + nregs; s++)
849         {
850           new_used |= (1 << s);
851           if (cif->vfp_used & (1 << s))
852             {
853               reg += align;
854               goto next_reg;
855             }
856         }
857       /* Found regs to allocate. */
858       cif->vfp_used |= new_used;
859       cif->vfp_args[cif->vfp_nargs++] = (signed char)reg;
860
861       /* Update vfp_reg_free. */
862       if (cif->vfp_used & (1 << cif->vfp_reg_free))
863         {
864           reg += nregs;
865           while (cif->vfp_used & (1 << reg))
866             reg += 1;
867           cif->vfp_reg_free = reg;
868         }
869       return 0;
870     next_reg:;
871     }
872   // done, mark all regs as used
873   cif->vfp_reg_free = 16;
874   cif->vfp_used = 0xFFFF;
875   return 1;
876 }
877
878 static void
879 layout_vfp_args (ffi_cif * cif)
880 {
881   unsigned int i;
882   /* Init VFP fields */
883   cif->vfp_used = 0;
884   cif->vfp_nargs = 0;
885   cif->vfp_reg_free = 0;
886   memset (cif->vfp_args, -1, 16);       /* Init to -1. */
887
888   for (i = 0; i < cif->nargs; i++)
889     {
890       int h = vfp_type_p (cif->arg_types[i]);
891       if (h && place_vfp_arg (cif, h) == 1)
892         break;
893     }
894 }
895
896 #if defined(FFI_EXEC_STATIC_TRAMP)
897 void *
898 ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
899 {
900   extern void *trampoline_code_table;
901
902   *tramp_size = ARM_TRAMP_SIZE;
903   *map_size = ARM_TRAMP_MAP_SIZE;
904   return &trampoline_code_table;
905 }
906 #endif
907
908 #endif /* __arm__ or _M_ARM */