1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008  Red Hat, Inc.
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           Copyright (c) 2002  Ranjit Mathew
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           Copyright (c) 2002  Bo Thorsen
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           Copyright (c) 2002  Roger Sayle
6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   Copyright (C) 2008  Free Software Foundation, Inc.
7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   x86 Foreign Function Interface
9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Permission is hereby granted, free of charge, to any person obtaining
11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   a copy of this software and associated documentation files (the
12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ``Software''), to deal in the Software without restriction, including
13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   without limitation the rights to use, copy, modify, merge, publish,
14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   distribute, sublicense, and/or sell copies of the Software, and to
15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   permit persons to whom the Software is furnished to do so, subject to
16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the following conditions:
17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The above copyright notice and this permission notice shall be included
19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   in all copies or substantial portions of the Software.
20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   DEALINGS IN THE SOFTWARE.
29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ----------------------------------------------------------------------- */
30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifndef __x86_64__
32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h>
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h>
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h>
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   has been allocated for the function's arguments */
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_prep_args(char *stack, extended_cif *ecif)
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int i;
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register void **p_argv;
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register char *argp;
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register ffi_type **p_arg;
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (ecif->cif->flags == FFI_TYPE_STRUCT)
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(void **) argp = ecif->rvalue;
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += 4;
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project       i != 0;
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project       i--, p_arg++)
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Align if necessary */
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if ((sizeof(int) - 1) & (unsigned) argp)
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	argp = (char *) ALIGN(argp, sizeof(int));
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof(int))
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = sizeof(int);
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT32:
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT32:
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy(argp, *p_argv, z);
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += z;
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return;
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif)
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(X86) || defined(X86_DARWIN)
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT8:
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT16:
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT8:
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT16:
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT64:
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_LONGDOUBLE:
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = (unsigned) cif->rtype->type;
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT64:
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = FFI_TYPE_SINT64;
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifndef X86
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (cif->rtype->size == 1)
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (cif->rtype->size == 2)
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (cif->rtype->size == 4)
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags = FFI_TYPE_INT; /* same as int type */
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (cif->rtype->size == 8)
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags = FFI_TYPE_STRUCT;
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = FFI_TYPE_INT;
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86_DARWIN
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->bytes = (cif->bytes + 15) & ~0xF;
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  unsigned, unsigned, unsigned *, void (*fn)(void));
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86_WIN32
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  unsigned, unsigned, unsigned *, void (*fn)(void));
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* X86_WIN32 */
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return	*/
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* value address then we need to make one		        */
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ((rvalue == NULL) &&
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      (cif->flags == FFI_TYPE_STRUCT))
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ecif.rvalue = alloca(cif->rtype->size);
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_SYSV:
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    fn);
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86_WIN32
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_STDCALL:
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       ecif.rvalue, fn);
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* X86_WIN32 */
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/** private members **/
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project					 void** args, ffi_cif* cif);
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     __attribute__ ((regparm(1)));
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectunsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     __attribute__ ((regparm(1)));
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     __attribute__ ((regparm(1)));
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86_WIN32
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid FFI_HIDDEN ffi_closure_STDCALL (ffi_closure *)
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     __attribute__ ((regparm(1)));
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This function is jumped to by the trampoline */
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectunsigned int FFI_HIDDEN
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_SYSV_inner (closure, respp, args)
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     ffi_closure *closure;
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     void **respp;
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     void *args;
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* our various things...  */
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif       *cif;
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void         **arg_area;
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif         = closure->cif;
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* this call will initialize ARG_AREA, such that each
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * element in that array points to the corresponding
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * value on the stack; and if the function returns
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * a structure, it will re-set RESP to point to the
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * structure return address.  */
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, *respp, arg_area, closure->user_data);
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return cif->flags;
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			    ffi_cif *cif)
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int i;
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register void **p_argv;
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register char *argp;
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register ffi_type **p_arg;
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ( cif->flags == FFI_TYPE_STRUCT ) {
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    *rvalue = *(void **) argp;
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    argp += 4;
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  }
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = avalue;
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Align if necessary */
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if ((sizeof(int) - 1) & (unsigned) argp) {
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	argp = (char *) ALIGN(argp, sizeof(int));
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* because we're little endian, this is what it turns into.   */
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *p_argv = (void*) argp;
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += z;
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return;
310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __fun = (unsigned int)(FUN); \
317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __ctx = (unsigned int)(CTX); \
318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __dis = __fun - (__ctx + 10);	\
319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned char*) &__tramp[0] = 0xb8; \
320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned char *)  &__tramp[5] = 0xe9; \
322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*)  &__tramp[6] = __dis; /* jmp __fun  */ \
323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project })
324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FFI_INIT_TRAMPOLINE_STDCALL(TRAMP,FUN,CTX,SIZE)  \
326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __fun = (unsigned int)(FUN); \
328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __ctx = (unsigned int)(CTX); \
329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __dis = __fun - (__ctx + 10); \
330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned short __size = (unsigned short)(SIZE); \
331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned char*) &__tramp[0] = 0xb8; \
332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*)  &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned char *)  &__tramp[5] = 0xe8; \
334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*)  &__tramp[6] = __dis; /* call __fun  */ \
335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned char *)  &__tramp[10] = 0xc2; \
336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned short*)  &__tramp[11] = __size; /* ret __size  */ \
337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project })
338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* the cif must already be prep'ed */
340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure,
343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif* cif,
344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif*,void*,void**,void*),
345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->abi == FFI_SYSV)
349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_INIT_TRAMPOLINE (&closure->tramp[0],
351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                           &ffi_closure_SYSV,
352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                           (void*)codeloc);
353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86_WIN32
355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (cif->abi == FFI_STDCALL)
356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_INIT_TRAMPOLINE_STDCALL (&closure->tramp[0],
358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                                   &ffi_closure_STDCALL,
359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                                   (void*)codeloc, cif->bytes);
360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return FFI_BAD_ABI;
365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif  = cif;
368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun  = fun;
370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ------- Native raw API support -------------------------------- */
375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if !FFI_NO_RAW_API
377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_raw_closure_loc (ffi_raw_closure* closure,
380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  ffi_cif* cif,
381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  void *user_data,
383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  void *codeloc)
384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i;
386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->abi != FFI_SYSV) {
388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_BAD_ABI;
389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  }
390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  // we currently don't support certain kinds of arguments for raw
392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  // closures.  This should be implemented by a separate assembly language
393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  // routine, since it would require argument processing, something we
394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  // don't do now for performance.
395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = cif->nargs-1; i >= 0; i--)
397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       codeloc);
405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif  = cif;
407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun  = fun;
409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void
414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_args_raw(char *stack, extended_cif *ecif)
415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  memcpy (stack, ecif->avalue, ecif->cif->bytes);
417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* we borrow this routine from libffi (it must be changed, though, to
420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * actually call the function passed in the first argument.  as of
421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * libffi-1.20, this is not the case.)
422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */
423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void
425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      unsigned, unsigned *, void (*fn)(void));
427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86_WIN32
429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void
430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		 unsigned, unsigned *, void (*fn)(void));
432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* X86_WIN32 */
433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid
435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue)
436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avalue = (void **)fake_avalue;
439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return	*/
444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* value address then we need to make one		        */
445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ((rvalue == NULL) &&
447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      (cif->rtype->type == FFI_TYPE_STRUCT))
448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ecif.rvalue = alloca(cif->rtype->size);
450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_SYSV:
458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    ecif.rvalue, fn);
460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef X86_WIN32
462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_STDCALL:
463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       ecif.rvalue, fn);
465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* X86_WIN32 */
467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* __x86_64__  */
476