1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - Copyright (c) 1996, 2007, 2008  Red Hat, Inc.
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           Copyright (c) 2008       David Daney
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   MIPS 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#ifdef __GNUC__
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#  if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#    define USE__BUILTIN___CLEAR_CACHE 1
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#  endif
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifndef USE__BUILTIN___CLEAR_CACHE
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <sys/cachectl.h>
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_DEBUG
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# define FFI_MIPS_STOP_HERE() ffi_stop_here()
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project# define FFI_MIPS_STOP_HERE() do {} while(0)
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FIX_ARGP \
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source ProjectFFI_ASSERT(argp <= &stack[bytes]); \
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectif (argp == &stack[bytes]) \
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{ \
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack; \
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_MIPS_STOP_HERE(); \
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FIX_ARGP
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   has been allocated for the function's arguments */
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void ffi_prep_args(char *stack,
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  extended_cif *ecif,
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  int bytes,
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  int flags)
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i;
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **p_argv;
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *argp;
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If more than 8 double words are used, the remainder go
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     on the stack. We reorder stuff on the stack here to
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     support this easily. */
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (bytes > 8 * sizeof(ffi_arg))
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    argp = &stack[bytes - (8 * sizeof(ffi_arg))];
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    argp = stack;
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  memset(stack, 0, bytes);
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ( ecif->cif->rstruct_flag != 0 )
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT )
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(ffi_arg *) argp = (ffi_arg) ecif->rvalue;
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += sizeof(ffi_arg);
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FIX_ARGP;
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++)
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      unsigned int a;
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Align if necessary.  */
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      a = (*p_arg)->alignment;
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (a < sizeof(ffi_arg))
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        a = sizeof(ffi_arg);
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if ((a - 1) & (unsigned long) argp)
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  argp = (char *) ALIGN(argp, a);
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  FIX_ARGP;
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      z = (*p_arg)->size;
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (z <= sizeof(ffi_arg))
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          int type = (*p_arg)->type;
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = sizeof(ffi_arg);
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          /* The size of a pointer depends on the ABI */
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          if (type == FFI_TYPE_POINTER)
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            type =
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              (ecif->cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch (type)
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_SINT8:
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(ffi_arg *)argp = *(SINT8 *)(* p_argv);
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_UINT8:
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(ffi_arg *)argp = *(UINT8 *)(* p_argv);
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_SINT16:
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(ffi_arg *)argp = *(SINT16 *)(* p_argv);
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_UINT16:
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(ffi_arg *)argp = *(UINT16 *)(* p_argv);
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_SINT32:
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(ffi_arg *)argp = *(SINT32 *)(* p_argv);
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_UINT32:
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(ffi_arg *)argp = *(UINT32 *)(* p_argv);
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /* This can only happen with 64bit slots.  */
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_FLOAT:
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(float *) argp = *(float *)(* p_argv);
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /* Handle structures.  */
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      default:
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		memcpy(argp, *p_argv, (*p_arg)->size);
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_O32
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  memcpy(argp, *p_argv, z);
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    unsigned long end = (unsigned long) argp + z;
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    unsigned long cap = (unsigned long) stack + bytes;
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    /* Check if the data will fit within the register space.
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	       Handle it if it doesn't.  */
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (end <= cap)
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      memcpy(argp, *p_argv, z);
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    else
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      {
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		unsigned long portion = cap - (unsigned long)argp;
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		memcpy(argp, *p_argv, portion);
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		argp = stack;
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                z -= portion;
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		memcpy(argp, (void*)((unsigned long)(*p_argv) + portion),
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                       z);
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      }
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += z;
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FIX_ARGP;
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* The n32 spec says that if "a chunk consists solely of a double
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   float field (but not a double, which is part of a union), it
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   is passed in a floating point register. Any other chunk is
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   passed in an integer register". This code traverses structure
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   definitions and generates the appropriate flags. */
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic unsigned
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectcalc_n32_struct_flags(ffi_type *arg, unsigned *loc, unsigned *arg_reg)
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned flags = 0;
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned index = 0;
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type *e;
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  while ((e = arg->elements[index]))
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Align this object.  */
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *loc = ALIGN(*loc, e->alignment);
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (e->type == FFI_TYPE_DOUBLE)
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          /* Already aligned to FFI_SIZEOF_ARG.  */
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          *arg_reg = *loc / FFI_SIZEOF_ARG;
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          if (*arg_reg > 7)
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            break;
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  flags += (FFI_TYPE_DOUBLE << (*arg_reg * FFI_FLAG_BITS));
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          *loc += e->size;
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        *loc += e->size;
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      index++;
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Next Argument register at alignment of FFI_SIZEOF_ARG.  */
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return flags;
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic unsigned
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectcalc_n32_return_struct_flags(ffi_type *arg)
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned flags = 0;
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned small = FFI_TYPE_SMALLSTRUCT;
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type *e;
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Returning structures under n32 is a tricky thing.
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     A struct with only one or two floating point fields
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     is returned in $f0 (and $f2 if necessary). Any other
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     struct results at most 128 bits are returned in $2
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     (the first 64 bits) and $3 (remainder, if necessary).
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     Larger structs are handled normally. */
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->size > 16)
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return 0;
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->size > 8)
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    small = FFI_TYPE_SMALLSTRUCT2;
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  e = arg->elements[0];
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (e->type == FFI_TYPE_DOUBLE)
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    flags = FFI_TYPE_DOUBLE;
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (e->type == FFI_TYPE_FLOAT)
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    flags = FFI_TYPE_FLOAT;
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (flags && (e = arg->elements[1]))
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (e->type == FFI_TYPE_DOUBLE)
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	flags += FFI_TYPE_DOUBLE << FFI_FLAG_BITS;
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (e->type == FFI_TYPE_FLOAT)
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	flags += FFI_TYPE_FLOAT << FFI_FLAG_BITS;
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	return small;
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (flags && (arg->elements[2]))
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* There are three arguments and the first two are
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     floats! This must be passed the old way. */
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  return small;
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    if (!flags)
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return small;
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return flags;
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing */
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif)
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->flags = 0;
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_O32
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the flags necessary for O32 processing.  FFI_O32_SOFT_FLOAT
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   * does not have special handling for floating point args.
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   */
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32)
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (cif->nargs > 0)
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch ((cif->arg_types)[0]->type)
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_FLOAT:
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_DOUBLE:
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      cif->flags += (cif->arg_types)[0]->type;
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default:
311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      break;
312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (cif->nargs > 1)
315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /* Only handle the second argument if the first
317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		 is a float or double. */
318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if (cif->flags)
319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		{
320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  switch ((cif->arg_types)[1]->type)
321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    {
322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    case FFI_TYPE_FLOAT:
323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    case FFI_TYPE_DOUBLE:
324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      cif->flags += (cif->arg_types)[1]->type << FFI_FLAG_BITS;
325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      break;
326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    default:
328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      break;
329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    }
330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		}
331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->abi == FFI_O32_SOFT_FLOAT)
338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (cif->rtype->type)
340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_VOID:
342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_STRUCT:
343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          break;
345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_SINT64:
347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_UINT64:
348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_DOUBLE:
349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          break;
351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_FLOAT:
353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        default:
354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          break;
356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* FFI_O32 */
361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (cif->rtype->type)
362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_VOID:
364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_STRUCT:
365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_FLOAT:
366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_DOUBLE:
367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 2);
368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          break;
369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_SINT64:
371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_UINT64:
372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags += FFI_TYPE_UINT64 << (FFI_FLAG_BITS * 2);
373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          break;
374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        default:
376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 2);
377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          break;
378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32
383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the flags necessary for N32 processing */
384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  {
385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    unsigned arg_reg = 0;
386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    unsigned loc = 0;
387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    unsigned count = (cif->nargs < 8) ? cif->nargs : 8;
388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    unsigned index = 0;
389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    unsigned struct_flags = 0;
391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    if (cif->rtype->type == FFI_TYPE_STRUCT)
393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	struct_flags = calc_n32_return_struct_flags(cif->rtype);
395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	if (struct_flags == 0)
397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    /* This means that the structure is being passed as
399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	       a hidden argument */
400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    arg_reg = 1;
402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    count = (cif->nargs < 7) ? cif->nargs : 7;
403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->rstruct_flag = !0;
405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	else
407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->rstruct_flag = 0;
408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    else
410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->rstruct_flag = 0;
411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    while (count-- > 0 && arg_reg < 8)
413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	switch ((cif->arg_types)[index]->type)
415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  case FFI_TYPE_FLOAT:
417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  case FFI_TYPE_DOUBLE:
418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->flags +=
419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              ((cif->arg_types)[index]->type << (arg_reg * FFI_FLAG_BITS));
420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    arg_reg++;
421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    break;
422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          case FFI_TYPE_LONGDOUBLE:
423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            /* Align it.  */
424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            arg_reg = ALIGN(arg_reg, 2);
425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            /* Treat it as two adjacent doubles.  */
426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->flags +=
427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            arg_reg++;
429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->flags +=
430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              (FFI_TYPE_DOUBLE << (arg_reg * FFI_FLAG_BITS));
431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            arg_reg++;
432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            break;
433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  case FFI_TYPE_STRUCT:
435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            loc = arg_reg * FFI_SIZEOF_ARG;
436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    cif->flags += calc_n32_struct_flags((cif->arg_types)[index],
437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project						&loc, &arg_reg);
438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    break;
439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  default:
441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    arg_reg++;
442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            break;
443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	index++;
446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    switch (cif->rtype->type)
450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      case FFI_TYPE_STRUCT:
452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (struct_flags == 0)
454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /* The structure is returned through a hidden
456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		 first argument. Do nothing, 'cause FFI_TYPE_VOID
457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		 is 0 */
458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /* The structure is returned via some tricky
462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		 mechanism */
463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      cif->flags += struct_flags << (4 + (FFI_FLAG_BITS * 8));
465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      case FFI_TYPE_VOID:
470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	/* Do nothing, 'cause FFI_TYPE_VOID is 0 */
471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	break;
472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      case FFI_TYPE_FLOAT:
474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      case FFI_TYPE_DOUBLE:
475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	cif->flags += cif->rtype->type << (FFI_FLAG_BITS * 8);
476a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	break;
477a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      case FFI_TYPE_LONGDOUBLE:
478a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	/* Long double is returned as if it were a struct containing
479a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   two doubles.  */
480a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	cif->flags += FFI_TYPE_STRUCT << (FFI_FLAG_BITS * 8);
481a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	cif->flags += (FFI_TYPE_DOUBLE + (FFI_TYPE_DOUBLE << FFI_FLAG_BITS))
482a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      << (4 + (FFI_FLAG_BITS * 8));
483a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	break;
484a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      default:
485a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	cif->flags += FFI_TYPE_INT << (FFI_FLAG_BITS * 8);
486a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	break;
487a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
488a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  }
489a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
490a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
491a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
492a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
493a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
494a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Low level routine for calling O32 functions */
495a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern int ffi_call_O32(void (*)(char *, extended_cif *, int, int),
496a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			extended_cif *, unsigned,
497a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			unsigned, unsigned *, void (*)(void));
498a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
499a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Low level routine for calling N32 functions */
500a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern int ffi_call_N32(void (*)(char *, extended_cif *, int, int),
501a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			extended_cif *, unsigned,
502a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			unsigned, unsigned *, void (*)(void));
503a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
504a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
505a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
506a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
507a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
508a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
509a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
510a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
511a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return	*/
512a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* value address then we need to make one		        */
513a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
514a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ((rvalue == NULL) &&
515a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      (cif->rtype->type == FFI_TYPE_STRUCT))
516a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = alloca(cif->rtype->size);
517a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
518a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
519a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
520a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
521a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
522a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_O32
523a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_O32:
524a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_O32_SOFT_FLOAT:
525a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_O32(ffi_prep_args, &ecif, cif->bytes,
526a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   cif->flags, ecif.rvalue, fn);
527a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
528a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
529a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
530a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef FFI_MIPS_N32
531a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_N32:
532a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_N64:
533a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
534a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        int copy_rvalue = 0;
535a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        void *rvalue_copy = ecif.rvalue;
536a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        if (cif->rtype->type == FFI_TYPE_STRUCT && cif->rtype->size < 16)
537a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          {
538a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            /* For structures smaller than 16 bytes we clobber memory
539a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project               in 8 byte increments.  Make a copy so we don't clobber
540a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project               the callers memory outside of the struct bounds.  */
541a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            rvalue_copy = alloca(16);
542a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            copy_rvalue = 1;
543a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          }
544a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        ffi_call_N32(ffi_prep_args, &ecif, cif->bytes,
545a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                     cif->flags, rvalue_copy, fn);
546a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        if (copy_rvalue)
547a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          memcpy(ecif.rvalue, rvalue_copy, cif->rtype->size);
548a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
549a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
550a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
551a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
552a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
553a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
554a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
555a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
556a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
557a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
558a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURES
559a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_O32)
560a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_O32(void);
561a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
562a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_N32(void);
563a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_MIPS_O32 */
564a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
565a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
566a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure *closure,
567a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif *cif,
568a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif*,void*,void**,void*),
569a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
570a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
571a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
572a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int *tramp = (unsigned int *) &closure->tramp[0];
573a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void * fn;
574a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *clear_location = (char *) codeloc;
575a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
576a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_O32)
577a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
578a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  fn = ffi_closure_O32;
579a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else /* FFI_MIPS_N32 */
580a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT(cif->abi == FFI_N32 || cif->abi == FFI_N64);
581a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  fn = ffi_closure_N32;
582a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_MIPS_O32 */
583a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
584a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32)
585a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* lui  $25,high(fn) */
586a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0x3c190000 | ((unsigned)fn >> 16);
587a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $25,low(fn)  */
588a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0x37390000 | ((unsigned)fn & 0xffff);
589a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* lui  $12,high(codeloc) */
590a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16);
591a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* jr   $25          */
592a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[3] = 0x03200008;
593a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $12,low(codeloc)  */
594a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff);
595a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
596a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* N64 has a somewhat larger trampoline.  */
597a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* lui  $25,high(fn) */
598a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0x3c190000 | ((unsigned long)fn >> 48);
599a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* lui  $12,high(codeloc) */
600a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0x3c0c0000 | ((unsigned long)codeloc >> 48);
601a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $25,mid-high(fn)  */
602a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[2] = 0x37390000 | (((unsigned long)fn >> 32 ) & 0xffff);
603a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $12,mid-high(codeloc)  */
604a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[3] = 0x358c0000 | (((unsigned long)codeloc >> 32) & 0xffff);
605a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* dsll $25,$25,16 */
606a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[4] = 0x0019cc38;
607a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* dsll $12,$12,16 */
608a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[5] = 0x000c6438;
609a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $25,mid-low(fn)  */
610a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[6] = 0x37390000 | (((unsigned long)fn >> 16 ) & 0xffff);
611a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $12,mid-low(codeloc)  */
612a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[7] = 0x358c0000 | (((unsigned long)codeloc >> 16) & 0xffff);
613a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* dsll $25,$25,16 */
614a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[8] = 0x0019cc38;
615a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* dsll $12,$12,16 */
616a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[9] = 0x000c6438;
617a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $25,low(fn)  */
618a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[10] = 0x37390000 | ((unsigned long)fn  & 0xffff);
619a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* jr   $25          */
620a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[11] = 0x03200008;
621a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* ori  $12,low(codeloc)  */
622a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff);
623a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
624a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
625a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
626a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif = cif;
627a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun = fun;
628a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
629a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
630a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef USE__BUILTIN___CLEAR_CACHE
631a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE);
632a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
633a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE);
634a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
635a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
636a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
637a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
638a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*
639a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Decodes the arguments to a function, which will be stored on the
640a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stack. AR is the pointer to the beginning of the integer arguments
641a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * (and, depending upon the arguments, some floating-point arguments
642a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * as well). FPR is a pointer to the area where floating point
643a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * registers have been saved, if any.
644a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
645a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * RVALUE is the location where the function return value will be
646a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stored. CLOSURE is the prepared closure to invoke.
647a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
648a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * This function should only be called from assembly, which is in
649a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * turn called from a trampoline.
650a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
651a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Returns the function return type.
652a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
653a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Based on the similar routine for sparc.
654a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */
655a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint
656a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_mips_inner_O32 (ffi_closure *closure,
657a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			    void *rvalue, ffi_arg *ar,
658a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			    double *fpr)
659a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
660a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif;
661a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avaluep;
662a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_arg *avalue;
663a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **arg_types;
664a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i, avn, argn, seen_int;
665a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
666a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
667a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avalue = alloca (cif->nargs * sizeof (ffi_arg));
668a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
669a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
670a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  seen_int = (cif->abi == FFI_O32_SOFT_FLOAT);
671a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argn = 0;
672a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
673a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT)
674a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
675a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      rvalue = (void *)(UINT32)ar[0];
676a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argn = 1;
677a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
678a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
679a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  i = 0;
680a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = cif->nargs;
681a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  arg_types = cif->arg_types;
682a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
683a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  while (i < avn)
684a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
685a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (i < 2 && !seen_int &&
686a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  (arg_types[i]->type == FFI_TYPE_FLOAT ||
687a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   arg_types[i]->type == FFI_TYPE_DOUBLE))
688a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
689a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __MIPSEB__
690a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (arg_types[i]->type == FFI_TYPE_FLOAT)
691a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avaluep[i] = ((char *) &fpr[i]) + sizeof (float);
692a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
693a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
694a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avaluep[i] = (char *) &fpr[i];
695a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
696a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
697a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
698a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (arg_types[i]->alignment == 8 && (argn & 0x1))
699a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    argn++;
700a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch (arg_types[i]->type)
701a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
702a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_SINT8:
703a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avaluep[i] = &avalue[i];
704a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(SINT8 *) &avalue[i] = (SINT8) ar[argn];
705a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
706a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
707a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_UINT8:
708a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avaluep[i] = &avalue[i];
709a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(UINT8 *) &avalue[i] = (UINT8) ar[argn];
710a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
711a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
712a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_SINT16:
713a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avaluep[i] = &avalue[i];
714a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(SINT16 *) &avalue[i] = (SINT16) ar[argn];
715a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
716a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
717a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case FFI_TYPE_UINT16:
718a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avaluep[i] = &avalue[i];
719a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(UINT16 *) &avalue[i] = (UINT16) ar[argn];
720a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
721a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
722a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      default:
723a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		avaluep[i] = (char *) &ar[argn];
724a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		break;
725a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
726a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  seen_int = 1;
727a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
728a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG;
729a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      i++;
730a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
731a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
732a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Invoke the closure. */
733a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
734a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
735a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->abi == FFI_O32_SOFT_FLOAT)
736a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
737a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (cif->rtype->type)
738a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
739a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_FLOAT:
740a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          return FFI_TYPE_INT;
741a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        case FFI_TYPE_DOUBLE:
742a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          return FFI_TYPE_UINT64;
743a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        default:
744a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          return cif->rtype->type;
745a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
746a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
747a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
748a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
749a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      return cif->rtype->type;
750a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
751a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
752a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
753a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if defined(FFI_MIPS_N32)
754a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
755a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void
756a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectcopy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type,
757a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                int argn, unsigned arg_offset, ffi_arg *ar,
758a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                ffi_arg *fpr)
759a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
760a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **elt_typep = type->elements;
761a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  while(*elt_typep)
762a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
763a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_type *elt_type = *elt_typep;
764a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      unsigned o;
765a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      char *tp;
766a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      char *argp;
767a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      char *fpp;
768a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
769a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      o = ALIGN(offset, elt_type->alignment);
770a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      arg_offset += o - offset;
771a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      offset = o;
772a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argn += arg_offset / sizeof(ffi_arg);
773a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      arg_offset = arg_offset % sizeof(ffi_arg);
774a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
775a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp = (char *)(ar + argn);
776a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      fpp = (char *)(argn >= 8 ? ar + argn : fpr + argn);
777a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
778a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      tp = target + offset;
779a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
780a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (elt_type->type == FFI_TYPE_DOUBLE)
781a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        *(double *)tp = *(double *)fpp;
782a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
783a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        memcpy(tp, argp + arg_offset, elt_type->size);
784a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
785a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      offset += elt_type->size;
786a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      arg_offset += elt_type->size;
787a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      elt_typep++;
788a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argn += arg_offset / sizeof(ffi_arg);
789a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      arg_offset = arg_offset % sizeof(ffi_arg);
790a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
791a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
792a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
793a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/*
794a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Decodes the arguments to a function, which will be stored on the
795a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stack. AR is the pointer to the beginning of the integer
796a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * arguments. FPR is a pointer to the area where floating point
797a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * registers have been saved.
798a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
799a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * RVALUE is the location where the function return value will be
800a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * stored. CLOSURE is the prepared closure to invoke.
801a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
802a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * This function should only be called from assembly, which is in
803a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * turn called from a trampoline.
804a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
805a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project * Returns the function return flags.
806a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project *
807a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project */
808a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint
809a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_closure_mips_inner_N32 (ffi_closure *closure,
810a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			    void *rvalue, ffi_arg *ar,
811a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			    ffi_arg *fpr)
812a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
813a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif;
814a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avaluep;
815a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_arg *avalue;
816a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **arg_types;
817a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i, avn, argn;
818a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
819a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
820a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avalue = alloca (cif->nargs * sizeof (ffi_arg));
821a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avaluep = alloca (cif->nargs * sizeof (ffi_arg));
822a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
823a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argn = 0;
824a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
825a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->rstruct_flag)
826a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
827a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if _MIPS_SIM==_ABIN32
828a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      rvalue = (void *)(UINT32)ar[0];
829a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else /* N64 */
830a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      rvalue = (void *)ar[0];
831a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
832a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argn = 1;
833a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
834a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
835a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  i = 0;
836a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = cif->nargs;
837a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  arg_types = cif->arg_types;
838a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
839a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  while (i < avn)
840a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
841a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (arg_types[i]->type == FFI_TYPE_FLOAT
842a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          || arg_types[i]->type == FFI_TYPE_DOUBLE)
843a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
844a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          ffi_arg *argp = argn >= 8 ? ar + argn : fpr + argn;
845a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef __MIPSEB__
846a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          if (arg_types[i]->type == FFI_TYPE_FLOAT && argn < 8)
847a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            avaluep[i] = ((char *) argp) + sizeof (float);
848a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          else
849a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
850a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            avaluep[i] = (char *) argp;
851a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
852a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
853a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        {
854a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          unsigned type = arg_types[i]->type;
855a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
856a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          if (arg_types[i]->alignment > sizeof(ffi_arg))
857a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg));
858a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
859a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          ffi_arg *argp = ar + argn;
860a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
861a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          /* The size of a pointer depends on the ABI */
862a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          if (type == FFI_TYPE_POINTER)
863a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            type = (cif->abi == FFI_N64) ? FFI_TYPE_SINT64 : FFI_TYPE_SINT32;
864a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
865a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project          switch (type)
866a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            {
867a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            case FFI_TYPE_SINT8:
868a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              avaluep[i] = &avalue[i];
869a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              *(SINT8 *) &avalue[i] = (SINT8) *argp;
870a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              break;
871a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
872a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            case FFI_TYPE_UINT8:
873a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              avaluep[i] = &avalue[i];
874a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              *(UINT8 *) &avalue[i] = (UINT8) *argp;
875a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              break;
876a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
877a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            case FFI_TYPE_SINT16:
878a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              avaluep[i] = &avalue[i];
879a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              *(SINT16 *) &avalue[i] = (SINT16) *argp;
880a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              break;
881a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
882a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            case FFI_TYPE_UINT16:
883a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              avaluep[i] = &avalue[i];
884a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              *(UINT16 *) &avalue[i] = (UINT16) *argp;
885a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              break;
886a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
887a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            case FFI_TYPE_SINT32:
888a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              avaluep[i] = &avalue[i];
889a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              *(SINT32 *) &avalue[i] = (SINT32) *argp;
890a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              break;
891a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
892a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            case FFI_TYPE_UINT32:
893a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              avaluep[i] = &avalue[i];
894a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              *(UINT32 *) &avalue[i] = (UINT32) *argp;
895a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              break;
896a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
897a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            case FFI_TYPE_STRUCT:
898a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              if (argn < 8)
899a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                {
900a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                  /* Allocate space for the struct as at least part of
901a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                     it was passed in registers.  */
902a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                  avaluep[i] = alloca(arg_types[i]->size);
903a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                  copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i],
904a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                                  argn, 0, ar, fpr);
905a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
906a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                  break;
907a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project                }
908a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              /* Else fall through.  */
909a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            default:
910a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              avaluep[i] = (char *) argp;
911a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project              break;
912a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project            }
913a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project        }
914a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg);
915a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      i++;
916a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
917a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
918a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Invoke the closure. */
919a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, rvalue, avaluep, closure->user_data);
920a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
921a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return cif->flags >> (FFI_FLAG_BITS * 8);
922a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
923a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
924a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_MIPS_N32 */
925a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
926a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif /* FFI_CLOSURES */
927