1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - Copyright (c) 1998 Cygnus Solutions
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           Copyright (c) 2004 Simon Posnjak
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   Copyright (c) 2005 Axis Communications AB
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	   Copyright (C) 2007 Free Software Foundation, Inc.
6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   CRIS Foreign Function Interface
8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Permission is hereby granted, free of charge, to any person obtaining
10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   a copy of this software and associated documentation files (the
11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ``Software''), to deal in the Software without restriction, including
12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   without limitation the rights to use, copy, modify, merge, publish,
13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   distribute, sublicense, and/or sell copies of the Software, and to
14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   permit persons to whom the Software is furnished to do so, subject to
15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the following conditions:
16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The above copyright notice and this permission notice shall be included
18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   in all copies or substantial portions of the Software.
19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   IN NO EVENT SHALL SIMON POSNJAK BE LIABLE FOR ANY CLAIM, DAMAGES OR
24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OTHER DEALINGS IN THE SOFTWARE.
27a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ----------------------------------------------------------------------- */
28a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
29a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi.h>
30a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <ffi_common.h>
31a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
32a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG)
33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic ffi_status
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectinitialize_aggregate_packed_struct (ffi_type * arg)
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **ptr;
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (arg != NULL);
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (arg->elements != NULL);
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (arg->size == 0);
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (arg->alignment == 0);
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ptr = &(arg->elements[0]);
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  while ((*ptr) != NULL)
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (((*ptr)->size == 0)
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	return FFI_BAD_TYPEDEF;
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT (ffi_type_test ((*ptr)));
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      arg->size += (*ptr)->size;
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      arg->alignment = (arg->alignment > (*ptr)->alignment) ?
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	arg->alignment : (*ptr)->alignment;
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ptr++;
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (arg->size == 0)
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_BAD_TYPEDEF;
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_OK;
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectint
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_args (char *stack, extended_cif * ecif)
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int i;
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int struct_count = 0;
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **p_argv;
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *argp;
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  argp = stack;
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project       (i != 0); i--, p_arg++)
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      size_t z;
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch ((*p_arg)->type)
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_STRUCT:
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    z = (*p_arg)->size;
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    if (z <= 4)
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      {
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		memcpy (argp, *p_argv, z);
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		z = 4;
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      }
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    else if (z <= 8)
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      {
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		memcpy (argp, *p_argv, z);
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		z = 8;
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      }
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    else
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      {
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		unsigned int uiLocOnStack;
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		z = sizeof (void *);
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		uiLocOnStack = 4 * ecif->cif->nargs + struct_count;
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		struct_count = struct_count + (*p_arg)->size;
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		*(unsigned int *) argp =
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  (unsigned int) (UINT32 *) (stack + uiLocOnStack);
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		memcpy ((stack + uiLocOnStack), *p_argv, (*p_arg)->size);
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      }
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    break;
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z = (*p_arg)->size;
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (z < sizeof (int))
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_SINT8:
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(signed int *) argp = (signed int) *(SINT8 *) (*p_argv);
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_UINT8:
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(unsigned int *) argp =
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    (unsigned int) *(UINT8 *) (*p_argv);
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_SINT16:
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(signed int *) argp = (signed int) *(SINT16 *) (*p_argv);
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		case FFI_TYPE_UINT16:
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  *(unsigned int *) argp =
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		    (unsigned int) *(UINT16 *) (*p_argv);
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  break;
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		default:
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  FFI_ASSERT (0);
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		}
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      z = sizeof (int);
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else if (z == sizeof (int))
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    *(unsigned int *) argp = (unsigned int) *(UINT32 *) (*p_argv);
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    memcpy (argp, *p_argv, z);
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      argp += z;
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return (struct_count);
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_cif (ffi_cif * cif,
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      ffi_abi abi, unsigned int nargs,
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      ffi_type * rtype, ffi_type ** atypes)
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned bytes = 0;
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int i;
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **ptr;
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif != NULL);
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT ((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI));
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->abi = abi;
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->arg_types = atypes;
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->nargs = nargs;
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->rtype = rtype;
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->flags = 0;
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ((cif->rtype->size == 0)
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && (initialize_aggregate_packed_struct (cif->rtype) != FFI_OK))
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_BAD_TYPEDEF;
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT_VALID_TYPE (cif->rtype);
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (((*ptr)->size == 0)
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  && (initialize_aggregate_packed_struct ((*ptr)) != FFI_OK))
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	return FFI_BAD_TYPEDEF;
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT_VALID_TYPE (*ptr);
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (((*ptr)->alignment - 1) & bytes)
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	bytes = ALIGN (bytes, (*ptr)->alignment);
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if ((*ptr)->type == FFI_TYPE_STRUCT)
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if ((*ptr)->size > 8)
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      bytes += (*ptr)->size;
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      bytes += sizeof (void *);
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      if ((*ptr)->size > 4)
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		bytes += 8;
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      else
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		bytes += 4;
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	bytes += STACK_ARG_SIZE ((*ptr)->size);
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif->bytes = bytes;
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return ffi_prep_cif_machdep (cif);
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_cif_machdep (ffi_cif * cif)
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
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 = (unsigned) 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 Projectextern void ffi_call_SYSV (int (*)(char *, extended_cif *),
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			   extended_cif *,
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			   unsigned, unsigned, unsigned *, void (*fn) ())
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     __attribute__ ((__visibility__ ("hidden")));
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_call (ffi_cif * cif, void (*fn) (), void *rvalue, void **avalue)
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if ((rvalue == NULL) && (cif->rtype->type == FFI_TYPE_STRUCT))
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ecif.rvalue = alloca (cif->rtype->size);
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_SYSV:
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_SYSV (ffi_prep_args, &ecif, cif->bytes,
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     cif->flags, ecif.rvalue, fn);
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT (0);
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Because the following variables are not exported outside libffi, we
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   mark them hidden.  */
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Assembly code for the jump stub.  */
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern const char ffi_cris_trampoline_template[]
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __attribute__ ((__visibility__ ("hidden")));
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Offset into ffi_cris_trampoline_template of where to put the
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi_prep_closure_inner function.  */
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern const int ffi_cris_trampoline_fn_offset
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __attribute__ ((__visibility__ ("hidden")));
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Offset into ffi_cris_trampoline_template of where to put the
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   closure data.  */
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern const int ffi_cris_trampoline_closure_offset
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project __attribute__ ((__visibility__ ("hidden")));
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This function is sibling-called (jumped to) by the closure
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   trampoline.  We get R10..R13 at PARAMS[0..3] and a copy of [SP] at
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   PARAMS[4] to simplify handling of a straddling parameter.  A copy
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   of R9 is at PARAMS[5] and SP at PARAMS[6].  These parameters are
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   put at the appropriate place in CLOSURE which is then executed and
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the return value is passed back to the caller.  */
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic unsigned long long
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_inner (void **params, ffi_closure* closure)
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *register_args = (char *) params;
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void *struct_ret = params[5];
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *stack_args = params[6];
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *ptr = register_args;
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif = closure->cif;
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **arg_types = cif->arg_types;
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Max room needed is number of arguments as 64-bit values.  */
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avalue = alloca (closure->cif->nargs * sizeof(void *));
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i;
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int doing_regs;
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  long long llret = 0;
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Find the address of each argument.  */
310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0, doing_regs = 1; i < cif->nargs; i++)
311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Types up to and including 8 bytes go by-value.  */
313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (arg_types[i]->size <= 4)
314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = ptr;
316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  ptr += 4;
317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else if (arg_types[i]->size <= 8)
319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = ptr;
321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  ptr += 8;
322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      else
324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  FFI_ASSERT (arg_types[i]->type == FFI_TYPE_STRUCT);
326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Passed by-reference, so copy the pointer.  */
328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = *(void **) ptr;
329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  ptr += 4;
330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* If we've handled more arguments than fit in registers, start
333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 looking at the those passed on the stack.  Step over the
334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 first one if we had a straddling parameter.  */
335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      if (doing_regs && ptr >= register_args + 4*4)
336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  ptr = stack_args + ((ptr > register_args + 4*4) ? 4 : 0);
338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  doing_regs = 0;
339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Invoke the closure.  */
343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif,
344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  cif->rtype->type == FFI_TYPE_STRUCT
346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  /* The caller allocated space for the return
347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     structure, and passed a pointer to this space in
348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     R9.  */
349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  ? struct_ret
350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  /* We take advantage of being able to ignore that
352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     the high part isn't set if the return value is
353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     not in R10:R11, but in R10 only.  */
354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  : (void *) &llret,
355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		  avalue, closure->user_data);
357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return llret;
359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* API function: Prepare the trampoline.  */
362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure,
365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif* cif,
366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif *, void *, void **, void*),
367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void *innerfn = ffi_prep_closure_inner;
371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_SYSV);
372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif  = cif;
373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun  = fun;
375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  memcpy (closure->tramp, ffi_cris_trampoline_template,
376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  FFI_CRIS_TRAMPOLINE_CODE_PART_SIZE);
377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  &innerfn, sizeof (void *));
379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  &codeloc, sizeof (void *));
381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
384