1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - Copyright (c) 2003, 2004 Kaz Kojima
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           Copyright (c) 2008 Anthony Green
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SuperH SHmedia 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 8
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define NFREGARG 12
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic int
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectreturn_type (ffi_type *arg)
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->type != FFI_TYPE_STRUCT)
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return arg->type;
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* gcc uses r2 if the result can be packed in on register.  */
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->size <= sizeof (UINT8))
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_UINT8;
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (arg->size <= sizeof (UINT16))
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_UINT16;
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (arg->size <= sizeof (UINT32))
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_UINT32;
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (arg->size <= sizeof (UINT64))
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_UINT64;
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_TYPE_STRUCT;
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   has been allocated for the function's arguments */
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@-exportheader@*/
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_prep_args(char *stack, extended_cif *ecif)
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@=exportheader@*/
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int i;
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int avn;
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register void **p_argv;
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register char *argp;
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register ffi_type **p_arg;
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (return_type (ecif->cif->rtype) == FFI_TYPE_STRUCT)
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(void **) argp = ecif->rvalue;
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += sizeof (UINT64);
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = ecif->cif->nargs;
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = ecif->cif->arg_types; i < avn; i++, p_arg++, p_argv++)
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      int align;
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      align = (*p_arg)->alignment;
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof (UINT32))
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(SINT64 *) argp = (SINT64) *(SINT8 *)(*p_argv);
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(UINT64 *) argp = (UINT64) *(UINT8 *)(*p_argv);
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(SINT64 *) argp = (SINT64) *(SINT16 *)(*p_argv);
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(UINT64 *) argp = (UINT64) *(UINT16 *)(*p_argv);
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      memcpy (argp, *p_argv, z);
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += sizeof (UINT64);
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (z == sizeof (UINT32) && align == sizeof (UINT32))
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_INT:
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT32:
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(SINT64 *) argp = (SINT64) *(SINT32 *) (*p_argv);
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_FLOAT:
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_POINTER:
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT32:
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      *(UINT64 *) argp = (UINT64) *(UINT32 *) (*p_argv);
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += sizeof (UINT64);
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (z == sizeof (UINT64)
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	       && align == sizeof (UINT64)
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	       && ((int) *p_argv & (sizeof (UINT64) - 1)) == 0)
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT64 *) argp = *(UINT64 *) (*p_argv);
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += sizeof (UINT64);
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy (argp, *p_argv, z);
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp += n * sizeof (UINT64);
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return;
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif)
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i, j;
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int size, type;
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int n, m;
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int greg;
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int freg;
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  greg = (return_type (cif->rtype) == FFI_TYPE_STRUCT ? 1 : 0);
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  freg = 0;
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->flags2 = 0;
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = j = 0; i < cif->nargs; i++)
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      type = (cif->arg_types)[i]->type;
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (type)
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_FLOAT:
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  greg++;
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->bytes += sizeof (UINT64) - sizeof (float);
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg >= NFREGARG - 1)
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  freg++;
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_DOUBLE:
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg++ >= NGREGARG && (freg + 1) >= NFREGARG)
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((freg + 1) < NFREGARG)
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg = (freg + 1) & ~1;
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg += 2;
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      cif->flags2 += ((cif->arg_types)[i]->type) << (2 * j++);
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->flags2 += FFI_TYPE_INT << (2 * j++);
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  size = (cif->arg_types)[i]->size;
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (size < sizeof (UINT64))
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->bytes += sizeof (UINT64) - size;
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  n = (size + sizeof (UINT64) - 1) / sizeof (UINT64);
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (greg >= NGREGARG)
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    continue;
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else if (greg + n - 1 >= NGREGARG)
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    greg = NGREGARG;
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    greg += n;
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  for (m = 0; m < n; m++)
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->flags2 += FFI_TYPE_INT << (2 * j++);
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = return_type (cif->rtype);
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT64:
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT64:
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = cif->rtype->type;
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = FFI_TYPE_INT;
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@-declundef@*/
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@-exportheader@*/
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_SYSV(void (*)(char *, extended_cif *),
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  /*@out@*/ extended_cif *,
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  unsigned, unsigned, long long,
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  /*@out@*/ unsigned *,
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  void (*fn)(void));
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@=declundef@*/
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*@=exportheader@*/
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(/*@dependent@*/ ffi_cif *cif,
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      void (*fn)(void),
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /*@out@*/ void *rvalue,
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /*@dependent@*/ void **avalue)
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT64 trvalue;
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return	*/
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* value address then we need to make one		        */
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->rtype->type == FFI_TYPE_STRUCT
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = &trvalue;
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if ((rvalue == NULL) &&
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      (cif->rtype->type == FFI_TYPE_STRUCT))
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /*@-sysunrecog@*/
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ecif.rvalue = alloca(cif->rtype->size);
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /*@=sysunrecog@*/
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_SYSV:
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /*@-usedef@*/
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    cif->flags, cif->flags2, ecif.rvalue, fn);
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /*@=usedef@*/
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (rvalue
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && cif->rtype->type == FFI_TYPE_STRUCT
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && return_type (cif->rtype) != FFI_TYPE_STRUCT)
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    memcpy (rvalue, &trvalue, cif->rtype->size);
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_SYSV (void);
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void __ic_invalidate (void *line);
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure (ffi_closure *closure,
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  ffi_cif *cif,
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  void (*fun)(ffi_cif*, void*, void**, void*),
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  void *user_data)
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int *tramp;
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_GCC_SYSV);
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp = (unsigned int *) &closure->tramp[0];
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Since ffi_closure is an aligned object, the ffi trampoline is
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     called as an SHcompact code.  Sigh.
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     SHcompact part:
310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     mova @(1,pc),r0; add #1,r0; jmp @r0; nop;
311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     SHmedia part:
312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     movi fnaddr >> 16,r1; shori fnaddr,r1; ptabs/l r1,tr0
313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     movi cxt >> 16,r1; shori cxt,r1; blink tr0,r63  */
314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __LITTLE_ENDIAN__
315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0x7001c701;
316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0x0009402b;
317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0xc7017001;
319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0x402b0009;
320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[4] = 0x6bf10600;
324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10;
325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10;
326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[7] = 0x4401fff0;
327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif = cif;
329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun = fun;
330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Flush the icache.  */
333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp));
334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Basically the trampoline invokes ffi_closure_SYSV, and on
339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * entry, r3 holds the address of the closure.
340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * After storing the registers that could possibly contain
341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * parameters to be passed into the stack frame and setting
342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * up space for a return value, ffi_closure_SYSV invokes the
343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * following helper function to do most of the work.
344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */
345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint
347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_helper_SYSV (ffi_closure *closure, UINT64 *rvalue,
348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			 UINT64 *pgr, UINT64 *pfr, UINT64 *pst)
349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avalue;
351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i, avn;
353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int greg, freg;
354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif;
355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avalue = alloca (cif->nargs * sizeof (void *));
358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Copy the caller's structure return value address so that the closure
360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     returns the data directly to the caller.  */
361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (return_type (cif->rtype) == FFI_TYPE_STRUCT)
362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      rvalue = *pgr;
364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      greg = 1;
365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    greg = 0;
368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  freg = 0;
370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = cif->nargs;
372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Grab the addresses of the arguments from the stack frame.  */
374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++)
375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      void *p;
378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z < sizeof (UINT32))
381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  p = pgr + greg++;
383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((*p_arg)->type)
385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT8:
387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT8:
388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SINT16:
389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_UINT16:
390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_STRUCT:
391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __LITTLE_ENDIAN__
392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = p;
393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = ((char *) p) + sizeof (UINT32) - z;
395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      FFI_ASSERT(0);
400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (z == sizeof (UINT32))
403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((*p_arg)->type == FFI_TYPE_FLOAT)
405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (freg < NFREGARG - 1)
407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __LITTLE_ENDIAN__
408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avalue[i] = (UINT32 *) pfr + (1 ^ freg++);
409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avalue[i] = (UINT32 *) pfr + freg++;
411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      else
413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __LITTLE_ENDIAN__
414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avalue[i] = pgr + greg;
415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avalue[i] = (UINT32 *) (pgr + greg) + 1;
417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __LITTLE_ENDIAN__
421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avalue[i] = pgr + greg;
422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avalue[i] = (UINT32 *) (pgr + greg) + 1;
424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  greg++;
426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if ((*p_arg)->type == FFI_TYPE_DOUBLE)
428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (freg + 1 >= NFREGARG)
430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avalue[i] = pgr + greg;
431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg = (freg + 1) & ~1;
434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = pfr + (freg >> 1);
435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      freg += 2;
436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  greg++;
438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  int n = (z + sizeof (UINT64) - 1) / sizeof (UINT64);
442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = pgr + greg;
444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  greg += n;
445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, rvalue, avalue, closure->user_data);
449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Tell ffi_closure_SYSV how to perform return type promotions.  */
451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return return_type (cif->rtype);
452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
454