1 /* -----------------------------------------------------------------------
2 ffi.c - (c) 2011 Anthony Green
4 (c) 2006 Free Software Foundation, Inc.
5 (c) 2003-2004 Randolph Chung <tausq@debian.org>
7 HPPA Foreign Function Interface
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:
18 The above copyright notice and this permission notice shall be included
19 in all copies or substantial portions of the Software.
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 ----------------------------------------------------------------------- */
32 #include <ffi_common.h>
37 #define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
39 #define MIN_STACK_SIZE 64
40 #define FIRST_ARG_SLOT 9
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))
52 #define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
54 static inline int ffi_struct_type(ffi_type
*t
)
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. */
65 return FFI_TYPE_UINT8
;
67 return FFI_TYPE_SMALL_STRUCT2
;
69 return FFI_TYPE_SMALL_STRUCT3
;
71 return FFI_TYPE_SMALL_STRUCT4
;
73 return FFI_TYPE_SMALL_STRUCT5
;
75 return FFI_TYPE_SMALL_STRUCT6
;
77 return FFI_TYPE_SMALL_STRUCT7
;
79 return FFI_TYPE_SMALL_STRUCT8
;
81 return FFI_TYPE_STRUCT
; /* else, we pass it by pointer. */
84 /* PA has a downward growing stack, which looks like this:
88 SP = (4*(n+9)) arg word N
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.
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.
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
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
122 Note that fr4R and fr6R are never used for arguments (i.e.,
123 doubles are not passed in fr4 or fr6).
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
128 This means we can have holes either in the register allocation,
131 /* ffi_prep_args is called by the assembly routine once stack space
132 has been allocated for the function's arguments
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
139 NOTE: We load floating point args in this function... that means we
140 assume gcc will not mess with fp regs in here. */
142 void ffi_prep_args_pa32(UINT32
*stack
, extended_cif
*ecif
, unsigned bytes
)
144 register unsigned int i
;
145 register ffi_type
**p_arg
;
146 register void **p_argv
;
147 unsigned int slot
= FIRST_ARG_SLOT
;
151 debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__
, stack
,
154 p_arg
= ecif
->cif
->arg_types
;
155 p_argv
= ecif
->avalue
;
157 for (i
= 0; i
< ecif
->cif
->nargs
; i
++)
159 int type
= (*p_arg
)->type
;
164 *(SINT32
*)(stack
- slot
) = *(SINT8
*)(*p_argv
);
168 *(UINT32
*)(stack
- slot
) = *(UINT8
*)(*p_argv
);
171 case FFI_TYPE_SINT16
:
172 *(SINT32
*)(stack
- slot
) = *(SINT16
*)(*p_argv
);
175 case FFI_TYPE_UINT16
:
176 *(UINT32
*)(stack
- slot
) = *(UINT16
*)(*p_argv
);
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
),
184 *(UINT32
*)(stack
- slot
) = *(UINT32
*)(*p_argv
);
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
);
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
)
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;
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
)
215 /* First 2 args go in fr5, fr7. */
216 case 1: fldd(stack
- slot
, fr5
); break;
217 case 3: fldd(stack
- slot
, fr7
); break;
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
);
229 case FFI_TYPE_STRUCT
:
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. */
235 len
= (*p_arg
)->size
;
238 dest_cpy
= (char *)(stack
- slot
) + 4 - len
;
239 memcpy(dest_cpy
, (char *)*p_argv
, len
);
243 slot
+= (slot
& 1) ? 1 : 2;
244 dest_cpy
= (char *)(stack
- slot
) + 8 - len
;
245 memcpy(dest_cpy
, (char *)*p_argv
, len
);
248 *(UINT32
*)(stack
- slot
) = (UINT32
)(*p_argv
);
260 /* Make sure we didn't mess up and scribble on the stack. */
264 debug(5, "Stack setup:\n");
265 for (n
= 0; n
< (bytes
+ 3) / 4; n
++)
267 if ((n
%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack
- n
)); }
268 debug(5, "%08x ", *(stack
- n
));
273 FFI_ASSERT(slot
* 4 <= bytes
);
278 static void ffi_size_stack_pa32(ffi_cif
*cif
)
282 int z
= 0; /* # stack slots */
284 for (ptr
= cif
->arg_types
, i
= 0; i
< cif
->nargs
; ptr
++, i
++)
286 int type
= (*ptr
)->type
;
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 */
297 case FFI_TYPE_LONGDOUBLE
:
299 case FFI_TYPE_STRUCT
:
300 z
+= 1; /* pass by ptr, callee will copy */
303 default: /* <= 32-bit values */
308 /* We can fit up to 6 args in the default 64-byte stack frame,
309 if we need more, we need more stack. */
311 cif
->bytes
= MIN_STACK_SIZE
; /* min stack size */
313 cif
->bytes
= 64 + ROUND_UP((z
- 6) * sizeof(UINT32
), MIN_STACK_SIZE
);
315 debug(3, "Calculated stack size is %u bytes\n", cif
->bytes
);
318 /* Perform machine dependent cif processing. */
319 ffi_status
ffi_prep_cif_machdep(ffi_cif
*cif
)
321 /* Set the return type flag */
322 switch (cif
->rtype
->type
)
326 case FFI_TYPE_DOUBLE
:
327 cif
->flags
= (unsigned) cif
->rtype
->type
;
331 case FFI_TYPE_LONGDOUBLE
:
332 /* Long doubles are treated like a structure. */
333 cif
->flags
= FFI_TYPE_STRUCT
;
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
);
346 case FFI_TYPE_UINT64
:
347 case FFI_TYPE_SINT64
:
348 cif
->flags
= FFI_TYPE_UINT64
;
352 cif
->flags
= FFI_TYPE_INT
;
356 /* Lucky us, because of the unique PA ABI we get to do our
361 ffi_size_stack_pa32(cif
);
372 extern void ffi_call_pa32(void (*)(UINT32
*, extended_cif
*, unsigned),
373 extended_cif
*, unsigned, unsigned, unsigned *,
376 void ffi_call(ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
381 ecif
.avalue
= avalue
;
383 /* If the return value is a struct and we don't have a return
384 value address then we need to make one. */
388 && (cif
->rtype
->type
== FFI_TYPE_STRUCT
389 || cif
->rtype
->type
== FFI_TYPE_LONGDOUBLE
))
391 && cif
->rtype
->type
== FFI_TYPE_STRUCT
)
394 ecif
.rvalue
= alloca(cif
->rtype
->size
);
397 ecif
.rvalue
= rvalue
;
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
);
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. */
419 ffi_status
ffi_closure_inner_pa32(ffi_closure
*closure
, UINT32
*stack
)
424 UINT32 ret
[2]; /* function can return up to 64-bits in registers */
428 unsigned int slot
= FIRST_ARG_SLOT
;
429 register UINT32 r28
asm("r28");
433 /* If returning via structure, callee will write to our pointer. */
434 if (cif
->flags
== FFI_TYPE_STRUCT
)
435 rvalue
= (void *)r28
;
439 avalue
= (void **)alloca(cif
->nargs
* FFI_SIZEOF_ARG
);
441 p_arg
= cif
->arg_types
;
443 for (i
= 0; i
< avn
; i
++)
445 int type
= (*p_arg
)->type
;
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
;
459 case FFI_TYPE_SINT64
:
460 case FFI_TYPE_UINT64
:
461 slot
+= (slot
& 1) ? 1 : 2;
462 avalue
[i
] = (void *)(stack
- slot
);
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
)
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;
481 avalue
[i
] = (void *)(stack
- slot
);
484 case FFI_TYPE_DOUBLE
:
485 slot
+= (slot
& 1) ? 1 : 2;
487 /* See previous comment for FFI_TYPE_FLOAT. */
488 switch (slot
- FIRST_ARG_SLOT
)
490 case 1: fstd(fr5
, (void *)(stack
- slot
)); break;
491 case 3: fstd(fr7
, (void *)(stack
- slot
)); break;
494 avalue
[i
] = (void *)(stack
- slot
);
498 case FFI_TYPE_LONGDOUBLE
:
499 /* Long doubles are treated like a big structure. */
500 avalue
[i
] = (void *) *(stack
- slot
);
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)
510 avalue
[i
] = (void *)(stack
- slot
) + sizeof(UINT32
) -
513 else if ((*p_arg
)->size
<= 8)
515 slot
+= (slot
& 1) ? 1 : 2;
516 avalue
[i
] = (void *)(stack
- slot
) + sizeof(UINT64
) -
520 avalue
[i
] = (void *) *(stack
- slot
);
531 /* Invoke the closure. */
532 (closure
->fun
) (cif
, rvalue
, avalue
, closure
->user_data
);
534 debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret
[0],
537 /* Store the result using the lower 2 bytes of the flags. */
541 *(stack
- FIRST_ARG_SLOT
) = (UINT8
)(ret
[0] >> 24);
544 *(stack
- FIRST_ARG_SLOT
) = (SINT8
)(ret
[0] >> 24);
546 case FFI_TYPE_UINT16
:
547 *(stack
- FIRST_ARG_SLOT
) = (UINT16
)(ret
[0] >> 16);
549 case FFI_TYPE_SINT16
:
550 *(stack
- FIRST_ARG_SLOT
) = (SINT16
)(ret
[0] >> 16);
553 case FFI_TYPE_SINT32
:
554 case FFI_TYPE_UINT32
:
555 *(stack
- FIRST_ARG_SLOT
) = ret
[0];
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];
563 case FFI_TYPE_DOUBLE
:
571 case FFI_TYPE_STRUCT
:
572 /* Don't need a return value, done by caller. */
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
);
583 case FFI_TYPE_SMALL_STRUCT5
:
584 case FFI_TYPE_SMALL_STRUCT6
:
585 case FFI_TYPE_SMALL_STRUCT7
:
586 case FFI_TYPE_SMALL_STRUCT8
:
588 unsigned int ret2
[2];
591 /* Right justify ret[0] and ret[1] */
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;
600 memset (ret2
, 0, sizeof (ret2
));
601 memcpy ((char *)ret2
+ off
, ret
, 8 - off
);
603 *(stack
- FIRST_ARG_SLOT
) = ret2
[0];
604 *(stack
- FIRST_ARG_SLOT
- 1) = ret2
[1];
608 case FFI_TYPE_POINTER
:
613 debug(0, "assert with cif->flags: %d\n",cif
->flags
);
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. */
624 extern void ffi_closure_pa32(void);
627 ffi_prep_closure_loc (ffi_closure
* closure
,
629 void (*fun
)(ffi_cif
*,void*,void**,void*),
633 UINT32
*tramp
= (UINT32
*)(closure
->tramp
);
638 if (cif
->abi
!= FFI_PA32
)
641 /* Make a small trampoline that will branch to our
642 handler function. Use PC-relative addressing. */
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);
654 /* Flush d/icache -- have to flush up 2 two lines because of
659 "fic 0(%%sr4, %0)\n\t"
660 "fic %1(%%sr4, %0)\n\t"
670 : "r"((unsigned long)tramp
& ~31),
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);
687 /* Flush d/icache -- have to flush three lines because of alignment. */
696 "fic,m %2(%%sr0,%0)\n\t"
697 "fic,m %2(%%sr0,%0)\n\t"
698 "fic,m %2(%%sr0,%0)\n\t"
707 : "=&r" ((unsigned long)tmp
)
708 : "r" ((unsigned long)tramp
& ~31),
714 closure
->user_data
= user_data
;