1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - Copyright (c) 1998, 2007, 2008 Red Hat, Inc.
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   Copyright (c) 2000 Hewlett Packard Company
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   IA64 Foreign Function Interface
6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Permission is hereby granted, free of charge, to any person obtaining
8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   a copy of this software and associated documentation files (the
9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ``Software''), to deal in the Software without restriction, including
10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   without limitation the rights to use, copy, modify, merge, publish,
11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   distribute, sublicense, and/or sell copies of the Software, and to
12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   permit persons to whom the Software is furnished to do so, subject to
13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the following conditions:
14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The above copyright notice and this permission notice shall be included
16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   in all copies or substantial portions of the Software.
17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   DEALINGS IN THE SOFTWARE.
26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ----------------------------------------------------------------------- */
27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h>
29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h>
30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h>
32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdbool.h>
33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <float.h>
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include "ia64_flags.h"
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* A 64-bit pointer value.  In LP64 mode, this is effectively a plain
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   pointer.  In ILP32 mode, it's a pointer that's been extended to
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   64 bits by "addp4".  */
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projecttypedef void *PTR64 __attribute__((mode(DI)));
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Memory image of fp register contents.  This is the implementation
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   specific format used by ldf.fill/stf.spill.  All we care about is
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   that it wants a 16 byte aligned slot.  */
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projecttypedef struct
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT64 x[2] __attribute__((aligned(16)));
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project} fpreg;
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* The stack layout given to ffi_call_unix and ffi_closure_unix_inner.  */
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstruct ia64_args
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  fpreg fp_regs[8];	/* Contents of 8 fp arg registers.  */
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT64 gp_regs[8];	/* Contents of 8 gp arg registers.  */
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT64 other_args[];	/* Arguments passed on stack, variable size.  */
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project};
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Adjust ADDR, a pointer to an 8 byte slot, to point to the low LEN bytes.  */
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic inline void *
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectendian_adjust (void *addr, size_t len)
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __BIG_ENDIAN__
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return addr + (8 - len);
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return addr;
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Store VALUE to ADDR in the current cpu implementation's fp spill format.
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   This is a macro instead of a function, so that it works for all 3 floating
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   point types without type conversions.  Type conversion to long double breaks
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the denorm support.  */
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define stf_spill(addr, value)	\
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  asm ("stf.spill %0 = %1%P0" : "=m" (*addr) : "f"(value));
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Load a value from ADDR, which is in the current cpu implementation's
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   fp spill format.  As above, this must also be a macro.  */
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define ldf_fill(result, addr)	\
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  asm ("ldf.fill %0 = %1%P1" : "=f"(result) : "m"(*addr));
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Return the size of the C type associated with with TYPE.  Which will
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   be one of the FFI_IA64_TYPE_HFA_* values.  */
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic size_t
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projecthfa_type_size (int type)
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (type)
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_FLOAT:
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return sizeof(float);
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_DOUBLE:
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return sizeof(double);
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_LDOUBLE:
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return sizeof(__float80);
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      abort ();
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Load from ADDR a value indicated by TYPE.  Which will be one of
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the FFI_IA64_TYPE_HFA_* values.  */
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projecthfa_type_load (fpreg *fpaddr, int type, void *addr)
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (type)
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_FLOAT:
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      stf_spill (fpaddr, *(float *) addr);
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return;
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_DOUBLE:
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      stf_spill (fpaddr, *(double *) addr);
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return;
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_LDOUBLE:
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      stf_spill (fpaddr, *(__float80 *) addr);
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return;
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      abort ();
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Load VALUE into ADDR as indicated by TYPE.  Which will be one of
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the FFI_IA64_TYPE_HFA_* values.  */
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projecthfa_type_store (int type, void *addr, fpreg *fpaddr)
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (type)
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_FLOAT:
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	float result;
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	ldf_fill (result, fpaddr);
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	*(float *) addr = result;
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	break;
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_DOUBLE:
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	double result;
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	ldf_fill (result, fpaddr);
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	*(double *) addr = result;
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	break;
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_IA64_TYPE_HFA_LDOUBLE:
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	__float80 result;
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	ldf_fill (result, fpaddr);
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	*(__float80 *) addr = result;
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	break;
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      abort ();
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Is TYPE a struct containing floats, doubles, or extended doubles,
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   all of the same fp type?  If so, return the element type.  Return
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   FFI_TYPE_VOID if not.  */
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projecthfa_element_type (ffi_type *type, int nested)
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int element = FFI_TYPE_VOID;
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (type->type)
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* We want to return VOID for raw floating-point types, but the
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 synthetic HFA type if we're nested within an aggregate.  */
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (nested)
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	element = FFI_IA64_TYPE_HFA_FLOAT;
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Similarly.  */
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (nested)
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	element = FFI_IA64_TYPE_HFA_DOUBLE;
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_LONGDOUBLE:
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Similarly, except that that HFA is true for double extended,
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 but not quad precision.  Both have sizeof == 16, so tell the
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 difference based on the precision.  */
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (LDBL_MANT_DIG == 64 && nested)
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	element = FFI_IA64_TYPE_HFA_LDOUBLE;
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	ffi_type **ptr = &type->elements[0];
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	for (ptr = &type->elements[0]; *ptr ; ptr++)
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    int sub_element = hfa_element_type (*ptr, 1);
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (sub_element == FFI_TYPE_VOID)
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      return FFI_TYPE_VOID;
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (element == FFI_TYPE_VOID)
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      element = sub_element;
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    else if (element != sub_element)
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      return FFI_TYPE_VOID;
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return FFI_TYPE_VOID;
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return element;
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing. */
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_cif_machdep(ffi_cif *cif)
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int flags;
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Adjust cif->bytes to include space for the bits of the ia64_args frame
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     that preceeds the integer register portion.  The estimate that the
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     generic bits did for the argument space required is good enough for the
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     integer component.  */
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->bytes += offsetof(struct ia64_args, gp_regs[0]);
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->bytes < sizeof(struct ia64_args))
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    cif->bytes = sizeof(struct ia64_args);
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag. */
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  flags = cif->rtype->type;
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_LONGDOUBLE:
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Leave FFI_TYPE_LONGDOUBLE as meaning double extended precision,
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 and encode quad precision as a two-word integer structure.  */
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (LDBL_MANT_DIG != 64)
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	flags = FFI_IA64_TYPE_SMALL_STRUCT | (16 << 8);
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        size_t size = cif->rtype->size;
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  	int hfa_type = hfa_element_type (cif->rtype, 0);
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	if (hfa_type != FFI_TYPE_VOID)
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    size_t nelts = size / hfa_type_size (hfa_type);
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (nelts <= 8)
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      flags = hfa_type | (size << 8);
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	else
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (size <= 32)
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      flags = FFI_IA64_TYPE_SMALL_STRUCT | (size << 8);
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->flags = flags;
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64);
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  struct ia64_args *stack;
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  long i, avn, gpcount, fpcount;
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_UNIX);
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If we have no spot for a return value, make one.  */
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (rvalue == NULL && cif->rtype->type != FFI_TYPE_VOID)
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    rvalue = alloca (cif->rtype->size);
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Allocate the stack frame.  */
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  stack = alloca (cif->bytes);
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  gpcount = fpcount = 0;
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = cif->nargs;
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch ((*p_arg)->type)
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT8:
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(SINT8 *)avalue[i];
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT8:
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(UINT8 *)avalue[i];
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT16:
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(SINT16 *)avalue[i];
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT16:
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(UINT16 *)avalue[i];
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT32:
310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(SINT32 *)avalue[i];
311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT32:
313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT64:
316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT64:
317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_POINTER:
321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = (UINT64)(PTR64) *(void **)avalue[i];
322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_FLOAT:
325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (gpcount < 8 && fpcount < 8)
326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    stf_spill (&stack->fp_regs[fpcount++], *(float *)avalue[i]);
327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(UINT32 *)avalue[i];
328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_DOUBLE:
331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (gpcount < 8 && fpcount < 8)
332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    stf_spill (&stack->fp_regs[fpcount++], *(double *)avalue[i]);
333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  stack->gp_regs[gpcount++] = *(UINT64 *)avalue[i];
334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_LONGDOUBLE:
337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (gpcount & 1)
338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    gpcount++;
339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    stf_spill (&stack->fp_regs[fpcount++], *(__float80 *)avalue[i]);
341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy (&stack->gp_regs[gpcount], avalue[i], 16);
342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  gpcount += 2;
343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_STRUCT:
346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    size_t size = (*p_arg)->size;
348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    size_t align = (*p_arg)->alignment;
349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    int hfa_type = hfa_element_type (*p_arg, 0);
350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    FFI_ASSERT (align <= 16);
352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (align == 16 && (gpcount & 1))
353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      gpcount++;
354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (hfa_type != FFI_TYPE_VOID)
356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      {
357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		size_t hfa_size = hfa_type_size (hfa_type);
358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		size_t offset = 0;
359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		size_t gp_offset = gpcount * 8;
360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		while (fpcount < 8
362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       && offset < size
363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       && gp_offset < 8 * 8)
364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  {
365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    hfa_type_load (&stack->fp_regs[fpcount], hfa_type,
366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project				   avalue[i] + offset);
367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    offset += hfa_size;
368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    gp_offset += hfa_size;
369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    fpcount += 1;
370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  }
371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      }
372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    memcpy (&stack->gp_regs[gpcount], avalue[i], size);
374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    gpcount += (size + 7) / 8;
375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  abort ();
380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_call_unix (stack, rvalue, fn, cif->flags);
384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Closures represent a pair consisting of a function pointer, and
387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   some user data.  A closure is invoked by reinterpreting the closure
388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   as a function pointer, and branching to it.  Thus we can make an
389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   interpreted function callable as a C function: We turn the
390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   interpreter itself, together with a pointer specifying the
391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   interpreted procedure, into a closure.
392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   For IA64, function pointer are already pairs consisting of a code
394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   pointer, and a gp pointer.  The latter is needed to access global
395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   variables.  Here we set up such a pair as the first two words of
396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the closure (in the "trampoline" area), but we replace the gp
397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   pointer with a pointer to the closure itself.  We also add the real
398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   gp pointer to the closure.  This allows the function entry code to
399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   both retrieve the user data, and to restire the correct gp pointer.  */
400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_unix ();
402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure,
405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif* cif,
406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif*,void*,void**,void*),
407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* The layout of a function descriptor.  A C function pointer really
411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     points to one of these.  */
412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  struct ia64_fd
413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  {
414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    UINT64 code_pointer;
415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    UINT64 gp;
416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  };
417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  struct ffi_ia64_trampoline_struct
419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  {
420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    UINT64 code_pointer;	/* Pointer to ffi_closure_unix.  */
421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    UINT64 fake_gp;		/* Pointer to closure, installed as gp.  */
422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    UINT64 real_gp;		/* Real gp value.  */
423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  };
424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  struct ffi_ia64_trampoline_struct *tramp;
426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  struct ia64_fd *fd;
427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_UNIX);
429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp = (struct ffi_ia64_trampoline_struct *)closure->tramp;
431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  fd = (struct ia64_fd *)(void *)ffi_closure_unix;
432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp->code_pointer = fd->code_pointer;
434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp->real_gp = fd->gp;
435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp->fake_gp = (UINT64)(PTR64)codeloc;
436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif = cif;
437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun = fun;
439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source ProjectUINT64
445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack,
446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			void *rvalue, void *r8)
447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif;
449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avalue;
450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  long i, avn, gpcount, fpcount;
452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = cif->nargs;
455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avalue = alloca (avn * sizeof (void *));
456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the structure return value is passed in memory get that location
458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     from r8 so as to pass the value directly back to the caller.  */
459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->flags == FFI_TYPE_STRUCT)
460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    rvalue = r8;
461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  gpcount = fpcount = 0;
463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch ((*p_arg)->type)
466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT8:
468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT8:
469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 1);
470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT16:
472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT16:
473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 2);
474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT32:
476a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT32:
477a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], 4);
478a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
479a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT64:
480a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT64:
481a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = &stack->gp_regs[gpcount++];
482a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
483a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_POINTER:
484a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = endian_adjust(&stack->gp_regs[gpcount++], sizeof(void*));
485a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
486a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
487a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_FLOAT:
488a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (gpcount < 8 && fpcount < 8)
489a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
490a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      fpreg *addr = &stack->fp_regs[fpcount++];
491a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      float result;
492a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = addr;
493a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      ldf_fill (result, addr);
494a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(float *)addr = result;
495a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
496a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
497a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avalue[i] = endian_adjust(&stack->gp_regs[gpcount], 4);
498a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  gpcount++;
499a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
500a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
501a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_DOUBLE:
502a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (gpcount < 8 && fpcount < 8)
503a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
504a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      fpreg *addr = &stack->fp_regs[fpcount++];
505a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      double result;
506a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = addr;
507a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      ldf_fill (result, addr);
508a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(double *)addr = result;
509a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
510a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
511a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avalue[i] = &stack->gp_regs[gpcount];
512a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  gpcount++;
513a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
514a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
515a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_LONGDOUBLE:
516a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (gpcount & 1)
517a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    gpcount++;
518a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8)
519a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
520a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      fpreg *addr = &stack->fp_regs[fpcount++];
521a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      __float80 result;
522a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = addr;
523a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      ldf_fill (result, addr);
524a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(__float80 *)addr = result;
525a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
526a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
527a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avalue[i] = &stack->gp_regs[gpcount];
528a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  gpcount += 2;
529a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
530a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
531a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_STRUCT:
532a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
533a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    size_t size = (*p_arg)->size;
534a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    size_t align = (*p_arg)->alignment;
535a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    int hfa_type = hfa_element_type (*p_arg, 0);
536a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
537a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    FFI_ASSERT (align <= 16);
538a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (align == 16 && (gpcount & 1))
539a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      gpcount++;
540a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
541a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (hfa_type != FFI_TYPE_VOID)
542a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      {
543a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		size_t hfa_size = hfa_type_size (hfa_type);
544a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		size_t offset = 0;
545a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		size_t gp_offset = gpcount * 8;
546a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		void *addr = alloca (size);
547a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
548a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avalue[i] = addr;
549a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
550a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		while (fpcount < 8
551a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       && offset < size
552a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       && gp_offset < 8 * 8)
553a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  {
554a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    hfa_type_store (hfa_type, addr + offset,
555a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project				    &stack->fp_regs[fpcount]);
556a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    offset += hfa_size;
557a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    gp_offset += hfa_size;
558a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    fpcount += 1;
559a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  }
560a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
561a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		if (offset < size)
562a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  memcpy (addr + offset, (char *)stack->gp_regs + gp_offset,
563a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  size - offset);
564a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      }
565a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    else
566a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = &stack->gp_regs[gpcount];
567a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
568a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    gpcount += (size + 7) / 8;
569a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
570a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
571a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
572a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
573a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  abort ();
574a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
575a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
576a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
577a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun (cif, rvalue, avalue, closure->user_data);
578a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
579a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return cif->flags;
580a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
581