1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   m68k Foreign Function Interface
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ----------------------------------------------------------------------- */
6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h>
8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h>
9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h>
11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <unistd.h>
12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/syscall.h>
13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <asm/cachectl.h>
14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call_SYSV (extended_cif *,
16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    unsigned, unsigned,
17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    void *, void (*fn) ());
18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid *ffi_prep_args (void *stack, extended_cif *ecif);
19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_closure_SYSV (ffi_closure *);
20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_closure_struct_SYSV (ffi_closure *);
21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectunsigned int ffi_closure_SYSV_inner (ffi_closure *closure,
22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project				     void *resp, void *args);
23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space has
25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   been allocated for the function's arguments.  */
26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid *
28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_args (void *stack, extended_cif *ecif)
29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int i;
31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **p_argv;
32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *argp;
33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void *struct_value_ptr;
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && !ecif->cif->flags)
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    struct_value_ptr = ecif->rvalue;
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    struct_value_ptr = NULL;
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project       i != 0;
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project       i--, p_arg++)
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof (int))
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int) *(SINT8 *) *p_argv;
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) *p_argv;
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int) *(SINT16 *) *p_argv;
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) *p_argv;
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      memcpy (argp + sizeof (int) - z, *p_argv, z);
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT (0);
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = sizeof (int);
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy (argp, *p_argv, z);
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Align if necessary.  */
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((sizeof(int) - 1) & z)
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    z = ALIGN(z, sizeof(int));
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += z;
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return struct_value_ptr;
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_INT		1
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_DINT		2
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_FLOAT		4
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_DOUBLE	8
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_LDOUBLE	16
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_POINTER	32
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_STRUCT1	64
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define CIF_FLAGS_STRUCT2	128
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_cif_machdep (ffi_cif *cif)
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = 0;
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (cif->rtype->size)
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case 1:
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags = CIF_FLAGS_STRUCT1;
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case 2:
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags = CIF_FLAGS_STRUCT2;
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case 4:
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags = CIF_FLAGS_INT;
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case 8:
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags = CIF_FLAGS_DINT;
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags = 0;
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = CIF_FLAGS_FLOAT;
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = CIF_FLAGS_DOUBLE;
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_LONGDOUBLE:
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = CIF_FLAGS_LDOUBLE;
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_POINTER:
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = CIF_FLAGS_POINTER;
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT64:
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT64:
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = CIF_FLAGS_DINT;
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = CIF_FLAGS_INT;
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_call (ffi_cif *cif, void (*fn) (), void *rvalue, void **avalue)
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return value
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     address then we need to make one.  */
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (rvalue == NULL
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && cif->rtype->type == FFI_TYPE_STRUCT
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && cif->rtype->size > 8)
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = alloca (cif->rtype->size);
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_SYSV:
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_SYSV (&ecif, cif->bytes, cif->flags,
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     ecif.rvalue, fn);
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT (0);
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif)
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int i;
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **p_argv;
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *argp;
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = avalue;
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z <= 4)
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *p_argv = (void *) (argp + 4 - z);
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = 4;
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *p_argv = (void *) argp;
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Align if necessary */
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((sizeof(int) - 1) & z)
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    z = ALIGN(z, sizeof(int));
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += z;
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectunsigned int
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_SYSV_inner (ffi_closure *closure, void *resp, void *args)
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif;
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **arg_area;
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  arg_area = (void**) alloca (cif->nargs * sizeof (void *));
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_prep_incoming_args_SYSV(args, arg_area, cif);
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, resp, arg_area, closure->user_data);
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return cif->flags;
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure,
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif* cif,
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif*,void*,void**,void*),
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_SYSV);
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  *(unsigned short *)closure->tramp = 0x207c;
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  *(void **)(closure->tramp + 2) = codeloc;
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  *(unsigned short *)(closure->tramp + 6) = 0x4ef9;
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->rtype->type == FFI_TYPE_STRUCT
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && !cif->flags)
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    *(void **)(closure->tramp + 8) = ffi_closure_struct_SYSV;
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    *(void **)(closure->tramp + 8) = ffi_closure_SYSV;
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  syscall(SYS_cacheflush, codeloc, FLUSH_SCOPE_LINE,
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  FLUSH_CACHE_BOTH, FFI_TRAMPOLINE_SIZE);
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif  = cif;
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun  = fun;
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
279