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