1 /* -----------------------------------------------------------------------
2 ffi.c - (c) 2016 John David Anglin
5 (c) 2006 Free Software Foundation, Inc.
6 (c) 2003-2004 Randolph Chung <tausq@debian.org>
8 HPPA Foreign Function Interface
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 ----------------------------------------------------------------------- */
33 #include <ffi_common.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
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)
56 ffi_struct_type (ffi_type
*t
)
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. */
67 return FFI_TYPE_UINT8
;
69 return FFI_TYPE_SMALL_STRUCT2
;
71 return FFI_TYPE_SMALL_STRUCT3
;
73 return FFI_TYPE_SMALL_STRUCT4
;
75 return FFI_TYPE_SMALL_STRUCT5
;
77 return FFI_TYPE_SMALL_STRUCT6
;
79 return FFI_TYPE_SMALL_STRUCT7
;
81 return FFI_TYPE_SMALL_STRUCT8
;
83 return FFI_TYPE_STRUCT
; /* else, we pass it by pointer. */
86 /* PA has a downward growing stack, which looks like this:
90 SP = (4*(n+9)) arg word N
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
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,
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. */
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
;
154 debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__
, stack
,
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
;
167 *(SINT32
*)(stack
- slot
) = *(SINT8
*)(*p_argv
);
171 *(UINT32
*)(stack
- slot
) = *(UINT8
*)(*p_argv
);
174 case FFI_TYPE_SINT16
:
175 *(SINT32
*)(stack
- slot
) = *(SINT16
*)(*p_argv
);
178 case FFI_TYPE_UINT16
:
179 *(UINT32
*)(stack
- slot
) = *(UINT16
*)(*p_argv
);
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
),
187 *(UINT32
*)(stack
- slot
) = *(UINT32
*)(*p_argv
);
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
);
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;
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;
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
);
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
;
241 dest_cpy
= (char *)(stack
- slot
) + 4 - len
;
242 memcpy(dest_cpy
, (char *)*p_argv
, len
);
246 slot
+= (slot
& 1) ? 1 : 2;
247 dest_cpy
= (char *)(stack
- slot
) + 8 - len
;
248 memcpy(dest_cpy
, (char *)*p_argv
, len
);
251 *(UINT32
*)(stack
- slot
) = (UINT32
)(*p_argv
);
263 /* Make sure we didn't mess up and scribble on the stack. */
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
));
276 FFI_ASSERT(slot
* 4 <= bytes
);
282 ffi_size_stack_pa32 (ffi_cif
*cif
)
286 int z
= 0; /* # stack slots */
288 for (ptr
= cif
->arg_types
, i
= 0; i
< cif
->nargs
; ptr
++, i
++)
290 int type
= (*ptr
)->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 */
301 case FFI_TYPE_LONGDOUBLE
:
303 case FFI_TYPE_STRUCT
:
304 z
+= 1; /* pass by ptr, callee will copy */
307 default: /* <= 32-bit values */
312 /* We can fit up to 6 args in the default 64-byte stack frame,
313 if we need more, we need more stack. */
315 cif
->bytes
= MIN_STACK_SIZE
; /* min stack size */
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. */
324 ffi_prep_cif_machdep (ffi_cif
*cif
)
326 /* Set the return type flag */
327 switch (cif
->rtype
->type
)
331 case FFI_TYPE_DOUBLE
:
332 cif
->flags
= (unsigned) cif
->rtype
->type
;
336 case FFI_TYPE_LONGDOUBLE
:
337 /* Long doubles are treated like a structure. */
338 cif
->flags
= FFI_TYPE_STRUCT
;
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
);
351 case FFI_TYPE_UINT64
:
352 case FFI_TYPE_SINT64
:
353 cif
->flags
= FFI_TYPE_UINT64
;
357 cif
->flags
= FFI_TYPE_INT
;
361 /* Lucky us, because of the unique PA ABI we get to do our
366 ffi_size_stack_pa32(cif
);
377 extern void ffi_call_pa32 (void (*)(UINT32
*, extended_cif
*, unsigned),
378 extended_cif
*, unsigned, unsigned, unsigned *,
379 void (*fn
)(void), void *closure
);
382 ffi_call_int (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
,
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. */
395 && (cif
->rtype
->type
== FFI_TYPE_STRUCT
396 || cif
->rtype
->type
== FFI_TYPE_LONGDOUBLE
))
398 && cif
->rtype
->type
== FFI_TYPE_STRUCT
)
401 ecif
.rvalue
= alloca(cif
->rtype
->size
);
404 ecif
.rvalue
= rvalue
;
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
);
422 ffi_call (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
)
424 ffi_call_int (cif
, fn
, rvalue
, avalue
, NULL
);
428 ffi_call_go (ffi_cif
*cif
, void (*fn
)(void), void *rvalue
, void **avalue
,
431 ffi_call_int (cif
, fn
, rvalue
, avalue
, closure
);
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. */
440 ffi_closure_inner_pa32 (void *closure
, UINT32
*stack
, int closure_type
)
443 void (*fun
)(ffi_cif
*,void *,void **,void *);
447 UINT32 ret
[2]; /* function can return up to 64-bits in registers */
451 unsigned int slot
= FIRST_ARG_SLOT
;
452 register UINT32 r28
asm("r28");
454 /* A non-zero closure type indicates a go closure. */
457 cif
= ((ffi_go_closure
*)closure
)->cif
;
458 fun
= ((ffi_go_closure
*)closure
)->fun
;
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
;
474 avalue
= (void **) alloca (cif
->nargs
* FFI_SIZEOF_ARG
);
476 p_arg
= cif
->arg_types
;
478 for (i
= 0; i
< avn
; i
++)
480 int type
= (*p_arg
)->type
;
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
;
494 case FFI_TYPE_SINT64
:
495 case FFI_TYPE_UINT64
:
496 slot
+= (slot
& 1) ? 1 : 2;
497 avalue
[i
] = (void *)(stack
- slot
);
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;
516 avalue
[i
] = (void *)(stack
- slot
);
519 case FFI_TYPE_DOUBLE
:
520 slot
+= (slot
& 1) ? 1 : 2;
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;
529 avalue
[i
] = (void *)(stack
- slot
);
533 case FFI_TYPE_LONGDOUBLE
:
534 /* Long doubles are treated like a big structure. */
535 avalue
[i
] = (void *) *(stack
- slot
);
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
) -
548 else if ((*p_arg
)->size
<= 8)
550 slot
+= (slot
& 1) ? 1 : 2;
551 avalue
[i
] = (void *)(stack
- slot
) + sizeof(UINT64
) -
555 avalue
[i
] = (void *) *(stack
- slot
);
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],
572 /* Store the result using the lower 2 bytes of the flags. */
576 *(stack
- FIRST_ARG_SLOT
) = (UINT8
)(ret
[0] >> 24);
579 *(stack
- FIRST_ARG_SLOT
) = (SINT8
)(ret
[0] >> 24);
581 case FFI_TYPE_UINT16
:
582 *(stack
- FIRST_ARG_SLOT
) = (UINT16
)(ret
[0] >> 16);
584 case FFI_TYPE_SINT16
:
585 *(stack
- FIRST_ARG_SLOT
) = (SINT16
)(ret
[0] >> 16);
588 case FFI_TYPE_SINT32
:
589 case FFI_TYPE_UINT32
:
590 *(stack
- FIRST_ARG_SLOT
) = ret
[0];
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];
598 case FFI_TYPE_DOUBLE
:
606 case FFI_TYPE_STRUCT
:
607 /* Don't need a return value, done by caller. */
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
);
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];
626 /* Right justify ret[0] and ret[1] */
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];
643 case FFI_TYPE_POINTER
:
648 debug(0, "assert with cif->flags: %d\n",cif
->flags
);
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);
663 ffi_prep_closure_loc (ffi_closure
* closure
,
665 void (*fun
)(ffi_cif
*,void*,void**,void*),
669 UINT32
*tramp
= (UINT32
*)(closure
->tramp
);
674 if (cif
->abi
!= FFI_PA32
)
677 /* Make a small trampoline that will branch to our
678 handler function. Use PC-relative addressing. */
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
695 "fic 0(%%sr4, %0)\n\t"
696 "fic %1(%%sr4, %0)\n\t"
706 : "r"((unsigned long)tramp
& ~31),
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. */
732 "fic,m %2(%%sr0,%0)\n\t"
733 "fic,m %2(%%sr0,%0)\n\t"
734 "fic,m %2(%%sr0,%0)\n\t"
743 : "=&r" ((unsigned long)tmp
)
744 : "r" ((unsigned long)tramp
& ~31),
750 closure
->user_data
= user_data
;
756 #ifdef FFI_GO_CLOSURES
758 ffi_prep_go_closure (ffi_go_closure
*closure
,
760 void (*fun
)(ffi_cif
*, void *, void **, void *))
762 if (cif
->abi
!= FFI_PA32
)
765 closure
->tramp
= &ffi_go_closure_pa32
;
771 #endif /* FFI_GO_CLOSURES */