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 ----------------------------------------------------------------------- */
29 #include <ffi_common.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
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
)
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. */
62 return FFI_TYPE_UINT8
;
64 return FFI_TYPE_SMALL_STRUCT2
;
66 return FFI_TYPE_SMALL_STRUCT3
;
68 return FFI_TYPE_SMALL_STRUCT4
;
70 return FFI_TYPE_SMALL_STRUCT5
;
72 return FFI_TYPE_SMALL_STRUCT6
;
74 return FFI_TYPE_SMALL_STRUCT7
;
76 return FFI_TYPE_SMALL_STRUCT8
;
78 return FFI_TYPE_STRUCT
; /* else, we pass it by pointer. */
81 /* PA has a downward growing stack, which looks like this:
85 SP = (4*(n+9)) arg word N
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
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,
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
;
148 debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__
, stack
,
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
;
161 *(SINT32
*)(stack
- slot
) = *(SINT8
*)(*p_argv
);
165 *(UINT32
*)(stack
- slot
) = *(UINT8
*)(*p_argv
);
168 case FFI_TYPE_SINT16
:
169 *(SINT32
*)(stack
- slot
) = *(SINT16
*)(*p_argv
);
172 case FFI_TYPE_UINT16
:
173 *(UINT32
*)(stack
- slot
) = *(UINT16
*)(*p_argv
);
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
),
181 *(UINT32
*)(stack
- slot
) = *(UINT32
*)(*p_argv
);
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
);
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;
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;
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
);
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
;
235 dest_cpy
= (char *)(stack
- slot
) + 4 - len
;
236 memcpy(dest_cpy
, (char *)*p_argv
, len
);
240 slot
+= (slot
& 1) ? 1 : 2;
241 dest_cpy
= (char *)(stack
- slot
) + 8 - len
;
242 memcpy(dest_cpy
, (char *)*p_argv
, len
);
245 *(UINT32
*)(stack
- slot
) = (UINT32
)(*p_argv
);
257 /* Make sure we didn't mess up and scribble on the stack. */
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
));
270 FFI_ASSERT(slot
* 4 <= bytes
);
275 static void ffi_size_stack_pa32(ffi_cif
*cif
)
279 int z
= 0; /* # stack slots */
281 for (ptr
= cif
->arg_types
, i
= 0; i
< cif
->nargs
; ptr
++, i
++)
283 int type
= (*ptr
)->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 */
294 case FFI_TYPE_LONGDOUBLE
:
296 case FFI_TYPE_STRUCT
:
297 z
+= 1; /* pass by ptr, callee will copy */
300 default: /* <= 32-bit values */
305 /* We can fit up to 6 args in the default 64-byte stack frame,
306 if we need more, we need more stack. */
308 cif
->bytes
= MIN_STACK_SIZE
; /* min stack size */
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
)
323 case FFI_TYPE_DOUBLE
:
324 cif
->flags
= (unsigned) cif
->rtype
->type
;
328 case FFI_TYPE_LONGDOUBLE
:
329 /* Long doubles are treated like a structure. */
330 cif
->flags
= FFI_TYPE_STRUCT
;
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
);
343 case FFI_TYPE_UINT64
:
344 case FFI_TYPE_SINT64
:
345 cif
->flags
= FFI_TYPE_UINT64
;
349 cif
->flags
= FFI_TYPE_INT
;
353 /* Lucky us, because of the unique PA ABI we get to do our
358 ffi_size_stack_pa32(cif
);
369 extern void ffi_call_pa32(void (*)(UINT32
*, extended_cif
*, unsigned),
370 extended_cif
*, unsigned, unsigned, unsigned *,
373 void ffi_call(ffi_cif
*cif
, void (*fn
)(), void *rvalue
, void **avalue
)
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. */
385 && (cif
->rtype
->type
== FFI_TYPE_STRUCT
386 || cif
->rtype
->type
== FFI_TYPE_LONGDOUBLE
))
388 && cif
->rtype
->type
== FFI_TYPE_STRUCT
)
391 ecif
.rvalue
= alloca(cif
->rtype
->size
);
394 ecif
.rvalue
= rvalue
;
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
);
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
)
421 UINT32 ret
[2]; /* function can return up to 64-bits in registers */
425 unsigned int slot
= FIRST_ARG_SLOT
;
426 register UINT32 r28
asm("r28");
430 /* If returning via structure, callee will write to our pointer. */
431 if (cif
->flags
== FFI_TYPE_STRUCT
)
432 rvalue
= (void *)r28
;
436 avalue
= (void **)alloca(cif
->nargs
* FFI_SIZEOF_ARG
);
438 p_arg
= cif
->arg_types
;
440 for (i
= 0; i
< avn
; i
++)
442 int type
= (*p_arg
)->type
;
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
;
456 case FFI_TYPE_SINT64
:
457 case FFI_TYPE_UINT64
:
458 slot
+= (slot
& 1) ? 1 : 2;
459 avalue
[i
] = (void *)(stack
- slot
);
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;
478 avalue
[i
] = (void *)(stack
- slot
);
481 case FFI_TYPE_DOUBLE
:
482 slot
+= (slot
& 1) ? 1 : 2;
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;
491 avalue
[i
] = (void *)(stack
- slot
);
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
) -
503 else if ((*p_arg
)->size
<= 8)
505 slot
+= (slot
& 1) ? 1 : 2;
506 avalue
[i
] = (void *)(stack
- slot
) + sizeof(UINT64
) -
510 avalue
[i
] = (void *) *(stack
- slot
);
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],
527 /* Store the result using the lower 2 bytes of the flags. */
531 *(stack
- FIRST_ARG_SLOT
) = (UINT8
)(ret
[0] >> 24);
534 *(stack
- FIRST_ARG_SLOT
) = (SINT8
)(ret
[0] >> 24);
536 case FFI_TYPE_UINT16
:
537 *(stack
- FIRST_ARG_SLOT
) = (UINT16
)(ret
[0] >> 16);
539 case FFI_TYPE_SINT16
:
540 *(stack
- FIRST_ARG_SLOT
) = (SINT16
)(ret
[0] >> 16);
543 case FFI_TYPE_SINT32
:
544 case FFI_TYPE_UINT32
:
545 *(stack
- FIRST_ARG_SLOT
) = ret
[0];
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];
553 case FFI_TYPE_DOUBLE
:
561 case FFI_TYPE_STRUCT
:
562 /* Don't need a return value, done by caller. */
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
);
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];
581 /* Right justify ret[0] and ret[1] */
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];
598 case FFI_TYPE_POINTER
:
603 debug(0, "assert with cif->flags: %d\n",cif
->flags
);
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);
617 ffi_prep_closure_loc (ffi_closure
* closure
,
619 void (*fun
)(ffi_cif
*,void*,void**,void*),
623 UINT32
*tramp
= (UINT32
*)(closure
->tramp
);
628 FFI_ASSERT (cif
->abi
== FFI_PA32
);
630 /* Make a small trampoline that will branch to our
631 handler function. Use PC-relative addressing. */
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
648 "fic 0(%%sr4, %0)\n\t"
649 "fic %1(%%sr4, %0)\n\t"
659 : "r"((unsigned long)tramp
& ~31),
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. */
685 "fic,m %2(%%sr0,%0)\n\t"
686 "fic,m %2(%%sr0,%0)\n\t"
687 "fic,m %2(%%sr0,%0)\n\t"
696 : "=&r" ((unsigned long)tmp
)
697 : "r" ((unsigned long)tramp
& ~31),
703 closure
->user_data
= user_data
;