1 /* -----------------------------------------------------------------------
2 ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
4 HPPA Foreign Function Interface
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 ``Software''), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 OTHER DEALINGS IN THE SOFTWARE.
24 ----------------------------------------------------------------------- */
27 #include <ffi_common.h>
31 #define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
32 #define ROUND_DOWN(v, a) (((size_t)(v) - (a) + 1) & ~((a) - 1))
33 #define MIN_STACK_SIZE 64
34 #define FIRST_ARG_SLOT 9
37 #define fldw(addr, fpreg) asm volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
38 #define fstw(fpreg, addr) asm volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
39 #define fldd(addr, fpreg) asm volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
40 #define fstd(fpreg, addr) asm volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
42 #define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
44 static inline int ffi_struct_type(ffi_type *t)
48 /* Small structure results are passed in registers,
49 larger ones are passed by pointer. */
52 return FFI_TYPE_UINT8;
54 return FFI_TYPE_UINT16;
56 return FFI_TYPE_SMALL_STRUCT1;
58 return FFI_TYPE_UINT32;
60 return FFI_TYPE_SMALL_STRUCT2;
62 return FFI_TYPE_UINT64;
64 return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
67 /* PA has a downward growing stack, which looks like this:
71 SP = (4*(n+9)) arg word N
84 First 4 non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23
85 First 2 non-FP 64-bit args are passed in register pairs, starting
86 on an even numbered register (i.e. r26/r25 and r24+r23)
87 First 4 FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L
88 First 2 FP 64-bit arguments are passed in fr5 and fr7
89 The rest are passed on the stack starting at SP-52, but 64-bit
90 arguments need to be aligned to an 8-byte boundary
92 This means we can have holes either in the register allocation,
95 /* ffi_prep_args is called by the assembly routine once stack space
96 has been allocated for the function's arguments
98 The following code will put everything into the stack frame
99 (which was allocated by the asm routine), and on return
100 the asm routine will load the arguments that should be
101 passed by register into the appropriate registers
103 NOTE: We load floating point args in this function... that means we
104 assume gcc will not mess with fp regs in here. */
107 void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
110 register unsigned int i;
111 register ffi_type **p_arg;
112 register void **p_argv;
113 unsigned int slot = FIRST_ARG_SLOT - 1;
116 debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, ecif, bytes);
118 p_arg = ecif->cif->arg_types;
119 p_argv = ecif->avalue;
121 for (i = 0; i < ecif->cif->nargs; i++)
123 int type = (*p_arg)->type;
129 *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
134 *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
137 case FFI_TYPE_SINT16:
139 *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
142 case FFI_TYPE_UINT16:
144 *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
147 case FFI_TYPE_UINT32:
148 case FFI_TYPE_SINT32:
149 case FFI_TYPE_POINTER:
151 debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), slot);
152 *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
155 case FFI_TYPE_UINT64:
156 case FFI_TYPE_SINT64:
161 *(UINT32 *)(stack - slot) = (*(UINT64 *)(*p_argv)) >> 32;
162 *(UINT32 *)(stack - slot + 1) = (*(UINT64 *)(*p_argv)) & 0xffffffffUL;
166 /* First 4 args go in fr4L - fr7L */
168 switch (slot - FIRST_ARG_SLOT)
170 case 0: fldw(*p_argv, fr4); break;
171 case 1: fldw(*p_argv, fr5); break;
172 case 2: fldw(*p_argv, fr6); break;
173 case 3: fldw(*p_argv, fr7); break;
175 /* Other ones are just passed on the stack. */
176 debug(3, "Storing UINT32(float) in slot %u\n", slot);
177 *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
182 case FFI_TYPE_DOUBLE:
186 switch (slot - FIRST_ARG_SLOT + 1)
188 /* First 2 args go in fr5, fr7 */
189 case 2: fldd(*p_argv, fr5); break;
190 case 4: fldd(*p_argv, fr7); break;
192 debug(3, "Storing UINT64(double) at slot %u\n", slot);
193 *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
198 case FFI_TYPE_STRUCT:
200 /* Structs smaller or equal than 4 bytes are passed in one
201 register. Structs smaller or equal 8 bytes are passed in two
202 registers. Larger structures are passed by pointer. */
204 if((*p_arg)->size <= 4)
207 dest_cpy = (char *)(stack - slot);
208 dest_cpy += 4 - (*p_arg)->size;
209 memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
211 else if ((*p_arg)->size <= 8)
216 dest_cpy = (char *)(stack - slot);
217 dest_cpy += 8 - (*p_arg)->size;
218 memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
223 *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
235 /* Make sure we didn't mess up and scribble on the stack. */
239 debug(5, "Stack setup:\n");
240 for (n = 0; n < (bytes + 3) / 4; n++)
242 if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
243 debug(5, "%08x ", *(stack - n));
248 FFI_ASSERT(slot * 4 <= bytes);
253 static void ffi_size_stack_LINUX(ffi_cif *cif)
257 int z = 0; /* # stack slots */
259 for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
261 int type = (*ptr)->type;
265 case FFI_TYPE_DOUBLE:
266 case FFI_TYPE_UINT64:
267 case FFI_TYPE_SINT64:
268 z += 2 + (z & 1); /* must start on even regs, so we may waste one */
271 case FFI_TYPE_STRUCT:
272 z += 1; /* pass by ptr, callee will copy */
275 default: /* <= 32-bit values */
280 /* We can fit up to 6 args in the default 64-byte stack frame,
281 if we need more, we need more stack. */
283 cif->bytes = MIN_STACK_SIZE; /* min stack size */
285 cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
287 debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
290 /* Perform machine dependent cif processing. */
291 ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
293 /* Set the return type flag */
294 switch (cif->rtype->type)
298 case FFI_TYPE_DOUBLE:
299 cif->flags = (unsigned) cif->rtype->type;
302 case FFI_TYPE_STRUCT:
303 /* For the return type we have to check the size of the structures.
304 If the size is smaller or equal 4 bytes, the result is given back
305 in one register. If the size is smaller or equal 8 bytes than we
306 return the result in two registers. But if the size is bigger than
307 8 bytes, we work with pointers. */
308 cif->flags = ffi_struct_type(cif->rtype);
311 case FFI_TYPE_UINT64:
312 case FFI_TYPE_SINT64:
313 cif->flags = FFI_TYPE_UINT64;
317 cif->flags = FFI_TYPE_INT;
321 /* Lucky us, because of the unique PA ABI we get to do our
326 ffi_size_stack_LINUX(cif);
339 extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned),
340 /*@out@*/ extended_cif *,
342 /*@out@*/ unsigned *,
347 void ffi_call(/*@dependent@*/ ffi_cif *cif,
349 /*@out@*/ void *rvalue,
350 /*@dependent@*/ void **avalue)
355 ecif.avalue = avalue;
357 /* If the return value is a struct and we don't have a return
358 value address then we need to make one. */
360 if ((rvalue == NULL) &&
361 (cif->rtype->type == FFI_TYPE_STRUCT))
364 ecif.rvalue = alloca(cif->rtype->size);
368 ecif.rvalue = rvalue;
375 debug(2, "Calling ffi_call_LINUX: ecif=%p, bytes=%u, flags=%u, rvalue=%p, fn=%p\n", &ecif, cif->bytes, cif->flags, ecif.rvalue, (void *)fn);
376 ffi_call_LINUX(ffi_prep_args_LINUX, &ecif, cif->bytes,
377 cif->flags, ecif.rvalue, fn);
388 /* This is more-or-less an inverse of ffi_call -- we have arguments on
389 the stack, and we need to fill them into a cif structure and invoke
390 the user function. This really ought to be in asm to make sure
391 the compiler doesn't do things we don't expect. */
392 UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
397 UINT32 ret[2]; /* function can return up to 64-bits in registers */
400 int i, avn, slot = FIRST_ARG_SLOT - 1;
401 register UINT32 r28 asm("r28");
405 /* If returning via structure, callee will write to our pointer. */
406 if (cif->flags == FFI_TYPE_STRUCT)
407 rvalue = (void *)r28;
411 avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
413 p_arg = cif->arg_types;
415 for (i = 0; i < avn; i++)
417 int type = (*p_arg)->type;
423 case FFI_TYPE_SINT16:
424 case FFI_TYPE_UINT16:
425 case FFI_TYPE_SINT32:
426 case FFI_TYPE_UINT32:
427 case FFI_TYPE_POINTER:
429 avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
432 case FFI_TYPE_SINT64:
433 case FFI_TYPE_UINT64:
437 avalue[i] = (void *)(stack - slot);
442 switch (slot - FIRST_ARG_SLOT)
444 case 0: fstw(fr4, (void *)(stack - slot)); break;
445 case 1: fstw(fr5, (void *)(stack - slot)); break;
446 case 2: fstw(fr6, (void *)(stack - slot)); break;
447 case 3: fstw(fr7, (void *)(stack - slot)); break;
449 avalue[i] = (void *)(stack - slot);
452 case FFI_TYPE_DOUBLE:
456 switch (slot - FIRST_ARG_SLOT + 1)
458 case 2: fstd(fr5, (void *)(stack - slot)); break;
459 case 4: fstd(fr7, (void *)(stack - slot)); break;
461 avalue[i] = (void *)(stack - slot);
464 case FFI_TYPE_STRUCT:
465 /* Structs smaller or equal than 4 bytes are passed in one
466 register. Structs smaller or equal 8 bytes are passed in two
467 registers. Larger structures are passed by pointer. */
468 if((*p_arg)->size <= 4) {
470 avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
472 } else if ((*p_arg)->size <= 8) {
476 avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
480 avalue[i] = (void *) *(stack - slot);
491 /* Invoke the closure. */
492 (closure->fun) (cif, rvalue, avalue, closure->user_data);
494 debug(3, "after calling function, ret[0] = %d, ret[1] = %d\n", ret[0], ret[1]);
496 /* Store the result */
500 *(stack - FIRST_ARG_SLOT) = *(UINT8 *)&ret[0];
503 *(stack - FIRST_ARG_SLOT) = *(SINT8 *)&ret[0];
505 case FFI_TYPE_UINT16:
506 *(stack - FIRST_ARG_SLOT) = *(UINT16 *)&ret[0];
508 case FFI_TYPE_SINT16:
509 *(stack - FIRST_ARG_SLOT) = *(SINT16 *)&ret[0];
512 case FFI_TYPE_UINT32:
513 *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
515 case FFI_TYPE_SINT32:
516 *(stack - FIRST_ARG_SLOT) = *(SINT32 *)&ret[0];
518 case FFI_TYPE_SINT64:
519 case FFI_TYPE_UINT64:
520 *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
521 *(stack - FIRST_ARG_SLOT - 1) = *(UINT32 *)&ret[1];
524 case FFI_TYPE_DOUBLE:
532 case FFI_TYPE_STRUCT:
533 /* Don't need a return value, done by caller. */
536 case FFI_TYPE_SMALL_STRUCT1:
537 tmp = (void*)(stack - FIRST_ARG_SLOT);
538 tmp += 4 - cif->rtype->size;
539 memcpy((void*)tmp, &ret[0], cif->rtype->size);
542 case FFI_TYPE_SMALL_STRUCT2:
543 *(stack - FIRST_ARG_SLOT) = ret[0];
544 *(stack - FIRST_ARG_SLOT - 1) = ret[1];
547 case FFI_TYPE_POINTER:
552 debug(0, "assert with cif->flags: %d\n",cif->flags);
559 /* Fill in a closure to refer to the specified fun and user_data.
560 cif specifies the argument and result types for fun.
561 The cif must already be prep'ed. */
563 void ffi_closure_LINUX(void);
566 ffi_prep_closure (ffi_closure* closure,
568 void (*fun)(ffi_cif*,void*,void**,void*),
571 UINT32 *tramp = (UINT32 *)(closure->tramp);
573 FFI_ASSERT (cif->abi == FFI_LINUX);
575 /* Make a small trampoline that will branch to our
576 handler function. Use PC-relative addressing. */
578 tramp[0] = 0xeaa00000; /* b,l .+8, %r21 ; %r21 <- pc+8 */
579 tramp[1] = 0xd6a01c1e; /* depi 0,31,2, %r21 ; mask priv bits */
580 tramp[2] = 0x4aa10028; /* ldw 20(%r21), %r1 ; load plabel */
581 tramp[3] = 0x36b53ff1; /* ldo -8(%r21), %r21 ; get closure addr */
582 tramp[4] = 0x0c201096; /* ldw 0(%r1), %r22 ; address of handler */
583 tramp[5] = 0xeac0c000; /* bv %r0(%r22) ; branch to handler */
584 tramp[6] = 0x0c281093; /* ldw 4(%r1), %r19 ; GP of handler */
585 tramp[7] = ((UINT32)(ffi_closure_LINUX) & ~2);
587 /* Flush d/icache -- have to flush up 2 two lines because of
593 "fic %1(%%sr4, %0)\n"
595 : : "r"((unsigned long)tramp & ~31), "r"(32 /* stride */));
598 closure->user_data = user_data;