1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - Copyright (c) 1998, 2008  Red Hat, Inc.
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ARM Foreign Function Interface
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Permission is hereby granted, free of charge, to any person obtaining
7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   a copy of this software and associated documentation files (the
8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ``Software''), to deal in the Software without restriction, including
9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   without limitation the rights to use, copy, modify, merge, publish,
10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   distribute, sublicense, and/or sell copies of the Software, and to
11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   permit persons to whom the Software is furnished to do so, subject to
12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the following conditions:
13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The above copyright notice and this permission notice shall be included
15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   in all copies or substantial portions of the Software.
16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   DEALINGS IN THE SOFTWARE.
25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ----------------------------------------------------------------------- */
26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h>
28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h>
29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h>
31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space
33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   has been allocated for the function's arguments */
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_prep_args(char *stack, extended_cif *ecif)
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int i;
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register void **p_argv;
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register char *argp;
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register ffi_type **p_arg;
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ( ecif->cif->flags == FFI_TYPE_STRUCT ) {
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    *(void **) argp = ecif->rvalue;
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    argp += 4;
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  }
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project       (i != 0);
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project       i--, p_arg++)
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Align if necessary */
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (((*p_arg)->alignment - 1) & (unsigned) argp) {
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	argp = (char *) ALIGN(argp, (*p_arg)->alignment);
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if ((*p_arg)->type == FFI_TYPE_STRUCT)
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	argp = (char *) ALIGN(argp, 4);
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = (*p_arg)->size;
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (z < sizeof(int))
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      z = sizeof(int);
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      switch ((*p_arg)->type)
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		{
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_SINT8:
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_UINT8:
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_SINT16:
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_UINT16:
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_STRUCT:
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  memcpy(argp, *p_argv, (*p_arg)->size);
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		default:
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  FFI_ASSERT(0);
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		}
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else if (z == sizeof(int))
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      memcpy(argp, *p_argv, z);
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  p_argv++;
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += z;
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return;
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif)
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Round the stack up to a multiple of 8 bytes.  This isn't needed
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     everywhere, but it is on some platforms, and it doesn't harm anything
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     when it isn't needed.  */
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->bytes = (cif->bytes + 7) & ~7;
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = (unsigned) cif->rtype->type;
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT64:
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT64:
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = (unsigned) FFI_TYPE_SINT64;
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (cif->rtype->size <= 4)
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	/* A Composite Type not larger than 4 bytes is returned in r0.  */
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	cif->flags = (unsigned)FFI_TYPE_INT;
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	/* A Composite Type larger than 4 bytes, or whose size cannot
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   be determined statically ... is stored in memory at an
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   address passed [in r0].  */
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	cif->flags = (unsigned)FFI_TYPE_STRUCT;
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = FFI_TYPE_INT;
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  unsigned, unsigned, unsigned *, void (*fn)(void));
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int small_struct = (cif->flags == FFI_TYPE_INT
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      && cif->rtype->type == FFI_TYPE_STRUCT);
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int temp;
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return	*/
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* value address then we need to make one		        */
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ((rvalue == NULL) &&
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      (cif->flags == FFI_TYPE_STRUCT))
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ecif.rvalue = alloca(cif->rtype->size);
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (small_struct)
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = &temp;
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_SYSV:
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    fn);
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (small_struct)
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    memcpy (rvalue, &temp, cif->rtype->size);
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/** private members **/
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project					 void** args, ffi_cif* cif);
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_closure_SYSV (ffi_closure *);
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This function is jumped to by the trampoline */
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectunsigned int
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_SYSV_inner (closure, respp, args)
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     ffi_closure *closure;
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     void **respp;
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     void *args;
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  // our various things...
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif       *cif;
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void         **arg_area;
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif         = closure->cif;
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  arg_area    = (void**) alloca (cif->nargs * sizeof (void*));
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* this call will initialize ARG_AREA, such that each
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * element in that array points to the corresponding
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * value on the stack; and if the function returns
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * a structure, it will re-set RESP to point to the
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * structure return address.  */
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, *respp, arg_area, closure->user_data);
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return cif->flags;
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@-exportheader@*/
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_incoming_args_SYSV(char *stack, void **rvalue,
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			    void **avalue, ffi_cif *cif)
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@=exportheader@*/
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int i;
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register void **p_argv;
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register char *argp;
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register ffi_type **p_arg;
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ( cif->flags == FFI_TYPE_STRUCT ) {
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    *rvalue = *(void **) argp;
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    argp += 4;
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  }
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = avalue;
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t alignment = (*p_arg)->alignment;
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (alignment < 4)
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	alignment = 4;
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Align if necessary */
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if ((alignment - 1) & (unsigned) argp) {
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	argp = (char *) ALIGN(argp, alignment);
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* because we're little endian, this is what it turns into.   */
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *p_argv = (void*) argp;
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += z;
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return;
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* How to make a trampoline.  */
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX)				\
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project({ unsigned char *__tramp = (unsigned char*)(TRAMP);			\
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __fun = (unsigned int)(FUN);				\
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   unsigned int  __ctx = (unsigned int)(CTX);				\
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*) &__tramp[0] = 0xe92d000f; /* stmfd sp!, {r0-r3} */	\
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*) &__tramp[4] = 0xe59f0000; /* ldr r0, [pc] */	\
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*) &__tramp[8] = 0xe59ff000; /* ldr pc, [pc] */	\
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*) &__tramp[12] = __ctx;				\
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   *(unsigned int*) &__tramp[16] = __fun;				\
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   __clear_cache((&__tramp[0]), (&__tramp[19]));			\
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project })
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* the cif must already be prep'ed */
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure,
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif* cif,
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif*,void*,void**,void*),
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_SYSV);
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       &ffi_closure_SYSV,  \
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		       codeloc);
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif  = cif;
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun  = fun;
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
310