xref: /aosp_15_r20/external/libffi/src/nios2/ffi.c (revision 1fd5a2e1d639cd1ddf29dd0c484c123bbd850c21)
1*1fd5a2e1SPrashanth Swaminathan /* libffi support for Altera Nios II.
2*1fd5a2e1SPrashanth Swaminathan 
3*1fd5a2e1SPrashanth Swaminathan    Copyright (c) 2013 Mentor Graphics.
4*1fd5a2e1SPrashanth Swaminathan 
5*1fd5a2e1SPrashanth Swaminathan    Permission is hereby granted, free of charge, to any person obtaining
6*1fd5a2e1SPrashanth Swaminathan    a copy of this software and associated documentation files (the
7*1fd5a2e1SPrashanth Swaminathan    ``Software''), to deal in the Software without restriction, including
8*1fd5a2e1SPrashanth Swaminathan    without limitation the rights to use, copy, modify, merge, publish,
9*1fd5a2e1SPrashanth Swaminathan    distribute, sublicense, and/or sell copies of the Software, and to
10*1fd5a2e1SPrashanth Swaminathan    permit persons to whom the Software is furnished to do so, subject to
11*1fd5a2e1SPrashanth Swaminathan    the following conditions:
12*1fd5a2e1SPrashanth Swaminathan 
13*1fd5a2e1SPrashanth Swaminathan    The above copyright notice and this permission notice shall be
14*1fd5a2e1SPrashanth Swaminathan    included in all copies or substantial portions of the Software.
15*1fd5a2e1SPrashanth Swaminathan 
16*1fd5a2e1SPrashanth Swaminathan    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
17*1fd5a2e1SPrashanth Swaminathan    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18*1fd5a2e1SPrashanth Swaminathan    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19*1fd5a2e1SPrashanth Swaminathan    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20*1fd5a2e1SPrashanth Swaminathan    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21*1fd5a2e1SPrashanth Swaminathan    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22*1fd5a2e1SPrashanth Swaminathan    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
23*1fd5a2e1SPrashanth Swaminathan 
24*1fd5a2e1SPrashanth Swaminathan 
25*1fd5a2e1SPrashanth Swaminathan #include <ffi.h>
26*1fd5a2e1SPrashanth Swaminathan #include <ffi_common.h>
27*1fd5a2e1SPrashanth Swaminathan 
28*1fd5a2e1SPrashanth Swaminathan #include <stdlib.h>
29*1fd5a2e1SPrashanth Swaminathan 
30*1fd5a2e1SPrashanth Swaminathan /* The Nios II Processor Reference Handbook defines the procedure call
31*1fd5a2e1SPrashanth Swaminathan    ABI as follows.
32*1fd5a2e1SPrashanth Swaminathan 
33*1fd5a2e1SPrashanth Swaminathan    Arguments are passed as if a structure containing the types of
34*1fd5a2e1SPrashanth Swaminathan    the arguments were constructed.  The first 16 bytes are passed in r4
35*1fd5a2e1SPrashanth Swaminathan    through r7, the remainder on the stack.  The first 16 bytes of a function
36*1fd5a2e1SPrashanth Swaminathan    taking variable arguments are passed in r4-r7 in the same way.
37*1fd5a2e1SPrashanth Swaminathan 
38*1fd5a2e1SPrashanth Swaminathan    Return values of types up to 8 bytes are returned in r2 and r3.  For
39*1fd5a2e1SPrashanth Swaminathan    return values greater than 8 bytes, the caller must allocate memory for
40*1fd5a2e1SPrashanth Swaminathan    the result and pass the address as if it were argument 0.
41*1fd5a2e1SPrashanth Swaminathan 
42*1fd5a2e1SPrashanth Swaminathan    While this isn't specified explicitly in the ABI documentation, GCC
43*1fd5a2e1SPrashanth Swaminathan    promotes integral arguments smaller than int size to 32 bits.
44*1fd5a2e1SPrashanth Swaminathan 
45*1fd5a2e1SPrashanth Swaminathan    Also of note, the ABI specifies that all structure objects are
46*1fd5a2e1SPrashanth Swaminathan    aligned to 32 bits even if all their fields have a smaller natural
47*1fd5a2e1SPrashanth Swaminathan    alignment.  See FFI_AGGREGATE_ALIGNMENT.  */
48*1fd5a2e1SPrashanth Swaminathan 
49*1fd5a2e1SPrashanth Swaminathan 
50*1fd5a2e1SPrashanth Swaminathan /* Declare the assembly language hooks.  */
51*1fd5a2e1SPrashanth Swaminathan 
52*1fd5a2e1SPrashanth Swaminathan extern UINT64 ffi_call_sysv (void (*) (char *, extended_cif *),
53*1fd5a2e1SPrashanth Swaminathan 			     extended_cif *,
54*1fd5a2e1SPrashanth Swaminathan 			     unsigned,
55*1fd5a2e1SPrashanth Swaminathan 			     void (*fn) (void));
56*1fd5a2e1SPrashanth Swaminathan extern void ffi_closure_sysv (void);
57*1fd5a2e1SPrashanth Swaminathan 
58*1fd5a2e1SPrashanth Swaminathan /* Perform machine-dependent cif processing.  */
59*1fd5a2e1SPrashanth Swaminathan 
ffi_prep_cif_machdep(ffi_cif * cif)60*1fd5a2e1SPrashanth Swaminathan ffi_status ffi_prep_cif_machdep (ffi_cif *cif)
61*1fd5a2e1SPrashanth Swaminathan {
62*1fd5a2e1SPrashanth Swaminathan   /* We always want at least 16 bytes in the parameter block since it
63*1fd5a2e1SPrashanth Swaminathan      simplifies the low-level call function.  Also round the parameter
64*1fd5a2e1SPrashanth Swaminathan      block size up to a multiple of 4 bytes to preserve
65*1fd5a2e1SPrashanth Swaminathan      32-bit alignment of the stack pointer.  */
66*1fd5a2e1SPrashanth Swaminathan   if (cif->bytes < 16)
67*1fd5a2e1SPrashanth Swaminathan     cif->bytes = 16;
68*1fd5a2e1SPrashanth Swaminathan   else
69*1fd5a2e1SPrashanth Swaminathan     cif->bytes = (cif->bytes + 3) & ~3;
70*1fd5a2e1SPrashanth Swaminathan 
71*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
72*1fd5a2e1SPrashanth Swaminathan }
73*1fd5a2e1SPrashanth Swaminathan 
74*1fd5a2e1SPrashanth Swaminathan 
75*1fd5a2e1SPrashanth Swaminathan /* ffi_prep_args is called by the assembly routine to transfer arguments
76*1fd5a2e1SPrashanth Swaminathan    to the stack using the pointers in the ecif array.
77*1fd5a2e1SPrashanth Swaminathan    Note that the stack buffer is big enough to fit all the arguments,
78*1fd5a2e1SPrashanth Swaminathan    but the first 16 bytes will be copied to registers for the actual
79*1fd5a2e1SPrashanth Swaminathan    call.  */
80*1fd5a2e1SPrashanth Swaminathan 
ffi_prep_args(char * stack,extended_cif * ecif)81*1fd5a2e1SPrashanth Swaminathan void ffi_prep_args (char *stack, extended_cif *ecif)
82*1fd5a2e1SPrashanth Swaminathan {
83*1fd5a2e1SPrashanth Swaminathan   char *argp = stack;
84*1fd5a2e1SPrashanth Swaminathan   unsigned int i;
85*1fd5a2e1SPrashanth Swaminathan 
86*1fd5a2e1SPrashanth Swaminathan   /* The implicit return value pointer is passed as if it were a hidden
87*1fd5a2e1SPrashanth Swaminathan      first argument.  */
88*1fd5a2e1SPrashanth Swaminathan   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT
89*1fd5a2e1SPrashanth Swaminathan       && ecif->cif->rtype->size > 8)
90*1fd5a2e1SPrashanth Swaminathan     {
91*1fd5a2e1SPrashanth Swaminathan       (*(void **) argp) = ecif->rvalue;
92*1fd5a2e1SPrashanth Swaminathan       argp += 4;
93*1fd5a2e1SPrashanth Swaminathan     }
94*1fd5a2e1SPrashanth Swaminathan 
95*1fd5a2e1SPrashanth Swaminathan   for (i = 0; i < ecif->cif->nargs; i++)
96*1fd5a2e1SPrashanth Swaminathan     {
97*1fd5a2e1SPrashanth Swaminathan       void *avalue = ecif->avalue[i];
98*1fd5a2e1SPrashanth Swaminathan       ffi_type *atype = ecif->cif->arg_types[i];
99*1fd5a2e1SPrashanth Swaminathan       size_t size = atype->size;
100*1fd5a2e1SPrashanth Swaminathan       size_t alignment = atype->alignment;
101*1fd5a2e1SPrashanth Swaminathan 
102*1fd5a2e1SPrashanth Swaminathan       /* Align argp as appropriate for the argument type.  */
103*1fd5a2e1SPrashanth Swaminathan       if ((alignment - 1) & (unsigned) argp)
104*1fd5a2e1SPrashanth Swaminathan 	argp = (char *) FFI_ALIGN (argp, alignment);
105*1fd5a2e1SPrashanth Swaminathan 
106*1fd5a2e1SPrashanth Swaminathan       /* Copy the argument, promoting integral types smaller than a
107*1fd5a2e1SPrashanth Swaminathan 	 word to word size.  */
108*1fd5a2e1SPrashanth Swaminathan       if (size < sizeof (int))
109*1fd5a2e1SPrashanth Swaminathan 	{
110*1fd5a2e1SPrashanth Swaminathan 	  size = sizeof (int);
111*1fd5a2e1SPrashanth Swaminathan 	  switch (atype->type)
112*1fd5a2e1SPrashanth Swaminathan 	    {
113*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT8:
114*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int) *(SINT8 *) avalue;
115*1fd5a2e1SPrashanth Swaminathan 	      break;
116*1fd5a2e1SPrashanth Swaminathan 
117*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT8:
118*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int) *(UINT8 *) avalue;
119*1fd5a2e1SPrashanth Swaminathan 	      break;
120*1fd5a2e1SPrashanth Swaminathan 
121*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_SINT16:
122*1fd5a2e1SPrashanth Swaminathan 	      *(signed int *) argp = (signed int) *(SINT16 *) avalue;
123*1fd5a2e1SPrashanth Swaminathan 	      break;
124*1fd5a2e1SPrashanth Swaminathan 
125*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_UINT16:
126*1fd5a2e1SPrashanth Swaminathan 	      *(unsigned int *) argp = (unsigned int) *(UINT16 *) avalue;
127*1fd5a2e1SPrashanth Swaminathan 	      break;
128*1fd5a2e1SPrashanth Swaminathan 
129*1fd5a2e1SPrashanth Swaminathan 	    case FFI_TYPE_STRUCT:
130*1fd5a2e1SPrashanth Swaminathan 	      memcpy (argp, avalue, atype->size);
131*1fd5a2e1SPrashanth Swaminathan 	      break;
132*1fd5a2e1SPrashanth Swaminathan 
133*1fd5a2e1SPrashanth Swaminathan 	    default:
134*1fd5a2e1SPrashanth Swaminathan 	      FFI_ASSERT(0);
135*1fd5a2e1SPrashanth Swaminathan 	    }
136*1fd5a2e1SPrashanth Swaminathan 	}
137*1fd5a2e1SPrashanth Swaminathan       else if (size == sizeof (int))
138*1fd5a2e1SPrashanth Swaminathan 	*(unsigned int *) argp = (unsigned int) *(UINT32 *) avalue;
139*1fd5a2e1SPrashanth Swaminathan       else
140*1fd5a2e1SPrashanth Swaminathan 	memcpy (argp, avalue, size);
141*1fd5a2e1SPrashanth Swaminathan       argp += size;
142*1fd5a2e1SPrashanth Swaminathan     }
143*1fd5a2e1SPrashanth Swaminathan }
144*1fd5a2e1SPrashanth Swaminathan 
145*1fd5a2e1SPrashanth Swaminathan 
146*1fd5a2e1SPrashanth Swaminathan /* Call FN using the prepared CIF.  RVALUE points to space allocated by
147*1fd5a2e1SPrashanth Swaminathan    the caller for the return value, and AVALUE is an array of argument
148*1fd5a2e1SPrashanth Swaminathan    pointers.  */
149*1fd5a2e1SPrashanth Swaminathan 
ffi_call(ffi_cif * cif,void (* fn)(void),void * rvalue,void ** avalue)150*1fd5a2e1SPrashanth Swaminathan void ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue)
151*1fd5a2e1SPrashanth Swaminathan {
152*1fd5a2e1SPrashanth Swaminathan 
153*1fd5a2e1SPrashanth Swaminathan   extended_cif ecif;
154*1fd5a2e1SPrashanth Swaminathan   UINT64 result;
155*1fd5a2e1SPrashanth Swaminathan 
156*1fd5a2e1SPrashanth Swaminathan   /* If bigret is true, this is the case where a return value of larger
157*1fd5a2e1SPrashanth Swaminathan      than 8 bytes is handled by being passed by reference as an implicit
158*1fd5a2e1SPrashanth Swaminathan      argument.  */
159*1fd5a2e1SPrashanth Swaminathan   int bigret = (cif->rtype->type == FFI_TYPE_STRUCT
160*1fd5a2e1SPrashanth Swaminathan 		&& cif->rtype->size > 8);
161*1fd5a2e1SPrashanth Swaminathan 
162*1fd5a2e1SPrashanth Swaminathan   ecif.cif = cif;
163*1fd5a2e1SPrashanth Swaminathan   ecif.avalue = avalue;
164*1fd5a2e1SPrashanth Swaminathan 
165*1fd5a2e1SPrashanth Swaminathan   /* Allocate space for return value if this is the pass-by-reference case
166*1fd5a2e1SPrashanth Swaminathan      and the caller did not provide a buffer.  */
167*1fd5a2e1SPrashanth Swaminathan   if (rvalue == NULL && bigret)
168*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = alloca (cif->rtype->size);
169*1fd5a2e1SPrashanth Swaminathan   else
170*1fd5a2e1SPrashanth Swaminathan     ecif.rvalue = rvalue;
171*1fd5a2e1SPrashanth Swaminathan 
172*1fd5a2e1SPrashanth Swaminathan   result = ffi_call_sysv (ffi_prep_args, &ecif, cif->bytes, fn);
173*1fd5a2e1SPrashanth Swaminathan 
174*1fd5a2e1SPrashanth Swaminathan   /* Now result contains the 64 bit contents returned from fn in
175*1fd5a2e1SPrashanth Swaminathan      r2 and r3.  Copy the value of the appropriate size to the user-provided
176*1fd5a2e1SPrashanth Swaminathan      rvalue buffer.  */
177*1fd5a2e1SPrashanth Swaminathan   if (rvalue && !bigret)
178*1fd5a2e1SPrashanth Swaminathan     switch (cif->rtype->size)
179*1fd5a2e1SPrashanth Swaminathan       {
180*1fd5a2e1SPrashanth Swaminathan       case 1:
181*1fd5a2e1SPrashanth Swaminathan 	*(UINT8 *)rvalue = (UINT8) result;
182*1fd5a2e1SPrashanth Swaminathan 	break;
183*1fd5a2e1SPrashanth Swaminathan       case 2:
184*1fd5a2e1SPrashanth Swaminathan 	*(UINT16 *)rvalue = (UINT16) result;
185*1fd5a2e1SPrashanth Swaminathan 	break;
186*1fd5a2e1SPrashanth Swaminathan       case 4:
187*1fd5a2e1SPrashanth Swaminathan 	*(UINT32 *)rvalue = (UINT32) result;
188*1fd5a2e1SPrashanth Swaminathan 	break;
189*1fd5a2e1SPrashanth Swaminathan       case 8:
190*1fd5a2e1SPrashanth Swaminathan 	*(UINT64 *)rvalue = (UINT64) result;
191*1fd5a2e1SPrashanth Swaminathan 	break;
192*1fd5a2e1SPrashanth Swaminathan       default:
193*1fd5a2e1SPrashanth Swaminathan 	memcpy (rvalue, (void *)&result, cif->rtype->size);
194*1fd5a2e1SPrashanth Swaminathan 	break;
195*1fd5a2e1SPrashanth Swaminathan       }
196*1fd5a2e1SPrashanth Swaminathan }
197*1fd5a2e1SPrashanth Swaminathan 
198*1fd5a2e1SPrashanth Swaminathan /* This function is invoked from the closure trampoline to invoke
199*1fd5a2e1SPrashanth Swaminathan    CLOSURE with argument block ARGS.  Parse ARGS according to
200*1fd5a2e1SPrashanth Swaminathan    CLOSURE->cfi and invoke CLOSURE->fun.  */
201*1fd5a2e1SPrashanth Swaminathan 
202*1fd5a2e1SPrashanth Swaminathan static UINT64
ffi_closure_helper(unsigned char * args,ffi_closure * closure)203*1fd5a2e1SPrashanth Swaminathan ffi_closure_helper (unsigned char *args,
204*1fd5a2e1SPrashanth Swaminathan 		    ffi_closure *closure)
205*1fd5a2e1SPrashanth Swaminathan {
206*1fd5a2e1SPrashanth Swaminathan   ffi_cif *cif = closure->cif;
207*1fd5a2e1SPrashanth Swaminathan   unsigned char *argp = args;
208*1fd5a2e1SPrashanth Swaminathan   void **parsed_args = alloca (cif->nargs * sizeof (void *));
209*1fd5a2e1SPrashanth Swaminathan   UINT64 result;
210*1fd5a2e1SPrashanth Swaminathan   void *retptr;
211*1fd5a2e1SPrashanth Swaminathan   unsigned int i;
212*1fd5a2e1SPrashanth Swaminathan 
213*1fd5a2e1SPrashanth Swaminathan   /* First figure out what to do about the return type.  If this is the
214*1fd5a2e1SPrashanth Swaminathan      big-structure-return case, the first arg is the hidden return buffer
215*1fd5a2e1SPrashanth Swaminathan      allocated by the caller.  */
216*1fd5a2e1SPrashanth Swaminathan   if (cif->rtype->type == FFI_TYPE_STRUCT
217*1fd5a2e1SPrashanth Swaminathan       && cif->rtype->size > 8)
218*1fd5a2e1SPrashanth Swaminathan     {
219*1fd5a2e1SPrashanth Swaminathan       retptr = *((void **) argp);
220*1fd5a2e1SPrashanth Swaminathan       argp += 4;
221*1fd5a2e1SPrashanth Swaminathan     }
222*1fd5a2e1SPrashanth Swaminathan   else
223*1fd5a2e1SPrashanth Swaminathan     retptr = (void *) &result;
224*1fd5a2e1SPrashanth Swaminathan 
225*1fd5a2e1SPrashanth Swaminathan   /* Fill in the array of argument pointers.  */
226*1fd5a2e1SPrashanth Swaminathan   for (i = 0; i < cif->nargs; i++)
227*1fd5a2e1SPrashanth Swaminathan     {
228*1fd5a2e1SPrashanth Swaminathan       size_t size = cif->arg_types[i]->size;
229*1fd5a2e1SPrashanth Swaminathan       size_t alignment = cif->arg_types[i]->alignment;
230*1fd5a2e1SPrashanth Swaminathan 
231*1fd5a2e1SPrashanth Swaminathan       /* Align argp as appropriate for the argument type.  */
232*1fd5a2e1SPrashanth Swaminathan       if ((alignment - 1) & (unsigned) argp)
233*1fd5a2e1SPrashanth Swaminathan 	argp = (char *) FFI_ALIGN (argp, alignment);
234*1fd5a2e1SPrashanth Swaminathan 
235*1fd5a2e1SPrashanth Swaminathan       /* Arguments smaller than an int are promoted to int.  */
236*1fd5a2e1SPrashanth Swaminathan       if (size < sizeof (int))
237*1fd5a2e1SPrashanth Swaminathan 	size = sizeof (int);
238*1fd5a2e1SPrashanth Swaminathan 
239*1fd5a2e1SPrashanth Swaminathan       /* Store the pointer.  */
240*1fd5a2e1SPrashanth Swaminathan       parsed_args[i] = argp;
241*1fd5a2e1SPrashanth Swaminathan       argp += size;
242*1fd5a2e1SPrashanth Swaminathan     }
243*1fd5a2e1SPrashanth Swaminathan 
244*1fd5a2e1SPrashanth Swaminathan   /* Call the user-supplied function.  */
245*1fd5a2e1SPrashanth Swaminathan   (closure->fun) (cif, retptr, parsed_args, closure->user_data);
246*1fd5a2e1SPrashanth Swaminathan   return result;
247*1fd5a2e1SPrashanth Swaminathan }
248*1fd5a2e1SPrashanth Swaminathan 
249*1fd5a2e1SPrashanth Swaminathan 
250*1fd5a2e1SPrashanth Swaminathan /* Initialize CLOSURE with a trampoline to call FUN with
251*1fd5a2e1SPrashanth Swaminathan    CIF and USER_DATA.  */
252*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)253*1fd5a2e1SPrashanth Swaminathan ffi_prep_closure_loc (ffi_closure* closure,
254*1fd5a2e1SPrashanth Swaminathan 		      ffi_cif* cif,
255*1fd5a2e1SPrashanth Swaminathan 		      void (*fun) (ffi_cif*, void*, void**, void*),
256*1fd5a2e1SPrashanth Swaminathan 		      void *user_data,
257*1fd5a2e1SPrashanth Swaminathan 		      void *codeloc)
258*1fd5a2e1SPrashanth Swaminathan {
259*1fd5a2e1SPrashanth Swaminathan   unsigned int *tramp = (unsigned int *) &closure->tramp[0];
260*1fd5a2e1SPrashanth Swaminathan   int i;
261*1fd5a2e1SPrashanth Swaminathan 
262*1fd5a2e1SPrashanth Swaminathan   if (cif->abi != FFI_SYSV)
263*1fd5a2e1SPrashanth Swaminathan     return FFI_BAD_ABI;
264*1fd5a2e1SPrashanth Swaminathan 
265*1fd5a2e1SPrashanth Swaminathan   /* The trampoline looks like:
266*1fd5a2e1SPrashanth Swaminathan        movhi r8, %hi(ffi_closure_sysv)
267*1fd5a2e1SPrashanth Swaminathan        ori r8, r8, %lo(ffi_closure_sysv)
268*1fd5a2e1SPrashanth Swaminathan        movhi r9, %hi(ffi_closure_helper)
269*1fd5a2e1SPrashanth Swaminathan        ori r0, r9, %lo(ffi_closure_helper)
270*1fd5a2e1SPrashanth Swaminathan        movhi r10, %hi(closure)
271*1fd5a2e1SPrashanth Swaminathan        ori r10, r10, %lo(closure)
272*1fd5a2e1SPrashanth Swaminathan        jmp r8
273*1fd5a2e1SPrashanth Swaminathan      and then ffi_closure_sysv retrieves the closure pointer out of r10
274*1fd5a2e1SPrashanth Swaminathan      in addition to the arguments passed in the normal way for the call,
275*1fd5a2e1SPrashanth Swaminathan      and invokes ffi_closure_helper.  We encode the pointer to
276*1fd5a2e1SPrashanth Swaminathan      ffi_closure_helper in the trampoline because making a PIC call
277*1fd5a2e1SPrashanth Swaminathan      to it in ffi_closure_sysv would be messy (it would have to indirect
278*1fd5a2e1SPrashanth Swaminathan      through the GOT).  */
279*1fd5a2e1SPrashanth Swaminathan 
280*1fd5a2e1SPrashanth Swaminathan #define HI(x) ((((unsigned int) (x)) >> 16) & 0xffff)
281*1fd5a2e1SPrashanth Swaminathan #define LO(x) (((unsigned int) (x)) & 0xffff)
282*1fd5a2e1SPrashanth Swaminathan   tramp[0] = (0 << 27) | (8 << 22) | (HI (ffi_closure_sysv) << 6) | 0x34;
283*1fd5a2e1SPrashanth Swaminathan   tramp[1] = (8 << 27) | (8 << 22) | (LO (ffi_closure_sysv) << 6) | 0x14;
284*1fd5a2e1SPrashanth Swaminathan   tramp[2] = (0 << 27) | (9 << 22) | (HI (ffi_closure_helper) << 6) | 0x34;
285*1fd5a2e1SPrashanth Swaminathan   tramp[3] = (9 << 27) | (9 << 22) | (LO (ffi_closure_helper) << 6) | 0x14;
286*1fd5a2e1SPrashanth Swaminathan   tramp[4] = (0 << 27) | (10 << 22) | (HI (closure) << 6) | 0x34;
287*1fd5a2e1SPrashanth Swaminathan   tramp[5] = (10 << 27) | (10 << 22) | (LO (closure) << 6) | 0x14;
288*1fd5a2e1SPrashanth Swaminathan   tramp[6] = (8 << 27) | (0x0d << 11) | 0x3a;
289*1fd5a2e1SPrashanth Swaminathan #undef HI
290*1fd5a2e1SPrashanth Swaminathan #undef LO
291*1fd5a2e1SPrashanth Swaminathan 
292*1fd5a2e1SPrashanth Swaminathan   /* Flush the caches.
293*1fd5a2e1SPrashanth Swaminathan      See Example 9-4 in the Nios II Software Developer's Handbook.  */
294*1fd5a2e1SPrashanth Swaminathan   for (i = 0; i < 7; i++)
295*1fd5a2e1SPrashanth Swaminathan     asm volatile ("flushd 0(%0); flushi %0" :: "r"(tramp + i) : "memory");
296*1fd5a2e1SPrashanth Swaminathan   asm volatile ("flushp" ::: "memory");
297*1fd5a2e1SPrashanth Swaminathan 
298*1fd5a2e1SPrashanth Swaminathan   closure->cif = cif;
299*1fd5a2e1SPrashanth Swaminathan   closure->fun = fun;
300*1fd5a2e1SPrashanth Swaminathan   closure->user_data = user_data;
301*1fd5a2e1SPrashanth Swaminathan 
302*1fd5a2e1SPrashanth Swaminathan   return FFI_OK;
303*1fd5a2e1SPrashanth Swaminathan }
304*1fd5a2e1SPrashanth Swaminathan 
305