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