1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Kaz Kojima
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           Copyright (c) 2008 Red Hat, Inc.
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SuperH Foreign Function Interface
6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Permission is hereby granted, free of charge, to any person obtaining
8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   a copy of this software and associated documentation files (the
9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ``Software''), to deal in the Software without restriction, including
10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   without limitation the rights to use, copy, modify, merge, publish,
11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   distribute, sublicense, and/or sell copies of the Software, and to
12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   permit persons to whom the Software is furnished to do so, subject to
13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the following conditions:
14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The above copyright notice and this permission notice shall be included
16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   in all copies or substantial portions of the Software.
17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   DEALINGS IN THE SOFTWARE.
26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ----------------------------------------------------------------------- */
27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h>
29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h>
30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdlib.h>
32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define NGREGARG 4
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define NFREGARG 8
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__HITACHI__)
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* If the structure has essentialy an unique element, return its type.  */
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectsimple_type (ffi_type *arg)
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->type != FFI_TYPE_STRUCT)
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return arg->type;
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (arg->elements[1])
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_STRUCT;
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return simple_type (arg->elements[0]);
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectreturn_type (ffi_type *arg)
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned short type;
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->type != FFI_TYPE_STRUCT)
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return arg->type;
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  type = simple_type (arg->elements[0]);
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (! arg->elements[1])
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (type)
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT8:
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT8:
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT16:
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT16:
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT32:
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT32:
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  return FFI_TYPE_INT;
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  return type;
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* gcc uses r0/r1 pair for some kind of structures.  */
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->size <= 2 * sizeof (int))
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      int i = 0;
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_type *e;
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      while ((e = arg->elements[i++]))
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  type = simple_type (e);
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch (type)
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT32:
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT32:
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_INT:
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_FLOAT:
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      return FFI_TYPE_UINT64;
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_TYPE_STRUCT;
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   has been allocated for the function's arguments */
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_prep_args(char *stack, extended_cif *ecif)
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int i;
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register int tmp;
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int avn;
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register void **p_argv;
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register char *argp;
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register ffi_type **p_arg;
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int greg, ireg;
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int freg = 0;
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tmp = 0;
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(void **) argp = ecif->rvalue;
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += 4;
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ireg = STRUCT_VALUE_ADDRESS_WITH_ARG ? 1 : 0;
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ireg = 0;
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set arguments for registers.  */
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  greg = ireg;
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = ecif->cif->nargs;
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof(int))
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg++ >= NGREGARG)
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = sizeof(int);
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += z;
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (z == sizeof(int))
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (freg++ >= NFREGARG)
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (greg++ >= NGREGARG)
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += z;
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg + 1 >= NFREGARG)
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg = (freg + 1) & ~1;
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg += 2;
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy (argp, *p_argv, z);
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += z;
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  int n = (z + sizeof (int) - 1) / sizeof (int);
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg + n - 1 >= NGREGARG)
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg >= NGREGARG)
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  greg += n;
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy (argp, *p_argv, z);
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += n * sizeof (int);
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set arguments on stack.  */
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  greg = ireg;
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  freg = 0;
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof(int))
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg++ < NGREGARG)
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = sizeof(int);
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += z;
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (z == sizeof(int))
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (freg++ < NFREGARG)
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (greg++ < NGREGARG)
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += z;
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg + 1 < NFREGARG)
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg = (freg + 1) & ~1;
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg += 2;
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      continue;
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy (argp, *p_argv, z);
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += z;
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  int n = (z + sizeof (int) - 1) / sizeof (int);
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg + n - 1 < NGREGARG)
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      greg += n;
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      continue;
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if (! defined(__SH4__))
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else if (greg < NGREGARG)
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      greg = NGREGARG;
310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      continue;
311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy (argp, *p_argv, z);
314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += n * sizeof (int);
315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return;
319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */
322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif)
323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i, j;
325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int size, type;
326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int n, m;
327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int greg;
328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int freg = 0;
330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->flags = 0;
333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  greg = ((return_type (cif->rtype) == FFI_TYPE_STRUCT) &&
335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  STRUCT_VALUE_ADDRESS_WITH_ARG) ? 1 : 0;
336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = j = 0; i < cif->nargs && j < 12; i++)
339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      type = (cif->arg_types)[i]->type;
341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (type)
342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_FLOAT:
344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg >= NFREGARG)
345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg++;
347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  j++;
349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_DOUBLE:
352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((freg + 1) >= NFREGARG)
353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg = (freg + 1) & ~1;
355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg += 2;
356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags += ((cif->arg_types)[i]->type) << (2 * j);
357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  j++;
358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  size = (cif->arg_types)[i]->size;
362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  n = (size + sizeof (int) - 1) / sizeof (int);
363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg + n - 1 >= NGREGARG)
364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  greg += n;
366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  for (m = 0; m < n; m++)
367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->flags += FFI_TYPE_INT << (2 * j++);
368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = j = 0; i < cif->nargs && j < 4; i++)
373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size = (cif->arg_types)[i]->size;
375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      n = (size + sizeof (int) - 1) / sizeof (int);
376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (greg >= NGREGARG)
377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	continue;
378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (greg + n - 1 >= NGREGARG)
379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	n = NGREGARG - greg;
380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      greg += n;
381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      for (m = 0; m < n; m++)
382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        cif->flags += FFI_TYPE_INT << (2 * j++);
383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags += (unsigned) (return_type (cif->rtype)) << 24;
391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT64:
397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT64:
398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags += (unsigned) cif->rtype->type << 24;
399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags += FFI_TYPE_INT << 24;
403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  unsigned, unsigned, unsigned *, void (*fn)(void));
411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT64 trvalue;
416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return	*/
421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* value address then we need to make one		        */
422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->rtype->type == FFI_TYPE_STRUCT
424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = &trvalue;
426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if ((rvalue == NULL) &&
427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      (cif->rtype->type == FFI_TYPE_STRUCT))
428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ecif.rvalue = alloca(cif->rtype->size);
430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_SYSV:
437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    fn);
439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (rvalue
446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && cif->rtype->type == FFI_TYPE_STRUCT
447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    memcpy (rvalue, &trvalue, cif->rtype->size);
449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_SYSV (void);
452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void __ic_invalidate (void *line);
454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure,
458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif* cif,
459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif*, void*, void**, void*),
460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int *tramp;
464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int insn;
465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp = (unsigned int *) &closure->tramp[0];
469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set T bit if the function returns a struct pointed with R2.  */
470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  insn = (return_type (cif->rtype) == FFI_TYPE_STRUCT
471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  ? 0x0018 /* sett */
472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  : 0x0008 /* clrt */);
473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __LITTLE_ENDIAN__
475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0xd301d102;
476a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0x0000412b | (insn << 16);
477a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
478a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0xd102d301;
479a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0x412b0000 | insn;
480a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
481a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  *(void **) &tramp[2] = (void *)codeloc;          /* ctx */
482a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
483a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
484a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif = cif;
485a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun = fun;
486a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
487a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
488a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
489a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Flush the icache.  */
490a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __ic_invalidate(codeloc);
491a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
492a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
493a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
494a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
495a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
496a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Basically the trampoline invokes ffi_closure_SYSV, and on
497a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * entry, r3 holds the address of the closure.
498a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * After storing the registers that could possibly contain
499a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * parameters to be passed into the stack frame and setting
500a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * up space for a return value, ffi_closure_SYSV invokes the
501a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * following helper function to do most of the work.
502a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */
503a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
504a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __LITTLE_ENDIAN__
505a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define OFS_INT8	0
506a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define OFS_INT16	0
507a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
508a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define OFS_INT8	3
509a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define OFS_INT16	2
510a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
511a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
512a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint
513a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue,
514a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			 unsigned long *pgr, unsigned long *pfr,
515a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			 unsigned long *pst)
516a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
517a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avalue;
518a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
519a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i, avn;
520a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int ireg, greg = 0;
521a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
522a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int freg = 0;
523a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
524a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif;
525a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
526a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
527a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avalue = alloca(cif->nargs * sizeof(void *));
528a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
529a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Copy the caller's structure return value address so that the closure
530a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     returns the data directly to the caller.  */
531a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->rtype->type == FFI_TYPE_STRUCT && STRUCT_VALUE_ADDRESS_WITH_ARG)
532a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
533a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      rvalue = (void *) *pgr++;
534a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ireg = 1;
535a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
536a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
537a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ireg = 0;
538a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
539a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
540a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  greg = ireg;
541a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = cif->nargs;
542a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
543a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Grab the addresses of the arguments from the stack frame.  */
544a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
545a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
546a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
547a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
548a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
549a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof(int))
550a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
551a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg++ >= NGREGARG)
552a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
553a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
554a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = sizeof(int);
555a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
556a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
557a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
558a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
559a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = (((char *)pgr) + OFS_INT8);
560a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
561a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
562a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
563a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
564a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = (((char *)pgr) + OFS_INT16);
565a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
566a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
567a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
568a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = pgr;
569a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
570a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
571a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
572a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
573a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
574a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  pgr++;
575a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
576a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (z == sizeof(int))
577a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
578a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
579a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
580a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
581a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (freg++ >= NFREGARG)
582a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
583a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = pfr;
584a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      pfr++;
585a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
586a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
587a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
588a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
589a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (greg++ >= NGREGARG)
590a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
591a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = pgr;
592a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      pgr++;
593a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
594a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
595a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
596a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
597a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
598a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg + 1 >= NFREGARG)
599a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
600a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg & 1)
601a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    pfr++;
602a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg = (freg + 1) & ~1;
603a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg += 2;
604a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = pfr;
605a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  pfr += 2;
606a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
607a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
608a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
609a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
610a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  int n = (z + sizeof (int) - 1) / sizeof (int);
611a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
612a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg + n - 1 >= NGREGARG)
613a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
614a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
615a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg >= NGREGARG)
616a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
617a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
618a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  greg += n;
619a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = pgr;
620a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  pgr += n;
621a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
622a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
623a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
624a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  greg = ireg;
625a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
626a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  freg = 0;
627a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
628a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
629a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
630a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
631a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
632a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
633a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
634a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof(int))
635a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
636a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg++ < NGREGARG)
637a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
638a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
639a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = sizeof(int);
640a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
641a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
642a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
643a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
644a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = (((char *)pst) + OFS_INT8);
645a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
646a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
647a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
648a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
649a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = (((char *)pst) + OFS_INT16);
650a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
651a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
652a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
653a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = pst;
654a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
655a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
656a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
657a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
658a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
659a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  pst++;
660a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
661a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (z == sizeof(int))
662a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
663a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
664a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
665a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
666a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (freg++ < NFREGARG)
667a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
668a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
669a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
670a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
671a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
672a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (greg++ < NGREGARG)
673a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		continue;
674a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
675a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = pst;
676a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  pst++;
677a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
678a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(__SH4__)
679a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
680a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
681a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg + 1 < NFREGARG)
682a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
683a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg = (freg + 1) & ~1;
684a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg += 2;
685a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      continue;
686a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
687a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = pst;
688a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  pst += 2;
689a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
690a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
691a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
692a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
693a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  int n = (z + sizeof (int) - 1) / sizeof (int);
694a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg + n - 1 < NGREGARG)
695a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
696a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      greg += n;
697a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      continue;
698a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
699a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if (! defined(__SH4__))
700a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else if (greg < NGREGARG)
701a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
702a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      greg += n;
703a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      pst += greg - NGREGARG;
704a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      continue;
705a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
706a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
707a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = pst;
708a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  pst += n;
709a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
710a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
711a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
712a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, rvalue, avalue, closure->user_data);
713a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
714a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
715a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return return_type (cif->rtype);
716a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
717