1457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd.
2457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
3457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiquePermission is hereby granted, free of charge, to any person obtaining
4457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquea copy of this software and associated documentation files (the
5457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique``Software''), to deal in the Software without restriction, including
6457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquewithout limitation the rights to use, copy, modify, merge, publish,
7457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquedistribute, sublicense, and/or sell copies of the Software, and to
8457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquepermit persons to whom the Software is furnished to do so, subject to
9457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquethe following conditions:
10457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
11457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueThe above copyright notice and this permission notice shall be
12457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueincluded in all copies or substantial portions of the Software.
13457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
14457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueTHE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
15457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd PiqueSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
21457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
22457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdio.h>
23457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
24457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi.h>
25457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <ffi_common.h>
26457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
27457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#include <stdlib.h>
28457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
29457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Stack alignment requirement in bytes */
30457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
31457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define AARCH64_STACK_ALIGN 1
32457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else
33457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define AARCH64_STACK_ALIGN 16
34457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
35457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
36457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define N_X_ARG_REG 8
37457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define N_V_ARG_REG 8
38457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
39457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT)
40457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
41457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueunion _d
42457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
43457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  UINT64 d;
44457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  UINT32 s[2];
45457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique};
46457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
47457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestruct call_context
48457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
49457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  UINT64 x [AARCH64_N_XREG];
50457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  struct
51457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  {
52457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    union _d d[2];
53457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  } v [AARCH64_N_VREG];
54457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique};
55457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
56457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__clang__) && defined (__APPLE__)
57457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void
58457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquesys_icache_invalidate (void *start, size_t len);
59457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
60457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
61457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic inline void
62457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_clear_cache (void *start, void *end)
63457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
64457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__clang__) && defined (__APPLE__)
65457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	sys_icache_invalidate (start, (char *)end - (char *)start);
66457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#elif defined (__GNUC__)
67457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	__builtin___clear_cache (start, end);
68457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else
69457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#error "Missing builtin to flush instruction cache"
70457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
71457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
72457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
73457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
74457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_x_addr (struct call_context *context, unsigned n)
75457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
76457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return &context->x[n];
77457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
78457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
79457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
80457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_s_addr (struct call_context *context, unsigned n)
81457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
82457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined __AARCH64EB__
83457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return &context->v[n].d[1].s[1];
84457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else
85457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return &context->v[n].d[0].s[0];
86457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
87457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
88457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
89457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
90457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_d_addr (struct call_context *context, unsigned n)
91457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
92457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined __AARCH64EB__
93457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return &context->v[n].d[1];
94457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else
95457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return &context->v[n].d[0];
96457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
97457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
98457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
99457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_v_addr (struct call_context *context, unsigned n)
101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return &context->v[n];
103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the memory location at which a basic type would reside
106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   were it to have been stored in register n.  */
107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_basic_type_addr (unsigned short type, struct call_context *context,
110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		     unsigned n)
111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  switch (type)
113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_FLOAT:
115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return get_s_addr (context, n);
116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_DOUBLE:
117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return get_d_addr (context, n);
118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_LONGDOUBLE:
120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return get_v_addr (context, n);
121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT8:
123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT8:
124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT16:
125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT16:
126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT32:
127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT32:
128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_INT:
129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_POINTER:
130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT64:
131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT64:
132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return get_x_addr (context, n);
133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_VOID:
134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return NULL;
135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    default:
136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      FFI_ASSERT (0);
137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return NULL;
138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the alignment width for each of the basic types.  */
142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic size_t
144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_basic_type_alignment (unsigned short type)
145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  switch (type)
147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_FLOAT:
149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT32);
151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_DOUBLE:
153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT64);
154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_LONGDOUBLE:
156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (long double);
157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT8:
159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT8:
160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  return sizeof (UINT8);
162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT16:
164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT16:
165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  return sizeof (UINT16);
167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT32:
169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_INT:
170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT32:
171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  return sizeof (UINT32);
173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_POINTER:
175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT64:
176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT64:
177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT64);
178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    default:
180457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      FFI_ASSERT (0);
181457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return 0;
182457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
183457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
184457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
185457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the size in bytes for each of the basic types.  */
186457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
187457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic size_t
188457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_basic_type_size (unsigned short type)
189457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
190457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  switch (type)
191457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
192457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_FLOAT:
193457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT32);
194457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_DOUBLE:
195457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT64);
196457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
197457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_LONGDOUBLE:
198457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (long double);
199457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
200457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT8:
201457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT8);
202457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT8:
203457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (SINT8);
204457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT16:
205457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT16);
206457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT16:
207457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (SINT16);
208457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT32:
209457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT32);
210457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_INT:
211457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT32:
212457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (SINT32);
213457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_POINTER:
214457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT64:
215457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (UINT64);
216457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT64:
217457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return sizeof (SINT64);
218457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
219457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    default:
220457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      FFI_ASSERT (0);
221457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return 0;
222457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
223457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
224457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
225457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void
226457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_call_SYSV (unsigned (*)(struct call_context *context, unsigned char *,
227457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			    extended_cif *),
228457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique               struct call_context *context,
229457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique               extended_cif *,
230457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique               size_t,
231457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique               void (*fn)(void));
232457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
233457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueextern void
234457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_closure_SYSV (ffi_closure *);
235457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
236457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test for an FFI floating point representation.  */
237457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
238457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned
239457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_floating_type (unsigned short type)
240457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
241457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE
242457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  || type == FFI_TYPE_LONGDOUBLE);
243457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
244457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
245457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test for a homogeneous structure.  */
246457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
247457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned short
248457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueget_homogeneous_type (ffi_type *ty)
249457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
250457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
251457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
252457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      unsigned i;
253457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      unsigned short candidate_type
254457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	= get_homogeneous_type (ty->elements[0]);
255457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      for (i =1; ty->elements[i]; i++)
256457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	{
257457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  unsigned short iteration_type = 0;
258457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  /* If we have a nested struct, we must find its homogeneous type.
259457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	     If that fits with our candidate type, we are still
260457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	     homogeneous.  */
261457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  if (ty->elements[i]->type == FFI_TYPE_STRUCT
262457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      && ty->elements[i]->elements)
263457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
264457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      iteration_type = get_homogeneous_type (ty->elements[i]);
265457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
266457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else
267457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
268457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      iteration_type = ty->elements[i]->type;
269457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
270457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
271457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  /* If we are not homogeneous, return FFI_TYPE_STRUCT.  */
272457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  if (candidate_type != iteration_type)
273457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    return FFI_TYPE_STRUCT;
274457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	}
275457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return candidate_type;
276457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
277457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
278457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  /* Base case, we have no more levels of nesting, so we
279457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     are a basic type, and so, trivially homogeneous in that type.  */
280457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return ty->type;
281457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
282457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
283457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Determine the number of elements within a STRUCT.
284457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
285457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   Note, we must handle nested structs.
286457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
287457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   If ty is not a STRUCT this function will return 0.  */
288457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
289457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned
290457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueelement_count (ffi_type *ty)
291457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
292457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (ty->type == FFI_TYPE_STRUCT && ty->elements)
293457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
294457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      unsigned n;
295457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      unsigned elems = 0;
296457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      for (n = 0; ty->elements[n]; n++)
297457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	{
298457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  if (ty->elements[n]->type == FFI_TYPE_STRUCT
299457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      && ty->elements[n]->elements)
300457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    elems += element_count (ty->elements[n]);
301457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else
302457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    elems++;
303457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	}
304457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return elems;
305457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
306457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return 0;
307457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
308457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
309457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test for a homogeneous floating point aggregate.
310457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
311457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   A homogeneous floating point aggregate is a homogeneous aggregate of
312457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   a half- single- or double- precision floating point type with one
313457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   to four elements.  Note that this includes nested structs of the
314457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   basic type.  */
315457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
316457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic int
317457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_hfa (ffi_type *ty)
318457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
319457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (ty->type == FFI_TYPE_STRUCT
320457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      && ty->elements[0]
321457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      && is_floating_type (get_homogeneous_type (ty)))
322457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
323457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      unsigned n = element_count (ty);
324457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return n >= 1 && n <= 4;
325457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
326457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return 0;
327457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
328457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
329457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test if an ffi_type is a candidate for passing in a register.
330457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
331457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   This test does not check that sufficient registers of the
332457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   appropriate class are actually available, merely that IFF
333457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   sufficient registers are available then the argument will be passed
334457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   in register(s).
335457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
336457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   Note that an ffi_type that is deemed to be a register candidate
337457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   will always be returned in registers.
338457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
339457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   Returns 1 if a register candidate else 0.  */
340457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
341457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic int
342457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_register_candidate (ffi_type *ty)
343457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
344457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  switch (ty->type)
345457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
346457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_VOID:
347457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_FLOAT:
348457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_DOUBLE:
349457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
350457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_LONGDOUBLE:
351457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
352457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT8:
353457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT16:
354457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT32:
355457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT64:
356457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_POINTER:
357457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT8:
358457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT16:
359457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT32:
360457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_INT:
361457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT64:
362457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      return 1;
363457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
364457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_STRUCT:
365457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      if (is_hfa (ty))
366457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        {
367457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          return 1;
368457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        }
369457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      else if (ty->size > 16)
370457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        {
371457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          /* Too large. Will be replaced with a pointer to memory. The
372457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique             pointer MAY be passed in a register, but the value will
373457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique             not. This test specifically fails since the argument will
374457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique             never be passed by value in registers. */
375457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          return 0;
376457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        }
377457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      else
378457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        {
379457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          /* Might be passed in registers depending on the number of
380457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique             registers required. */
381457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          return (ty->size + 7) / 8 < N_X_ARG_REG;
382457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        }
383457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
384457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
385457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    default:
386457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      FFI_ASSERT (0);
387457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
388457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
389457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
390457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return 0;
391457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
392457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
393457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Test if an ffi_type argument or result is a candidate for a vector
394457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   register.  */
395457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
396457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic int
397457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueis_v_register_candidate (ffi_type *ty)
398457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
399457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return is_floating_type (ty->type)
400457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	   || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty));
401457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
402457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
403457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Representation of the procedure call argument marshalling
404457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   state.
405457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
406457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   The terse state variable names match the names used in the AARCH64
407457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   PCS. */
408457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
409457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestruct arg_state
410457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
411457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  unsigned ngrn;                /* Next general-purpose register number. */
412457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  unsigned nsrn;                /* Next vector register number. */
413457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  size_t nsaa;                  /* Next stack offset. */
414457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
415457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
416457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  unsigned allocating_variadic;
417457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
418457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique};
419457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
420457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Initialize a procedure call argument marshalling state.  */
421457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void
422457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquearg_init (struct arg_state *state, size_t call_frame_size)
423457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
424457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->ngrn = 0;
425457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->nsrn = 0;
426457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->nsaa = 0;
427457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
428457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
429457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->allocating_variadic = 0;
430457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
431457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
432457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
433457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the number of available consecutive core argument
434457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   registers.  */
435457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
436457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned
437457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueavailable_x (struct arg_state *state)
438457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
439457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return N_X_ARG_REG - state->ngrn;
440457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
441457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
442457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Return the number of available consecutive vector argument
443457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   registers.  */
444457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
445457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned
446457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueavailable_v (struct arg_state *state)
447457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
448457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return N_V_ARG_REG - state->nsrn;
449457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
450457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
451457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
452457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_x (struct call_context *context, struct arg_state *state)
453457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
454457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  FFI_ASSERT (state->ngrn < N_X_ARG_REG);
455457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return get_x_addr (context, (state->ngrn)++);
456457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
457457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
458457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
459457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_s (struct call_context *context, struct arg_state *state)
460457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
461457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  FFI_ASSERT (state->nsrn < N_V_ARG_REG);
462457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return get_s_addr (context, (state->nsrn)++);
463457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
464457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
465457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
466457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_d (struct call_context *context, struct arg_state *state)
467457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
468457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  FFI_ASSERT (state->nsrn < N_V_ARG_REG);
469457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return get_d_addr (context, (state->nsrn)++);
470457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
471457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
472457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
473457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_v (struct call_context *context, struct arg_state *state)
474457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
475457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  FFI_ASSERT (state->nsrn < N_V_ARG_REG);
476457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return get_v_addr (context, (state->nsrn)++);
477457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
478457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
479457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Allocate an aligned slot on the stack and return a pointer to it.  */
480457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
481457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_stack (struct arg_state *state, void *stack, size_t alignment,
482457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		   size_t size)
483457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
484457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  void *allocation;
485457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
486457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  /* Round up the NSAA to the larger of 8 or the natural
487457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     alignment of the argument's type.  */
488457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->nsaa = ALIGN (state->nsaa, alignment);
489457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->nsaa = ALIGN (state->nsaa, alignment);
490457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
491457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (state->allocating_variadic)
492457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    state->nsaa = ALIGN (state->nsaa, 8);
493457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#else
494457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->nsaa = ALIGN (state->nsaa, 8);
495457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
496457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
497457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  allocation = stack + state->nsaa;
498457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
499457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  state->nsaa += size;
500457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return allocation;
501457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
502457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
503457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void
504457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquecopy_basic_type (void *dest, void *source, unsigned short type)
505457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
506457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  /* This is necessary to ensure that basic types are copied
507457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     sign extended to 64-bits as libffi expects.  */
508457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  switch (type)
509457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
510457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_FLOAT:
511457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(float *) dest = *(float *) source;
512457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
513457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_DOUBLE:
514457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(double *) dest = *(double *) source;
515457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
516457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
517457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_LONGDOUBLE:
518457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(long double *) dest = *(long double *) source;
519457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
520457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
521457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT8:
522457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_arg *) dest = *(UINT8 *) source;
523457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
524457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT8:
525457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_sarg *) dest = *(SINT8 *) source;
526457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
527457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT16:
528457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_arg *) dest = *(UINT16 *) source;
529457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
530457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT16:
531457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_sarg *) dest = *(SINT16 *) source;
532457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
533457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT32:
534457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_arg *) dest = *(UINT32 *) source;
535457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
536457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_INT:
537457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT32:
538457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_sarg *) dest = *(SINT32 *) source;
539457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
540457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_POINTER:
541457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT64:
542457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_arg *) dest = *(UINT64 *) source;
543457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
544457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT64:
545457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      *(ffi_sarg *) dest = *(SINT64 *) source;
546457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
547457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_VOID:
548457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
549457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
550457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    default:
551457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      FFI_ASSERT (0);
552457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
553457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
554457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
555457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void
556457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquecopy_hfa_to_reg_or_stack (void *memory,
557457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  ffi_type *ty,
558457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  struct call_context *context,
559457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  unsigned char *stack,
560457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  struct arg_state *state)
561457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
562457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  unsigned elems = element_count (ty);
563457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (available_v (state) < elems)
564457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
565457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      /* There are insufficient V registers. Further V register allocations
566457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	 are prevented, the NSAA is adjusted (by allocate_to_stack ())
567457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	 and the argument is copied to memory at the adjusted NSAA.  */
568457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      state->nsrn = N_V_ARG_REG;
569457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size),
570457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      memory,
571457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      ty->size);
572457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
573457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  else
574457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
575457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      int i;
576457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      unsigned short type = get_homogeneous_type (ty);
577457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      for (i = 0; i < elems; i++)
578457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	{
579457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  void *reg = allocate_to_v (context, state);
580457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  copy_basic_type (reg, memory, type);
581457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  memory += get_basic_type_size (type);
582457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	}
583457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
584457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
585457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
586457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Either allocate an appropriate register for the argument type, or if
587457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   none are available, allocate a stack slot and return a pointer
588457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   to the allocated space.  */
589457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
590457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void *
591457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueallocate_to_register_or_stack (struct call_context *context,
592457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			       unsigned char *stack,
593457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			       struct arg_state *state,
594457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			       unsigned short type)
595457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
596457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  size_t alignment = get_basic_type_alignment (type);
597457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  size_t size = alignment;
598457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  switch (type)
599457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
600457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_FLOAT:
601457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      /* This is the only case for which the allocated stack size
602457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	 should not match the alignment of the type.  */
603457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      size = sizeof (UINT32);
604457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      /* Fall through.  */
605457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_DOUBLE:
606457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      if (state->nsrn < N_V_ARG_REG)
607457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	return allocate_to_d (context, state);
608457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      state->nsrn = N_V_ARG_REG;
609457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
610457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
611457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_LONGDOUBLE:
612457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      if (state->nsrn < N_V_ARG_REG)
613457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	return allocate_to_v (context, state);
614457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      state->nsrn = N_V_ARG_REG;
615457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
616457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
617457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT8:
618457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT8:
619457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT16:
620457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT16:
621457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT32:
622457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT32:
623457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_INT:
624457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_POINTER:
625457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_UINT64:
626457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_TYPE_SINT64:
627457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      if (state->ngrn < N_X_ARG_REG)
628457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	return allocate_to_x (context, state);
629457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      state->ngrn = N_X_ARG_REG;
630457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
631457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    default:
632457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      FFI_ASSERT (0);
633457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
634457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
635457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    return allocate_to_stack (state, stack, alignment, size);
636457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
637457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
638457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Copy a value to an appropriate register, or if none are
639457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   available, to the stack.  */
640457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
641457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic void
642457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquecopy_to_register_or_stack (struct call_context *context,
643457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   unsigned char *stack,
644457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   struct arg_state *state,
645457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   void *value,
646457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   unsigned short type)
647457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
648457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  copy_basic_type (
649457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  allocate_to_register_or_stack (context, stack, state, type),
650457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  value,
651457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  type);
652457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
653457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
654457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Marshall the arguments from FFI representation to procedure call
655457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   context and stack.  */
656457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
657457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned
658457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueaarch64_prep_args (struct call_context *context, unsigned char *stack,
659457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		   extended_cif *ecif)
660457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
661457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  int i;
662457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  struct arg_state state;
663457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
664457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  arg_init (&state, ALIGN(ecif->cif->bytes, 16));
665457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
666457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  for (i = 0; i < ecif->cif->nargs; i++)
667457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
668457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      ffi_type *ty = ecif->cif->arg_types[i];
669457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      switch (ty->type)
670457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	{
671457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_VOID:
672457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  FFI_ASSERT (0);
673457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
674457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
675457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	/* If the argument is a basic type the argument is allocated to an
676457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	   appropriate register, or if none are available, to the stack.  */
677457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_FLOAT:
678457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_DOUBLE:
679457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
680457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_LONGDOUBLE:
681457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
682457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT8:
683457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT8:
684457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT16:
685457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT16:
686457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT32:
687457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_INT:
688457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT32:
689457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_POINTER:
690457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT64:
691457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT64:
692457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  copy_to_register_or_stack (context, stack, &state,
693457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				     ecif->avalue[i], ty->type);
694457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
695457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
696457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_STRUCT:
697457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  if (is_hfa (ty))
698457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
699457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context,
700457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique					stack, &state);
701457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
702457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else if (ty->size > 16)
703457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
704457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      /* If the argument is a composite type that is larger than 16
705457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 bytes, then the argument has been copied to memory, and
706457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 the argument is replaced by a pointer to the copy.  */
707457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
708457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      copy_to_register_or_stack (context, stack, &state,
709457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique					 &(ecif->avalue[i]), FFI_TYPE_POINTER);
710457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
711457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else if (available_x (&state) >= (ty->size + 7) / 8)
712457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
713457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      /* If the argument is a composite type and the size in
714457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 double-words is not more than the number of available
715457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 X registers, then the argument is copied into consecutive
716457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 X registers.  */
717457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      int j;
718457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      for (j = 0; j < (ty->size + 7) / 8; j++)
719457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		{
720457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  memcpy (allocate_to_x (context, &state),
721457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  &(((UINT64 *) ecif->avalue[i])[j]),
722457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  sizeof (UINT64));
723457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		}
724457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
725457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else
726457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
727457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      /* Otherwise, there are insufficient X registers. Further X
728457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 register allocations are prevented, the NSAA is adjusted
729457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 (by allocate_to_stack ()) and the argument is copied to
730457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 memory at the adjusted NSAA.  */
731457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      state.ngrn = N_X_ARG_REG;
732457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
733457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      memcpy (allocate_to_stack (&state, stack, ty->alignment,
734457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique					 ty->size), ecif->avalue + i, ty->size);
735457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
736457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
737457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
738457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	default:
739457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  FFI_ASSERT (0);
740457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
741457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	}
742457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
743457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
744457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      if (i + 1 == ecif->cif->aarch64_nfixedargs)
745457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	{
746457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  state.ngrn = N_X_ARG_REG;
747457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  state.nsrn = N_V_ARG_REG;
748457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
749457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  state.allocating_variadic = 1;
750457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	}
751457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
752457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
753457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
754457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return ecif->cif->aarch64_flags;
755457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
756457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
757457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status
758457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_prep_cif_machdep (ffi_cif *cif)
759457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
760457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  /* Round the stack up to a multiple of the stack alignment requirement. */
761457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  cif->bytes =
762457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1);
763457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
764457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  /* Initialize our flags. We are interested if this CIF will touch a
765457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     vector register, if so we will enable context save and load to
766457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     those registers, otherwise not. This is intended to be friendly
767457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     to lazy float context switching in the kernel.  */
768457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  cif->aarch64_flags = 0;
769457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
770457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (is_v_register_candidate (cif->rtype))
771457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
772457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      cif->aarch64_flags |= AARCH64_FFI_WITH_V;
773457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
774457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  else
775457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
776457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      int i;
777457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      for (i = 0; i < cif->nargs; i++)
778457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        if (is_v_register_candidate (cif->arg_types[i]))
779457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          {
780457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            cif->aarch64_flags |= AARCH64_FFI_WITH_V;
781457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            break;
782457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          }
783457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
784457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
785457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
786457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  cif->aarch64_nfixedargs = 0;
787457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
788457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
789457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return FFI_OK;
790457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
791457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
792457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if defined (__APPLE__)
793457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
794457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Perform Apple-specific cif processing for variadic calls */
795457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status ffi_prep_cif_machdep_var(ffi_cif *cif,
796457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				    unsigned int nfixedargs,
797457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				    unsigned int ntotalargs)
798457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
799457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  ffi_status status;
800457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
801457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  status = ffi_prep_cif_machdep (cif);
802457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
803457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  cif->aarch64_nfixedargs = nfixedargs;
804457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
805457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return status;
806457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
807457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
808457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
809457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
810457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Call a function with the provided arguments and capture the return
811457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   value.  */
812457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid
813457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
814457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
815457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  extended_cif ecif;
816457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
817457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  ecif.cif = cif;
818457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  ecif.avalue = avalue;
819457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  ecif.rvalue = rvalue;
820457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
821457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  switch (cif->abi)
822457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
823457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    case FFI_SYSV:
824457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      {
825457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        struct call_context context;
826457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	size_t stack_bytes;
827457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
828457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	/* Figure out the total amount of stack space we need, the
829457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	   above call frame space needs to be 16 bytes aligned to
830457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	   ensure correct alignment of the first object inserted in
831457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	   that space hence the ALIGN applied to cif->bytes.*/
832457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	stack_bytes = ALIGN(cif->bytes, 16);
833457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
834457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	memset (&context, 0, sizeof (context));
835457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        if (is_register_candidate (cif->rtype))
836457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          {
837457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            ffi_call_SYSV (aarch64_prep_args, &context, &ecif, stack_bytes, fn);
838457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            switch (cif->rtype->type)
839457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              {
840457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_VOID:
841457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_FLOAT:
842457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_DOUBLE:
843457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
844457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_LONGDOUBLE:
845457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
846457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_UINT8:
847457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_SINT8:
848457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_UINT16:
849457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_SINT16:
850457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_UINT32:
851457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_SINT32:
852457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_POINTER:
853457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_UINT64:
854457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_INT:
855457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_SINT64:
856457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		{
857457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  void *addr = get_basic_type_addr (cif->rtype->type,
858457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique						    &context, 0);
859457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  copy_basic_type (rvalue, addr, cif->rtype->type);
860457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  break;
861457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		}
862457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
863457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              case FFI_TYPE_STRUCT:
864457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                if (is_hfa (cif->rtype))
865457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  {
866457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    int j;
867457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    unsigned short type = get_homogeneous_type (cif->rtype);
868457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    unsigned elems = element_count (cif->rtype);
869457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    for (j = 0; j < elems; j++)
870457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      {
871457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			void *reg = get_basic_type_addr (type, &context, j);
872457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			copy_basic_type (rvalue, reg, type);
873457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			rvalue += get_basic_type_size (type);
874457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      }
875457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  }
876457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
877457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                  {
878457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                    size_t size = ALIGN (cif->rtype->size, sizeof (UINT64));
879457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                    memcpy (rvalue, get_x_addr (&context, 0), size);
880457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                  }
881457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                else
882457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                  {
883457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                    FFI_ASSERT (0);
884457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                  }
885457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                break;
886457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
887457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              default:
888457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                FFI_ASSERT (0);
889457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                break;
890457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              }
891457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          }
892457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        else
893457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          {
894457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            memcpy (get_x_addr (&context, 8), &rvalue, sizeof (UINT64));
895457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            ffi_call_SYSV (aarch64_prep_args, &context, &ecif,
896457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   stack_bytes, fn);
897457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          }
898457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        break;
899457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      }
900457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
901457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    default:
902457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      FFI_ASSERT (0);
903457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      break;
904457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
905457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
906457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
907457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquestatic unsigned char trampoline [] =
908457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{ 0x70, 0x00, 0x00, 0x58,	/* ldr	x16, 1f	*/
909457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  0x91, 0x00, 0x00, 0x10,	/* adr	x17, 2f	*/
910457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  0x00, 0x02, 0x1f, 0xd6	/* br	x16	*/
911457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique};
912457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
913457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Build a trampoline.  */
914457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
915457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS)			\
916457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  ({unsigned char *__tramp = (unsigned char*)(TRAMP);			\
917457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    UINT64  __fun = (UINT64)(FUN);					\
918457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    UINT64  __ctx = (UINT64)(CTX);					\
919457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    UINT64  __flags = (UINT64)(FLAGS);					\
920457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    memcpy (__tramp, trampoline, sizeof (trampoline));			\
921457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    memcpy (__tramp + 12, &__fun, sizeof (__fun));			\
922457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    memcpy (__tramp + 20, &__ctx, sizeof (__ctx));			\
923457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    memcpy (__tramp + 28, &__flags, sizeof (__flags));			\
924457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    ffi_clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE);		\
925457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  })
926457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
927457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_status
928457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_prep_closure_loc (ffi_closure* closure,
929457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                      ffi_cif* cif,
930457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                      void (*fun)(ffi_cif*,void*,void**,void*),
931457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                      void *user_data,
932457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique                      void *codeloc)
933457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
934457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (cif->abi != FFI_SYSV)
935457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    return FFI_BAD_ABI;
936457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
937457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc,
938457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		       cif->aarch64_flags);
939457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
940457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  closure->cif  = cif;
941457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  closure->user_data = user_data;
942457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  closure->fun  = fun;
943457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
944457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  return FFI_OK;
945457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
946457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
947457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique/* Primary handler to setup and invoke a function within a closure.
948457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
949457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   A closure when invoked enters via the assembler wrapper
950457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   ffi_closure_SYSV(). The wrapper allocates a call context on the
951457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   stack, saves the interesting registers (from the perspective of
952457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   the calling convention) into the context then passes control to
953457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   ffi_closure_SYSV_inner() passing the saved context and a pointer to
954457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   the stack at the point ffi_closure_SYSV() was invoked.
955457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
956457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   On the return path the assembler wrapper will reload call context
957457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   registers.
958457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
959457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   ffi_closure_SYSV_inner() marshalls the call context into ffi value
960457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   descriptors, invokes the wrapped function, then marshalls the return
961457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique   value back into the call context.  */
962457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
963457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piquevoid FFI_HIDDEN
964457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Piqueffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context,
965457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			void *stack)
966457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique{
967457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  ffi_cif *cif = closure->cif;
968457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  void **avalue = (void**) alloca (cif->nargs * sizeof (void*));
969457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  void *rvalue = NULL;
970457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  int i;
971457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  struct arg_state state;
972457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
973457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  arg_init (&state, ALIGN(cif->bytes, 16));
974457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
975457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  for (i = 0; i < cif->nargs; i++)
976457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
977457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      ffi_type *ty = cif->arg_types[i];
978457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
979457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      switch (ty->type)
980457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	{
981457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_VOID:
982457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  FFI_ASSERT (0);
983457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
984457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
985457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT8:
986457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT8:
987457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT16:
988457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT16:
989457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT32:
990457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT32:
991457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_INT:
992457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_POINTER:
993457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_UINT64:
994457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_SINT64:
995457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case  FFI_TYPE_FLOAT:
996457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case  FFI_TYPE_DOUBLE:
997457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
998457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case  FFI_TYPE_LONGDOUBLE:
999457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  avalue[i] = allocate_to_register_or_stack (context, stack,
1000457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique						     &state, ty->type);
1001457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
1002457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
1003457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1004457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	case FFI_TYPE_STRUCT:
1005457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  if (is_hfa (ty))
1006457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
1007457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      unsigned n = element_count (ty);
1008457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      if (available_v (&state) < n)
1009457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		{
1010457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  state.nsrn = N_V_ARG_REG;
1011457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
1012457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique						 ty->size);
1013457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		}
1014457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      else
1015457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		{
1016457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  switch (get_homogeneous_type (ty))
1017457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    {
1018457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    case FFI_TYPE_FLOAT:
1019457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      {
1020457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			/* Eeek! We need a pointer to the structure,
1021457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   however the homogeneous float elements are
1022457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   being passed in individual S registers,
1023457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   therefore the structure is not represented as
1024457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   a contiguous sequence of bytes in our saved
1025457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   register context. We need to fake up a copy
1026457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   of the structure laid out in memory
1027457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   correctly. The fake can be tossed once the
1028457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   closure function has returned hence alloca()
1029457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   is sufficient. */
1030457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			int j;
1031457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			UINT32 *p = avalue[i] = alloca (ty->size);
1032457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			for (j = 0; j < element_count (ty); j++)
1033457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  memcpy (&p[j],
1034457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				  allocate_to_s (context, &state),
1035457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				  sizeof (*p));
1036457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			break;
1037457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      }
1038457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1039457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    case FFI_TYPE_DOUBLE:
1040457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      {
1041457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			/* Eeek! We need a pointer to the structure,
1042457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   however the homogeneous float elements are
1043457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   being passed in individual S registers,
1044457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   therefore the structure is not represented as
1045457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   a contiguous sequence of bytes in our saved
1046457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   register context. We need to fake up a copy
1047457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   of the structure laid out in memory
1048457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   correctly. The fake can be tossed once the
1049457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   closure function has returned hence alloca()
1050457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			   is sufficient. */
1051457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			int j;
1052457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			UINT64 *p = avalue[i] = alloca (ty->size);
1053457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			for (j = 0; j < element_count (ty); j++)
1054457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  memcpy (&p[j],
1055457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				  allocate_to_d (context, &state),
1056457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				  sizeof (*p));
1057457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			break;
1058457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      }
1059457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1060457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
1061457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    case FFI_TYPE_LONGDOUBLE:
1062457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique			  memcpy (&avalue[i],
1063457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				  allocate_to_v (context, &state),
1064457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique				  sizeof (*avalue));
1065457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      break;
1066457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
1067457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1068457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    default:
1069457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      FFI_ASSERT (0);
1070457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      break;
1071457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		    }
1072457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		}
1073457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
1074457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else if (ty->size > 16)
1075457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
1076457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      /* Replace Composite type of size greater than 16 with a
1077457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		 pointer.  */
1078457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      memcpy (&avalue[i],
1079457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      allocate_to_register_or_stack (context, stack,
1080457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique						     &state, FFI_TYPE_POINTER),
1081457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		      sizeof (avalue[i]));
1082457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
1083457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else if (available_x (&state) >= (ty->size + 7) / 8)
1084457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
1085457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      avalue[i] = get_x_addr (context, state.ngrn);
1086457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      state.ngrn += (ty->size + 7) / 8;
1087457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
1088457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  else
1089457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
1090457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      state.ngrn = N_X_ARG_REG;
1091457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1092457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      avalue[i] = allocate_to_stack (&state, stack, ty->alignment,
1093457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique					     ty->size);
1094457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
1095457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
1096457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1097457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	default:
1098457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  FFI_ASSERT (0);
1099457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  break;
1100457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	}
1101457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
1102457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1103457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  /* Figure out where the return value will be passed, either in
1104457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     registers or in a memory block allocated by the caller and passed
1105457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique     in x8.  */
1106457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1107457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  if (is_register_candidate (cif->rtype))
1108457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
1109457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      /* Register candidates are *always* returned in registers. */
1110457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1111457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      /* Allocate a scratchpad for the return value, we will let the
1112457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique         callee scrible the result into the scratch pad then move the
1113457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique         contents into the appropriate return value location for the
1114457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique         call convention.  */
1115457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      rvalue = alloca (cif->rtype->size);
1116457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      (closure->fun) (cif, rvalue, avalue, closure->user_data);
1117457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1118457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      /* Copy the return value into the call context so that it is returned
1119457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique         as expected to our caller.  */
1120457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      switch (cif->rtype->type)
1121457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        {
1122457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_VOID:
1123457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          break;
1124457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1125457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_UINT8:
1126457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_UINT16:
1127457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_UINT32:
1128457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_POINTER:
1129457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_UINT64:
1130457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_SINT8:
1131457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_SINT16:
1132457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_INT:
1133457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_SINT32:
1134457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_SINT64:
1135457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_FLOAT:
1136457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_DOUBLE:
1137457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE
1138457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_LONGDOUBLE:
1139457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique#endif
1140457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  {
1141457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    void *addr = get_basic_type_addr (cif->rtype->type, context, 0);
1142457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    copy_basic_type (addr, rvalue, cif->rtype->type);
1143457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            break;
1144457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	  }
1145457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        case FFI_TYPE_STRUCT:
1146457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          if (is_hfa (cif->rtype))
1147457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    {
1148457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      int j;
1149457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      unsigned short type = get_homogeneous_type (cif->rtype);
1150457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      unsigned elems = element_count (cif->rtype);
1151457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	      for (j = 0; j < elems; j++)
1152457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		{
1153457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  void *reg = get_basic_type_addr (type, context, j);
1154457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  copy_basic_type (reg, rvalue, type);
1155457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		  rvalue += get_basic_type_size (type);
1156457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique		}
1157457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique	    }
1158457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          else if ((cif->rtype->size + 7) / 8 < N_X_ARG_REG)
1159457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            {
1160457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)) ;
1161457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              memcpy (get_x_addr (context, 0), rvalue, size);
1162457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            }
1163457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          else
1164457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            {
1165457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique              FFI_ASSERT (0);
1166457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique            }
1167457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          break;
1168457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        default:
1169457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          FFI_ASSERT (0);
1170457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique          break;
1171457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique        }
1172457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
1173457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique  else
1174457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    {
1175457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64));
1176457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique      (closure->fun) (cif, rvalue, avalue, closure->user_data);
1177457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique    }
1178457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique}
1179457ba79995d512b9e8c07061fe10d4cd88273b2Lloyd Pique
1180