AArch64 port
[platform/upstream/libffi.git] / patches / aarch64
1 Index: libffi/README
2 ===================================================================
3 --- libffi.orig/README
4 +++ libffi/README
5 @@ -51,6 +51,7 @@ tested:
6  |-----------------+------------------|
7  | Architecture    | Operating System |
8  |-----------------+------------------|
9 +| AArch64         | Linux            |
10  | Alpha           | Linux            |
11  | Alpha           | Tru64            |
12  | ARM             | Linux            |
13 @@ -152,6 +153,7 @@ See the ChangeLog files for details.
14  3.0.12 XXX-XX-XX
15         Add Blackfin support.
16         Add TILE-Gx/TILEPro support.
17 +       Add AArch64 support.
18  
19  3.0.11 Apr-11-12
20          Lots of build fixes.
21 @@ -323,6 +325,7 @@ Thorup.
22  Major processor architecture ports were contributed by the following
23  developers:
24  
25 +aarch64                Marcus Shawcroft, James Greenhalgh
26  alpha          Richard Henderson
27  arm            Raffaele Sena
28  blackfin        Alexandre Keunecke I. de Mendonca
29 Index: libffi/src/aarch64/ffi.c
30 ===================================================================
31 --- /dev/null
32 +++ libffi/src/aarch64/ffi.c
33 @@ -0,0 +1,1076 @@
34 +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
35 +
36 +Permission is hereby granted, free of charge, to any person obtaining
37 +a copy of this software and associated documentation files (the
38 +``Software''), to deal in the Software without restriction, including
39 +without limitation the rights to use, copy, modify, merge, publish,
40 +distribute, sublicense, and/or sell copies of the Software, and to
41 +permit persons to whom the Software is furnished to do so, subject to
42 +the following conditions:
43 +
44 +The above copyright notice and this permission notice shall be
45 +included in all copies or substantial portions of the Software.
46 +
47 +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
48 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
50 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
51 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
52 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
53 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
54 +
55 +#include <stdio.h>
56 +
57 +#include <ffi.h>
58 +#include <ffi_common.h>
59 +
60 +#include <stdlib.h>
61 +
62 +/* Stack alignment requirement in bytes */
63 +#define AARCH64_STACK_ALIGN 16
64 +
65 +#define N_X_ARG_REG 8
66 +#define N_V_ARG_REG 8
67 +
68 +#define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT)
69 +
70 +union _d
71 +{
72 +  UINT64 d;
73 +  UINT32 s[2];
74 +};
75 +
76 +struct call_context
77 +{
78 +  UINT64 x [AARCH64_N_XREG];
79 +  struct
80 +  {
81 +    union _d d[2];
82 +  } v [AARCH64_N_VREG];
83 +};
84 +
85 +static void *
86 +get_x_addr (struct call_context *context, unsigned n)
87 +{
88 +  return &context->x[n];
89 +}
90 +
91 +static void *
92 +get_s_addr (struct call_context *context, unsigned n)
93 +{
94 +#if defined __AARCH64EB__
95 +  return &context->v[n].d[1].s[1];
96 +#else
97 +  return &context->v[n].d[0].s[0];
98 +#endif
99 +}
100 +
101 +static void *
102 +get_d_addr (struct call_context *context, unsigned n)
103 +{
104 +#if defined __AARCH64EB__
105 +  return &context->v[n].d[1];
106 +#else
107 +  return &context->v[n].d[0];
108 +#endif
109 +}
110 +
111 +static void *
112 +get_v_addr (struct call_context *context, unsigned n)
113 +{
114 +  return &context->v[n];
115 +}
116 +
117 +/* Return the memory location at which a basic type would reside
118 +   were it to have been stored in register n.  */
119 +
120 +static void *
121 +get_basic_type_addr (unsigned short type, struct call_context *context,
122 +                    unsigned n)
123 +{
124 +  switch (type)
125 +    {
126 +    case FFI_TYPE_FLOAT:
127 +      return get_s_addr (context, n);
128 +    case FFI_TYPE_DOUBLE:
129 +      return get_d_addr (context, n);
130 +    case FFI_TYPE_LONGDOUBLE:
131 +      return get_v_addr (context, n);
132 +    case FFI_TYPE_UINT8:
133 +    case FFI_TYPE_SINT8:
134 +    case FFI_TYPE_UINT16:
135 +    case FFI_TYPE_SINT16:
136 +    case FFI_TYPE_UINT32:
137 +    case FFI_TYPE_SINT32:
138 +    case FFI_TYPE_INT:
139 +    case FFI_TYPE_POINTER:
140 +    case FFI_TYPE_UINT64:
141 +    case FFI_TYPE_SINT64:
142 +      return get_x_addr (context, n);
143 +    default:
144 +      FFI_ASSERT (0);
145 +      return NULL;
146 +    }
147 +}
148 +
149 +/* Return the alignment width for each of the basic types.  */
150 +
151 +static size_t
152 +get_basic_type_alignment (unsigned short type)
153 +{
154 +  switch (type)
155 +    {
156 +    case FFI_TYPE_FLOAT:
157 +    case FFI_TYPE_DOUBLE:
158 +      return sizeof (UINT64);
159 +    case FFI_TYPE_LONGDOUBLE:
160 +      return sizeof (long double);
161 +    case FFI_TYPE_UINT8:
162 +    case FFI_TYPE_SINT8:
163 +    case FFI_TYPE_UINT16:
164 +    case FFI_TYPE_SINT16:
165 +    case FFI_TYPE_UINT32:
166 +    case FFI_TYPE_INT:
167 +    case FFI_TYPE_SINT32:
168 +    case FFI_TYPE_POINTER:
169 +    case FFI_TYPE_UINT64:
170 +    case FFI_TYPE_SINT64:
171 +      return sizeof (UINT64);
172 +
173 +    default:
174 +      FFI_ASSERT (0);
175 +      return 0;
176 +    }
177 +}
178 +
179 +/* Return the size in bytes for each of the basic types.  */
180 +
181 +static size_t
182 +get_basic_type_size (unsigned short type)
183 +{
184 +  switch (type)
185 +    {
186 +    case FFI_TYPE_FLOAT:
187 +      return sizeof (UINT32);
188 +    case FFI_TYPE_DOUBLE:
189 +      return sizeof (UINT64);
190 +    case FFI_TYPE_LONGDOUBLE:
191 +      return sizeof (long double);
192 +    case FFI_TYPE_UINT8:
193 +      return sizeof (UINT8);
194 +    case FFI_TYPE_SINT8:
195 +      return sizeof (SINT8);
196 +    case FFI_TYPE_UINT16:
197 +      return sizeof (UINT16);
198 +    case FFI_TYPE_SINT16:
199 +      return sizeof (SINT16);
200 +    case FFI_TYPE_UINT32:
201 +      return sizeof (UINT32);
202 +    case FFI_TYPE_INT:
203 +    case FFI_TYPE_SINT32:
204 +      return sizeof (SINT32);
205 +    case FFI_TYPE_POINTER:
206 +    case FFI_TYPE_UINT64:
207 +      return sizeof (UINT64);
208 +    case FFI_TYPE_SINT64:
209 +      return sizeof (SINT64);
210 +
211 +    default:
212 +      FFI_ASSERT (0);
213 +      return 0;
214 +    }
215 +}
216 +
217 +extern void
218 +ffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *,
219 +                           extended_cif *),
220 +               struct call_context *context,
221 +               extended_cif *,
222 +               unsigned,
223 +               void (*fn)(void));
224 +
225 +extern void
226 +ffi_closure_SYSV (ffi_closure *);
227 +
228 +/* Test for an FFI floating point representation.  */
229 +
230 +static unsigned
231 +is_floating_type (unsigned short type)
232 +{
233 +  return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE
234 +         || type == FFI_TYPE_LONGDOUBLE);
235 +}
236 +
237 +/* Test for a homogeneous structure.  */
238 +
239 +static unsigned short
240 +get_homogeneous_type (ffi_type *ty)
241 +{
242 +  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
243 +    {
244 +      unsigned i;
245 +      unsigned short candidate_type
246 +       = get_homogeneous_type (ty->elements[0]);
247 +      for (i =1; ty->elements[i]; i++)
248 +       {
249 +         unsigned short iteration_type = 0;
250 +         /* If we have a nested struct, we must find its homogeneous type.
251 +            If that fits with our candidate type, we are still
252 +            homogeneous.  */
253 +         if (ty->elements[i]->type == FFI_TYPE_STRUCT
254 +             && ty->elements[i]->elements)
255 +           {
256 +             iteration_type = get_homogeneous_type (ty->elements[i]);
257 +           }
258 +         else
259 +           {
260 +             iteration_type = ty->elements[i]->type;
261 +           }
262 +
263 +         /* If we are not homogeneous, return FFI_TYPE_STRUCT.  */
264 +         if (candidate_type != iteration_type)
265 +           return FFI_TYPE_STRUCT;
266 +       }
267 +      return candidate_type;
268 +    }
269 +
270 +  /* Base case, we have no more levels of nesting, so we
271 +     are a basic type, and so, trivially homogeneous in that type.  */
272 +  return ty->type;
273 +}
274 +
275 +/* Determine the number of elements within a STRUCT.
276 +
277 +   Note, we must handle nested structs.
278 +
279 +   If ty is not a STRUCT this function will return 0.  */
280 +
281 +static unsigned
282 +element_count (ffi_type *ty)
283 +{
284 +  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
285 +    {
286 +      unsigned n;
287 +      unsigned elems = 0;
288 +      for (n = 0; ty->elements[n]; n++)
289 +       {
290 +         if (ty->elements[n]->type == FFI_TYPE_STRUCT
291 +             && ty->elements[n]->elements)
292 +           elems += element_count (ty->elements[n]);
293 +         else
294 +           elems++;
295 +       }
296 +      return elems;
297 +    }
298 +  return 0;
299 +}
300 +
301 +/* Test for a homogeneous floating point aggregate.
302 +
303 +   A homogeneous floating point aggregate is a homogeneous aggregate of
304 +   a half- single- or double- precision floating point type with one
305 +   to four elements.  Note that this includes nested structs of the
306 +   basic type.  */
307 +
308 +static int
309 +is_hfa (ffi_type *ty)
310 +{
311 +  if (ty->type == FFI_TYPE_STRUCT
312 +      && ty->elements[0]
313 +      && is_floating_type (get_homogeneous_type (ty)))
314 +    {
315 +      unsigned n = element_count (ty);
316 +      return n >= 1 && n <= 4;
317 +    }
318 +  return 0;
319 +}
320 +
321 +/* Test if an ffi_type is a candidate for passing in a register.
322 +
323 +   This test does not check that sufficient registers of the
324 +   appropriate class are actually available, merely that IFF
325 +   sufficient registers are available then the argument will be passed
326 +   in register(s).
327 +
328 +   Note that an ffi_type that is deemed to be a register candidate
329 +   will always be returned in registers.
330 +
331 +   Returns 1 if a register candidate else 0.  */
332 +
333 +static int
334 +is_register_candidate (ffi_type *ty)
335 +{
336 +  switch (ty->type)
337 +    {
338 +    case FFI_TYPE_VOID:
339 +    case FFI_TYPE_FLOAT:
340 +    case FFI_TYPE_DOUBLE:
341 +    case FFI_TYPE_LONGDOUBLE:
342 +    case FFI_TYPE_UINT8:
343 +    case FFI_TYPE_UINT16:
344 +    case FFI_TYPE_UINT32:
345 +    case FFI_TYPE_UINT64:
346 +    case FFI_TYPE_POINTER:
347 +    case FFI_TYPE_SINT8:
348 +    case FFI_TYPE_SINT16:
349 +    case FFI_TYPE_SINT32:
350 +    case FFI_TYPE_INT:
351 +    case FFI_TYPE_SINT64:
352 +      return 1;
353 +
354 +    case FFI_TYPE_STRUCT:
355 +      if (is_hfa (ty))
356 +        {
357 +          return 1;
358 +        }
359 +      else if (ty->size > 16)
360 +        {
361 +          /* Too large. Will be replaced with a pointer to memory. The
362 +             pointer MAY be passed in a register, but the value will
363 +             not. This test specifically fails since the argument will
364 +             never be passed by value in registers. */
365 +          return 0;
366 +        }
367 +      else
368 +        {
369 +          /* Might be passed in registers depending on the number of
370 +             registers required. */
371 +          return (ty->size + 7) / 8 < N_X_ARG_REG;
372 +        }
373 +      break;
374 +
375 +    default:
376 +      FFI_ASSERT (0);
377 +      break;
378 +    }
379 +
380 +  return 0;
381 +}
382 +
383 +/* Test if an ffi_type argument or result is a candidate for a vector
384 +   register.  */
385 +
386 +static int
387 +is_v_register_candidate (ffi_type *ty)
388 +{
389 +  return is_floating_type (ty->type)
390 +          || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty));
391 +}
392 +
393 +/* Representation of the procedure call argument marshalling
394 +   state.
395 +
396 +   The terse state variable names match the names used in the AARCH64
397 +   PCS. */
398 +
399 +struct arg_state
400 +{
401 +  unsigned ngrn;                /* Next general-purpose register number. */
402 +  unsigned nsrn;                /* Next vector register number. */
403 +  unsigned nsaa;                /* Next stack offset. */
404 +};
405 +
406 +/* Initialize a procedure call argument marshalling state.  */
407 +static void
408 +arg_init (struct arg_state *state, unsigned call_frame_size)
409 +{
410 +  state->ngrn = 0;
411 +  state->nsrn = 0;
412 +  state->nsaa = 0;
413 +}
414 +
415 +/* Return the number of available consecutive core argument
416 +   registers.  */
417 +
418 +static unsigned
419 +available_x (struct arg_state *state)
420 +{
421 +  return N_X_ARG_REG - state->ngrn;
422 +}
423 +
424 +/* Return the number of available consecutive vector argument
425 +   registers.  */
426 +
427 +static unsigned
428 +available_v (struct arg_state *state)
429 +{
430 +  return N_V_ARG_REG - state->nsrn;
431 +}
432 +
433 +static void *
434 +allocate_to_x (struct call_context *context, struct arg_state *state)
435 +{
436 +  FFI_ASSERT (state->ngrn < N_X_ARG_REG)
437 +  return get_x_addr (context, (state->ngrn)++);
438 +}
439 +
440 +static void *
441 +allocate_to_s (struct call_context *context, struct arg_state *state)
442 +{
443 +  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
444 +  return get_s_addr (context, (state->nsrn)++);
445 +}
446 +
447 +static void *
448 +allocate_to_d (struct call_context *context, struct arg_state *state)
449 +{
450 +  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
451 +  return get_d_addr (context, (state->nsrn)++);
452 +}
453 +
454 +static void *
455 +allocate_to_v (struct call_context *context, struct arg_state *state)
456 +{
457 +  FFI_ASSERT (state->nsrn < N_V_ARG_REG)
458 +  return get_v_addr (context, (state->nsrn)++);
459 +}
460 +
461 +/* Allocate an aligned slot on the stack and return a pointer to it.  */
462 +static void *
463 +allocate_to_stack (struct arg_state *state, void *stack, unsigned alignment,
464 +                  unsigned size)
465 +{
466 +  void *allocation;
467 +
468 +  /* Round up the NSAA to the larger of 8 or the natural
469 +     alignment of the argument's type.  */
470 +  state->nsaa = ALIGN (state->nsaa, alignment);
471 +  state->nsaa = ALIGN (state->nsaa, alignment);
472 +  state->nsaa = ALIGN (state->nsaa, 8);
473 +
474 +  allocation = stack + state->nsaa;
475 +
476 +  state->nsaa += size;
477 +  return allocation;
478 +}
479 +
480 +static void
481 +copy_basic_type (void *dest, void *source, unsigned short type)
482 +{
483 +  /* This is neccessary to ensure that basic types are copied
484 +     sign extended to 64-bits as libffi expects.  */
485 +  switch (type)
486 +    {
487 +    case FFI_TYPE_FLOAT:
488 +      *(float *) dest = *(float *) source;
489 +      break;
490 +    case FFI_TYPE_DOUBLE:
491 +      *(double *) dest = *(double *) source;
492 +      break;
493 +    case FFI_TYPE_LONGDOUBLE:
494 +      *(long double *) dest = *(long double *) source;
495 +      break;
496 +    case FFI_TYPE_UINT8:
497 +      *(ffi_arg *) dest = *(UINT8 *) source;
498 +      break;
499 +    case FFI_TYPE_SINT8:
500 +      *(ffi_sarg *) dest = *(SINT8 *) source;
501 +      break;
502 +    case FFI_TYPE_UINT16:
503 +      *(ffi_arg *) dest = *(UINT16 *) source;
504 +      break;
505 +    case FFI_TYPE_SINT16:
506 +      *(ffi_sarg *) dest = *(SINT16 *) source;
507 +      break;
508 +    case FFI_TYPE_UINT32:
509 +      *(ffi_arg *) dest = *(UINT32 *) source;
510 +      break;
511 +    case FFI_TYPE_INT:
512 +    case FFI_TYPE_SINT32:
513 +      *(ffi_sarg *) dest = *(SINT32 *) source;
514 +      break;
515 +    case FFI_TYPE_POINTER:
516 +    case FFI_TYPE_UINT64:
517 +      *(ffi_arg *) dest = *(UINT64 *) source;
518 +      break;
519 +    case FFI_TYPE_SINT64:
520 +      *(ffi_sarg *) dest = *(SINT64 *) source;
521 +      break;
522 +
523 +    default:
524 +      FFI_ASSERT (0);
525 +    }
526 +}
527 +
528 +static void
529 +copy_hfa_to_reg_or_stack (void *memory,
530 +                         ffi_type *ty,
531 +                         struct call_context *context,
532 +                         unsigned char *stack,
533 +                         struct arg_state *state)
534 +{
535 +  unsigned elems = element_count (ty);
536 +  if (available_v (state) < elems)
537 +    {
538 +      /* There are insufficient V registers. Further V register allocations
539 +        are prevented, the NSAA is adjusted (by allocate_to_stack ())
540 +        and the argument is copied to memory at the adjusted NSAA.  */
541 +      state->nsrn = N_V_ARG_REG;
542 +      memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size),
543 +             memory,
544 +             ty->size);
545 +    }
546 +  else
547 +    {
548 +      int i;
549 +      unsigned short type = get_homogeneous_type (ty);
550 +      unsigned elems = element_count (ty);
551 +      for (i = 0; i < elems; i++)
552 +       {
553 +         void *reg = allocate_to_v (context, state);
554 +         copy_basic_type (reg, memory, type);
555 +         memory += get_basic_type_size (type);
556 +       }
557 +    }
558 +}
559 +
560 +/* Either allocate an appropriate register for the argument type, or if
561 +   none are available, allocate a stack slot and return a pointer
562 +   to the allocated space.  */
563 +
564 +static void *
565 +allocate_to_register_or_stack (struct call_context *context,
566 +                              unsigned char *stack,
567 +                              struct arg_state *state,
568 +                              unsigned short type)
569 +{
570 +  size_t alignment = get_basic_type_alignment (type);
571 +  size_t size = alignment;
572 +  switch (type)
573 +    {
574 +    case FFI_TYPE_FLOAT:
575 +      /* This is the only case for which the allocated stack size
576 +        should not match the alignment of the type.  */
577 +      size = sizeof (UINT32);
578 +      /* Fall through.  */
579 +    case FFI_TYPE_DOUBLE:
580 +      if (state->nsrn < N_V_ARG_REG)
581 +       return allocate_to_d (context, state);
582 +      state->nsrn = N_V_ARG_REG;
583 +      break;
584 +    case FFI_TYPE_LONGDOUBLE:
585 +      if (state->nsrn < N_V_ARG_REG)
586 +       return allocate_to_v (context, state);
587 +      state->nsrn = N_V_ARG_REG;
588 +      break;
589 +    case FFI_TYPE_UINT8:
590 +    case FFI_TYPE_SINT8:
591 +    case FFI_TYPE_UINT16:
592 +    case FFI_TYPE_SINT16:
593 +    case FFI_TYPE_UINT32:
594 +    case FFI_TYPE_SINT32:
595 +    case FFI_TYPE_INT:
596 +    case FFI_TYPE_POINTER:
597 +    case FFI_TYPE_UINT64:
598 +    case FFI_TYPE_SINT64:
599 +      if (state->ngrn < N_X_ARG_REG)
600 +       return allocate_to_x (context, state);
601 +      state->ngrn = N_X_ARG_REG;
602 +      break;
603 +    default:
604 +      FFI_ASSERT (0);
605 +    }
606 +
607 +    return allocate_to_stack (state, stack, alignment, size);
608 +}
609 +
610 +/* Copy a value to an appropriate register, or if none are
611 +   available, to the stack.  */
612 +
613 +static void
614 +copy_to_register_or_stack (struct call_context *context,
615 +                          unsigned char *stack,
616 +                          struct arg_state *state,
617 +                          void *value,
618 +                          unsigned short type)
619 +{
620 +  copy_basic_type (
621 +         allocate_to_register_or_stack (context, stack, state, type),
622 +         value,
623 +         type);
624 +}
625 +
626 +/* Marshall the arguments from FFI representation to procedure call
627 +   context and stack.  */
628 +
629 +static unsigned
630 +aarch64_prep_args (struct call_context *context, unsigned char *stack,
631 +                  extended_cif *ecif)
632 +{
633 +  int i;
634 +  struct arg_state state;
635 +
636 +  arg_init (&state, ALIGN(ecif->cif->bytes, 16));
637 +
638 +  for (i = 0; i < ecif->cif->nargs; i++)
639 +    {
640 +      ffi_type *ty = ecif->cif->arg_types[i];
641 +      switch (ty->type)
642 +       {
643 +       case FFI_TYPE_VOID:
644 +         FFI_ASSERT (0);
645 +         break;
646 +
647 +       /* If the argument is a basic type the argument is allocated to an
648 +          appropriate register, or if none are available, to the stack.  */
649 +       case FFI_TYPE_FLOAT:
650 +       case FFI_TYPE_DOUBLE:
651 +       case FFI_TYPE_LONGDOUBLE:
652 +       case FFI_TYPE_UINT8:
653 +       case FFI_TYPE_SINT8:
654 +       case FFI_TYPE_UINT16:
655 +       case FFI_TYPE_SINT16:
656 +       case FFI_TYPE_UINT32:
657 +       case FFI_TYPE_INT:
658 +       case FFI_TYPE_SINT32:
659 +       case FFI_TYPE_POINTER:
660 +       case FFI_TYPE_UINT64:
661 +       case FFI_TYPE_SINT64:
662 +         copy_to_register_or_stack (context, stack, &state,
663 +                                    ecif->avalue[i], ty->type);
664 +         break;
665 +
666 +       case FFI_TYPE_STRUCT:
667 +         if (is_hfa (ty))
668 +           {
669 +             copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context,
670 +                                       stack, &state);
671 +           }
672 +         else if (ty->size > 16)
673 +           {
674 +             /* If the argument is a composite type that is larger than 16
675 +                bytes, then the argument has been copied to memory, and
676 +                the argument is replaced by a pointer to the copy.  */
677 +
678 +             copy_to_register_or_stack (context, stack, &state,
679 +                                        &(ecif->avalue[i]), FFI_TYPE_POINTER);
680 +           }
681 +         else if (available_x (&state) >= (ty->size + 7) / 8)
682 +           {
683 +             /* If the argument is a composite type and the size in
684 +                double-words is not more than the number of available
685 +                X registers, then the argument is copied into consecutive
686 +                X registers.  */
687 +             int j;
688 +             for (j = 0; j < (ty->size + 7) / 8; j++)
689 +               {
690 +                 memcpy (allocate_to_x (context, &state),
691 +                         &(((UINT64 *) ecif->avalue[i])[j]),
692 +                         sizeof (UINT64));
693 +               }
694 +           }
695 +         else
696 +           {
697 +             /* Otherwise, there are insufficient X registers. Further X
698 +                register allocations are prevented, the NSAA is adjusted
699 +                (by allocate_to_stack ()) and the argument is copied to
700 +                memory at the adjusted NSAA.  */
701 +             state.ngrn = N_X_ARG_REG;
702 +
703 +             memcpy (allocate_to_stack (&state, stack, ty->alignment,
704 +                                        ty->size), ecif->avalue + i, ty->size);
705 +           }
706 +         break;
707 +
708 +       default:
709 +         FFI_ASSERT (0);
710 +         break;
711 +       }
712 +    }
713 +
714 +  return ecif->cif->aarch64_flags;
715 +}
716 +
717 +ffi_status
718 +ffi_prep_cif_machdep (ffi_cif *cif)
719 +{
720 +  /* Round the stack up to a multiple of the stack alignment requirement. */
721 +  cif->bytes =
722 +    (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1);
723 +
724 +  /* Initialize our flags. We are interested if this CIF will touch a
725 +     vector register, if so we will enable context save and load to
726 +     those registers, otherwise not. This is intended to be friendly
727 +     to lazy float context switching in the kernel.  */
728 +  cif->aarch64_flags = 0;
729 +
730 +  if (is_v_register_candidate (cif->rtype))
731 +    {
732 +      cif->aarch64_flags |= AARCH64_FFI_WITH_V;
733 +    }
734 +  else
735 +    {
736 +      int i;
737 +      for (i = 0; i < cif->nargs; i++)
738 +        if (is_v_register_candidate (cif->arg_types[i]))
739 +          {
740 +            cif->aarch64_flags |= AARCH64_FFI_WITH_V;
741 +            break;
742 +          }
743 +    }
744 +
745 +  return FFI_OK;
746 +}
747 +
748 +/* Call a function with the provided arguments and capture the return
749 +   value.  */
750 +void
751 +ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
752 +{
753 +  extended_cif ecif;
754 +
755 +  ecif.cif = cif;
756 +  ecif.avalue = avalue;
757 +  ecif.rvalue = rvalue;
758 +
759 +  switch (cif->abi)
760 +    {
761 +    case FFI_SYSV:
762 +      {
763 +        struct call_context context;
764 +       unsigned stack_bytes;
765 +
766 +       /* Figure out the total amount of stack space we need, the
767 +          above call frame space needs to be 16 bytes aligned to
768 +          ensure correct alignment of the first object inserted in
769 +          that space hence the ALIGN applied to cif->bytes.*/
770 +       stack_bytes = ALIGN(cif->bytes, 16);
771 +
772 +       memset (&context, 0, sizeof (context));
773 +        if (is_register_candidate (cif->rtype))
774 +          {
775 +            ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn);
776 +            switch (cif->rtype->type)
777 +              {
778 +              case FFI_TYPE_VOID:
779 +              case FFI_TYPE_FLOAT:
780 +              case FFI_TYPE_DOUBLE:
781 +              case FFI_TYPE_LONGDOUBLE:
782 +              case FFI_TYPE_UINT8:
783 +              case FFI_TYPE_SINT8:
784 +              case FFI_TYPE_UINT16:
785 +              case FFI_TYPE_SINT16:
786 +              case FFI_TYPE_UINT32:
787 +              case FFI_TYPE_SINT32:
788 +              case FFI_TYPE_POINTER:
789 +              case FFI_TYPE_UINT64:
790 +              case FFI_TYPE_INT:
791 +              case FFI_TYPE_SINT64:
792 +               {
793 +                 void *addr = get_basic_type_addr (cif->rtype->type,
794 +                                                   &context, 0);
795 +                 copy_basic_type (rvalue, addr, cif->rtype->type);
796 +                 break;
797 +               }
798 +
799 +              case FFI_TYPE_STRUCT:
800 +                if (is_hfa (cif->rtype))
801 +                 {
802 +                   int j;
803 +                   unsigned short type = get_homogeneous_type (cif->rtype);
804 +                   unsigned elems = element_count (cif->rtype);
805 +                   for (j = 0; j < elems; j++)
806 +                     {
807 +                       void *reg = get_basic_type_addr (type, &context, j);
808 +                       copy_basic_type (rvalue, reg, type);
809 +                       rvalue += get_basic_type_size (type);
810 +                     }
811 +                 }
812 +                else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
813 +                  {
814 +                    unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64));
815 +                    memcpy (rvalue, get_x_addr (&context, 0), size);
816 +                  }
817 +                else
818 +                  {
819 +                    FFI_ASSERT (0);
820 +                  }
821 +                break;
822 +
823 +              default:
824 +                FFI_ASSERT (0);
825 +                break;
826 +              }
827 +          }
828 +        else
829 +          {
830 +            memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64));
831 +            ffi_call_SYSV (aarch64_prep_args, &context, &ecif,
832 +                          stack_bytes, fn);
833 +          }
834 +        break;
835 +      }
836 +
837 +    default:
838 +      FFI_ASSERT (0);
839 +      break;
840 +    }
841 +}
842 +
843 +static unsigned char trampoline [] =
844 +{ 0x70, 0x00, 0x00, 0x58,      /* ldr  x16, 1f */
845 +  0x91, 0x00, 0x00, 0x10,      /* adr  x17, 2f */
846 +  0x00, 0x02, 0x1f, 0xd6       /* br   x16     */
847 +};
848 +
849 +/* Build a trampoline.  */
850 +
851 +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS)                       \
852 +  ({unsigned char *__tramp = (unsigned char*)(TRAMP);                  \
853 +    UINT64  __fun = (UINT64)(FUN);                                     \
854 +    UINT64  __ctx = (UINT64)(CTX);                                     \
855 +    UINT64  __flags = (UINT64)(FLAGS);                                 \
856 +    memcpy (__tramp, trampoline, sizeof (trampoline));                 \
857 +    memcpy (__tramp + 12, &__fun, sizeof (__fun));                     \
858 +    memcpy (__tramp + 20, &__ctx, sizeof (__ctx));                     \
859 +    memcpy (__tramp + 28, &__flags, sizeof (__flags));                 \
860 +    __clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE);             \
861 +  })
862 +
863 +ffi_status
864 +ffi_prep_closure_loc (ffi_closure* closure,
865 +                      ffi_cif* cif,
866 +                      void (*fun)(ffi_cif*,void*,void**,void*),
867 +                      void *user_data,
868 +                      void *codeloc)
869 +{
870 +  if (cif->abi != FFI_SYSV)
871 +    return FFI_BAD_ABI;
872 +
873 +  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc,
874 +                      cif->aarch64_flags);
875 +
876 +  closure->cif  = cif;
877 +  closure->user_data = user_data;
878 +  closure->fun  = fun;
879 +
880 +  return FFI_OK;
881 +}
882 +
883 +/* Primary handler to setup and invoke a function within a closure.
884 +
885 +   A closure when invoked enters via the assembler wrapper
886 +   ffi_closure_SYSV(). The wrapper allocates a call context on the
887 +   stack, saves the interesting registers (from the perspective of
888 +   the calling convention) into the context then passes control to
889 +   ffi_closure_SYSV_inner() passing the saved context and a pointer to
890 +   the stack at the point ffi_closure_SYSV() was invoked.
891 +
892 +   On the return path the assembler wrapper will reload call context
893 +   regsiters.
894 +
895 +   ffi_closure_SYSV_inner() marshalls the call context into ffi value
896 +   desriptors, invokes the wrapped function, then marshalls the return
897 +   value back into the call context.  */
898 +
899 +void
900 +ffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context,
901 +                       void *stack)
902 +{
903 +  ffi_cif *cif = closure->cif;
904 +  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
905 +  void *rvalue = NULL;
906 +  int i;
907 +  struct arg_state state;
908 +
909 +  arg_init (&state, ALIGN(cif->bytes, 16));
910 +
911 +  for (i = 0; i < cif->nargs; i++)
912 +    {
913 +      ffi_type *ty = cif->arg_types[i];
914 +
915 +      switch (ty->type)
916 +       {
917 +       case FFI_TYPE_VOID:
918 +         FFI_ASSERT (0);
919 +         break;
920 +
921 +       case FFI_TYPE_UINT8:
922 +       case FFI_TYPE_SINT8:
923 +       case FFI_TYPE_UINT16:
924 +       case FFI_TYPE_SINT16:
925 +       case FFI_TYPE_UINT32:
926 +       case FFI_TYPE_SINT32:
927 +       case FFI_TYPE_INT:
928 +       case FFI_TYPE_POINTER:
929 +       case FFI_TYPE_UINT64:
930 +       case FFI_TYPE_SINT64:
931 +       case  FFI_TYPE_FLOAT:
932 +       case  FFI_TYPE_DOUBLE:
933 +       case  FFI_TYPE_LONGDOUBLE:
934 +         avalue[i] = allocate_to_register_or_stack (context, stack,
935 +                                                    &state, ty->type);
936 +         break;
937 +
938 +       case FFI_TYPE_STRUCT:
939 +         if (is_hfa (ty))
940 +           {
941 +             unsigned n = element_count (ty);
942 +             if (available_v (&state) < n)
943 +               {
944 +                 state.nsrn = N_V_ARG_REG;
945 +                 avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
946 +                                                ty->size);
947 +               }
948 +             else
949 +               {
950 +                 switch (get_homogeneous_type (ty))
951 +                   {
952 +                   case FFI_TYPE_FLOAT:
953 +                     {
954 +                       /* Eeek! We need a pointer to the structure,
955 +                          however the homogeneous float elements are
956 +                          being passed in individual S registers,
957 +                          therefore the structure is not represented as
958 +                          a contiguous sequence of bytes in our saved
959 +                          register context. We need to fake up a copy
960 +                          of the structure layed out in memory
961 +                          correctly. The fake can be tossed once the
962 +                          closure function has returned hence alloca()
963 +                          is sufficient. */
964 +                       int j;
965 +                       UINT32 *p = avalue[i] = alloca (ty->size);
966 +                       for (j = 0; j < element_count (ty); j++)
967 +                         memcpy (&p[j],
968 +                                 allocate_to_s (context, &state),
969 +                                 sizeof (*p));
970 +                       break;
971 +                     }
972 +
973 +                   case FFI_TYPE_DOUBLE:
974 +                     {
975 +                       /* Eeek! We need a pointer to the structure,
976 +                          however the homogeneous float elements are
977 +                          being passed in individual S registers,
978 +                          therefore the structure is not represented as
979 +                          a contiguous sequence of bytes in our saved
980 +                          register context. We need to fake up a copy
981 +                          of the structure layed out in memory
982 +                          correctly. The fake can be tossed once the
983 +                          closure function has returned hence alloca()
984 +                          is sufficient. */
985 +                       int j;
986 +                       UINT64 *p = avalue[i] = alloca (ty->size);
987 +                       for (j = 0; j < element_count (ty); j++)
988 +                         memcpy (&p[j],
989 +                                 allocate_to_d (context, &state),
990 +                                 sizeof (*p));
991 +                       break;
992 +                     }
993 +
994 +                   case FFI_TYPE_LONGDOUBLE:
995 +                         memcpy (&avalue[i],
996 +                                 allocate_to_v (context, &state),
997 +                                 sizeof (*avalue));
998 +                     break;
999 +
1000 +                   default:
1001 +                     FFI_ASSERT (0);
1002 +                     break;
1003 +                   }
1004 +               }
1005 +           }
1006 +         else if (ty->size > 16)
1007 +           {
1008 +             /* Replace Composite type of size greater than 16 with a
1009 +                pointer.  */
1010 +             memcpy (&avalue[i],
1011 +                     allocate_to_register_or_stack (context, stack,
1012 +                                                    &state, FFI_TYPE_POINTER),
1013 +                     sizeof (avalue[i]));
1014 +           }
1015 +         else if (available_x (&state) >= (ty->size + 7) / 8)
1016 +           {
1017 +             avalue[i] = get_x_addr (context, state.ngrn);
1018 +             state.ngrn += (ty->size + 7) / 8;
1019 +           }
1020 +         else
1021 +           {
1022 +             state.ngrn = N_X_ARG_REG;
1023 +
1024 +             avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
1025 +                                            ty->size);
1026 +           }
1027 +         break;
1028 +
1029 +       default:
1030 +         FFI_ASSERT (0);
1031 +         break;
1032 +       }
1033 +    }
1034 +
1035 +  /* Figure out where the return value will be passed, either in
1036 +     registers or in a memory block allocated by the caller and passed
1037 +     in x8.  */
1038 +
1039 +  if (is_register_candidate (cif->rtype))
1040 +    {
1041 +      /* Register candidates are *always* returned in registers. */
1042 +
1043 +      /* Allocate a scratchpad for the return value, we will let the
1044 +         callee scrible the result into the scratch pad then move the
1045 +         contents into the appropriate return value location for the
1046 +         call convention.  */
1047 +      rvalue = alloca (cif->rtype->size);
1048 +      (closure->fun) (cif, rvalue, avalue, closure->user_data);
1049 +
1050 +      /* Copy the return value into the call context so that it is returned
1051 +         as expected to our caller.  */
1052 +      switch (cif->rtype->type)
1053 +        {
1054 +        case FFI_TYPE_VOID:
1055 +          break;
1056 +
1057 +        case FFI_TYPE_UINT8:
1058 +        case FFI_TYPE_UINT16:
1059 +        case FFI_TYPE_UINT32:
1060 +        case FFI_TYPE_POINTER:
1061 +        case FFI_TYPE_UINT64:
1062 +        case FFI_TYPE_SINT8:
1063 +        case FFI_TYPE_SINT16:
1064 +        case FFI_TYPE_INT:
1065 +        case FFI_TYPE_SINT32:
1066 +        case FFI_TYPE_SINT64:
1067 +        case FFI_TYPE_FLOAT:
1068 +        case FFI_TYPE_DOUBLE:
1069 +        case FFI_TYPE_LONGDOUBLE:
1070 +         {
1071 +           void *addr = get_basic_type_addr (cif->rtype->type, context, 0);
1072 +           copy_basic_type (addr, rvalue, cif->rtype->type);
1073 +            break;
1074 +         }
1075 +        case FFI_TYPE_STRUCT:
1076 +          if (is_hfa (cif->rtype))
1077 +           {
1078 +             int i;
1079 +             unsigned short type = get_homogeneous_type (cif->rtype);
1080 +             unsigned elems = element_count (cif->rtype);
1081 +             for (i = 0; i < elems; i++)
1082 +               {
1083 +                 void *reg = get_basic_type_addr (type, context, i);
1084 +                 copy_basic_type (reg, rvalue, type);
1085 +                 rvalue += get_basic_type_size (type);
1086 +               }
1087 +           }
1088 +          else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
1089 +            {
1090 +              unsigned size = ALIGN (cif->rtype->size, sizeof (UINT64)) ;
1091 +              memcpy (get_x_addr (context, 0), rvalue, size);
1092 +            }
1093 +          else
1094 +            {
1095 +              FFI_ASSERT (0);
1096 +            }
1097 +          break;
1098 +        default:
1099 +          FFI_ASSERT (0);
1100 +          break;
1101 +        }
1102 +    }
1103 +  else
1104 +    {
1105 +      memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64));
1106 +      (closure->fun) (cif, rvalue, avalue, closure->user_data);
1107 +    }
1108 +}
1109 +
1110 Index: libffi/src/aarch64/ffitarget.h
1111 ===================================================================
1112 --- /dev/null
1113 +++ libffi/src/aarch64/ffitarget.h
1114 @@ -0,0 +1,59 @@
1115 +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
1116 +
1117 +Permission is hereby granted, free of charge, to any person obtaining
1118 +a copy of this software and associated documentation files (the
1119 +``Software''), to deal in the Software without restriction, including
1120 +without limitation the rights to use, copy, modify, merge, publish,
1121 +distribute, sublicense, and/or sell copies of the Software, and to
1122 +permit persons to whom the Software is furnished to do so, subject to
1123 +the following conditions:
1124 +
1125 +The above copyright notice and this permission notice shall be
1126 +included in all copies or substantial portions of the Software.
1127 +
1128 +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
1129 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1130 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1131 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1132 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1133 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1134 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
1135 +
1136 +#ifndef LIBFFI_TARGET_H
1137 +#define LIBFFI_TARGET_H
1138 +
1139 +#ifndef LIBFFI_H
1140 +#error "Please do not include ffitarget.h directly into your source.  Use ffi.h instead."
1141 +#endif
1142 +
1143 +#ifndef LIBFFI_ASM
1144 +typedef unsigned long ffi_arg;
1145 +typedef signed long ffi_sarg;
1146 +
1147 +typedef enum ffi_abi
1148 +  {
1149 +    FFI_FIRST_ABI = 0,
1150 +    FFI_SYSV,
1151 +    FFI_LAST_ABI,
1152 +    FFI_DEFAULT_ABI = FFI_SYSV
1153 +  } ffi_abi;
1154 +#endif
1155 +
1156 +/* ---- Definitions for closures ----------------------------------------- */
1157 +
1158 +#define FFI_CLOSURES 1
1159 +#define FFI_TRAMPOLINE_SIZE 36
1160 +#define FFI_NATIVE_RAW_API 0
1161 +
1162 +/* ---- Internal ---- */
1163 +
1164 +
1165 +#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags
1166 +
1167 +#define AARCH64_FFI_WITH_V_BIT 0
1168 +
1169 +#define AARCH64_N_XREG 32
1170 +#define AARCH64_N_VREG 32
1171 +#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16)
1172 +
1173 +#endif
1174 Index: libffi/src/aarch64/sysv.S
1175 ===================================================================
1176 --- /dev/null
1177 +++ libffi/src/aarch64/sysv.S
1178 @@ -0,0 +1,307 @@
1179 +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
1180 +
1181 +Permission is hereby granted, free of charge, to any person obtaining
1182 +a copy of this software and associated documentation files (the
1183 +``Software''), to deal in the Software without restriction, including
1184 +without limitation the rights to use, copy, modify, merge, publish,
1185 +distribute, sublicense, and/or sell copies of the Software, and to
1186 +permit persons to whom the Software is furnished to do so, subject to
1187 +the following conditions:
1188 +
1189 +The above copyright notice and this permission notice shall be
1190 +included in all copies or substantial portions of the Software.
1191 +
1192 +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
1193 +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1194 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1195 +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1196 +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1197 +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1198 +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
1199 +
1200 +#define LIBFFI_ASM
1201 +#include <fficonfig.h>
1202 +#include <ffi.h>
1203 +
1204 +#define cfi_adjust_cfa_offset(off)     .cfi_adjust_cfa_offset off
1205 +#define cfi_rel_offset(reg, off)       .cfi_rel_offset reg, off
1206 +#define cfi_restore(reg)               .cfi_restore reg
1207 +#define cfi_def_cfa_register(reg)      .cfi_def_cfa_register reg
1208 +
1209 +        .text
1210 +        .globl ffi_call_SYSV
1211 +        .type ffi_call_SYSV, #function
1212 +
1213 +/* ffi_call_SYSV()
1214 +
1215 +   Create a stack frame, setup an argument context, call the callee
1216 +   and extract the result.
1217 +
1218 +   The maximum required argument stack size is provided,
1219 +   ffi_call_SYSV() allocates that stack space then calls the
1220 +   prepare_fn to populate register context and stack.  The
1221 +   argument passing registers are loaded from the register
1222 +   context and the callee called, on return the register passing
1223 +   register are saved back to the context.  Our caller will
1224 +   extract the return value from the final state of the saved
1225 +   register context.
1226 +
1227 +   Prototype:
1228 +
1229 +   extern unsigned
1230 +   ffi_call_SYSV (void (*)(struct call_context *context, unsigned char *,
1231 +                          extended_cif *),
1232 +                  struct call_context *context,
1233 +                  extended_cif *,
1234 +                  unsigned required_stack_size,
1235 +                  void (*fn)(void));
1236 +
1237 +   Therefore on entry we have:
1238 +
1239 +   x0 prepare_fn
1240 +   x1 &context
1241 +   x2 &ecif
1242 +   x3 bytes
1243 +   x4 fn
1244 +
1245 +   This function uses the following stack frame layout:
1246 +
1247 +   ==
1248 +                saved x30(lr)
1249 +   x29(fp)->    saved x29(fp)
1250 +                saved x24
1251 +                saved x23
1252 +                saved x22
1253 +   sp'    ->    saved x21
1254 +                ...
1255 +   sp     ->    (constructed callee stack arguments)
1256 +   ==
1257 +
1258 +   Voila! */
1259 +
1260 +#define ffi_call_SYSV_FS (8 * 4)
1261 +
1262 +        .cfi_startproc
1263 +ffi_call_SYSV:
1264 +        stp     x29, x30, [sp, #-16]!
1265 +       cfi_adjust_cfa_offset (16)
1266 +        cfi_rel_offset (x29, 0)
1267 +        cfi_rel_offset (x30, 8)
1268 +
1269 +        mov     x29, sp
1270 +       cfi_def_cfa_register (x29)
1271 +        sub     sp, sp, #ffi_call_SYSV_FS
1272 +
1273 +        stp     x21, x22, [sp, 0]
1274 +        cfi_rel_offset (x21, 0 - ffi_call_SYSV_FS)
1275 +        cfi_rel_offset (x22, 8 - ffi_call_SYSV_FS)
1276 +
1277 +        stp     x23, x24, [sp, 16]
1278 +        cfi_rel_offset (x23, 16 - ffi_call_SYSV_FS)
1279 +        cfi_rel_offset (x24, 24 - ffi_call_SYSV_FS)
1280 +
1281 +        mov     x21, x1
1282 +        mov     x22, x2
1283 +        mov     x24, x4
1284 +
1285 +        /* Allocate the stack space for the actual arguments, many
1286 +           arguments will be passed in registers, but we assume
1287 +           worst case and allocate sufficient stack for ALL of
1288 +           the arguments.  */
1289 +        sub     sp, sp, x3
1290 +
1291 +        /* unsigned (*prepare_fn) (struct call_context *context,
1292 +                                  unsigned char *stack, extended_cif *ecif);
1293 +        */
1294 +        mov     x23, x0
1295 +        mov     x0, x1
1296 +        mov     x1, sp
1297 +        /* x2 already in place */
1298 +        blr     x23
1299 +
1300 +        /* Preserve the flags returned.  */
1301 +        mov     x23, x0
1302 +
1303 +        /* Figure out if we should touch the vector registers.  */
1304 +        tbz     x23, #AARCH64_FFI_WITH_V_BIT, 1f
1305 +
1306 +        /* Load the vector argument passing registers.  */
1307 +        ldp     q0, q1, [x21, #8*32 +  0]
1308 +        ldp     q2, q3, [x21, #8*32 + 32]
1309 +        ldp     q4, q5, [x21, #8*32 + 64]
1310 +        ldp     q6, q7, [x21, #8*32 + 96]
1311 +1:
1312 +        /* Load the core argument passing registers.  */
1313 +        ldp     x0, x1, [x21,  #0]
1314 +        ldp     x2, x3, [x21, #16]
1315 +        ldp     x4, x5, [x21, #32]
1316 +        ldp     x6, x7, [x21, #48]
1317 +
1318 +        /* Don't forget x8 which may be holding the address of a return buffer.
1319 +        */
1320 +        ldr     x8,     [x21, #8*8]
1321 +
1322 +        blr     x24
1323 +
1324 +        /* Save the core argument passing registers.  */
1325 +        stp     x0, x1, [x21,  #0]
1326 +        stp     x2, x3, [x21, #16]
1327 +        stp     x4, x5, [x21, #32]
1328 +        stp     x6, x7, [x21, #48]
1329 +
1330 +        /* Note nothing useful ever comes back in x8!  */
1331 +
1332 +        /* Figure out if we should touch the vector registers.  */
1333 +        tbz     x23, #AARCH64_FFI_WITH_V_BIT, 1f
1334 +
1335 +        /* Save the vector argument passing registers.  */
1336 +        stp     q0, q1, [x21, #8*32 + 0]
1337 +        stp     q2, q3, [x21, #8*32 + 32]
1338 +        stp     q4, q5, [x21, #8*32 + 64]
1339 +        stp     q6, q7, [x21, #8*32 + 96]
1340 +1:
1341 +        /* All done, unwind our stack frame.  */
1342 +        ldp     x21, x22, [x29,  # - ffi_call_SYSV_FS]
1343 +        cfi_restore (x21)
1344 +        cfi_restore (x22)
1345 +
1346 +        ldp     x23, x24, [x29,  # - ffi_call_SYSV_FS + 16]
1347 +        cfi_restore (x23)
1348 +        cfi_restore (x24)
1349 +
1350 +        mov     sp, x29
1351 +       cfi_def_cfa_register (sp)
1352 +
1353 +        ldp     x29, x30, [sp], #16
1354 +       cfi_adjust_cfa_offset (-16)
1355 +        cfi_restore (x29)
1356 +        cfi_restore (x30)
1357 +
1358 +        ret
1359 +
1360 +        .cfi_endproc
1361 +        .size ffi_call_SYSV, .-ffi_call_SYSV
1362 +
1363 +#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE)
1364 +
1365 +/* ffi_closure_SYSV
1366 +
1367 +   Closure invocation glue. This is the low level code invoked directly by
1368 +   the closure trampoline to setup and call a closure.
1369 +
1370 +   On entry x17 points to a struct trampoline_data, x16 has been clobbered
1371 +   all other registers are preserved.
1372 +
1373 +   We allocate a call context and save the argument passing registers,
1374 +   then invoked the generic C ffi_closure_SYSV_inner() function to do all
1375 +   the real work, on return we load the result passing registers back from
1376 +   the call context.
1377 +
1378 +   On entry
1379 +
1380 +   extern void
1381 +   ffi_closure_SYSV (struct trampoline_data *);
1382 +
1383 +   struct trampoline_data
1384 +   {
1385 +        UINT64 *ffi_closure;
1386 +        UINT64 flags;
1387 +   };
1388 +
1389 +   This function uses the following stack frame layout:
1390 +
1391 +   ==
1392 +                saved x30(lr)
1393 +   x29(fp)->    saved x29(fp)
1394 +                saved x22
1395 +                saved x21
1396 +                ...
1397 +   sp     ->    call_context
1398 +   ==
1399 +
1400 +   Voila!  */
1401 +
1402 +        .text
1403 +        .globl ffi_closure_SYSV
1404 +        .cfi_startproc
1405 +ffi_closure_SYSV:
1406 +        stp     x29, x30, [sp, #-16]!
1407 +       cfi_adjust_cfa_offset (16)
1408 +        cfi_rel_offset (x29, 0)
1409 +        cfi_rel_offset (x30, 8)
1410 +
1411 +        mov     x29, sp
1412 +
1413 +        sub     sp, sp, #ffi_closure_SYSV_FS
1414 +       cfi_adjust_cfa_offset (ffi_closure_SYSV_FS)
1415 +
1416 +        stp     x21, x22, [x29, #-16]
1417 +        cfi_rel_offset (x21, 0)
1418 +        cfi_rel_offset (x22, 8)
1419 +
1420 +        /* Load x21 with &call_context.  */
1421 +        mov     x21, sp
1422 +        /* Preserve our struct trampoline_data *  */
1423 +        mov     x22, x17
1424 +
1425 +        /* Save the rest of the argument passing registers.  */
1426 +        stp     x0, x1, [x21, #0]
1427 +        stp     x2, x3, [x21, #16]
1428 +        stp     x4, x5, [x21, #32]
1429 +        stp     x6, x7, [x21, #48]
1430 +        /* Don't forget we may have been given a result scratch pad address.
1431 +        */
1432 +        str     x8,     [x21, #64]
1433 +
1434 +        /* Figure out if we should touch the vector registers.  */
1435 +        ldr     x0, [x22, #8]
1436 +        tbz     x0, #AARCH64_FFI_WITH_V_BIT, 1f
1437 +
1438 +        /* Save the argument passing vector registers.  */
1439 +        stp     q0, q1, [x21, #8*32 + 0]
1440 +        stp     q2, q3, [x21, #8*32 + 32]
1441 +        stp     q4, q5, [x21, #8*32 + 64]
1442 +        stp     q6, q7, [x21, #8*32 + 96]
1443 +1:
1444 +        /* Load &ffi_closure..  */
1445 +        ldr     x0, [x22, #0]
1446 +        mov     x1, x21
1447 +        /* Compute the location of the stack at the point that the
1448 +           trampoline was called.  */
1449 +        add     x2, x29, #16
1450 +
1451 +        bl      ffi_closure_SYSV_inner
1452 +
1453 +        /* Figure out if we should touch the vector registers.  */
1454 +        ldr     x0, [x22, #8]
1455 +        tbz     x0, #AARCH64_FFI_WITH_V_BIT, 1f
1456 +
1457 +        /* Load the result passing vector registers.  */
1458 +        ldp     q0, q1, [x21, #8*32 + 0]
1459 +        ldp     q2, q3, [x21, #8*32 + 32]
1460 +        ldp     q4, q5, [x21, #8*32 + 64]
1461 +        ldp     q6, q7, [x21, #8*32 + 96]
1462 +1:
1463 +        /* Load the result passing core registers.  */
1464 +        ldp     x0, x1, [x21,  #0]
1465 +        ldp     x2, x3, [x21, #16]
1466 +        ldp     x4, x5, [x21, #32]
1467 +        ldp     x6, x7, [x21, #48]
1468 +        /* Note nothing usefull is returned in x8.  */
1469 +
1470 +        /* We are done, unwind our frame.  */
1471 +        ldp     x21, x22, [x29,  #-16]
1472 +        cfi_restore (x21)
1473 +        cfi_restore (x22)
1474 +
1475 +        mov     sp, x29
1476 +       cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS)
1477 +
1478 +        ldp     x29, x30, [sp], #16
1479 +       cfi_adjust_cfa_offset (-16)
1480 +        cfi_restore (x29)
1481 +        cfi_restore (x30)
1482 +
1483 +        ret
1484 +        .cfi_endproc
1485 +        .size ffi_closure_SYSV, .-ffi_closure_SYSV
1486 Index: libffi/testsuite/lib/libffi.exp
1487 ===================================================================
1488 --- libffi.orig/testsuite/lib/libffi.exp
1489 +++ libffi/testsuite/lib/libffi.exp
1490 @@ -203,6 +203,10 @@ proc libffi_target_compile { source dest
1491  
1492      lappend options "libs= -lffi"
1493  
1494 +    if { [string match "aarch64*-*-linux*" $target_triplet] } {
1495 +       lappend options "libs= -lpthread"
1496 +    }
1497 +
1498      verbose "options: $options"
1499      return [target_compile $source $dest $type $options]
1500  }
1501 Index: libffi/testsuite/libffi.call/cls_struct_va1.c
1502 ===================================================================
1503 --- /dev/null
1504 +++ libffi/testsuite/libffi.call/cls_struct_va1.c
1505 @@ -0,0 +1,114 @@
1506 +/* Area:               ffi_call, closure_call
1507 +   Purpose:            Test doubles passed in variable argument lists.
1508 +   Limitations:        none.
1509 +   PR:                 none.
1510 +   Originator: Blake Chaffin 6/6/2007   */
1511 +
1512 +/* { dg-do run } */
1513 +/* { dg-output "" { xfail avr32*-*-* } } */
1514 +#include "ffitest.h"
1515 +
1516 +struct small_tag
1517 +{
1518 +  unsigned char a;
1519 +  unsigned char b;
1520 +};
1521 +
1522 +struct large_tag
1523 +{
1524 +  unsigned a;
1525 +  unsigned b;
1526 +  unsigned c;
1527 +  unsigned d;
1528 +  unsigned e;
1529 +};
1530 +
1531 +static void
1532 +test_fn (ffi_cif* cif __UNUSED__, void* resp,
1533 +        void** args, void* userdata __UNUSED__)
1534 +{
1535 +  int n = *(int*)args[0];
1536 +  struct small_tag s1 = * (struct small_tag *) args[1];
1537 +  struct large_tag l1 = * (struct large_tag *) args[2];
1538 +  struct small_tag s2 = * (struct small_tag *) args[3];
1539 +
1540 +  printf ("%d %d %d %d %d %d %d %d %d %d\n", n, s1.a, s1.b,
1541 +         l1.a, l1.b, l1.c, l1.d, l1.e,
1542 +         s2.a, s2.b);
1543 +  * (int*) resp = 42;
1544 +}
1545 +
1546 +int
1547 +main (void)
1548 +{
1549 +  ffi_cif cif;
1550 +  void *code;
1551 +  ffi_closure *pcl = ffi_closure_alloc (sizeof (ffi_closure), &code);
1552 +  ffi_type* arg_types[5];
1553 +
1554 +  ffi_arg res = 0;
1555 +
1556 +  ffi_type s_type;
1557 +  ffi_type *s_type_elements[3];
1558 +
1559 +  ffi_type l_type;
1560 +  ffi_type *l_type_elements[6];
1561 +
1562 +  struct small_tag s1;
1563 +  struct small_tag s2;
1564 +  struct large_tag l1;
1565 +
1566 +  int si;
1567 +
1568 +  s_type.size = 0;
1569 +  s_type.alignment = 0;
1570 +  s_type.type = FFI_TYPE_STRUCT;
1571 +  s_type.elements = s_type_elements;
1572 +
1573 +  s_type_elements[0] = &ffi_type_uchar;
1574 +  s_type_elements[1] = &ffi_type_uchar;
1575 +  s_type_elements[2] = NULL;
1576 +
1577 +  l_type.size = 0;
1578 +  l_type.alignment = 0;
1579 +  l_type.type = FFI_TYPE_STRUCT;
1580 +  l_type.elements = l_type_elements;
1581 +
1582 +  l_type_elements[0] = &ffi_type_uint;
1583 +  l_type_elements[1] = &ffi_type_uint;
1584 +  l_type_elements[2] = &ffi_type_uint;
1585 +  l_type_elements[3] = &ffi_type_uint;
1586 +  l_type_elements[4] = &ffi_type_uint;
1587 +  l_type_elements[5] = NULL;
1588 +
1589 +  arg_types[0] = &ffi_type_sint;
1590 +  arg_types[1] = &s_type;
1591 +  arg_types[2] = &l_type;
1592 +  arg_types[3] = &s_type;
1593 +  arg_types[4] = NULL;
1594 +
1595 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint,
1596 +                        arg_types) == FFI_OK);
1597 +
1598 +  si = 4;
1599 +  s1.a = 5;
1600 +  s1.b = 6;
1601 +
1602 +  s2.a = 20;
1603 +  s2.b = 21;
1604 +
1605 +  l1.a = 10;
1606 +  l1.b = 11;
1607 +  l1.c = 12;
1608 +  l1.d = 13;
1609 +  l1.e = 14;
1610 +
1611 +  CHECK(ffi_prep_closure_loc(pcl, &cif, test_fn, NULL, code) == FFI_OK);
1612 +
1613 +  res = ((int (*)(int, ...))(code))(si, s1, l1, s2);
1614 +  // { dg-output "4 5 6 10 11 12 13 14 20 21" }
1615 +  printf("res: %d\n", (int) res);
1616 +  // { dg-output "\nres: 42" }
1617 +
1618 +  exit(0);
1619 +}
1620 Index: libffi/testsuite/libffi.call/cls_uchar_va.c
1621 ===================================================================
1622 --- /dev/null
1623 +++ libffi/testsuite/libffi.call/cls_uchar_va.c
1624 @@ -0,0 +1,44 @@
1625 +/* Area:       closure_call
1626 +   Purpose:    Test anonymous unsigned char argument.
1627 +   Limitations:        none.
1628 +   PR:         none.
1629 +   Originator: ARM Ltd. */
1630 +
1631 +/* { dg-do run } */
1632 +#include "ffitest.h"
1633 +
1634 +typedef unsigned char T;
1635 +
1636 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1637 +                        void* userdata __UNUSED__)
1638 + {
1639 +   *(T *)resp = *(T *)args[0];
1640 +
1641 +   printf("%d: %d %d\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1642 + }
1643 +
1644 +typedef T (*cls_ret_T)(T, ...);
1645 +
1646 +int main (void)
1647 +{
1648 +  ffi_cif cif;
1649 +  void *code;
1650 +  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1651 +  ffi_type * cl_arg_types[3];
1652 +  T res;
1653 +
1654 +  cl_arg_types[0] = &ffi_type_uchar;
1655 +  cl_arg_types[1] = &ffi_type_uchar;
1656 +  cl_arg_types[2] = NULL;
1657 +
1658 +  /* Initialize the cif */
1659 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1660 +                        &ffi_type_uchar, cl_arg_types) == FFI_OK);
1661 +
1662 +  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
1663 +  res = ((((cls_ret_T)code)(67, 4)));
1664 +  /* { dg-output "67: 67 4" } */
1665 +  printf("res: %d\n", res);
1666 +  /* { dg-output "\nres: 67" } */
1667 +  exit(0);
1668 +}
1669 Index: libffi/testsuite/libffi.call/cls_uint_va.c
1670 ===================================================================
1671 --- /dev/null
1672 +++ libffi/testsuite/libffi.call/cls_uint_va.c
1673 @@ -0,0 +1,45 @@
1674 +/* Area:       closure_call
1675 +   Purpose:    Test anonymous unsigned int argument.
1676 +   Limitations:        none.
1677 +   PR:         none.
1678 +   Originator: ARM Ltd. */
1679 +
1680 +/* { dg-do run } */
1681 +
1682 +#include "ffitest.h"
1683 +
1684 +typedef unsigned int T;
1685 +
1686 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1687 +                        void* userdata __UNUSED__)
1688 + {
1689 +   *(T *)resp = *(T *)args[0];
1690 +
1691 +   printf("%d: %d %d\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1692 + }
1693 +
1694 +typedef T (*cls_ret_T)(T, ...);
1695 +
1696 +int main (void)
1697 +{
1698 +  ffi_cif cif;
1699 +  void *code;
1700 +  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1701 +  ffi_type * cl_arg_types[3];
1702 +  T res;
1703 +
1704 +  cl_arg_types[0] = &ffi_type_uint;
1705 +  cl_arg_types[1] = &ffi_type_uint;
1706 +  cl_arg_types[2] = NULL;
1707 +
1708 +  /* Initialize the cif */
1709 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1710 +                        &ffi_type_uint, cl_arg_types) == FFI_OK);
1711 +
1712 +  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
1713 +  res = ((((cls_ret_T)code)(67, 4)));
1714 +  /* { dg-output "67: 67 4" } */
1715 +  printf("res: %d\n", res);
1716 +  /* { dg-output "\nres: 67" } */
1717 +  exit(0);
1718 +}
1719 Index: libffi/testsuite/libffi.call/cls_ulong_va.c
1720 ===================================================================
1721 --- /dev/null
1722 +++ libffi/testsuite/libffi.call/cls_ulong_va.c
1723 @@ -0,0 +1,45 @@
1724 +/* Area:       closure_call
1725 +   Purpose:    Test anonymous unsigned long argument.
1726 +   Limitations:        none.
1727 +   PR:         none.
1728 +   Originator: ARM Ltd. */
1729 +
1730 +/* { dg-do run } */
1731 +
1732 +#include "ffitest.h"
1733 +
1734 +typedef unsigned long T;
1735 +
1736 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1737 +                        void* userdata __UNUSED__)
1738 + {
1739 +   *(T *)resp = *(T *)args[0];
1740 +
1741 +   printf("%ld: %ld %ld\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1742 + }
1743 +
1744 +typedef T (*cls_ret_T)(T, ...);
1745 +
1746 +int main (void)
1747 +{
1748 +  ffi_cif cif;
1749 +  void *code;
1750 +  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1751 +  ffi_type * cl_arg_types[3];
1752 +  T res;
1753 +
1754 +  cl_arg_types[0] = &ffi_type_ulong;
1755 +  cl_arg_types[1] = &ffi_type_ulong;
1756 +  cl_arg_types[2] = NULL;
1757 +
1758 +  /* Initialize the cif */
1759 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1760 +                        &ffi_type_ulong, cl_arg_types) == FFI_OK);
1761 +
1762 +  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
1763 +  res = ((((cls_ret_T)code)(67, 4)));
1764 +  /* { dg-output "67: 67 4" } */
1765 +  printf("res: %ld\n", res);
1766 +  /* { dg-output "\nres: 67" } */
1767 +  exit(0);
1768 +}
1769 Index: libffi/testsuite/libffi.call/cls_ushort_va.c
1770 ===================================================================
1771 --- /dev/null
1772 +++ libffi/testsuite/libffi.call/cls_ushort_va.c
1773 @@ -0,0 +1,44 @@
1774 +/* Area:       closure_call
1775 +   Purpose:    Test anonymous unsigned short argument.
1776 +   Limitations:        none.
1777 +   PR:         none.
1778 +   Originator: ARM Ltd. */
1779 +
1780 +/* { dg-do run } */
1781 +#include "ffitest.h"
1782 +
1783 +typedef unsigned short T;
1784 +
1785 +static void cls_ret_T_fn(ffi_cif* cif __UNUSED__, void* resp, void** args,
1786 +                        void* userdata __UNUSED__)
1787 + {
1788 +   *(T *)resp = *(T *)args[0];
1789 +
1790 +   printf("%d: %d %d\n", *(T *)resp, *(T *)args[0], *(T *)args[1]);
1791 + }
1792 +
1793 +typedef T (*cls_ret_T)(T, ...);
1794 +
1795 +int main (void)
1796 +{
1797 +  ffi_cif cif;
1798 +  void *code;
1799 +  ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);
1800 +  ffi_type * cl_arg_types[3];
1801 +  T res;
1802 +
1803 +  cl_arg_types[0] = &ffi_type_ushort;
1804 +  cl_arg_types[1] = &ffi_type_ushort;
1805 +  cl_arg_types[2] = NULL;
1806 +
1807 +  /* Initialize the cif */
1808 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 2,
1809 +                        &ffi_type_ushort, cl_arg_types) == FFI_OK);
1810 +
1811 +  CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_T_fn, NULL, code)  == FFI_OK);
1812 +  res = ((((cls_ret_T)code)(67, 4)));
1813 +  /* { dg-output "67: 67 4" } */
1814 +  printf("res: %d\n", res);
1815 +  /* { dg-output "\nres: 67" } */
1816 +  exit(0);
1817 +}
1818 Index: libffi/testsuite/libffi.call/nested_struct11.c
1819 ===================================================================
1820 --- /dev/null
1821 +++ libffi/testsuite/libffi.call/nested_struct11.c
1822 @@ -0,0 +1,121 @@
1823 +/* Area:       ffi_call, closure_call
1824 +   Purpose:    Check parameter passing with nested structs
1825 +               of a single type.  This tests the special cases
1826 +               for homogenous floating-point aggregates in the
1827 +               AArch64 PCS.
1828 +   Limitations:        none.
1829 +   PR:         none.
1830 +   Originator:  ARM Ltd.  */
1831 +
1832 +/* { dg-do run } */
1833 +#include "ffitest.h"
1834 +
1835 +typedef struct A {
1836 +  float a_x;
1837 +  float a_y;
1838 +} A;
1839 +
1840 +typedef struct B {
1841 +  float b_x;
1842 +  float b_y;
1843 +} B;
1844 +
1845 +typedef struct C {
1846 +  A a;
1847 +  B b;
1848 +} C;
1849 +
1850 +static C C_fn (int x, int y, int z, C source, int i, int j, int k)
1851 +{
1852 +  C result;
1853 +  result.a.a_x = source.a.a_x;
1854 +  result.a.a_y = source.a.a_y;
1855 +  result.b.b_x = source.b.b_x;
1856 +  result.b.b_y = source.b.b_y;
1857 +
1858 +  printf ("%d, %d, %d, %d, %d, %d\n", x, y, z, i, j, k);
1859 +
1860 +  printf ("%.1f, %.1f, %.1f, %.1f, "
1861 +         "%.1f, %.1f, %.1f, %.1f\n",
1862 +         source.a.a_x, source.a.a_y,
1863 +         source.b.b_x, source.b.b_y,
1864 +         result.a.a_x, result.a.a_y,
1865 +         result.b.b_x, result.b.b_y);
1866 +
1867 +  return result;
1868 +}
1869 +
1870 +int main (void)
1871 +{
1872 +  ffi_cif cif;
1873 +
1874 +  ffi_type* struct_fields_source_a[3];
1875 +  ffi_type* struct_fields_source_b[3];
1876 +  ffi_type* struct_fields_source_c[3];
1877 +  ffi_type* arg_types[8];
1878 +
1879 +  ffi_type struct_type_a, struct_type_b, struct_type_c;
1880 +
1881 +  struct A source_fld_a = {1.0, 2.0};
1882 +  struct B source_fld_b = {4.0, 8.0};
1883 +  int k = 1;
1884 +
1885 +  struct C result;
1886 +  struct C source = {source_fld_a, source_fld_b};
1887 +
1888 +  struct_type_a.size = 0;
1889 +  struct_type_a.alignment = 0;
1890 +  struct_type_a.type = FFI_TYPE_STRUCT;
1891 +  struct_type_a.elements = struct_fields_source_a;
1892 +
1893 +  struct_type_b.size = 0;
1894 +  struct_type_b.alignment = 0;
1895 +  struct_type_b.type = FFI_TYPE_STRUCT;
1896 +  struct_type_b.elements = struct_fields_source_b;
1897 +
1898 +  struct_type_c.size = 0;
1899 +  struct_type_c.alignment = 0;
1900 +  struct_type_c.type = FFI_TYPE_STRUCT;
1901 +  struct_type_c.elements = struct_fields_source_c;
1902 +
1903 +  struct_fields_source_a[0] = &ffi_type_float;
1904 +  struct_fields_source_a[1] = &ffi_type_float;
1905 +  struct_fields_source_a[2] = NULL;
1906 +
1907 +  struct_fields_source_b[0] = &ffi_type_float;
1908 +  struct_fields_source_b[1] = &ffi_type_float;
1909 +  struct_fields_source_b[2] = NULL;
1910 +
1911 +  struct_fields_source_c[0] = &struct_type_a;
1912 +  struct_fields_source_c[1] = &struct_type_b;
1913 +  struct_fields_source_c[2] = NULL;
1914 +
1915 +  arg_types[0] = &ffi_type_sint32;
1916 +  arg_types[1] = &ffi_type_sint32;
1917 +  arg_types[2] = &ffi_type_sint32;
1918 +  arg_types[3] = &struct_type_c;
1919 +  arg_types[4] = &ffi_type_sint32;
1920 +  arg_types[5] = &ffi_type_sint32;
1921 +  arg_types[6] = &ffi_type_sint32;
1922 +  arg_types[7] = NULL;
1923 +
1924 +  void *args[7];
1925 +  args[0] = &k;
1926 +  args[1] = &k;
1927 +  args[2] = &k;
1928 +  args[3] = &source;
1929 +  args[4] = &k;
1930 +  args[5] = &k;
1931 +  args[6] = &k;
1932 +  CHECK (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, 7, &struct_type_c,
1933 +                      arg_types) == FFI_OK);
1934 +
1935 +  ffi_call (&cif, FFI_FN (C_fn), &result, args);
1936 +  /* { dg-output "1, 1, 1, 1, 1, 1\n" } */
1937 +  /* { dg-output "1.0, 2.0, 4.0, 8.0, 1.0, 2.0, 4.0, 8.0" } */
1938 +  CHECK (result.a.a_x == source.a.a_x);
1939 +  CHECK (result.a.a_y == source.a.a_y);
1940 +  CHECK (result.b.b_x == source.b.b_x);
1941 +  CHECK (result.b.b_y == source.b.b_y);
1942 +  exit (0);
1943 +}
1944 Index: libffi/testsuite/libffi.call/uninitialized.c
1945 ===================================================================
1946 --- /dev/null
1947 +++ libffi/testsuite/libffi.call/uninitialized.c
1948 @@ -0,0 +1,61 @@
1949 +/* { dg-do run } */
1950 +#include "ffitest.h"
1951 +
1952 +typedef struct
1953 +{
1954 +  unsigned char uc;
1955 +  double d;
1956 +  unsigned int ui;
1957 +} test_structure_1;
1958 +
1959 +static test_structure_1 struct1(test_structure_1 ts)
1960 +{
1961 +  ts.uc++;
1962 +  ts.d--;
1963 +  ts.ui++;
1964 +
1965 +  return ts;
1966 +}
1967 +
1968 +int main (void)
1969 +{
1970 +  ffi_cif cif;
1971 +  ffi_type *args[MAX_ARGS];
1972 +  void *values[MAX_ARGS];
1973 +  ffi_type ts1_type;
1974 +  ffi_type *ts1_type_elements[4];
1975 +
1976 +  memset(&cif, 1, sizeof(cif));
1977 +  ts1_type.size = 0;
1978 +  ts1_type.alignment = 0;
1979 +  ts1_type.type = FFI_TYPE_STRUCT;
1980 +  ts1_type.elements = ts1_type_elements;
1981 +  ts1_type_elements[0] = &ffi_type_uchar;
1982 +  ts1_type_elements[1] = &ffi_type_double;
1983 +  ts1_type_elements[2] = &ffi_type_uint;
1984 +  ts1_type_elements[3] = NULL;
1985 +
1986 +  test_structure_1 ts1_arg;
1987 +  /* This is a hack to get a properly aligned result buffer */
1988 +  test_structure_1 *ts1_result =
1989 +    (test_structure_1 *) malloc (sizeof(test_structure_1));
1990 +
1991 +  args[0] = &ts1_type;
1992 +  values[0] = &ts1_arg;
1993 +
1994 +  /* Initialize the cif */
1995 +  CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
1996 +                    &ts1_type, args) == FFI_OK);
1997 +
1998 +  ts1_arg.uc = '\x01';
1999 +  ts1_arg.d = 3.14159;
2000 +  ts1_arg.ui = 555;
2001 +
2002 +  ffi_call(&cif, FFI_FN(struct1), ts1_result, values);
2003 +
2004 +  CHECK(ts1_result->ui == 556);
2005 +  CHECK(ts1_result->d == 3.14159 - 1);
2006 +
2007 +  free (ts1_result);
2008 +  exit(0);
2009 +}
2010 Index: libffi/testsuite/libffi.call/va_1.c
2011 ===================================================================
2012 --- /dev/null
2013 +++ libffi/testsuite/libffi.call/va_1.c
2014 @@ -0,0 +1,196 @@
2015 +/* Area:               ffi_call
2016 +   Purpose:            Test passing struct in variable argument lists.
2017 +   Limitations:        none.
2018 +   PR:                 none.
2019 +   Originator:         ARM Ltd. */
2020 +
2021 +/* { dg-do run } */
2022 +/* { dg-output "" { xfail avr32*-*-* x86_64-*-*-* } } */
2023 +
2024 +#include "ffitest.h"
2025 +#include <stdarg.h>
2026 +
2027 +struct small_tag
2028 +{
2029 +  unsigned char a;
2030 +  unsigned char b;
2031 +};
2032 +
2033 +struct large_tag
2034 +{
2035 +  unsigned a;
2036 +  unsigned b;
2037 +  unsigned c;
2038 +  unsigned d;
2039 +  unsigned e;
2040 +};
2041 +
2042 +static int
2043 +test_fn (int n, ...)
2044 +{
2045 +  va_list ap;
2046 +  struct small_tag s1;
2047 +  struct small_tag s2;
2048 +  struct large_tag l;
2049 +  unsigned char uc;
2050 +  signed char sc;
2051 +  unsigned short us;
2052 +  signed short ss;
2053 +  unsigned int ui;
2054 +  signed int si;
2055 +  unsigned long ul;
2056 +  signed long sl;
2057 +  float f;
2058 +  double d;
2059 +
2060 +  va_start (ap, n);
2061 +  s1 = va_arg (ap, struct small_tag);
2062 +  l = va_arg (ap, struct large_tag);
2063 +  s2 = va_arg (ap, struct small_tag);
2064 +
2065 +  uc = va_arg (ap, unsigned);
2066 +  sc = va_arg (ap, signed);
2067 +
2068 +  us = va_arg (ap, unsigned);
2069 +  ss = va_arg (ap, signed);
2070 +
2071 +  ui = va_arg (ap, unsigned int);
2072 +  si = va_arg (ap, signed int);
2073 +
2074 +  ul = va_arg (ap, unsigned long);
2075 +  sl = va_arg (ap, signed long);
2076 +
2077 +  f = va_arg (ap, double);     /* C standard promotes float->double
2078 +                                  when anonymous */
2079 +  d = va_arg (ap, double);
2080 +
2081 +  printf ("%u %u %u %u %u %u %u %u %u uc=%u sc=%d %u %d %u %d %lu %ld %f %f\n",
2082 +         s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2083 +         s2.a, s2.b,
2084 +         uc, sc,
2085 +         us, ss,
2086 +         ui, si,
2087 +         ul, sl,
2088 +         f, d);
2089 +  va_end (ap);
2090 +  return n + 1;
2091 +}
2092 +
2093 +int
2094 +main (void)
2095 +{
2096 +  ffi_cif cif;
2097 +  void* args[15];
2098 +  ffi_type* arg_types[15];
2099 +
2100 +  ffi_type s_type;
2101 +  ffi_type *s_type_elements[3];
2102 +
2103 +  ffi_type l_type;
2104 +  ffi_type *l_type_elements[6];
2105 +
2106 +  struct small_tag s1;
2107 +  struct small_tag s2;
2108 +  struct large_tag l1;
2109 +
2110 +  int n;
2111 +  int res;
2112 +
2113 +  unsigned char uc;
2114 +  signed char sc;
2115 +  unsigned short us;
2116 +  signed short ss;
2117 +  unsigned int ui;
2118 +  signed int si;
2119 +  unsigned long ul;
2120 +  signed long sl;
2121 +  double d1;
2122 +  double f1;
2123 +
2124 +  s_type.size = 0;
2125 +  s_type.alignment = 0;
2126 +  s_type.type = FFI_TYPE_STRUCT;
2127 +  s_type.elements = s_type_elements;
2128 +
2129 +  s_type_elements[0] = &ffi_type_uchar;
2130 +  s_type_elements[1] = &ffi_type_uchar;
2131 +  s_type_elements[2] = NULL;
2132 +
2133 +  l_type.size = 0;
2134 +  l_type.alignment = 0;
2135 +  l_type.type = FFI_TYPE_STRUCT;
2136 +  l_type.elements = l_type_elements;
2137 +
2138 +  l_type_elements[0] = &ffi_type_uint;
2139 +  l_type_elements[1] = &ffi_type_uint;
2140 +  l_type_elements[2] = &ffi_type_uint;
2141 +  l_type_elements[3] = &ffi_type_uint;
2142 +  l_type_elements[4] = &ffi_type_uint;
2143 +  l_type_elements[5] = NULL;
2144 +
2145 +  arg_types[0] = &ffi_type_sint;
2146 +  arg_types[1] = &s_type;
2147 +  arg_types[2] = &l_type;
2148 +  arg_types[3] = &s_type;
2149 +  arg_types[4] = &ffi_type_uint;
2150 +  arg_types[5] = &ffi_type_sint;
2151 +  arg_types[6] = &ffi_type_uint;
2152 +  arg_types[7] = &ffi_type_sint;
2153 +  arg_types[8] = &ffi_type_uint;
2154 +  arg_types[9] = &ffi_type_sint;
2155 +  arg_types[10] = &ffi_type_ulong;
2156 +  arg_types[11] = &ffi_type_slong;
2157 +  arg_types[12] = &ffi_type_double;
2158 +  arg_types[13] = &ffi_type_double;
2159 +  arg_types[14] = NULL;
2160 +
2161 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 14, &ffi_type_sint, arg_types) == FFI_OK);
2162 +
2163 +  s1.a = 5;
2164 +  s1.b = 6;
2165 +
2166 +  l1.a = 10;
2167 +  l1.b = 11;
2168 +  l1.c = 12;
2169 +  l1.d = 13;
2170 +  l1.e = 14;
2171 +
2172 +  s2.a = 7;
2173 +  s2.b = 8;
2174 +
2175 +  n = 41;
2176 +
2177 +  uc = 9;
2178 +  sc = 10;
2179 +  us = 11;
2180 +  ss = 12;
2181 +  ui = 13;
2182 +  si = 14;
2183 +  ul = 15;
2184 +  sl = 16;
2185 +  f1 = 2.12;
2186 +  d1 = 3.13;
2187 +
2188 +  args[0] = &n;
2189 +  args[1] = &s1;
2190 +  args[2] = &l1;
2191 +  args[3] = &s2;
2192 +  args[4] = &uc;
2193 +  args[5] = &sc;
2194 +  args[6] = &us;
2195 +  args[7] = &ss;
2196 +  args[8] = &ui;
2197 +  args[9] = &si;
2198 +  args[10] = &ul;
2199 +  args[11] = &sl;
2200 +  args[12] = &f1;
2201 +  args[13] = &d1;
2202 +  args[14] = NULL;
2203 +
2204 +  ffi_call(&cif, FFI_FN(test_fn), &res, args);
2205 +  /* { dg-output "5 6 10 11 12 13 14 7 8 uc=9 sc=10 11 12 13 14 15 16 2.120000 3.130000" } */
2206 +  printf("res: %d\n", (int) res);
2207 +  /* { dg-output "\nres: 42" } */
2208 +
2209 +  return 0;
2210 +}
2211 Index: libffi/testsuite/libffi.call/va_struct1.c
2212 ===================================================================
2213 --- /dev/null
2214 +++ libffi/testsuite/libffi.call/va_struct1.c
2215 @@ -0,0 +1,121 @@
2216 +/* Area:               ffi_call
2217 +   Purpose:            Test passing struct in variable argument lists.
2218 +   Limitations:        none.
2219 +   PR:                 none.
2220 +   Originator: ARM Ltd. */
2221 +
2222 +/* { dg-do run } */
2223 +/* { dg-output "" { xfail avr32*-*-* } } */
2224 +
2225 +#include "ffitest.h"
2226 +#include <stdarg.h>
2227 +
2228 +struct small_tag
2229 +{
2230 +  unsigned char a;
2231 +  unsigned char b;
2232 +};
2233 +
2234 +struct large_tag
2235 +{
2236 +  unsigned a;
2237 +  unsigned b;
2238 +  unsigned c;
2239 +  unsigned d;
2240 +  unsigned e;
2241 +};
2242 +
2243 +static int
2244 +test_fn (int n, ...)
2245 +{
2246 +  va_list ap;
2247 +  struct small_tag s1;
2248 +  struct small_tag s2;
2249 +  struct large_tag l;
2250 +
2251 +  va_start (ap, n);
2252 +  s1 = va_arg (ap, struct small_tag);
2253 +  l = va_arg (ap, struct large_tag);
2254 +  s2 = va_arg (ap, struct small_tag);
2255 +  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2256 +         s2.a, s2.b);
2257 +  va_end (ap);
2258 +  return n + 1;
2259 +}
2260 +
2261 +int
2262 +main (void)
2263 +{
2264 +  ffi_cif cif;
2265 +  void* args[5];
2266 +  ffi_type* arg_types[5];
2267 +
2268 +  ffi_type s_type;
2269 +  ffi_type *s_type_elements[3];
2270 +
2271 +  ffi_type l_type;
2272 +  ffi_type *l_type_elements[6];
2273 +
2274 +  struct small_tag s1;
2275 +  struct small_tag s2;
2276 +  struct large_tag l1;
2277 +
2278 +  int n;
2279 +  int res;
2280 +
2281 +  s_type.size = 0;
2282 +  s_type.alignment = 0;
2283 +  s_type.type = FFI_TYPE_STRUCT;
2284 +  s_type.elements = s_type_elements;
2285 +
2286 +  s_type_elements[0] = &ffi_type_uchar;
2287 +  s_type_elements[1] = &ffi_type_uchar;
2288 +  s_type_elements[2] = NULL;
2289 +
2290 +  l_type.size = 0;
2291 +  l_type.alignment = 0;
2292 +  l_type.type = FFI_TYPE_STRUCT;
2293 +  l_type.elements = l_type_elements;
2294 +
2295 +  l_type_elements[0] = &ffi_type_uint;
2296 +  l_type_elements[1] = &ffi_type_uint;
2297 +  l_type_elements[2] = &ffi_type_uint;
2298 +  l_type_elements[3] = &ffi_type_uint;
2299 +  l_type_elements[4] = &ffi_type_uint;
2300 +  l_type_elements[5] = NULL;
2301 +
2302 +  arg_types[0] = &ffi_type_sint;
2303 +  arg_types[1] = &s_type;
2304 +  arg_types[2] = &l_type;
2305 +  arg_types[3] = &s_type;
2306 +  arg_types[4] = NULL;
2307 +
2308 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &ffi_type_sint, arg_types) == FFI_OK);
2309 +
2310 +  s1.a = 5;
2311 +  s1.b = 6;
2312 +
2313 +  l1.a = 10;
2314 +  l1.b = 11;
2315 +  l1.c = 12;
2316 +  l1.d = 13;
2317 +  l1.e = 14;
2318 +
2319 +  s2.a = 7;
2320 +  s2.b = 8;
2321 +
2322 +  n = 41;
2323 +
2324 +  args[0] = &n;
2325 +  args[1] = &s1;
2326 +  args[2] = &l1;
2327 +  args[3] = &s2;
2328 +  args[4] = NULL;
2329 +
2330 +  ffi_call(&cif, FFI_FN(test_fn), &res, args);
2331 +  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
2332 +  printf("res: %d\n", (int) res);
2333 +  /* { dg-output "\nres: 42" } */
2334 +
2335 +  return 0;
2336 +}
2337 Index: libffi/testsuite/libffi.call/va_struct2.c
2338 ===================================================================
2339 --- /dev/null
2340 +++ libffi/testsuite/libffi.call/va_struct2.c
2341 @@ -0,0 +1,123 @@
2342 +/* Area:               ffi_call
2343 +   Purpose:            Test passing struct in variable argument lists.
2344 +   Limitations:        none.
2345 +   PR:                 none.
2346 +   Originator: ARM Ltd. */
2347 +
2348 +/* { dg-do run } */
2349 +/* { dg-output "" { xfail avr32*-*-* } } */
2350 +
2351 +#include "ffitest.h"
2352 +#include <stdarg.h>
2353 +
2354 +struct small_tag
2355 +{
2356 +  unsigned char a;
2357 +  unsigned char b;
2358 +};
2359 +
2360 +struct large_tag
2361 +{
2362 +  unsigned a;
2363 +  unsigned b;
2364 +  unsigned c;
2365 +  unsigned d;
2366 +  unsigned e;
2367 +};
2368 +
2369 +static struct small_tag
2370 +test_fn (int n, ...)
2371 +{
2372 +  va_list ap;
2373 +  struct small_tag s1;
2374 +  struct small_tag s2;
2375 +  struct large_tag l;
2376 +
2377 +  va_start (ap, n);
2378 +  s1 = va_arg (ap, struct small_tag);
2379 +  l = va_arg (ap, struct large_tag);
2380 +  s2 = va_arg (ap, struct small_tag);
2381 +  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2382 +         s2.a, s2.b);
2383 +  va_end (ap);
2384 +  s1.a += s2.a;
2385 +  s1.b += s2.b;
2386 +  return s1;
2387 +}
2388 +
2389 +int
2390 +main (void)
2391 +{
2392 +  ffi_cif cif;
2393 +  void* args[5];
2394 +  ffi_type* arg_types[5];
2395 +
2396 +  ffi_type s_type;
2397 +  ffi_type *s_type_elements[3];
2398 +
2399 +  ffi_type l_type;
2400 +  ffi_type *l_type_elements[6];
2401 +
2402 +  struct small_tag s1;
2403 +  struct small_tag s2;
2404 +  struct large_tag l1;
2405 +
2406 +  int n;
2407 +  struct small_tag res;
2408 +
2409 +  s_type.size = 0;
2410 +  s_type.alignment = 0;
2411 +  s_type.type = FFI_TYPE_STRUCT;
2412 +  s_type.elements = s_type_elements;
2413 +
2414 +  s_type_elements[0] = &ffi_type_uchar;
2415 +  s_type_elements[1] = &ffi_type_uchar;
2416 +  s_type_elements[2] = NULL;
2417 +
2418 +  l_type.size = 0;
2419 +  l_type.alignment = 0;
2420 +  l_type.type = FFI_TYPE_STRUCT;
2421 +  l_type.elements = l_type_elements;
2422 +
2423 +  l_type_elements[0] = &ffi_type_uint;
2424 +  l_type_elements[1] = &ffi_type_uint;
2425 +  l_type_elements[2] = &ffi_type_uint;
2426 +  l_type_elements[3] = &ffi_type_uint;
2427 +  l_type_elements[4] = &ffi_type_uint;
2428 +  l_type_elements[5] = NULL;
2429 +
2430 +  arg_types[0] = &ffi_type_sint;
2431 +  arg_types[1] = &s_type;
2432 +  arg_types[2] = &l_type;
2433 +  arg_types[3] = &s_type;
2434 +  arg_types[4] = NULL;
2435 +
2436 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &s_type, arg_types) == FFI_OK);
2437 +
2438 +  s1.a = 5;
2439 +  s1.b = 6;
2440 +
2441 +  l1.a = 10;
2442 +  l1.b = 11;
2443 +  l1.c = 12;
2444 +  l1.d = 13;
2445 +  l1.e = 14;
2446 +
2447 +  s2.a = 7;
2448 +  s2.b = 8;
2449 +
2450 +  n = 41;
2451 +
2452 +  args[0] = &n;
2453 +  args[1] = &s1;
2454 +  args[2] = &l1;
2455 +  args[3] = &s2;
2456 +  args[4] = NULL;
2457 +
2458 +  ffi_call(&cif, FFI_FN(test_fn), &res, args);
2459 +  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
2460 +  printf("res: %d %d\n", res.a, res.b);
2461 +  /* { dg-output "\nres: 12 14" } */
2462 +
2463 +  return 0;
2464 +}
2465 Index: libffi/testsuite/libffi.call/va_struct3.c
2466 ===================================================================
2467 --- /dev/null
2468 +++ libffi/testsuite/libffi.call/va_struct3.c
2469 @@ -0,0 +1,125 @@
2470 +/* Area:               ffi_call
2471 +   Purpose:            Test passing struct in variable argument lists.
2472 +   Limitations:        none.
2473 +   PR:                 none.
2474 +   Originator: ARM Ltd. */
2475 +
2476 +/* { dg-do run } */
2477 +/* { dg-output "" { xfail avr32*-*-* } } */
2478 +
2479 +#include "ffitest.h"
2480 +#include <stdarg.h>
2481 +
2482 +struct small_tag
2483 +{
2484 +  unsigned char a;
2485 +  unsigned char b;
2486 +};
2487 +
2488 +struct large_tag
2489 +{
2490 +  unsigned a;
2491 +  unsigned b;
2492 +  unsigned c;
2493 +  unsigned d;
2494 +  unsigned e;
2495 +};
2496 +
2497 +static struct large_tag
2498 +test_fn (int n, ...)
2499 +{
2500 +  va_list ap;
2501 +  struct small_tag s1;
2502 +  struct small_tag s2;
2503 +  struct large_tag l;
2504 +
2505 +  va_start (ap, n);
2506 +  s1 = va_arg (ap, struct small_tag);
2507 +  l = va_arg (ap, struct large_tag);
2508 +  s2 = va_arg (ap, struct small_tag);
2509 +  printf ("%u %u %u %u %u %u %u %u %u\n", s1.a, s1.b, l.a, l.b, l.c, l.d, l.e,
2510 +         s2.a, s2.b);
2511 +  va_end (ap);
2512 +  l.a += s1.a;
2513 +  l.b += s1.b;
2514 +  l.c += s2.a;
2515 +  l.d += s2.b;
2516 +  return l;
2517 +}
2518 +
2519 +int
2520 +main (void)
2521 +{
2522 +  ffi_cif cif;
2523 +  void* args[5];
2524 +  ffi_type* arg_types[5];
2525 +
2526 +  ffi_type s_type;
2527 +  ffi_type *s_type_elements[3];
2528 +
2529 +  ffi_type l_type;
2530 +  ffi_type *l_type_elements[6];
2531 +
2532 +  struct small_tag s1;
2533 +  struct small_tag s2;
2534 +  struct large_tag l1;
2535 +
2536 +  int n;
2537 +  struct large_tag res;
2538 +
2539 +  s_type.size = 0;
2540 +  s_type.alignment = 0;
2541 +  s_type.type = FFI_TYPE_STRUCT;
2542 +  s_type.elements = s_type_elements;
2543 +
2544 +  s_type_elements[0] = &ffi_type_uchar;
2545 +  s_type_elements[1] = &ffi_type_uchar;
2546 +  s_type_elements[2] = NULL;
2547 +
2548 +  l_type.size = 0;
2549 +  l_type.alignment = 0;
2550 +  l_type.type = FFI_TYPE_STRUCT;
2551 +  l_type.elements = l_type_elements;
2552 +
2553 +  l_type_elements[0] = &ffi_type_uint;
2554 +  l_type_elements[1] = &ffi_type_uint;
2555 +  l_type_elements[2] = &ffi_type_uint;
2556 +  l_type_elements[3] = &ffi_type_uint;
2557 +  l_type_elements[4] = &ffi_type_uint;
2558 +  l_type_elements[5] = NULL;
2559 +
2560 +  arg_types[0] = &ffi_type_sint;
2561 +  arg_types[1] = &s_type;
2562 +  arg_types[2] = &l_type;
2563 +  arg_types[3] = &s_type;
2564 +  arg_types[4] = NULL;
2565 +
2566 +  CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 4, &l_type, arg_types) == FFI_OK);
2567 +
2568 +  s1.a = 5;
2569 +  s1.b = 6;
2570 +
2571 +  l1.a = 10;
2572 +  l1.b = 11;
2573 +  l1.c = 12;
2574 +  l1.d = 13;
2575 +  l1.e = 14;
2576 +
2577 +  s2.a = 7;
2578 +  s2.b = 8;
2579 +
2580 +  n = 41;
2581 +
2582 +  args[0] = &n;
2583 +  args[1] = &s1;
2584 +  args[2] = &l1;
2585 +  args[3] = &s2;
2586 +  args[4] = NULL;
2587 +
2588 +  ffi_call(&cif, FFI_FN(test_fn), &res, args);
2589 +  /* { dg-output "5 6 10 11 12 13 14 7 8" } */
2590 +  printf("res: %d %d %d %d %d\n", res.a, res.b, res.c, res.d, res.e);
2591 +  /* { dg-output "\nres: 15 17 19 21 14" } */
2592 +
2593 +  return 0;
2594 +}
2595 Index: libffi/ChangeLog
2596 ===================================================================
2597 --- libffi.orig/ChangeLog
2598 +++ libffi/ChangeLog
2599 @@ -1,3 +1,27 @@
2600 +2012-10-30  James Greenhalgh  <james.greenhalgh at arm.com>
2601 +            Marcus Shawcroft  <marcus.shawcroft at arm.com>
2602 +
2603 +        * README: Add details of aarch64 port.
2604 +        * src/aarch64/ffi.c: New.
2605 +        * src/aarch64/ffitarget.h: Likewise.
2606 +        * src/aarch64/sysv.S: Likewise.
2607 +
2608 +2012-10-30  James Greenhalgh  <james.greenhalgh at arm.com>
2609 +            Marcus Shawcroft  <marcus.shawcroft at arm.com>
2610 +
2611 +        * testsuite/lib/libffi.exp: Add support for aarch64.
2612 +        * testsuite/libffi.call/cls_struct_va1.c: New.
2613 +        * testsuite/libffi.call/cls_uchar_va.c: Likewise.
2614 +        * testsuite/libffi.call/cls_uint_va.c: Likewise.
2615 +        * testsuite/libffi.call/cls_ulong_va.c: Liekwise.
2616 +        * testsuite/libffi.call/cls_ushort_va.c: Likewise.
2617 +        * testsuite/libffi.call/nested_struct11.c: Likewise.
2618 +        * testsuite/libffi.call/uninitialized.c: Likewise.
2619 +        * testsuite/libffi.call/va_1.c: Likewise.
2620 +        * testsuite/libffi.call/va_struct1.c: Likewise.
2621 +        * testsuite/libffi.call/va_struct2.c: Likewise.
2622 +        * testsuite/libffi.call/va_struct3.c: Likewise.
2623 +
2624  2012-10-12  Walter Lee  <walt@tilera.com>
2625  
2626          * Makefile.am: Add TILE-Gx/TILEPro support.