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