1a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* -----------------------------------------------------------------------
2a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
3a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project           (c) 2008 Red Hat, Inc.
4a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
5a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   HPPA Foreign Function Interface
6a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   HP-UX PA ABI support (c) 2006 Free Software Foundation, Inc.
7a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
8a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Permission is hereby granted, free of charge, to any person obtaining
9a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   a copy of this software and associated documentation files (the
10a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ``Software''), to deal in the Software without restriction, including
11a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   without limitation the rights to use, copy, modify, merge, publish,
12a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   distribute, sublicense, and/or sell copies of the Software, and to
13a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   permit persons to whom the Software is furnished to do so, subject to
14a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the following conditions:
15a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
16a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The above copyright notice and this permission notice shall be included
17a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   in all copies or substantial portions of the Software.
18a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
19a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   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#include <stdlib.h>
33a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#include <stdio.h>
34a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
35a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define ROUND_UP(v, a)  (((size_t)(v) + (a) - 1) & ~((a) - 1))
36a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
37a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define MIN_STACK_SIZE  64
38a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define FIRST_ARG_SLOT  9
39a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define DEBUG_LEVEL   0
40a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
41a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fldw(addr, fpreg) \
42a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __asm__ volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
43a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fstw(fpreg, addr) \
44a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __asm__ volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
45a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fldd(addr, fpreg) \
46a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __asm__ volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
47a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define fstd(fpreg, addr) \
48a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __asm__ volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
49a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
50a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
51a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
52a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic inline int ffi_struct_type(ffi_type *t)
53a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
54a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  size_t sz = t->size;
55a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
56a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Small structure results are passed in registers,
57a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     larger ones are passed by pointer.  Note that
58a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     small structures of size 2, 4 and 8 differ from
59a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     the corresponding integer types in that they have
60a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     different alignment requirements.  */
61a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
62a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (sz <= 1)
63a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_UINT8;
64a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (sz == 2)
65a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_SMALL_STRUCT2;
66a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (sz == 3)
67a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_SMALL_STRUCT3;
68a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (sz == 4)
69a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_SMALL_STRUCT4;
70a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (sz == 5)
71a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_SMALL_STRUCT5;
72a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (sz == 6)
73a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_SMALL_STRUCT6;
74a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (sz == 7)
75a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_SMALL_STRUCT7;
76a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else if (sz <= 8)
77a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_SMALL_STRUCT8;
78a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
79a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    return FFI_TYPE_STRUCT; /* else, we pass it by pointer.  */
80a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
81a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
82a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* PA has a downward growing stack, which looks like this:
83a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
84a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Offset
85a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	[ Variable args ]
86a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP = (4*(n+9))       arg word N
87a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ...
88a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP-52                arg word 4
89a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	[ Fixed args ]
90a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP-48                arg word 3
91a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP-44                arg word 2
92a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP-40                arg word 1
93a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP-36                arg word 0
94a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	[ Frame marker ]
95a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   ...
96a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP-20                RP
97a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   SP-4                 previous SP
98a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
99a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The first four argument words on the stack are reserved for use by
100a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the callee.  Instead, the general and floating registers replace
101a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the first four argument slots.  Non FP arguments are passed solely
102a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   in the general registers.  FP arguments are passed in both general
103a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   and floating registers when using libffi.
104a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
105a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23.
106a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Non-FP 64-bit args are passed in register pairs, starting
107a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   on an odd numbered register (i.e. r25+r26 and r23+r24).
108a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L.
109a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   FP 64-bit arguments are passed in fr5 and fr7.
110a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
111a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The registers are allocated in the same manner as stack slots.
112a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   This allows the callee to save its arguments on the stack if
113a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   necessary:
114a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
115a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   arg word 3 -> gr23 or fr7L
116a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   arg word 2 -> gr24 or fr6L or fr7R
117a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   arg word 1 -> gr25 or fr5L
118a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   arg word 0 -> gr26 or fr4L or fr5R
119a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
120a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   Note that fr4R and fr6R are never used for arguments (i.e.,
121a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   doubles are not passed in fr4 or fr6).
122a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
123a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The rest of the arguments are passed on the stack starting at SP-52,
124a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   but 64-bit arguments need to be aligned to an 8-byte boundary
125a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
126a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   This means we can have holes either in the register allocation,
127a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   or in the stack.  */
128a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
129a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* ffi_prep_args is called by the assembly routine once stack space
130a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   has been allocated for the function's arguments
131a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
132a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The following code will put everything into the stack frame
133a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   (which was allocated by the asm routine), and on return
134a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the asm routine will load the arguments that should be
135a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   passed by register into the appropriate registers
136a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
137a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   NOTE: We load floating point args in this function... that means we
138a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   assume gcc will not mess with fp regs in here.  */
139a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
140a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_prep_args_pa32(UINT32 *stack, extended_cif *ecif, unsigned bytes)
141a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
142a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register unsigned int i;
143a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register ffi_type **p_arg;
144a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register void **p_argv;
145a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int slot = FIRST_ARG_SLOT;
146a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *dest_cpy;
147a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  size_t len;
148a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
149a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack,
150a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	ecif, bytes);
151a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
152a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_arg = ecif->cif->arg_types;
153a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_argv = ecif->avalue;
154a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
155a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0; i < ecif->cif->nargs; i++)
156a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
157a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      int type = (*p_arg)->type;
158a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
159a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (type)
160a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
161a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT8:
162a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
163a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
164a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
165a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT8:
166a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
167a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
168a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
169a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT16:
170a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
171a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
172a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
173a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT16:
174a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
175a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
176a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
177a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT32:
178a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT32:
179a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_POINTER:
180a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv),
181a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		slot);
182a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
183a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
184a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
185a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT64:
186a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT64:
187a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Align slot for 64-bit type.  */
188a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  slot += (slot & 1) ? 1 : 2;
189a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
190a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
191a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
192a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_FLOAT:
193a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* First 4 args go in fr4L - fr7L.  */
194a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  debug(3, "Storing UINT32(float) in slot %u\n", slot);
195a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
196a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch (slot - FIRST_ARG_SLOT)
197a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
198a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    /* First 4 args go in fr4L - fr7L.  */
199a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 0: fldw(stack - slot, fr4); break;
200a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 1: fldw(stack - slot, fr5); break;
201a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 2: fldw(stack - slot, fr6); break;
202a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 3: fldw(stack - slot, fr7); break;
203a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
204a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
205a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
206a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_DOUBLE:
207a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Align slot for 64-bit type.  */
208a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  slot += (slot & 1) ? 1 : 2;
209a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  debug(3, "Storing UINT64(double) at slot %u\n", slot);
210a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
211a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch (slot - FIRST_ARG_SLOT)
212a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
213a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      /* First 2 args go in fr5, fr7.  */
214a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case 1: fldd(stack - slot, fr5); break;
215a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      case 3: fldd(stack - slot, fr7); break;
216a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
217a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
218a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
219a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX
220a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_LONGDOUBLE:
221a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Long doubles are passed in the same manner as structures
222a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     larger than 8 bytes.  */
223a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
224a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
225a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
226a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
227a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_STRUCT:
228a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
229a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Structs smaller or equal than 4 bytes are passed in one
230a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     register. Structs smaller or equal 8 bytes are passed in two
231a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     registers. Larger structures are passed by pointer.  */
232a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
233a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  len = (*p_arg)->size;
234a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if (len <= 4)
235a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
236a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      dest_cpy = (char *)(stack - slot) + 4 - len;
237a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      memcpy(dest_cpy, (char *)*p_argv, len);
238a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
239a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else if (len <= 8)
240a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
241a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      slot += (slot & 1) ? 1 : 2;
242a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      dest_cpy = (char *)(stack - slot) + 8 - len;
243a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      memcpy(dest_cpy, (char *)*p_argv, len);
244a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
245a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
246a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
247a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
248a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
249a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
250a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  FFI_ASSERT(0);
251a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
252a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
253a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      slot++;
254a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_arg++;
255a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_argv++;
256a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
257a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
258a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Make sure we didn't mess up and scribble on the stack.  */
259a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  {
260a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    unsigned int n;
261a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
262a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    debug(5, "Stack setup:\n");
263a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    for (n = 0; n < (bytes + 3) / 4; n++)
264a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
265a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
266a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	debug(5, "%08x ", *(stack - n));
267a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
268a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    debug(5, "\n");
269a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  }
270a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
271a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT(slot * 4 <= bytes);
272a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
273a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return;
274a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
275a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
276a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectstatic void ffi_size_stack_pa32(ffi_cif *cif)
277a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
278a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **ptr;
279a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i;
280a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int z = 0; /* # stack slots */
281a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
282a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
283a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
284a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      int type = (*ptr)->type;
285a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
286a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (type)
287a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
288a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_DOUBLE:
289a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT64:
290a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT64:
291a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z += 2 + (z & 1); /* must start on even regs, so we may waste one */
292a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
293a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
294a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX
295a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_LONGDOUBLE:
296a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
297a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_STRUCT:
298a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z += 1; /* pass by ptr, callee will copy */
299a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
300a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
301a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default: /* <= 32-bit values */
302a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  z++;
303a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
304a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
305a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
306a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* We can fit up to 6 args in the default 64-byte stack frame,
307a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     if we need more, we need more stack.  */
308a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (z <= 6)
309a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    cif->bytes = MIN_STACK_SIZE; /* min stack size */
310a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
311a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
312a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
313a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
314a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
315a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
316a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Perform machine dependent cif processing.  */
317a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_prep_cif_machdep(ffi_cif *cif)
318a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
319a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Set the return type flag */
320a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->rtype->type)
321a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
322a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
323a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
324a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
325a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = (unsigned) cif->rtype->type;
326a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
327a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
328a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX
329a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_LONGDOUBLE:
330a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Long doubles are treated like a structure.  */
331a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = FFI_TYPE_STRUCT;
332a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
333a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
334a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
335a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
336a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* For the return type we have to check the size of the structures.
337a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 If the size is smaller or equal 4 bytes, the result is given back
338a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 in one register. If the size is smaller or equal 8 bytes than we
339a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 return the result in two registers. But if the size is bigger than
340a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	 8 bytes, we work with pointers.  */
341a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = ffi_struct_type(cif->rtype);
342a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
343a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
344a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT64:
345a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT64:
346a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = FFI_TYPE_UINT64;
347a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
348a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
349a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
350a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      cif->flags = FFI_TYPE_INT;
351a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
352a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
353a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
354a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Lucky us, because of the unique PA ABI we get to do our
355a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     own stack sizing.  */
356a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
357a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
358a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_PA32:
359a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_size_stack_pa32(cif);
360a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
361a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
362a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
363a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
364a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
365a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
366a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
367a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
368a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
369a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
370a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_call_pa32(void (*)(UINT32 *, extended_cif *, unsigned),
371a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  extended_cif *, unsigned, unsigned, unsigned *,
372a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project			  void (*fn)(void));
373a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
374a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectvoid ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
375a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
376a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  extended_cif ecif;
377a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
378a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.cif = cif;
379a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ecif.avalue = avalue;
380a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
381a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If the return value is a struct and we don't have a return
382a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     value address then we need to make one.  */
383a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
384a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (rvalue == NULL
385a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX
386a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && (cif->rtype->type == FFI_TYPE_STRUCT
387a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  || cif->rtype->type == FFI_TYPE_LONGDOUBLE))
388a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#else
389a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      && cif->rtype->type == FFI_TYPE_STRUCT)
390a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
391a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
392a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ecif.rvalue = alloca(cif->rtype->size);
393a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
394a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
395a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    ecif.rvalue = rvalue;
396a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
397a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
398a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->abi)
399a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
400a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_PA32:
401a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      debug(3, "Calling ffi_call_pa32: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
402a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      ffi_call_pa32(ffi_prep_args_pa32, &ecif, cif->bytes,
403a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     cif->flags, ecif.rvalue, fn);
404a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
405a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
406a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
407a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
408a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
409a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
410a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
411a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
412a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#if FFI_CLOSURES
413a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* This is more-or-less an inverse of ffi_call -- we have arguments on
414a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the stack, and we need to fill them into a cif structure and invoke
415a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the user function. This really ought to be in asm to make sure
416a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   the compiler doesn't do things we don't expect.  */
417a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
418a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
419a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_cif *cif;
420a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void **avalue;
421a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  void *rvalue;
422a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT32 ret[2]; /* function can return up to 64-bits in registers */
423a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  ffi_type **p_arg;
424a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  char *tmp;
425a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  int i, avn;
426a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  unsigned int slot = FIRST_ARG_SLOT;
427a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  register UINT32 r28 asm("r28");
428a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
429a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  cif = closure->cif;
430a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
431a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* If returning via structure, callee will write to our pointer.  */
432a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  if (cif->flags == FFI_TYPE_STRUCT)
433a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    rvalue = (void *)r28;
434a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  else
435a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    rvalue = &ret[0];
436a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
437a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
438a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  avn = cif->nargs;
439a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  p_arg = cif->arg_types;
440a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
441a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  for (i = 0; i < avn; i++)
442a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
443a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      int type = (*p_arg)->type;
444a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
445a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      switch (type)
446a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	{
447a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT8:
448a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT8:
449a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT16:
450a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT16:
451a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT32:
452a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT32:
453a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_POINTER:
454a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
455a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
456a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
457a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_SINT64:
458a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_UINT64:
459a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  slot += (slot & 1) ? 1 : 2;
460a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = (void *)(stack - slot);
461a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
462a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
463a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_FLOAT:
464a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_LINUX
465a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* The closure call is indirect.  In Linux, floating point
466a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     arguments in indirect calls with a prototype are passed
467a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     in the floating point registers instead of the general
468a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     registers.  So, we need to replace what was previously
469a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     stored in the current slot with the value in the
470a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     corresponding floating point register.  */
471a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch (slot - FIRST_ARG_SLOT)
472a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
473a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 0: fstw(fr4, (void *)(stack - slot)); break;
474a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 1: fstw(fr5, (void *)(stack - slot)); break;
475a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 2: fstw(fr6, (void *)(stack - slot)); break;
476a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 3: fstw(fr7, (void *)(stack - slot)); break;
477a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
478a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
479a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = (void *)(stack - slot);
480a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
481a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
482a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_DOUBLE:
483a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  slot += (slot & 1) ? 1 : 2;
484a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_LINUX
485a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* See previous comment for FFI_TYPE_FLOAT.  */
486a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  switch (slot - FIRST_ARG_SLOT)
487a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
488a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 1: fstd(fr5, (void *)(stack - slot)); break;
489a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case 3: fstd(fr7, (void *)(stack - slot)); break;
490a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
491a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
492a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  avalue[i] = (void *)(stack - slot);
493a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
494a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
495a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	case FFI_TYPE_STRUCT:
496a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  /* Structs smaller or equal than 4 bytes are passed in one
497a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     register. Structs smaller or equal 8 bytes are passed in two
498a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	     registers. Larger structures are passed by pointer.  */
499a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  if((*p_arg)->size <= 4)
500a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
501a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
502a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		(*p_arg)->size;
503a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
504a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else if ((*p_arg)->size <= 8)
505a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    {
506a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      slot += (slot & 1) ? 1 : 2;
507a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	      avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
508a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		(*p_arg)->size;
509a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    }
510a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  else
511a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    avalue[i] = (void *) *(stack - slot);
512a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  break;
513a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
514a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	default:
515a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  FFI_ASSERT(0);
516a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	}
517a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
518a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      slot++;
519a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      p_arg++;
520a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
521a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
522a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Invoke the closure.  */
523a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  (closure->fun) (cif, rvalue, avalue, closure->user_data);
524a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
525a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0],
526a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	ret[1]);
527a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
528a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Store the result using the lower 2 bytes of the flags.  */
529a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  switch (cif->flags)
530a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    {
531a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT8:
532a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24);
533a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
534a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT8:
535a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24);
536a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
537a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT16:
538a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16);
539a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
540a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT16:
541a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16);
542a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
543a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_INT:
544a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT32:
545a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT32:
546a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(stack - FIRST_ARG_SLOT) = ret[0];
547a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
548a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SINT64:
549a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_UINT64:
550a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(stack - FIRST_ARG_SLOT) = ret[0];
551a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      *(stack - FIRST_ARG_SLOT - 1) = ret[1];
552a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
553a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
554a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_DOUBLE:
555a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      fldd(rvalue, fr4);
556a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
557a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
558a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_FLOAT:
559a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      fldw(rvalue, fr4);
560a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
561a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
562a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_STRUCT:
563a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      /* Don't need a return value, done by caller.  */
564a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
565a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
566a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SMALL_STRUCT2:
567a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SMALL_STRUCT3:
568a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SMALL_STRUCT4:
569a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      tmp = (void*)(stack -  FIRST_ARG_SLOT);
570a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      tmp += 4 - cif->rtype->size;
571a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      memcpy((void*)tmp, &ret[0], cif->rtype->size);
572a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
573a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
574a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SMALL_STRUCT5:
575a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SMALL_STRUCT6:
576a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SMALL_STRUCT7:
577a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_SMALL_STRUCT8:
578a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      {
579a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	unsigned int ret2[2];
580a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	int off;
581a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
582a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	/* Right justify ret[0] and ret[1] */
583a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	switch (cif->flags)
584a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  {
585a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SMALL_STRUCT5: off = 3; break;
586a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SMALL_STRUCT6: off = 2; break;
587a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    case FFI_TYPE_SMALL_STRUCT7: off = 1; break;
588a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	    default: off = 0; break;
589a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	  }
590a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
591a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	memset (ret2, 0, sizeof (ret2));
592a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	memcpy ((char *)ret2 + off, ret, 8 - off);
593a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
594a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	*(stack - FIRST_ARG_SLOT) = ret2[0];
595a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project	*(stack - FIRST_ARG_SLOT - 1) = ret2[1];
596a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      }
597a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
598a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
599a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_POINTER:
600a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    case FFI_TYPE_VOID:
601a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
602a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
603a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    default:
604a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      debug(0, "assert with cif->flags: %d\n",cif->flags);
605a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      FFI_ASSERT(0);
606a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project      break;
607a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project    }
608a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
609a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
610a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
611a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project/* Fill in a closure to refer to the specified fun and user_data.
612a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   cif specifies the argument and result types for fun.
613a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project   The cif must already be prep'ed.  */
614a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
615a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectextern void ffi_closure_pa32(void);
616a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
617a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_status
618a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Projectffi_prep_closure_loc (ffi_closure* closure,
619a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      ffi_cif* cif,
620a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void (*fun)(ffi_cif*,void*,void**,void*),
621a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *user_data,
622a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		      void *codeloc)
623a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project{
624a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT32 *tramp = (UINT32 *)(closure->tramp);
625a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX
626a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  UINT32 *tmp;
627a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
628a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
629a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  FFI_ASSERT (cif->abi == FFI_PA32);
630a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
631a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Make a small trampoline that will branch to our
632a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     handler function. Use PC-relative addressing.  */
633a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
634a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_LINUX
635a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8 */
636a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits */
637a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1    ; load plabel */
638a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr */
639a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler */
640a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[5] = 0xeac0c000; /* bv%r0(%r22)         ; branch to handler */
641a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler */
642a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2);
643a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
644a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Flush d/icache -- have to flush up 2 two lines because of
645a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project     alignment.  */
646a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __asm__ volatile(
647a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fdc 0(%0)\n\t"
648a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fdc %1(%0)\n\t"
649a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fic 0(%%sr4, %0)\n\t"
650a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fic %1(%%sr4, %0)\n\t"
651a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "sync\n\t"
652a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
653a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
654a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
655a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
656a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
657a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
658a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n"
659a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   :
660a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   : "r"((unsigned long)tramp & ~31),
661a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     "r"(32 /* stride */)
662a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   : "memory");
663a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
664a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
665a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#ifdef PA_HPUX
666a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[0] = 0xeaa00000; /* b,l .+8,%r21        ; %r21 <- pc+8  */
667a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21    ; mask priv bits  */
668a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1    ; load plabel  */
669a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21   ; get closure addr  */
670a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22     ; address of handler  */
671a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20   ; load space id  */
672a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[6] = 0x00141820; /* mtsp %r20,%sr0      ; into %sr0  */
673a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22)     ; branch to handler  */
674a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19     ; GP of handler  */
675a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2);
676a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
677a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  /* Flush d/icache -- have to flush three lines because of alignment.  */
678a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  __asm__ volatile(
679a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "copy %1,%0\n\t"
680a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fdc,m %2(%0)\n\t"
681a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fdc,m %2(%0)\n\t"
682a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fdc,m %2(%0)\n\t"
683a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "ldsid (%1),%0\n\t"
684a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "mtsp %0,%%sr0\n\t"
685a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "copy %1,%0\n\t"
686a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fic,m %2(%%sr0,%0)\n\t"
687a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fic,m %2(%%sr0,%0)\n\t"
688a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "fic,m %2(%%sr0,%0)\n\t"
689a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "sync\n\t"
690a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
691a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
692a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
693a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
694a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
695a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n\t"
696a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   "nop\n"
697a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   : "=&r" ((unsigned long)tmp)
698a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   : "r" ((unsigned long)tramp & ~31),
699a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		     "r" (32/* stride */)
700a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project		   : "memory");
701a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
702a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
703a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->cif  = cif;
704a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->user_data = user_data;
705a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  closure->fun  = fun;
706a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project
707a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project  return FFI_OK;
708a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project}
709a89495f48f185779ff7d9d64ce6e6b037c9ded87The Android Open Source Project#endif
710