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