xref: /aosp_15_r20/external/libffi/src/sparc/ffi64.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan    ffi.c - Copyright (c) 2011, 2013 Anthony Green
3*1fd5a2e1SPrashanth Swaminathan            Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc.
4*1fd5a2e1SPrashanth Swaminathan 
5*1fd5a2e1SPrashanth Swaminathan    SPARC Foreign Function Interface
6*1fd5a2e1SPrashanth Swaminathan 
7*1fd5a2e1SPrashanth Swaminathan    Permission is hereby granted, free of charge, to any person obtaining
8*1fd5a2e1SPrashanth Swaminathan    a copy of this software and associated documentation files (the
9*1fd5a2e1SPrashanth Swaminathan    ``Software''), to deal in the Software without restriction, including
10*1fd5a2e1SPrashanth Swaminathan    without limitation the rights to use, copy, modify, merge, publish,
11*1fd5a2e1SPrashanth Swaminathan    distribute, sublicense, and/or sell copies of the Software, and to
12*1fd5a2e1SPrashanth Swaminathan    permit persons to whom the Software is furnished to do so, subject to
13*1fd5a2e1SPrashanth Swaminathan    the following conditions:
14*1fd5a2e1SPrashanth Swaminathan 
15*1fd5a2e1SPrashanth Swaminathan    The above copyright notice and this permission notice shall be included
16*1fd5a2e1SPrashanth Swaminathan    in all copies or substantial portions of the Software.
17*1fd5a2e1SPrashanth Swaminathan 
18*1fd5a2e1SPrashanth Swaminathan    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19*1fd5a2e1SPrashanth Swaminathan    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20*1fd5a2e1SPrashanth Swaminathan    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21*1fd5a2e1SPrashanth Swaminathan    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22*1fd5a2e1SPrashanth Swaminathan    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23*1fd5a2e1SPrashanth Swaminathan    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24*1fd5a2e1SPrashanth Swaminathan    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25*1fd5a2e1SPrashanth Swaminathan    DEALINGS IN THE SOFTWARE.
26*1fd5a2e1SPrashanth Swaminathan    ----------------------------------------------------------------------- */
27*1fd5a2e1SPrashanth Swaminathan 
28*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
29*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
30*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
31*1fd5a2e1SPrashanth Swaminathan #include "internal.h"
32*1fd5a2e1SPrashanth Swaminathan 
33*1fd5a2e1SPrashanth Swaminathan /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
34*1fd5a2e1SPrashanth Swaminathan    all further uses in this file will refer to the 128-bit type.  */
35*1fd5a2e1SPrashanth Swaminathan #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
36*1fd5a2e1SPrashanth Swaminathan # if FFI_TYPE_LONGDOUBLE != 4
37*1fd5a2e1SPrashanth Swaminathan #  error FFI_TYPE_LONGDOUBLE out of date
38*1fd5a2e1SPrashanth Swaminathan # endif
39*1fd5a2e1SPrashanth Swaminathan #else
40*1fd5a2e1SPrashanth Swaminathan # undef FFI_TYPE_LONGDOUBLE
41*1fd5a2e1SPrashanth Swaminathan # define FFI_TYPE_LONGDOUBLE 4
42*1fd5a2e1SPrashanth Swaminathan #endif
43*1fd5a2e1SPrashanth Swaminathan 
44*1fd5a2e1SPrashanth Swaminathan #ifdef SPARC64
45*1fd5a2e1SPrashanth Swaminathan 
46*1fd5a2e1SPrashanth Swaminathan /* Flatten the contents of a structure to the parts that are passed in
47*1fd5a2e1SPrashanth Swaminathan    floating point registers.  The return is a bit mask wherein bit N
48*1fd5a2e1SPrashanth Swaminathan    set means bytes [4*n, 4*n+3] are passed in %fN.
49*1fd5a2e1SPrashanth Swaminathan 
50*1fd5a2e1SPrashanth Swaminathan    We encode both the (running) size (maximum 32) and mask (maxumum 255)
51*1fd5a2e1SPrashanth Swaminathan    into one integer.  The size is placed in the low byte, so that align
52*1fd5a2e1SPrashanth Swaminathan    and addition work correctly.  The mask is placed in the second byte.  */
53*1fd5a2e1SPrashanth Swaminathan 
54*1fd5a2e1SPrashanth Swaminathan static int
ffi_struct_float_mask(ffi_type * outer_type,int size_mask)55*1fd5a2e1SPrashanth Swaminathan ffi_struct_float_mask (ffi_type *outer_type, int size_mask)
56*1fd5a2e1SPrashanth Swaminathan {
57*1fd5a2e1SPrashanth Swaminathan   ffi_type **elts;
58*1fd5a2e1SPrashanth Swaminathan   ffi_type *t;
59*1fd5a2e1SPrashanth Swaminathan 
60*1fd5a2e1SPrashanth Swaminathan   if (outer_type->type == FFI_TYPE_COMPLEX)
61*1fd5a2e1SPrashanth Swaminathan     {
62*1fd5a2e1SPrashanth Swaminathan       int m = 0, tt = outer_type->elements[0]->type;
63*1fd5a2e1SPrashanth Swaminathan       size_t z = outer_type->size;
64*1fd5a2e1SPrashanth Swaminathan 
65*1fd5a2e1SPrashanth Swaminathan       if (tt == FFI_TYPE_FLOAT
66*1fd5a2e1SPrashanth Swaminathan 	  || tt == FFI_TYPE_DOUBLE
67*1fd5a2e1SPrashanth Swaminathan 	  || tt == FFI_TYPE_LONGDOUBLE)
68*1fd5a2e1SPrashanth Swaminathan         m = (1 << (z / 4)) - 1;
69*1fd5a2e1SPrashanth Swaminathan       return (m << 8) | z;
70*1fd5a2e1SPrashanth Swaminathan     }
71*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT);
72*1fd5a2e1SPrashanth Swaminathan 
73*1fd5a2e1SPrashanth Swaminathan   for (elts = outer_type->elements; (t = *elts) != NULL; elts++)
74*1fd5a2e1SPrashanth Swaminathan     {
75*1fd5a2e1SPrashanth Swaminathan       size_t z = t->size;
76*1fd5a2e1SPrashanth Swaminathan       int o, m, tt;
77*1fd5a2e1SPrashanth Swaminathan 
78*1fd5a2e1SPrashanth Swaminathan       size_mask = FFI_ALIGN(size_mask, t->alignment);
79*1fd5a2e1SPrashanth Swaminathan       switch (t->type)
80*1fd5a2e1SPrashanth Swaminathan 	{
81*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
82*1fd5a2e1SPrashanth Swaminathan 	  size_mask = ffi_struct_float_mask (t, size_mask);
83*1fd5a2e1SPrashanth Swaminathan 	  continue;
84*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_COMPLEX:
85*1fd5a2e1SPrashanth Swaminathan 	  tt = t->elements[0]->type;
86*1fd5a2e1SPrashanth Swaminathan 	  if (tt != FFI_TYPE_FLOAT
87*1fd5a2e1SPrashanth Swaminathan 	      && tt != FFI_TYPE_DOUBLE
88*1fd5a2e1SPrashanth Swaminathan 	      && tt != FFI_TYPE_LONGDOUBLE)
89*1fd5a2e1SPrashanth Swaminathan 	    break;
90*1fd5a2e1SPrashanth Swaminathan 	  /* FALLTHRU */
91*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
92*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
93*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_LONGDOUBLE:
94*1fd5a2e1SPrashanth Swaminathan 	  m = (1 << (z / 4)) - 1;	/* compute mask for type */
95*1fd5a2e1SPrashanth Swaminathan 	  o = (size_mask >> 2) & 0x3f;	/* extract word offset */
96*1fd5a2e1SPrashanth Swaminathan 	  size_mask |= m << (o + 8);	/* insert mask into place */
97*1fd5a2e1SPrashanth Swaminathan 	  break;
98*1fd5a2e1SPrashanth Swaminathan 	}
99*1fd5a2e1SPrashanth Swaminathan       size_mask += z;
100*1fd5a2e1SPrashanth Swaminathan     }
101*1fd5a2e1SPrashanth Swaminathan 
102*1fd5a2e1SPrashanth Swaminathan   size_mask = FFI_ALIGN(size_mask, outer_type->alignment);
103*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT ((size_mask & 0xff) == outer_type->size);
104*1fd5a2e1SPrashanth Swaminathan 
105*1fd5a2e1SPrashanth Swaminathan   return size_mask;
106*1fd5a2e1SPrashanth Swaminathan }
107*1fd5a2e1SPrashanth Swaminathan 
108*1fd5a2e1SPrashanth Swaminathan /* Merge floating point data into integer data.  If the structure is
109*1fd5a2e1SPrashanth Swaminathan    entirely floating point, simply return a pointer to the fp data.  */
110*1fd5a2e1SPrashanth Swaminathan 
111*1fd5a2e1SPrashanth Swaminathan static void *
ffi_struct_float_merge(int size_mask,void * vi,void * vf)112*1fd5a2e1SPrashanth Swaminathan ffi_struct_float_merge (int size_mask, void *vi, void *vf)
113*1fd5a2e1SPrashanth Swaminathan {
114*1fd5a2e1SPrashanth Swaminathan   int size = size_mask & 0xff;
115*1fd5a2e1SPrashanth Swaminathan   int mask = size_mask >> 8;
116*1fd5a2e1SPrashanth Swaminathan   int n = size >> 2;
117*1fd5a2e1SPrashanth Swaminathan 
118*1fd5a2e1SPrashanth Swaminathan   if (mask == 0)
119*1fd5a2e1SPrashanth Swaminathan     return vi;
120*1fd5a2e1SPrashanth Swaminathan   else if (mask == (1 << n) - 1)
121*1fd5a2e1SPrashanth Swaminathan     return vf;
122*1fd5a2e1SPrashanth Swaminathan   else
123*1fd5a2e1SPrashanth Swaminathan     {
124*1fd5a2e1SPrashanth Swaminathan       unsigned int *wi = vi, *wf = vf;
125*1fd5a2e1SPrashanth Swaminathan       int i;
126*1fd5a2e1SPrashanth Swaminathan 
127*1fd5a2e1SPrashanth Swaminathan       for (i = 0; i < n; ++i)
128*1fd5a2e1SPrashanth Swaminathan 	if ((mask >> i) & 1)
129*1fd5a2e1SPrashanth Swaminathan 	  wi[i] = wf[i];
130*1fd5a2e1SPrashanth Swaminathan 
131*1fd5a2e1SPrashanth Swaminathan       return vi;
132*1fd5a2e1SPrashanth Swaminathan     }
133*1fd5a2e1SPrashanth Swaminathan }
134*1fd5a2e1SPrashanth Swaminathan 
135*1fd5a2e1SPrashanth Swaminathan /* Similar, but place the data into VD in the end.  */
136*1fd5a2e1SPrashanth Swaminathan 
137*1fd5a2e1SPrashanth Swaminathan void FFI_HIDDEN
ffi_struct_float_copy(int size_mask,void * vd,void * vi,void * vf)138*1fd5a2e1SPrashanth Swaminathan ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf)
139*1fd5a2e1SPrashanth Swaminathan {
140*1fd5a2e1SPrashanth Swaminathan   int size = size_mask & 0xff;
141*1fd5a2e1SPrashanth Swaminathan   int mask = size_mask >> 8;
142*1fd5a2e1SPrashanth Swaminathan   int n = size >> 2;
143*1fd5a2e1SPrashanth Swaminathan 
144*1fd5a2e1SPrashanth Swaminathan   if (mask == 0)
145*1fd5a2e1SPrashanth Swaminathan     ;
146*1fd5a2e1SPrashanth Swaminathan   else if (mask == (1 << n) - 1)
147*1fd5a2e1SPrashanth Swaminathan     vi = vf;
148*1fd5a2e1SPrashanth Swaminathan   else
149*1fd5a2e1SPrashanth Swaminathan     {
150*1fd5a2e1SPrashanth Swaminathan       unsigned int *wd = vd, *wi = vi, *wf = vf;
151*1fd5a2e1SPrashanth Swaminathan       int i;
152*1fd5a2e1SPrashanth Swaminathan 
153*1fd5a2e1SPrashanth Swaminathan       for (i = 0; i < n; ++i)
154*1fd5a2e1SPrashanth Swaminathan 	wd[i] = ((mask >> i) & 1 ? wf : wi)[i];
155*1fd5a2e1SPrashanth Swaminathan       return;
156*1fd5a2e1SPrashanth Swaminathan     }
157*1fd5a2e1SPrashanth Swaminathan   memcpy (vd, vi, size);
158*1fd5a2e1SPrashanth Swaminathan }
159*1fd5a2e1SPrashanth Swaminathan 
160*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
161*1fd5a2e1SPrashanth Swaminathan 
162*1fd5a2e1SPrashanth Swaminathan static ffi_status
ffi_prep_cif_machdep_core(ffi_cif * cif)163*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep_core(ffi_cif *cif)
164*1fd5a2e1SPrashanth Swaminathan {
165*1fd5a2e1SPrashanth Swaminathan   ffi_type *rtype = cif->rtype;
166*1fd5a2e1SPrashanth Swaminathan   int rtt = rtype->type;
167*1fd5a2e1SPrashanth Swaminathan   size_t bytes = 0;
168*1fd5a2e1SPrashanth Swaminathan   int i, n, flags;
169*1fd5a2e1SPrashanth Swaminathan 
170*1fd5a2e1SPrashanth Swaminathan   /* Set the return type flag */
171*1fd5a2e1SPrashanth Swaminathan   switch (rtt)
172*1fd5a2e1SPrashanth Swaminathan     {
173*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_VOID:
174*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_VOID;
175*1fd5a2e1SPrashanth Swaminathan       break;
176*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_FLOAT:
177*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_F_1;
178*1fd5a2e1SPrashanth Swaminathan       break;
179*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_DOUBLE:
180*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_F_2;
181*1fd5a2e1SPrashanth Swaminathan       break;
182*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_LONGDOUBLE:
183*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_F_4;
184*1fd5a2e1SPrashanth Swaminathan       break;
185*1fd5a2e1SPrashanth Swaminathan 
186*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_COMPLEX:
187*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_STRUCT:
188*1fd5a2e1SPrashanth Swaminathan       if (rtype->size > 32)
189*1fd5a2e1SPrashanth Swaminathan 	{
190*1fd5a2e1SPrashanth Swaminathan 	  flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM;
191*1fd5a2e1SPrashanth Swaminathan 	  bytes = 8;
192*1fd5a2e1SPrashanth Swaminathan 	}
193*1fd5a2e1SPrashanth Swaminathan       else
194*1fd5a2e1SPrashanth Swaminathan 	{
195*1fd5a2e1SPrashanth Swaminathan 	  int size_mask = ffi_struct_float_mask (rtype, 0);
196*1fd5a2e1SPrashanth Swaminathan 	  int word_size = (size_mask >> 2) & 0x3f;
197*1fd5a2e1SPrashanth Swaminathan 	  int all_mask = (1 << word_size) - 1;
198*1fd5a2e1SPrashanth Swaminathan 	  int fp_mask = size_mask >> 8;
199*1fd5a2e1SPrashanth Swaminathan 
200*1fd5a2e1SPrashanth Swaminathan 	  flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT;
201*1fd5a2e1SPrashanth Swaminathan 
202*1fd5a2e1SPrashanth Swaminathan 	  /* For special cases of all-int or all-fp, we can return
203*1fd5a2e1SPrashanth Swaminathan 	     the value directly without popping through a struct copy.  */
204*1fd5a2e1SPrashanth Swaminathan 	  if (fp_mask == 0)
205*1fd5a2e1SPrashanth Swaminathan 	    {
206*1fd5a2e1SPrashanth Swaminathan 	      if (rtype->alignment >= 8)
207*1fd5a2e1SPrashanth Swaminathan 		{
208*1fd5a2e1SPrashanth Swaminathan 		  if (rtype->size == 8)
209*1fd5a2e1SPrashanth Swaminathan 		    flags = SPARC_RET_INT64;
210*1fd5a2e1SPrashanth Swaminathan 		  else if (rtype->size == 16)
211*1fd5a2e1SPrashanth Swaminathan 		    flags = SPARC_RET_INT128;
212*1fd5a2e1SPrashanth Swaminathan 		}
213*1fd5a2e1SPrashanth Swaminathan 	    }
214*1fd5a2e1SPrashanth Swaminathan 	  else if (fp_mask == all_mask)
215*1fd5a2e1SPrashanth Swaminathan 	    switch (word_size)
216*1fd5a2e1SPrashanth Swaminathan 	      {
217*1fd5a2e1SPrashanth Swaminathan 	      case 1: flags = SPARC_RET_F_1; break;
218*1fd5a2e1SPrashanth Swaminathan 	      case 2: flags = SPARC_RET_F_2; break;
219*1fd5a2e1SPrashanth Swaminathan 	      case 3: flags = SP_V9_RET_F_3; break;
220*1fd5a2e1SPrashanth Swaminathan 	      case 4: flags = SPARC_RET_F_4; break;
221*1fd5a2e1SPrashanth Swaminathan 	      /* 5 word structures skipped; handled via RET_STRUCT.  */
222*1fd5a2e1SPrashanth Swaminathan 	      case 6: flags = SPARC_RET_F_6; break;
223*1fd5a2e1SPrashanth Swaminathan 	      /* 7 word structures skipped; handled via RET_STRUCT.  */
224*1fd5a2e1SPrashanth Swaminathan 	      case 8: flags = SPARC_RET_F_8; break;
225*1fd5a2e1SPrashanth Swaminathan 	      }
226*1fd5a2e1SPrashanth Swaminathan 	}
227*1fd5a2e1SPrashanth Swaminathan       break;
228*1fd5a2e1SPrashanth Swaminathan 
229*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_SINT8:
230*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_SINT8;
231*1fd5a2e1SPrashanth Swaminathan       break;
232*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_UINT8:
233*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_UINT8;
234*1fd5a2e1SPrashanth Swaminathan       break;
235*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_SINT16:
236*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_SINT16;
237*1fd5a2e1SPrashanth Swaminathan       break;
238*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_UINT16:
239*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_UINT16;
240*1fd5a2e1SPrashanth Swaminathan       break;
241*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_INT:
242*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_SINT32:
243*1fd5a2e1SPrashanth Swaminathan       flags = SP_V9_RET_SINT32;
244*1fd5a2e1SPrashanth Swaminathan       break;
245*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_UINT32:
246*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_UINT32;
247*1fd5a2e1SPrashanth Swaminathan       break;
248*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_SINT64:
249*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_UINT64:
250*1fd5a2e1SPrashanth Swaminathan     case FFI_TYPE_POINTER:
251*1fd5a2e1SPrashanth Swaminathan       flags = SPARC_RET_INT64;
252*1fd5a2e1SPrashanth Swaminathan       break;
253*1fd5a2e1SPrashanth Swaminathan 
254*1fd5a2e1SPrashanth Swaminathan     default:
255*1fd5a2e1SPrashanth Swaminathan       abort();
256*1fd5a2e1SPrashanth Swaminathan     }
257*1fd5a2e1SPrashanth Swaminathan 
258*1fd5a2e1SPrashanth Swaminathan   bytes = 0;
259*1fd5a2e1SPrashanth Swaminathan   for (i = 0, n = cif->nargs; i < n; ++i)
260*1fd5a2e1SPrashanth Swaminathan     {
261*1fd5a2e1SPrashanth Swaminathan       ffi_type *ty = cif->arg_types[i];
262*1fd5a2e1SPrashanth Swaminathan       size_t z = ty->size;
263*1fd5a2e1SPrashanth Swaminathan       size_t a = ty->alignment;
264*1fd5a2e1SPrashanth Swaminathan 
265*1fd5a2e1SPrashanth Swaminathan       switch (ty->type)
266*1fd5a2e1SPrashanth Swaminathan 	{
267*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_COMPLEX:
268*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
269*1fd5a2e1SPrashanth Swaminathan 	  /* Large structs passed by reference.  */
270*1fd5a2e1SPrashanth Swaminathan 	  if (z > 16)
271*1fd5a2e1SPrashanth Swaminathan 	    {
272*1fd5a2e1SPrashanth Swaminathan 	      a = z = 8;
273*1fd5a2e1SPrashanth Swaminathan 	      break;
274*1fd5a2e1SPrashanth Swaminathan 	    }
275*1fd5a2e1SPrashanth Swaminathan 	  /* Small structs may be passed in integer or fp regs or both.  */
276*1fd5a2e1SPrashanth Swaminathan 	  if (bytes >= 16*8)
277*1fd5a2e1SPrashanth Swaminathan 	    break;
278*1fd5a2e1SPrashanth Swaminathan 	  if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0)
279*1fd5a2e1SPrashanth Swaminathan 	    break;
280*1fd5a2e1SPrashanth Swaminathan 	  /* FALLTHRU */
281*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
282*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
283*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_LONGDOUBLE:
284*1fd5a2e1SPrashanth Swaminathan 	  flags |= SPARC_FLAG_FP_ARGS;
285*1fd5a2e1SPrashanth Swaminathan 	  break;
286*1fd5a2e1SPrashanth Swaminathan 	}
287*1fd5a2e1SPrashanth Swaminathan       bytes = FFI_ALIGN(bytes, a);
288*1fd5a2e1SPrashanth Swaminathan       bytes += FFI_ALIGN(z, 8);
289*1fd5a2e1SPrashanth Swaminathan     }
290*1fd5a2e1SPrashanth Swaminathan 
291*1fd5a2e1SPrashanth Swaminathan   /* Sparc call frames require that space is allocated for 6 args,
292*1fd5a2e1SPrashanth Swaminathan      even if they aren't used. Make that space if necessary. */
293*1fd5a2e1SPrashanth Swaminathan   if (bytes < 6 * 8)
294*1fd5a2e1SPrashanth Swaminathan     bytes = 6 * 8;
295*1fd5a2e1SPrashanth Swaminathan 
296*1fd5a2e1SPrashanth Swaminathan   /* The stack must be 2 word aligned, so round bytes up appropriately. */
297*1fd5a2e1SPrashanth Swaminathan   bytes = FFI_ALIGN(bytes, 16);
298*1fd5a2e1SPrashanth Swaminathan 
299*1fd5a2e1SPrashanth Swaminathan   /* Include the call frame to prep_args.  */
300*1fd5a2e1SPrashanth Swaminathan   bytes += 8*16 + 8*8;
301*1fd5a2e1SPrashanth Swaminathan 
302*1fd5a2e1SPrashanth Swaminathan   cif->bytes = bytes;
303*1fd5a2e1SPrashanth Swaminathan   cif->flags = flags;
304*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
305*1fd5a2e1SPrashanth Swaminathan }
306*1fd5a2e1SPrashanth Swaminathan 
307*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif * cif)308*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep(ffi_cif *cif)
309*1fd5a2e1SPrashanth Swaminathan {
310*1fd5a2e1SPrashanth Swaminathan   cif->nfixedargs = cif->nargs;
311*1fd5a2e1SPrashanth Swaminathan   return ffi_prep_cif_machdep_core(cif);
312*1fd5a2e1SPrashanth Swaminathan }
313*1fd5a2e1SPrashanth Swaminathan 
314*1fd5a2e1SPrashanth Swaminathan ffi_status FFI_HIDDEN
ffi_prep_cif_machdep_var(ffi_cif * cif,unsigned nfixedargs,unsigned ntotalargs)315*1fd5a2e1SPrashanth Swaminathan ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs)
316*1fd5a2e1SPrashanth Swaminathan {
317*1fd5a2e1SPrashanth Swaminathan   cif->nfixedargs = nfixedargs;
318*1fd5a2e1SPrashanth Swaminathan   return ffi_prep_cif_machdep_core(cif);
319*1fd5a2e1SPrashanth Swaminathan }
320*1fd5a2e1SPrashanth Swaminathan 
321*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue,
322*1fd5a2e1SPrashanth Swaminathan 			void **avalue, size_t bytes, void *closure) FFI_HIDDEN;
323*1fd5a2e1SPrashanth Swaminathan 
324*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
325*1fd5a2e1SPrashanth Swaminathan    has been allocated for the function's arguments */
326*1fd5a2e1SPrashanth Swaminathan 
327*1fd5a2e1SPrashanth Swaminathan int FFI_HIDDEN
ffi_prep_args_v9(ffi_cif * cif,unsigned long * argp,void * rvalue,void ** avalue)328*1fd5a2e1SPrashanth Swaminathan ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue)
329*1fd5a2e1SPrashanth Swaminathan {
330*1fd5a2e1SPrashanth Swaminathan   ffi_type **p_arg;
331*1fd5a2e1SPrashanth Swaminathan   int flags = cif->flags;
332*1fd5a2e1SPrashanth Swaminathan   int i, nargs;
333*1fd5a2e1SPrashanth Swaminathan 
334*1fd5a2e1SPrashanth Swaminathan   if (rvalue == NULL)
335*1fd5a2e1SPrashanth Swaminathan     {
336*1fd5a2e1SPrashanth Swaminathan       if (flags & SPARC_FLAG_RET_IN_MEM)
337*1fd5a2e1SPrashanth Swaminathan 	{
338*1fd5a2e1SPrashanth Swaminathan 	  /* Since we pass the pointer to the callee, we need a value.
339*1fd5a2e1SPrashanth Swaminathan 	     We allowed for this space in ffi_call, before ffi_call_v8
340*1fd5a2e1SPrashanth Swaminathan 	     alloca'd the space.  */
341*1fd5a2e1SPrashanth Swaminathan 	  rvalue = (char *)argp + cif->bytes;
342*1fd5a2e1SPrashanth Swaminathan 	}
343*1fd5a2e1SPrashanth Swaminathan       else
344*1fd5a2e1SPrashanth Swaminathan 	{
345*1fd5a2e1SPrashanth Swaminathan 	  /* Otherwise, we can ignore the return value.  */
346*1fd5a2e1SPrashanth Swaminathan 	  flags = SPARC_RET_VOID;
347*1fd5a2e1SPrashanth Swaminathan 	}
348*1fd5a2e1SPrashanth Swaminathan     }
349*1fd5a2e1SPrashanth Swaminathan 
350*1fd5a2e1SPrashanth Swaminathan #ifdef USING_PURIFY
351*1fd5a2e1SPrashanth Swaminathan   /* Purify will probably complain in our assembly routine,
352*1fd5a2e1SPrashanth Swaminathan      unless we zero out this memory. */
353*1fd5a2e1SPrashanth Swaminathan   memset(argp, 0, 6*8);
354*1fd5a2e1SPrashanth Swaminathan #endif
355*1fd5a2e1SPrashanth Swaminathan 
356*1fd5a2e1SPrashanth Swaminathan   if (flags & SPARC_FLAG_RET_IN_MEM)
357*1fd5a2e1SPrashanth Swaminathan     *argp++ = (unsigned long)rvalue;
358*1fd5a2e1SPrashanth Swaminathan 
359*1fd5a2e1SPrashanth Swaminathan   p_arg = cif->arg_types;
360*1fd5a2e1SPrashanth Swaminathan   for (i = 0, nargs = cif->nargs; i < nargs; i++)
361*1fd5a2e1SPrashanth Swaminathan     {
362*1fd5a2e1SPrashanth Swaminathan       ffi_type *ty = p_arg[i];
363*1fd5a2e1SPrashanth Swaminathan       void *a = avalue[i];
364*1fd5a2e1SPrashanth Swaminathan       size_t z;
365*1fd5a2e1SPrashanth Swaminathan 
366*1fd5a2e1SPrashanth Swaminathan       switch (ty->type)
367*1fd5a2e1SPrashanth Swaminathan 	{
368*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT8:
369*1fd5a2e1SPrashanth Swaminathan 	  *argp++ = *(SINT8 *)a;
370*1fd5a2e1SPrashanth Swaminathan 	  break;
371*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT8:
372*1fd5a2e1SPrashanth Swaminathan 	  *argp++ = *(UINT8 *)a;
373*1fd5a2e1SPrashanth Swaminathan 	  break;
374*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT16:
375*1fd5a2e1SPrashanth Swaminathan 	  *argp++ = *(SINT16 *)a;
376*1fd5a2e1SPrashanth Swaminathan 	  break;
377*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT16:
378*1fd5a2e1SPrashanth Swaminathan 	  *argp++ = *(UINT16 *)a;
379*1fd5a2e1SPrashanth Swaminathan 	  break;
380*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_INT:
381*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT32:
382*1fd5a2e1SPrashanth Swaminathan 	  *argp++ = *(SINT32 *)a;
383*1fd5a2e1SPrashanth Swaminathan 	  break;
384*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT32:
385*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
386*1fd5a2e1SPrashanth Swaminathan 	  *argp++ = *(UINT32 *)a;
387*1fd5a2e1SPrashanth Swaminathan 	  break;
388*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT64:
389*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT64:
390*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_POINTER:
391*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
392*1fd5a2e1SPrashanth Swaminathan 	  *argp++ = *(UINT64 *)a;
393*1fd5a2e1SPrashanth Swaminathan 	  break;
394*1fd5a2e1SPrashanth Swaminathan 
395*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_LONGDOUBLE:
396*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_COMPLEX:
397*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
398*1fd5a2e1SPrashanth Swaminathan 	  z = ty->size;
399*1fd5a2e1SPrashanth Swaminathan 	  if (z > 16)
400*1fd5a2e1SPrashanth Swaminathan 	    {
401*1fd5a2e1SPrashanth Swaminathan 	      /* For structures larger than 16 bytes we pass reference.  */
402*1fd5a2e1SPrashanth Swaminathan 	      *argp++ = (unsigned long)a;
403*1fd5a2e1SPrashanth Swaminathan 	      break;
404*1fd5a2e1SPrashanth Swaminathan 	    }
405*1fd5a2e1SPrashanth Swaminathan 	  if (((unsigned long)argp & 15) && ty->alignment > 8)
406*1fd5a2e1SPrashanth Swaminathan 	    argp++;
407*1fd5a2e1SPrashanth Swaminathan 	  memcpy(argp, a, z);
408*1fd5a2e1SPrashanth Swaminathan 	  argp += FFI_ALIGN(z, 8) / 8;
409*1fd5a2e1SPrashanth Swaminathan 	  break;
410*1fd5a2e1SPrashanth Swaminathan 
411*1fd5a2e1SPrashanth Swaminathan 	default:
412*1fd5a2e1SPrashanth Swaminathan 	  abort();
413*1fd5a2e1SPrashanth Swaminathan 	}
414*1fd5a2e1SPrashanth Swaminathan     }
415*1fd5a2e1SPrashanth Swaminathan 
416*1fd5a2e1SPrashanth Swaminathan   return flags;
417*1fd5a2e1SPrashanth Swaminathan }
418*1fd5a2e1SPrashanth Swaminathan 
419*1fd5a2e1SPrashanth Swaminathan static void
ffi_call_int(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)420*1fd5a2e1SPrashanth Swaminathan ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
421*1fd5a2e1SPrashanth Swaminathan 	     void **avalue, void *closure)
422*1fd5a2e1SPrashanth Swaminathan {
423*1fd5a2e1SPrashanth Swaminathan   size_t bytes = cif->bytes;
424*1fd5a2e1SPrashanth Swaminathan 
425*1fd5a2e1SPrashanth Swaminathan   FFI_ASSERT (cif->abi == FFI_V9);
426*1fd5a2e1SPrashanth Swaminathan 
427*1fd5a2e1SPrashanth Swaminathan   if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
428*1fd5a2e1SPrashanth Swaminathan     bytes += FFI_ALIGN (cif->rtype->size, 16);
429*1fd5a2e1SPrashanth Swaminathan 
430*1fd5a2e1SPrashanth Swaminathan   ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
431*1fd5a2e1SPrashanth Swaminathan }
432*1fd5a2e1SPrashanth Swaminathan 
433*1fd5a2e1SPrashanth Swaminathan void
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)434*1fd5a2e1SPrashanth Swaminathan ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
435*1fd5a2e1SPrashanth Swaminathan {
436*1fd5a2e1SPrashanth Swaminathan   ffi_call_int(cif, fn, rvalue, avalue, NULL);
437*1fd5a2e1SPrashanth Swaminathan }
438*1fd5a2e1SPrashanth Swaminathan 
439*1fd5a2e1SPrashanth Swaminathan void
ffi_call_go(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue,void * closure)440*1fd5a2e1SPrashanth Swaminathan ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue,
441*1fd5a2e1SPrashanth Swaminathan 	    void **avalue, void *closure)
442*1fd5a2e1SPrashanth Swaminathan {
443*1fd5a2e1SPrashanth Swaminathan   ffi_call_int(cif, fn, rvalue, avalue, closure);
444*1fd5a2e1SPrashanth Swaminathan }
445*1fd5a2e1SPrashanth Swaminathan 
446*1fd5a2e1SPrashanth Swaminathan #ifdef __GNUC__
447*1fd5a2e1SPrashanth Swaminathan static inline void
ffi_flush_icache(void * p)448*1fd5a2e1SPrashanth Swaminathan ffi_flush_icache (void *p)
449*1fd5a2e1SPrashanth Swaminathan {
450*1fd5a2e1SPrashanth Swaminathan   asm volatile ("flush	%0; flush %0+8" : : "r" (p) : "memory");
451*1fd5a2e1SPrashanth Swaminathan }
452*1fd5a2e1SPrashanth Swaminathan #else
453*1fd5a2e1SPrashanth Swaminathan extern void ffi_flush_icache (void *) FFI_HIDDEN;
454*1fd5a2e1SPrashanth Swaminathan #endif
455*1fd5a2e1SPrashanth Swaminathan 
456*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_v9(void) FFI_HIDDEN;
457*1fd5a2e1SPrashanth Swaminathan extern void ffi_go_closure_v9(void) FFI_HIDDEN;
458*1fd5a2e1SPrashanth Swaminathan 
459*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)460*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
461*1fd5a2e1SPrashanth Swaminathan 		      ffi_cif* cif,
462*1fd5a2e1SPrashanth Swaminathan 		      void (*fun)(ffi_cif*, void*, void**, void*),
463*1fd5a2e1SPrashanth Swaminathan 		      void *user_data,
464*1fd5a2e1SPrashanth Swaminathan 		      void *codeloc)
465*1fd5a2e1SPrashanth Swaminathan {
466*1fd5a2e1SPrashanth Swaminathan   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
467*1fd5a2e1SPrashanth Swaminathan   unsigned long fn;
468*1fd5a2e1SPrashanth Swaminathan 
469*1fd5a2e1SPrashanth Swaminathan   if (cif->abi != FFI_V9)
470*1fd5a2e1SPrashanth Swaminathan     return FFI_BAD_ABI;
471*1fd5a2e1SPrashanth Swaminathan 
472*1fd5a2e1SPrashanth Swaminathan   /* Trampoline address is equal to the closure address.  We take advantage
473*1fd5a2e1SPrashanth Swaminathan      of that to reduce the trampoline size by 8 bytes. */
474*1fd5a2e1SPrashanth Swaminathan   fn = (unsigned long) ffi_closure_v9;
475*1fd5a2e1SPrashanth Swaminathan   tramp[0] = 0x83414000;	/* rd	%pc, %g1	*/
476*1fd5a2e1SPrashanth Swaminathan   tramp[1] = 0xca586010;	/* ldx	[%g1+16], %g5	*/
477*1fd5a2e1SPrashanth Swaminathan   tramp[2] = 0x81c14000;	/* jmp	%g5		*/
478*1fd5a2e1SPrashanth Swaminathan   tramp[3] = 0x01000000;	/* nop			*/
479*1fd5a2e1SPrashanth Swaminathan   *((unsigned long *) &tramp[4]) = fn;
480*1fd5a2e1SPrashanth Swaminathan 
481*1fd5a2e1SPrashanth Swaminathan   closure->cif = cif;
482*1fd5a2e1SPrashanth Swaminathan   closure->fun = fun;
483*1fd5a2e1SPrashanth Swaminathan   closure->user_data = user_data;
484*1fd5a2e1SPrashanth Swaminathan 
485*1fd5a2e1SPrashanth Swaminathan   ffi_flush_icache (closure);
486*1fd5a2e1SPrashanth Swaminathan 
487*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
488*1fd5a2e1SPrashanth Swaminathan }
489*1fd5a2e1SPrashanth Swaminathan 
490*1fd5a2e1SPrashanth Swaminathan ffi_status
ffi_prep_go_closure(ffi_go_closure * closure,ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *))491*1fd5a2e1SPrashanth Swaminathan ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
492*1fd5a2e1SPrashanth Swaminathan 		     void (*fun)(ffi_cif*, void*, void**, void*))
493*1fd5a2e1SPrashanth Swaminathan {
494*1fd5a2e1SPrashanth Swaminathan   if (cif->abi != FFI_V9)
495*1fd5a2e1SPrashanth Swaminathan     return FFI_BAD_ABI;
496*1fd5a2e1SPrashanth Swaminathan 
497*1fd5a2e1SPrashanth Swaminathan   closure->tramp = ffi_go_closure_v9;
498*1fd5a2e1SPrashanth Swaminathan   closure->cif = cif;
499*1fd5a2e1SPrashanth Swaminathan   closure->fun = fun;
500*1fd5a2e1SPrashanth Swaminathan 
501*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
502*1fd5a2e1SPrashanth Swaminathan }
503*1fd5a2e1SPrashanth Swaminathan 
504*1fd5a2e1SPrashanth Swaminathan int FFI_HIDDEN
ffi_closure_sparc_inner_v9(ffi_cif * cif,void (* fun)(ffi_cif *,void *,void **,void *),void * user_data,void * rvalue,unsigned long * gpr,unsigned long * fpr)505*1fd5a2e1SPrashanth Swaminathan ffi_closure_sparc_inner_v9(ffi_cif *cif,
506*1fd5a2e1SPrashanth Swaminathan 			   void (*fun)(ffi_cif*, void*, void**, void*),
507*1fd5a2e1SPrashanth Swaminathan 			   void *user_data, void *rvalue,
508*1fd5a2e1SPrashanth Swaminathan 			   unsigned long *gpr, unsigned long *fpr)
509*1fd5a2e1SPrashanth Swaminathan {
510*1fd5a2e1SPrashanth Swaminathan   ffi_type **arg_types;
511*1fd5a2e1SPrashanth Swaminathan   void **avalue;
512*1fd5a2e1SPrashanth Swaminathan   int i, argn, argx, nargs, flags, nfixedargs;
513*1fd5a2e1SPrashanth Swaminathan 
514*1fd5a2e1SPrashanth Swaminathan   arg_types = cif->arg_types;
515*1fd5a2e1SPrashanth Swaminathan   nargs = cif->nargs;
516*1fd5a2e1SPrashanth Swaminathan   flags = cif->flags;
517*1fd5a2e1SPrashanth Swaminathan   nfixedargs = cif->nfixedargs;
518*1fd5a2e1SPrashanth Swaminathan 
519*1fd5a2e1SPrashanth Swaminathan   avalue = alloca(nargs * sizeof(void *));
520*1fd5a2e1SPrashanth Swaminathan 
521*1fd5a2e1SPrashanth Swaminathan   /* Copy the caller's structure return address so that the closure
522*1fd5a2e1SPrashanth Swaminathan      returns the data directly to the caller.  */
523*1fd5a2e1SPrashanth Swaminathan   if (flags & SPARC_FLAG_RET_IN_MEM)
524*1fd5a2e1SPrashanth Swaminathan     {
525*1fd5a2e1SPrashanth Swaminathan       rvalue = (void *) gpr[0];
526*1fd5a2e1SPrashanth Swaminathan       /* Skip the structure return address.  */
527*1fd5a2e1SPrashanth Swaminathan       argn = 1;
528*1fd5a2e1SPrashanth Swaminathan     }
529*1fd5a2e1SPrashanth Swaminathan   else
530*1fd5a2e1SPrashanth Swaminathan     argn = 0;
531*1fd5a2e1SPrashanth Swaminathan 
532*1fd5a2e1SPrashanth Swaminathan   /* Grab the addresses of the arguments from the stack frame.  */
533*1fd5a2e1SPrashanth Swaminathan   for (i = 0; i < nargs; i++, argn = argx)
534*1fd5a2e1SPrashanth Swaminathan     {
535*1fd5a2e1SPrashanth Swaminathan       int named = i < nfixedargs;
536*1fd5a2e1SPrashanth Swaminathan       ffi_type *ty = arg_types[i];
537*1fd5a2e1SPrashanth Swaminathan       void *a = &gpr[argn];
538*1fd5a2e1SPrashanth Swaminathan       size_t z;
539*1fd5a2e1SPrashanth Swaminathan 
540*1fd5a2e1SPrashanth Swaminathan       argx = argn + 1;
541*1fd5a2e1SPrashanth Swaminathan       switch (ty->type)
542*1fd5a2e1SPrashanth Swaminathan 	{
543*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_COMPLEX:
544*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
545*1fd5a2e1SPrashanth Swaminathan 	  z = ty->size;
546*1fd5a2e1SPrashanth Swaminathan 	  if (z > 16)
547*1fd5a2e1SPrashanth Swaminathan 	    a = *(void **)a;
548*1fd5a2e1SPrashanth Swaminathan 	  else
549*1fd5a2e1SPrashanth Swaminathan 	    {
550*1fd5a2e1SPrashanth Swaminathan 	      argx = argn + FFI_ALIGN (z, 8) / 8;
551*1fd5a2e1SPrashanth Swaminathan 	      if (named && argn < 16)
552*1fd5a2e1SPrashanth Swaminathan 		{
553*1fd5a2e1SPrashanth Swaminathan 		  int size_mask = ffi_struct_float_mask (ty, 0);
554*1fd5a2e1SPrashanth Swaminathan 		  int argn_mask = (0xffff00 >> argn) & 0xff00;
555*1fd5a2e1SPrashanth Swaminathan 
556*1fd5a2e1SPrashanth Swaminathan 		  /* Eliminate fp registers off the end.  */
557*1fd5a2e1SPrashanth Swaminathan 		  size_mask = (size_mask & 0xff) | (size_mask & argn_mask);
558*1fd5a2e1SPrashanth Swaminathan 		  a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn);
559*1fd5a2e1SPrashanth Swaminathan 		}
560*1fd5a2e1SPrashanth Swaminathan 	    }
561*1fd5a2e1SPrashanth Swaminathan 	  break;
562*1fd5a2e1SPrashanth Swaminathan 
563*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_LONGDOUBLE:
564*1fd5a2e1SPrashanth Swaminathan 	  argn = FFI_ALIGN (argn, 2);
565*1fd5a2e1SPrashanth Swaminathan 	  a = (named && argn < 16 ? fpr : gpr) + argn;
566*1fd5a2e1SPrashanth Swaminathan 	  argx = argn + 2;
567*1fd5a2e1SPrashanth Swaminathan 	  break;
568*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_DOUBLE:
569*1fd5a2e1SPrashanth Swaminathan 	  if (named && argn < 16)
570*1fd5a2e1SPrashanth Swaminathan 	    a = fpr + argn;
571*1fd5a2e1SPrashanth Swaminathan 	  break;
572*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
573*1fd5a2e1SPrashanth Swaminathan 	  if (named && argn < 16)
574*1fd5a2e1SPrashanth Swaminathan 	    a = fpr + argn;
575*1fd5a2e1SPrashanth Swaminathan 	  a += 4;
576*1fd5a2e1SPrashanth Swaminathan 	  break;
577*1fd5a2e1SPrashanth Swaminathan 
578*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT64:
579*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT64:
580*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_POINTER:
581*1fd5a2e1SPrashanth Swaminathan 	  break;
582*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_INT:
583*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT32:
584*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT32:
585*1fd5a2e1SPrashanth Swaminathan 	  a += 4;
586*1fd5a2e1SPrashanth Swaminathan 	  break;
587*1fd5a2e1SPrashanth Swaminathan         case FFI_TYPE_UINT16:
588*1fd5a2e1SPrashanth Swaminathan         case FFI_TYPE_SINT16:
589*1fd5a2e1SPrashanth Swaminathan 	  a += 6;
590*1fd5a2e1SPrashanth Swaminathan 	  break;
591*1fd5a2e1SPrashanth Swaminathan         case FFI_TYPE_UINT8:
592*1fd5a2e1SPrashanth Swaminathan         case FFI_TYPE_SINT8:
593*1fd5a2e1SPrashanth Swaminathan 	  a += 7;
594*1fd5a2e1SPrashanth Swaminathan 	  break;
595*1fd5a2e1SPrashanth Swaminathan 
596*1fd5a2e1SPrashanth Swaminathan 	default:
597*1fd5a2e1SPrashanth Swaminathan 	  abort();
598*1fd5a2e1SPrashanth Swaminathan 	}
599*1fd5a2e1SPrashanth Swaminathan       avalue[i] = a;
600*1fd5a2e1SPrashanth Swaminathan     }
601*1fd5a2e1SPrashanth Swaminathan 
602*1fd5a2e1SPrashanth Swaminathan   /* Invoke the closure.  */
603*1fd5a2e1SPrashanth Swaminathan   fun (cif, rvalue, avalue, user_data);
604*1fd5a2e1SPrashanth Swaminathan 
605*1fd5a2e1SPrashanth Swaminathan   /* Tell ffi_closure_sparc how to perform return type promotions.  */
606*1fd5a2e1SPrashanth Swaminathan   return flags;
607*1fd5a2e1SPrashanth Swaminathan }
608*1fd5a2e1SPrashanth Swaminathan #endif /* SPARC64 */
609