xref: /aosp_15_r20/external/libffi/src/frv/ffi.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan /* -----------------------------------------------------------------------
2*1fd5a2e1SPrashanth Swaminathan    ffi.c - Copyright (C) 2004  Anthony Green
3*1fd5a2e1SPrashanth Swaminathan    Copyright (C) 2007  Free Software Foundation, Inc.
4*1fd5a2e1SPrashanth Swaminathan 	   Copyright (C) 2008  Red Hat, Inc.
5*1fd5a2e1SPrashanth Swaminathan 
6*1fd5a2e1SPrashanth Swaminathan    FR-V Foreign Function Interface
7*1fd5a2e1SPrashanth Swaminathan 
8*1fd5a2e1SPrashanth Swaminathan    Permission is hereby granted, free of charge, to any person obtaining
9*1fd5a2e1SPrashanth Swaminathan    a copy of this software and associated documentation files (the
10*1fd5a2e1SPrashanth Swaminathan    ``Software''), to deal in the Software without restriction, including
11*1fd5a2e1SPrashanth Swaminathan    without limitation the rights to use, copy, modify, merge, publish,
12*1fd5a2e1SPrashanth Swaminathan    distribute, sublicense, and/or sell copies of the Software, and to
13*1fd5a2e1SPrashanth Swaminathan    permit persons to whom the Software is furnished to do so, subject to
14*1fd5a2e1SPrashanth Swaminathan    the following conditions:
15*1fd5a2e1SPrashanth Swaminathan 
16*1fd5a2e1SPrashanth Swaminathan    The above copyright notice and this permission notice shall be included
17*1fd5a2e1SPrashanth Swaminathan    in all copies or substantial portions of the Software.
18*1fd5a2e1SPrashanth Swaminathan 
19*1fd5a2e1SPrashanth Swaminathan    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
20*1fd5a2e1SPrashanth Swaminathan    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21*1fd5a2e1SPrashanth Swaminathan    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22*1fd5a2e1SPrashanth Swaminathan    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23*1fd5a2e1SPrashanth Swaminathan    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24*1fd5a2e1SPrashanth Swaminathan    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25*1fd5a2e1SPrashanth Swaminathan    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26*1fd5a2e1SPrashanth Swaminathan    DEALINGS IN THE SOFTWARE.
27*1fd5a2e1SPrashanth Swaminathan    ----------------------------------------------------------------------- */
28*1fd5a2e1SPrashanth Swaminathan 
29*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
30*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
31*1fd5a2e1SPrashanth Swaminathan 
32*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
33*1fd5a2e1SPrashanth Swaminathan 
34*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine once stack space
35*1fd5a2e1SPrashanth Swaminathan    has been allocated for the function's arguments */
36*1fd5a2e1SPrashanth Swaminathan 
ffi_prep_args(char * stack,extended_cif * ecif)37*1fd5a2e1SPrashanth Swaminathan void *ffi_prep_args(char *stack, extended_cif *ecif)
38*1fd5a2e1SPrashanth Swaminathan {
39*1fd5a2e1SPrashanth Swaminathan   register unsigned int i;
40*1fd5a2e1SPrashanth Swaminathan   register void **p_argv;
41*1fd5a2e1SPrashanth Swaminathan   register char *argp;
42*1fd5a2e1SPrashanth Swaminathan   register ffi_type **p_arg;
43*1fd5a2e1SPrashanth Swaminathan   register int count = 0;
44*1fd5a2e1SPrashanth Swaminathan 
45*1fd5a2e1SPrashanth Swaminathan   p_argv = ecif->avalue;
46*1fd5a2e1SPrashanth Swaminathan   argp = stack;
47*1fd5a2e1SPrashanth Swaminathan 
48*1fd5a2e1SPrashanth Swaminathan   for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
49*1fd5a2e1SPrashanth Swaminathan        (i != 0);
50*1fd5a2e1SPrashanth Swaminathan        i--, p_arg++)
51*1fd5a2e1SPrashanth Swaminathan     {
52*1fd5a2e1SPrashanth Swaminathan       size_t z;
53*1fd5a2e1SPrashanth Swaminathan 
54*1fd5a2e1SPrashanth Swaminathan       z = (*p_arg)->size;
55*1fd5a2e1SPrashanth Swaminathan 
56*1fd5a2e1SPrashanth Swaminathan       if ((*p_arg)->type == FFI_TYPE_STRUCT)
57*1fd5a2e1SPrashanth Swaminathan 	{
58*1fd5a2e1SPrashanth Swaminathan 	  z = sizeof(void*);
59*1fd5a2e1SPrashanth Swaminathan 	  *(void **) argp = *p_argv;
60*1fd5a2e1SPrashanth Swaminathan 	}
61*1fd5a2e1SPrashanth Swaminathan       /*      if ((*p_arg)->type == FFI_TYPE_FLOAT)
62*1fd5a2e1SPrashanth Swaminathan 	{
63*1fd5a2e1SPrashanth Swaminathan 	  if (count > 24)
64*1fd5a2e1SPrashanth Swaminathan 	    {
65*1fd5a2e1SPrashanth Swaminathan 	      // This is going on the stack.  Turn it into a double.
66*1fd5a2e1SPrashanth Swaminathan 	      *(double *) argp = (double) *(float*)(* p_argv);
67*1fd5a2e1SPrashanth Swaminathan 	      z = sizeof(double);
68*1fd5a2e1SPrashanth Swaminathan 	    }
69*1fd5a2e1SPrashanth Swaminathan 	  else
70*1fd5a2e1SPrashanth Swaminathan 	    *(void **) argp = *(void **)(* p_argv);
71*1fd5a2e1SPrashanth Swaminathan 	}  */
72*1fd5a2e1SPrashanth Swaminathan       else if (z < sizeof(int))
73*1fd5a2e1SPrashanth Swaminathan 	{
74*1fd5a2e1SPrashanth Swaminathan 	  z = sizeof(int);
75*1fd5a2e1SPrashanth Swaminathan 	  switch ((*p_arg)->type)
76*1fd5a2e1SPrashanth Swaminathan 	    {
77*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT8:
78*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
79*1fd5a2e1SPrashanth Swaminathan 	      break;
80*1fd5a2e1SPrashanth Swaminathan 
81*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT8:
82*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
83*1fd5a2e1SPrashanth Swaminathan 	      break;
84*1fd5a2e1SPrashanth Swaminathan 
85*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT16:
86*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
87*1fd5a2e1SPrashanth Swaminathan 	      break;
88*1fd5a2e1SPrashanth Swaminathan 
89*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT16:
90*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
91*1fd5a2e1SPrashanth Swaminathan 	      break;
92*1fd5a2e1SPrashanth Swaminathan 
93*1fd5a2e1SPrashanth Swaminathan 	    default:
94*1fd5a2e1SPrashanth Swaminathan 	      FFI_ASSERT(0);
95*1fd5a2e1SPrashanth Swaminathan 	    }
96*1fd5a2e1SPrashanth Swaminathan 	}
97*1fd5a2e1SPrashanth Swaminathan       else if (z == sizeof(int))
98*1fd5a2e1SPrashanth Swaminathan 	{
99*1fd5a2e1SPrashanth Swaminathan 	  *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
100*1fd5a2e1SPrashanth Swaminathan 	}
101*1fd5a2e1SPrashanth Swaminathan       else
102*1fd5a2e1SPrashanth Swaminathan 	{
103*1fd5a2e1SPrashanth Swaminathan 	  memcpy(argp, *p_argv, z);
104*1fd5a2e1SPrashanth Swaminathan 	}
105*1fd5a2e1SPrashanth Swaminathan       p_argv++;
106*1fd5a2e1SPrashanth Swaminathan       argp += z;
107*1fd5a2e1SPrashanth Swaminathan       count += z;
108*1fd5a2e1SPrashanth Swaminathan     }
109*1fd5a2e1SPrashanth Swaminathan 
110*1fd5a2e1SPrashanth Swaminathan   return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8)));
111*1fd5a2e1SPrashanth Swaminathan }
112*1fd5a2e1SPrashanth Swaminathan 
113*1fd5a2e1SPrashanth Swaminathan /* Perform machine dependent cif processing */
ffi_prep_cif_machdep(ffi_cif * cif)114*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
115*1fd5a2e1SPrashanth Swaminathan {
116*1fd5a2e1SPrashanth Swaminathan   if (cif->rtype->type == FFI_TYPE_STRUCT)
117*1fd5a2e1SPrashanth Swaminathan     cif->flags = -1;
118*1fd5a2e1SPrashanth Swaminathan   else
119*1fd5a2e1SPrashanth Swaminathan     cif->flags = cif->rtype->size;
120*1fd5a2e1SPrashanth Swaminathan 
121*1fd5a2e1SPrashanth Swaminathan   cif->bytes = FFI_ALIGN (cif->bytes, 8);
122*1fd5a2e1SPrashanth Swaminathan 
123*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
124*1fd5a2e1SPrashanth Swaminathan }
125*1fd5a2e1SPrashanth Swaminathan 
126*1fd5a2e1SPrashanth Swaminathan extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
127*1fd5a2e1SPrashanth Swaminathan 			  extended_cif *,
128*1fd5a2e1SPrashanth Swaminathan 			  unsigned, unsigned,
129*1fd5a2e1SPrashanth Swaminathan 			  unsigned *,
130*1fd5a2e1SPrashanth Swaminathan 			  void (*fn)(void));
131*1fd5a2e1SPrashanth Swaminathan 
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)132*1fd5a2e1SPrashanth Swaminathan void ffi_call(ffi_cif *cif,
133*1fd5a2e1SPrashanth Swaminathan 	      void (*fn)(void),
134*1fd5a2e1SPrashanth Swaminathan 	      void *rvalue,
135*1fd5a2e1SPrashanth Swaminathan 	      void **avalue)
136*1fd5a2e1SPrashanth Swaminathan {
137*1fd5a2e1SPrashanth Swaminathan   extended_cif ecif;
138*1fd5a2e1SPrashanth Swaminathan 
139*1fd5a2e1SPrashanth Swaminathan   ecif.cif = cif;
140*1fd5a2e1SPrashanth Swaminathan   ecif.avalue = avalue;
141*1fd5a2e1SPrashanth Swaminathan 
142*1fd5a2e1SPrashanth Swaminathan   /* If the return value is a struct and we don't have a return	*/
143*1fd5a2e1SPrashanth Swaminathan   /* value address then we need to make one		        */
144*1fd5a2e1SPrashanth Swaminathan 
145*1fd5a2e1SPrashanth Swaminathan   if ((rvalue == NULL) &&
146*1fd5a2e1SPrashanth Swaminathan       (cif->rtype->type == FFI_TYPE_STRUCT))
147*1fd5a2e1SPrashanth Swaminathan     {
148*1fd5a2e1SPrashanth Swaminathan       ecif.rvalue = alloca(cif->rtype->size);
149*1fd5a2e1SPrashanth Swaminathan     }
150*1fd5a2e1SPrashanth Swaminathan   else
151*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = rvalue;
152*1fd5a2e1SPrashanth Swaminathan 
153*1fd5a2e1SPrashanth Swaminathan 
154*1fd5a2e1SPrashanth Swaminathan   switch (cif->abi)
155*1fd5a2e1SPrashanth Swaminathan     {
156*1fd5a2e1SPrashanth Swaminathan     case FFI_EABI:
157*1fd5a2e1SPrashanth Swaminathan       ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
158*1fd5a2e1SPrashanth Swaminathan 		    cif->flags, ecif.rvalue, fn);
159*1fd5a2e1SPrashanth Swaminathan       break;
160*1fd5a2e1SPrashanth Swaminathan     default:
161*1fd5a2e1SPrashanth Swaminathan       FFI_ASSERT(0);
162*1fd5a2e1SPrashanth Swaminathan       break;
163*1fd5a2e1SPrashanth Swaminathan     }
164*1fd5a2e1SPrashanth Swaminathan }
165*1fd5a2e1SPrashanth Swaminathan 
ffi_closure_eabi(unsigned arg1,unsigned arg2,unsigned arg3,unsigned arg4,unsigned arg5,unsigned arg6)166*1fd5a2e1SPrashanth Swaminathan void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
167*1fd5a2e1SPrashanth Swaminathan 		       unsigned arg4, unsigned arg5, unsigned arg6)
168*1fd5a2e1SPrashanth Swaminathan {
169*1fd5a2e1SPrashanth Swaminathan   /* This function is called by a trampoline.  The trampoline stows a
170*1fd5a2e1SPrashanth Swaminathan      pointer to the ffi_closure object in gr7.  We must save this
171*1fd5a2e1SPrashanth Swaminathan      pointer in a place that will persist while we do our work.  */
172*1fd5a2e1SPrashanth Swaminathan   register ffi_closure *creg __asm__ ("gr7");
173*1fd5a2e1SPrashanth Swaminathan   ffi_closure *closure = creg;
174*1fd5a2e1SPrashanth Swaminathan 
175*1fd5a2e1SPrashanth Swaminathan   /* Arguments that don't fit in registers are found on the stack
176*1fd5a2e1SPrashanth Swaminathan      at a fixed offset above the current frame pointer.  */
177*1fd5a2e1SPrashanth Swaminathan   register char *frame_pointer __asm__ ("fp");
178*1fd5a2e1SPrashanth Swaminathan   char *stack_args = frame_pointer + 16;
179*1fd5a2e1SPrashanth Swaminathan 
180*1fd5a2e1SPrashanth Swaminathan   /* Lay the register arguments down in a continuous chunk of memory.  */
181*1fd5a2e1SPrashanth Swaminathan   unsigned register_args[6] =
182*1fd5a2e1SPrashanth Swaminathan     { arg1, arg2, arg3, arg4, arg5, arg6 };
183*1fd5a2e1SPrashanth Swaminathan 
184*1fd5a2e1SPrashanth Swaminathan   ffi_cif *cif = closure->cif;
185*1fd5a2e1SPrashanth Swaminathan   ffi_type **arg_types = cif->arg_types;
186*1fd5a2e1SPrashanth Swaminathan   void **avalue = alloca (cif->nargs * sizeof(void *));
187*1fd5a2e1SPrashanth Swaminathan   char *ptr = (char *) register_args;
188*1fd5a2e1SPrashanth Swaminathan   int i;
189*1fd5a2e1SPrashanth Swaminathan 
190*1fd5a2e1SPrashanth Swaminathan   /* Find the address of each argument.  */
191*1fd5a2e1SPrashanth Swaminathan   for (i = 0; i < cif->nargs; i++)
192*1fd5a2e1SPrashanth Swaminathan     {
193*1fd5a2e1SPrashanth Swaminathan       switch (arg_types[i]->type)
194*1fd5a2e1SPrashanth Swaminathan 	{
195*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT8:
196*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT8:
197*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = ptr + 3;
198*1fd5a2e1SPrashanth Swaminathan 	  break;
199*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT16:
200*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT16:
201*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = ptr + 2;
202*1fd5a2e1SPrashanth Swaminathan 	  break;
203*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_SINT32:
204*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_UINT32:
205*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_FLOAT:
206*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = ptr;
207*1fd5a2e1SPrashanth Swaminathan 	  break;
208*1fd5a2e1SPrashanth Swaminathan 	case FFI_TYPE_STRUCT:
209*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = *(void**)ptr;
210*1fd5a2e1SPrashanth Swaminathan 	  break;
211*1fd5a2e1SPrashanth Swaminathan 	default:
212*1fd5a2e1SPrashanth Swaminathan 	  /* This is an 8-byte value.  */
213*1fd5a2e1SPrashanth Swaminathan 	  avalue[i] = ptr;
214*1fd5a2e1SPrashanth Swaminathan 	  ptr += 4;
215*1fd5a2e1SPrashanth Swaminathan 	  break;
216*1fd5a2e1SPrashanth Swaminathan 	}
217*1fd5a2e1SPrashanth Swaminathan       ptr += 4;
218*1fd5a2e1SPrashanth Swaminathan 
219*1fd5a2e1SPrashanth Swaminathan       /* If we've handled more arguments than fit in registers,
220*1fd5a2e1SPrashanth Swaminathan 	 start looking at the those passed on the stack.  */
221*1fd5a2e1SPrashanth Swaminathan       if (ptr == ((char *)register_args + (6*4)))
222*1fd5a2e1SPrashanth Swaminathan 	ptr = stack_args;
223*1fd5a2e1SPrashanth Swaminathan     }
224*1fd5a2e1SPrashanth Swaminathan 
225*1fd5a2e1SPrashanth Swaminathan   /* Invoke the closure.  */
226*1fd5a2e1SPrashanth Swaminathan   if (cif->rtype->type == FFI_TYPE_STRUCT)
227*1fd5a2e1SPrashanth Swaminathan     {
228*1fd5a2e1SPrashanth Swaminathan       /* The caller allocates space for the return structure, and
229*1fd5a2e1SPrashanth Swaminathan        passes a pointer to this space in gr3.  Use this value directly
230*1fd5a2e1SPrashanth Swaminathan        as the return value.  */
231*1fd5a2e1SPrashanth Swaminathan       register void *return_struct_ptr __asm__("gr3");
232*1fd5a2e1SPrashanth Swaminathan       (closure->fun) (cif, return_struct_ptr, avalue, closure->user_data);
233*1fd5a2e1SPrashanth Swaminathan     }
234*1fd5a2e1SPrashanth Swaminathan   else
235*1fd5a2e1SPrashanth Swaminathan     {
236*1fd5a2e1SPrashanth Swaminathan       /* Allocate space for the return value and call the function.  */
237*1fd5a2e1SPrashanth Swaminathan       long long rvalue;
238*1fd5a2e1SPrashanth Swaminathan       (closure->fun) (cif, &rvalue, avalue, closure->user_data);
239*1fd5a2e1SPrashanth Swaminathan 
240*1fd5a2e1SPrashanth Swaminathan       /* Functions return 4-byte or smaller results in gr8.  8-byte
241*1fd5a2e1SPrashanth Swaminathan 	 values also use gr9.  We fill the both, even for small return
242*1fd5a2e1SPrashanth Swaminathan 	 values, just to avoid a branch.  */
243*1fd5a2e1SPrashanth Swaminathan       asm ("ldi  @(%0, #0), gr8" : : "r" (&rvalue));
244*1fd5a2e1SPrashanth Swaminathan       asm ("ldi  @(%0, #0), gr9" : : "r" (&((int *) &rvalue)[1]));
245*1fd5a2e1SPrashanth Swaminathan     }
246*1fd5a2e1SPrashanth Swaminathan }
247*1fd5a2e1SPrashanth Swaminathan 
248*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)249*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
250*1fd5a2e1SPrashanth Swaminathan 		      ffi_cif* cif,
251*1fd5a2e1SPrashanth Swaminathan 		      void (*fun)(ffi_cif*, void*, void**, void*),
252*1fd5a2e1SPrashanth Swaminathan 		      void *user_data,
253*1fd5a2e1SPrashanth Swaminathan 		      void *codeloc)
254*1fd5a2e1SPrashanth Swaminathan {
255*1fd5a2e1SPrashanth Swaminathan   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
256*1fd5a2e1SPrashanth Swaminathan   unsigned long fn = (long) ffi_closure_eabi;
257*1fd5a2e1SPrashanth Swaminathan   unsigned long cls = (long) codeloc;
258*1fd5a2e1SPrashanth Swaminathan #ifdef __FRV_FDPIC__
259*1fd5a2e1SPrashanth Swaminathan   register void *got __asm__("gr15");
260*1fd5a2e1SPrashanth Swaminathan #endif
261*1fd5a2e1SPrashanth Swaminathan   int i;
262*1fd5a2e1SPrashanth Swaminathan 
263*1fd5a2e1SPrashanth Swaminathan   fn = (unsigned long) ffi_closure_eabi;
264*1fd5a2e1SPrashanth Swaminathan 
265*1fd5a2e1SPrashanth Swaminathan #ifdef __FRV_FDPIC__
266*1fd5a2e1SPrashanth Swaminathan   tramp[0] = &((unsigned int *)codeloc)[2];
267*1fd5a2e1SPrashanth Swaminathan   tramp[1] = got;
268*1fd5a2e1SPrashanth Swaminathan   tramp[2] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
269*1fd5a2e1SPrashanth Swaminathan   tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
270*1fd5a2e1SPrashanth Swaminathan   tramp[4] = 0x8cf80000 + (fn  >> 16);	  /* sethi hi(fn), gr6     */
271*1fd5a2e1SPrashanth Swaminathan   tramp[5] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
272*1fd5a2e1SPrashanth Swaminathan   tramp[6] = 0x9cc86000;                  /* ldi @(gr6, #0), gr14  */
273*1fd5a2e1SPrashanth Swaminathan   tramp[7] = 0x8030e000;                  /* jmpl @(gr14, gr0)     */
274*1fd5a2e1SPrashanth Swaminathan #else
275*1fd5a2e1SPrashanth Swaminathan   tramp[0] = 0x8cfc0000 + (fn  & 0xffff); /* setlos lo(fn), gr6    */
276*1fd5a2e1SPrashanth Swaminathan   tramp[1] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7   */
277*1fd5a2e1SPrashanth Swaminathan   tramp[2] = 0x8cf80000 + (fn  >> 16);	  /* sethi hi(fn), gr6     */
278*1fd5a2e1SPrashanth Swaminathan   tramp[3] = 0x8ef80000 + (cls >> 16);    /* sethi hi(cls), gr7    */
279*1fd5a2e1SPrashanth Swaminathan   tramp[4] = 0x80300006;                  /* jmpl @(gr0, gr6)      */
280*1fd5a2e1SPrashanth Swaminathan #endif
281*1fd5a2e1SPrashanth Swaminathan 
282*1fd5a2e1SPrashanth Swaminathan   closure->cif = cif;
283*1fd5a2e1SPrashanth Swaminathan   closure->fun = fun;
284*1fd5a2e1SPrashanth Swaminathan   closure->user_data = user_data;
285*1fd5a2e1SPrashanth Swaminathan 
286*1fd5a2e1SPrashanth Swaminathan   /* Cache flushing.  */
287*1fd5a2e1SPrashanth Swaminathan   for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
288*1fd5a2e1SPrashanth Swaminathan     __asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
289*1fd5a2e1SPrashanth Swaminathan 		      "r" (codeloc));
290*1fd5a2e1SPrashanth Swaminathan 
291*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
292*1fd5a2e1SPrashanth Swaminathan }
293