summaryrefslogtreecommitdiff
path: root/libffi/src/pa
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/pa')
-rw-r--r--libffi/src/pa/ffi.c603
-rw-r--r--libffi/src/pa/ffitarget.h57
-rw-r--r--libffi/src/pa/linux.S281
3 files changed, 0 insertions, 941 deletions
diff --git a/libffi/src/pa/ffi.c b/libffi/src/pa/ffi.c
deleted file mode 100644
index 57331fe..0000000
--- a/libffi/src/pa/ffi.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/* -----------------------------------------------------------------------
- ffi.c - (c) 2003-2004 Randolph Chung <tausq@debian.org>
-
- HPPA Foreign Function Interface
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#include <ffi.h>
-#include <ffi_common.h>
-
-#include <stdlib.h>
-
-#define ROUND_UP(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1))
-#define ROUND_DOWN(v, a) (((size_t)(v) - (a) + 1) & ~((a) - 1))
-#define MIN_STACK_SIZE 64
-#define FIRST_ARG_SLOT 9
-#define DEBUG_LEVEL 0
-
-#define fldw(addr, fpreg) asm volatile ("fldw 0(%0), %%" #fpreg "L" : : "r"(addr) : #fpreg)
-#define fstw(fpreg, addr) asm volatile ("fstw %%" #fpreg "L, 0(%0)" : : "r"(addr))
-#define fldd(addr, fpreg) asm volatile ("fldd 0(%0), %%" #fpreg : : "r"(addr) : #fpreg)
-#define fstd(fpreg, addr) asm volatile ("fstd %%" #fpreg "L, 0(%0)" : : "r"(addr))
-
-#define debug(lvl, x...) do { if (lvl <= DEBUG_LEVEL) { printf(x); } } while (0)
-
-static inline int ffi_struct_type(ffi_type *t)
-{
- size_t sz = t->size;
-
- /* Small structure results are passed in registers,
- larger ones are passed by pointer. */
-
- if (sz <= 1)
- return FFI_TYPE_UINT8;
- else if (sz == 2)
- return FFI_TYPE_UINT16;
- else if (sz == 3)
- return FFI_TYPE_SMALL_STRUCT1;
- else if (sz == 4)
- return FFI_TYPE_UINT32;
- else if (sz <= 6)
- return FFI_TYPE_SMALL_STRUCT2;
- else if (sz <= 8)
- return FFI_TYPE_UINT64;
- else
- return FFI_TYPE_STRUCT; /* else, we pass it by pointer. */
-}
-
-/* PA has a downward growing stack, which looks like this:
-
- Offset
- [ Variable args ]
- SP = (4*(n+9)) arg word N
- ...
- SP-52 arg word 4
- [ Fixed args ]
- SP-48 arg word 3
- SP-44 arg word 2
- SP-40 arg word 1
- SP-36 arg word 0
- [ Frame marker ]
- ...
- SP-20 RP
- SP-4 previous SP
-
- First 4 non-FP 32-bit args are passed in gr26, gr25, gr24 and gr23
- First 2 non-FP 64-bit args are passed in register pairs, starting
- on an even numbered register (i.e. r26/r25 and r24+r23)
- First 4 FP 32-bit arguments are passed in fr4L, fr5L, fr6L and fr7L
- First 2 FP 64-bit arguments are passed in fr5 and fr7
- The rest are passed on the stack starting at SP-52, but 64-bit
- arguments need to be aligned to an 8-byte boundary
-
- This means we can have holes either in the register allocation,
- or in the stack. */
-
-/* ffi_prep_args is called by the assembly routine once stack space
- has been allocated for the function's arguments
-
- The following code will put everything into the stack frame
- (which was allocated by the asm routine), and on return
- the asm routine will load the arguments that should be
- passed by register into the appropriate registers
-
- NOTE: We load floating point args in this function... that means we
- assume gcc will not mess with fp regs in here. */
-
-/*@-exportheader@*/
-void ffi_prep_args_LINUX(UINT32 *stack, extended_cif *ecif, unsigned bytes)
-/*@=exportheader@*/
-{
- register unsigned int i;
- register ffi_type **p_arg;
- register void **p_argv;
- unsigned int slot = FIRST_ARG_SLOT - 1;
- char *dest_cpy;
-
- debug(1, "%s: stack = %p, ecif = %p, bytes = %u\n", __FUNCTION__, stack, ecif, bytes);
-
- p_arg = ecif->cif->arg_types;
- p_argv = ecif->avalue;
-
- for (i = 0; i < ecif->cif->nargs; i++)
- {
- int type = (*p_arg)->type;
-
- switch (type)
- {
- case FFI_TYPE_SINT8:
- slot++;
- *(SINT32 *)(stack - slot) = *(SINT8 *)(*p_argv);
- break;
-
- case FFI_TYPE_UINT8:
- slot++;
- *(UINT32 *)(stack - slot) = *(UINT8 *)(*p_argv);
- break;
-
- case FFI_TYPE_SINT16:
- slot++;
- *(SINT32 *)(stack - slot) = *(SINT16 *)(*p_argv);
- break;
-
- case FFI_TYPE_UINT16:
- slot++;
- *(UINT32 *)(stack - slot) = *(UINT16 *)(*p_argv);
- break;
-
- case FFI_TYPE_UINT32:
- case FFI_TYPE_SINT32:
- case FFI_TYPE_POINTER:
- slot++;
- debug(3, "Storing UINT32 %u in slot %u\n", *(UINT32 *)(*p_argv), slot);
- *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
- break;
-
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- slot += 2;
- if (slot & 1)
- slot++;
-
- *(UINT32 *)(stack - slot) = (*(UINT64 *)(*p_argv)) >> 32;
- *(UINT32 *)(stack - slot + 1) = (*(UINT64 *)(*p_argv)) & 0xffffffffUL;
- break;
-
- case FFI_TYPE_FLOAT:
- /* First 4 args go in fr4L - fr7L */
- slot++;
- switch (slot - FIRST_ARG_SLOT)
- {
- case 0: fldw(*p_argv, fr4); break;
- case 1: fldw(*p_argv, fr5); break;
- case 2: fldw(*p_argv, fr6); break;
- case 3: fldw(*p_argv, fr7); break;
- default:
- /* Other ones are just passed on the stack. */
- debug(3, "Storing UINT32(float) in slot %u\n", slot);
- *(UINT32 *)(stack - slot) = *(UINT32 *)(*p_argv);
- break;
- }
- break;
-
- case FFI_TYPE_DOUBLE:
- slot += 2;
- if (slot & 1)
- slot++;
- switch (slot - FIRST_ARG_SLOT + 1)
- {
- /* First 2 args go in fr5, fr7 */
- case 2: fldd(*p_argv, fr5); break;
- case 4: fldd(*p_argv, fr7); break;
- default:
- debug(3, "Storing UINT64(double) at slot %u\n", slot);
- *(UINT64 *)(stack - slot) = *(UINT64 *)(*p_argv);
- break;
- }
- break;
-
- case FFI_TYPE_STRUCT:
-
- /* Structs smaller or equal than 4 bytes are passed in one
- register. Structs smaller or equal 8 bytes are passed in two
- registers. Larger structures are passed by pointer. */
-
- if((*p_arg)->size <= 4)
- {
- slot++;
- dest_cpy = (char *)(stack - slot);
- dest_cpy += 4 - (*p_arg)->size;
- memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
- }
- else if ((*p_arg)->size <= 8)
- {
- slot += 2;
- if (slot & 1)
- slot++;
- dest_cpy = (char *)(stack - slot);
- dest_cpy += 8 - (*p_arg)->size;
- memcpy((char *)dest_cpy, (char *)*p_argv, (*p_arg)->size);
- }
- else
- {
- slot++;
- *(UINT32 *)(stack - slot) = (UINT32)(*p_argv);
- }
- break;
-
- default:
- FFI_ASSERT(0);
- }
-
- p_arg++;
- p_argv++;
- }
-
- /* Make sure we didn't mess up and scribble on the stack. */
- {
- int n;
-
- debug(5, "Stack setup:\n");
- for (n = 0; n < (bytes + 3) / 4; n++)
- {
- if ((n%4) == 0) { debug(5, "\n%08x: ", (unsigned int)(stack - n)); }
- debug(5, "%08x ", *(stack - n));
- }
- debug(5, "\n");
- }
-
- FFI_ASSERT(slot * 4 <= bytes);
-
- return;
-}
-
-static void ffi_size_stack_LINUX(ffi_cif *cif)
-{
- ffi_type **ptr;
- int i;
- int z = 0; /* # stack slots */
-
- for (ptr = cif->arg_types, i = 0; i < cif->nargs; ptr++, i++)
- {
- int type = (*ptr)->type;
-
- switch (type)
- {
- case FFI_TYPE_DOUBLE:
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- z += 2 + (z & 1); /* must start on even regs, so we may waste one */
- break;
-
- case FFI_TYPE_STRUCT:
- z += 1; /* pass by ptr, callee will copy */
- break;
-
- default: /* <= 32-bit values */
- z++;
- }
- }
-
- /* We can fit up to 6 args in the default 64-byte stack frame,
- if we need more, we need more stack. */
- if (z <= 6)
- cif->bytes = MIN_STACK_SIZE; /* min stack size */
- else
- cif->bytes = 64 + ROUND_UP((z - 6) * sizeof(UINT32), MIN_STACK_SIZE);
-
- debug(3, "Calculated stack size is %u bytes\n", cif->bytes);
-}
-
-/* Perform machine dependent cif processing. */
-ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
-{
- /* Set the return type flag */
- switch (cif->rtype->type)
- {
- case FFI_TYPE_VOID:
- case FFI_TYPE_FLOAT:
- case FFI_TYPE_DOUBLE:
- cif->flags = (unsigned) cif->rtype->type;
- break;
-
- case FFI_TYPE_STRUCT:
- /* For the return type we have to check the size of the structures.
- If the size is smaller or equal 4 bytes, the result is given back
- in one register. If the size is smaller or equal 8 bytes than we
- return the result in two registers. But if the size is bigger than
- 8 bytes, we work with pointers. */
- cif->flags = ffi_struct_type(cif->rtype);
- break;
-
- case FFI_TYPE_UINT64:
- case FFI_TYPE_SINT64:
- cif->flags = FFI_TYPE_UINT64;
- break;
-
- default:
- cif->flags = FFI_TYPE_INT;
- break;
- }
-
- /* Lucky us, because of the unique PA ABI we get to do our
- own stack sizing. */
- switch (cif->abi)
- {
- case FFI_LINUX:
- ffi_size_stack_LINUX(cif);
- break;
-
- default:
- FFI_ASSERT(0);
- break;
- }
-
- return FFI_OK;
-}
-
-/*@-declundef@*/
-/*@-exportheader@*/
-extern void ffi_call_LINUX(void (*)(UINT32 *, extended_cif *, unsigned),
- /*@out@*/ extended_cif *,
- unsigned, unsigned,
- /*@out@*/ unsigned *,
- void (*fn)());
-/*@=declundef@*/
-/*@=exportheader@*/
-
-void ffi_call(/*@dependent@*/ ffi_cif *cif,
- void (*fn)(),
- /*@out@*/ void *rvalue,
- /*@dependent@*/ void **avalue)
-{
- extended_cif ecif;
-
- ecif.cif = cif;
- ecif.avalue = avalue;
-
- /* If the return value is a struct and we don't have a return
- value address then we need to make one. */
-
- if ((rvalue == NULL) &&
- (cif->rtype->type == FFI_TYPE_STRUCT))
- {
- /*@-sysunrecog@*/
- ecif.rvalue = alloca(cif->rtype->size);
- /*@=sysunrecog@*/
- }
- else
- ecif.rvalue = rvalue;
-
-
- switch (cif->abi)
- {
- case FFI_LINUX:
- /*@-usedef@*/
- 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);
- ffi_call_LINUX(ffi_prep_args_LINUX, &ecif, cif->bytes,
- cif->flags, ecif.rvalue, fn);
- /*@=usedef@*/
- break;
-
- default:
- FFI_ASSERT(0);
- break;
- }
-}
-
-#if FFI_CLOSURES
-/* This is more-or-less an inverse of ffi_call -- we have arguments on
- the stack, and we need to fill them into a cif structure and invoke
- the user function. This really ought to be in asm to make sure
- the compiler doesn't do things we don't expect. */
-UINT32 ffi_closure_inner_LINUX(ffi_closure *closure, UINT32 *stack)
-{
- ffi_cif *cif;
- void **avalue;
- void *rvalue;
- UINT32 ret[2]; /* function can return up to 64-bits in registers */
- ffi_type **p_arg;
- char *tmp;
- int i, avn, slot = FIRST_ARG_SLOT - 1;
- register UINT32 r28 asm("r28");
-
- cif = closure->cif;
-
- /* If returning via structure, callee will write to our pointer. */
- if (cif->flags == FFI_TYPE_STRUCT)
- rvalue = (void *)r28;
- else
- rvalue = &ret[0];
-
- avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG);
- avn = cif->nargs;
- p_arg = cif->arg_types;
-
- for (i = 0; i < avn; i++)
- {
- int type = (*p_arg)->type;
-
- switch (type)
- {
- case FFI_TYPE_SINT8:
- case FFI_TYPE_UINT8:
- case FFI_TYPE_SINT16:
- case FFI_TYPE_UINT16:
- case FFI_TYPE_SINT32:
- case FFI_TYPE_UINT32:
- case FFI_TYPE_POINTER:
- slot++;
- avalue[i] = (char *)(stack - slot) + sizeof(UINT32) - (*p_arg)->size;
- break;
-
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- slot += 2;
- if (slot & 1)
- slot++;
- avalue[i] = (void *)(stack - slot);
- break;
-
- case FFI_TYPE_FLOAT:
- slot++;
- switch (slot - FIRST_ARG_SLOT)
- {
- case 0: fstw(fr4, (void *)(stack - slot)); break;
- case 1: fstw(fr5, (void *)(stack - slot)); break;
- case 2: fstw(fr6, (void *)(stack - slot)); break;
- case 3: fstw(fr7, (void *)(stack - slot)); break;
- }
- avalue[i] = (void *)(stack - slot);
- break;
-
- case FFI_TYPE_DOUBLE:
- slot += 2;
- if (slot & 1)
- slot++;
- switch (slot - FIRST_ARG_SLOT + 1)
- {
- case 2: fstd(fr5, (void *)(stack - slot)); break;
- case 4: fstd(fr7, (void *)(stack - slot)); break;
- }
- avalue[i] = (void *)(stack - slot);
- break;
-
- case FFI_TYPE_STRUCT:
- /* Structs smaller or equal than 4 bytes are passed in one
- register. Structs smaller or equal 8 bytes are passed in two
- registers. Larger structures are passed by pointer. */
- if((*p_arg)->size <= 4) {
- slot++;
- avalue[i] = (void *)(stack - slot) + sizeof(UINT32) -
- (*p_arg)->size;
- } else if ((*p_arg)->size <= 8) {
- slot += 2;
- if (slot & 1)
- slot++;
- avalue[i] = (void *)(stack - slot) + sizeof(UINT64) -
- (*p_arg)->size;
- } else {
- slot++;
- avalue[i] = (void *) *(stack - slot);
- }
- break;
-
- default:
- FFI_ASSERT(0);
- }
-
- p_arg++;
- }
-
- /* Invoke the closure. */
- (closure->fun) (cif, rvalue, avalue, closure->user_data);
-
- debug(3, "after calling function, ret[0] = %d, ret[1] = %d\n", ret[0], ret[1]);
-
- /* Store the result */
- switch (cif->flags)
- {
- case FFI_TYPE_UINT8:
- *(stack - FIRST_ARG_SLOT) = *(UINT8 *)&ret[0];
- break;
- case FFI_TYPE_SINT8:
- *(stack - FIRST_ARG_SLOT) = *(SINT8 *)&ret[0];
- break;
- case FFI_TYPE_UINT16:
- *(stack - FIRST_ARG_SLOT) = *(UINT16 *)&ret[0];
- break;
- case FFI_TYPE_SINT16:
- *(stack - FIRST_ARG_SLOT) = *(SINT16 *)&ret[0];
- break;
- case FFI_TYPE_INT:
- case FFI_TYPE_UINT32:
- *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
- break;
- case FFI_TYPE_SINT32:
- *(stack - FIRST_ARG_SLOT) = *(SINT32 *)&ret[0];
- break;
- case FFI_TYPE_SINT64:
- case FFI_TYPE_UINT64:
- *(stack - FIRST_ARG_SLOT) = *(UINT32 *)&ret[0];
- *(stack - FIRST_ARG_SLOT - 1) = *(UINT32 *)&ret[1];
- break;
-
- case FFI_TYPE_DOUBLE:
- fldd(rvalue, fr4);
- break;
-
- case FFI_TYPE_FLOAT:
- fldw(rvalue, fr4);
- break;
-
- case FFI_TYPE_STRUCT:
- /* Don't need a return value, done by caller. */
- break;
-
- case FFI_TYPE_SMALL_STRUCT1:
- tmp = (void*)(stack - FIRST_ARG_SLOT);
- tmp += 4 - cif->rtype->size;
- memcpy((void*)tmp, &ret[0], cif->rtype->size);
- break;
-
- case FFI_TYPE_SMALL_STRUCT2:
- *(stack - FIRST_ARG_SLOT) = ret[0];
- *(stack - FIRST_ARG_SLOT - 1) = ret[1];
- break;
-
- case FFI_TYPE_POINTER:
- case FFI_TYPE_VOID:
- break;
-
- default:
- debug(0, "assert with cif->flags: %d\n",cif->flags);
- FFI_ASSERT(0);
- break;
- }
- return FFI_OK;
-}
-
-/* Fill in a closure to refer to the specified fun and user_data.
- cif specifies the argument and result types for fun.
- The cif must already be prep'ed. */
-
-void ffi_closure_LINUX(void);
-
-ffi_status
-ffi_prep_closure (ffi_closure* closure,
- ffi_cif* cif,
- void (*fun)(ffi_cif*,void*,void**,void*),
- void *user_data)
-{
- UINT32 *tramp = (UINT32 *)(closure->tramp);
-
- FFI_ASSERT (cif->abi == FFI_LINUX);
-
- /* Make a small trampoline that will branch to our
- handler function. Use PC-relative addressing. */
-
- tramp[0] = 0xeaa00000; /* b,l .+8, %r21 ; %r21 <- pc+8 */
- tramp[1] = 0xd6a01c1e; /* depi 0,31,2, %r21 ; mask priv bits */
- tramp[2] = 0x4aa10028; /* ldw 20(%r21), %r1 ; load plabel */
- tramp[3] = 0x36b53ff1; /* ldo -8(%r21), %r21 ; get closure addr */
- tramp[4] = 0x0c201096; /* ldw 0(%r1), %r22 ; address of handler */
- tramp[5] = 0xeac0c000; /* bv %r0(%r22) ; branch to handler */
- tramp[6] = 0x0c281093; /* ldw 4(%r1), %r19 ; GP of handler */
- tramp[7] = ((UINT32)(ffi_closure_LINUX) & ~2);
-
- /* Flush d/icache -- have to flush up 2 two lines because of
- alignment. */
- asm volatile (
- "fdc 0(%0)\n"
- "fdc %1(%0)\n"
- "fic 0(%%sr4, %0)\n"
- "fic %1(%%sr4, %0)\n"
- "sync\n"
- : : "r"((unsigned long)tramp & ~31), "r"(32 /* stride */));
-
- closure->cif = cif;
- closure->user_data = user_data;
- closure->fun = fun;
-
- return FFI_OK;
-}
-#endif
diff --git a/libffi/src/pa/ffitarget.h b/libffi/src/pa/ffitarget.h
deleted file mode 100644
index b8bcad0..0000000
--- a/libffi/src/pa/ffitarget.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -----------------------------------------------------------------*-C-*-
- ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
- Target configuration macros for hppa.
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
-
- ----------------------------------------------------------------------- */
-
-#ifndef LIBFFI_TARGET_H
-#define LIBFFI_TARGET_H
-
-/* ---- System specific configurations ----------------------------------- */
-
-#ifndef LIBFFI_ASM
-typedef unsigned long ffi_arg;
-typedef signed long ffi_sarg;
-
-typedef enum ffi_abi {
- FFI_FIRST_ABI = 0,
-
-#ifdef PA
- FFI_LINUX,
- FFI_DEFAULT_ABI = FFI_LINUX,
-#endif
-
- FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
-} ffi_abi;
-#endif
-
-/* ---- Definitions for closures ----------------------------------------- */
-
-#define FFI_CLOSURES 1
-#define FFI_NATIVE_RAW_API 0
-
-#define FFI_TRAMPOLINE_SIZE 32
-
-#define FFI_TYPE_SMALL_STRUCT1 -1
-#define FFI_TYPE_SMALL_STRUCT2 -2
-#endif
-
diff --git a/libffi/src/pa/linux.S b/libffi/src/pa/linux.S
deleted file mode 100644
index 1a2ecdb..0000000
--- a/libffi/src/pa/linux.S
+++ /dev/null
@@ -1,281 +0,0 @@
-/* -----------------------------------------------------------------------
- linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
-
- HPPA Foreign Function Interface
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- ``Software''), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- OTHER DEALINGS IN THE SOFTWARE.
- ----------------------------------------------------------------------- */
-
-#define LIBFFI_ASM
-#include <fficonfig.h>
-#include <ffi.h>
-
- .text
- .align 4
-
- /* void ffi_call_LINUX(void (*)(char *, extended_cif *),
- extended_cif *ecif,
- unsigned bytes,
- unsigned flags,
- unsigned *rvalue,
- void (*fn)());
- */
-
- .export ffi_call_LINUX,code
- .import ffi_prep_args_LINUX,code
-
- .type ffi_call_LINUX, @function
-.LFB1:
-ffi_call_LINUX:
- .proc
- .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
- .entry
- stw %rp, -20(%sp)
- copy %r3, %r1
-.LCFI11:
-
- copy %sp, %r3
-.LCFI12:
-
- /* Setup the stack for calling prep_args...
- We want the stack to look like this:
-
- [ Previous stack ] <- %r3
-
- [ 64-bytes register save area ] <- %r4
-
- [ Stack space for actual call, passed as ] <- %arg0
- [ arg0 to ffi_prep_args_LINUX ]
-
- [ Stack for calling prep_args ] <- %sp
- */
-
- stwm %r1, 64(%sp)
- stw %r4, 12(%r3)
-.LCFI13:
- copy %sp, %r4
-
- addl %arg2, %r4, %arg0 /* arg stack */
- stw %arg3, -48(%r3) /* save flags; we need it later */
-
- /* Call prep_args:
- %arg0(stack) -- set up above
- %arg1(ecif) -- same as incoming param
- %arg2(bytes) -- same as incoming param */
- bl ffi_prep_args_LINUX,%r2
- ldo 64(%arg0), %sp
- ldo -64(%sp), %sp
-
- /* now %sp should point where %arg0 was pointing. */
-
- /* Load the arguments that should be passed in registers
- The fp args were loaded by the prep_args function. */
- ldw -36(%sp), %arg0
- ldw -40(%sp), %arg1
- ldw -44(%sp), %arg2
- ldw -48(%sp), %arg3
-
- /* in case the function is going to return a structure
- we need to give it a place to put the result. */
- ldw -52(%r3), %ret0 /* %ret0 <- rvalue */
- ldw -56(%r3), %r22 /* %r22 <- function to call */
- bl $$dyncall, %r31 /* Call the user function */
- copy %r31, %rp
-
- /* Prepare to store the result; we need to recover flags and rvalue. */
- ldw -48(%r3), %r21 /* r21 <- flags */
- ldw -52(%r3), %r20 /* r20 <- rvalue */
-
- /* Store the result according to the return type. */
-
-checksmst1:
- comib,<>,n FFI_TYPE_SMALL_STRUCT1, %r21, checksmst2
- /* There is maybe a better way to handle 3 byte structs. */
- sh2add %ret0,0,%ret0
- sh2add %ret0,0,%ret0
- sh2add %ret0,0,%ret0
- sh2add %ret0,0,%ret0
- b done
- stw %ret0, 0(%r20)
-
-checksmst2:
- comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, checkint8
- /* Up to now I don't have a way to handle 6/7 byte structs.
- The values are left bounded in the registers. In the struct
- itself they are left bounded. */
- stw %ret0, 0(%r20)
- b done
- stw %ret1, 4(%r20)
-
-checkint8:
- comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
- b done
- stb %ret0, 0(%r20)
-
-checkint16:
- comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
- b done
- sth %ret0, 0(%r20)
-
-checkint32:
- comib,<>,n FFI_TYPE_UINT32, %r21, checkint
- b done
- stw %ret0, 0(%r20)
-
-checkint:
- comib,<>,n FFI_TYPE_INT, %r21, checkll
- b done
- stw %ret0, 0(%r20)
-
-checkll:
- comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
- stw %ret0, 0(%r20)
- b done
- stw %ret1, 4(%r20)
-
-checkdbl:
- comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
- b done
- fstd %fr4,0(%r20)
-
-checkfloat:
- comib,<>,n FFI_TYPE_FLOAT, %r21, done
- fstw %fr4L,0(%r20)
-
- /* structure returns are either handled by one of the
- INT/UINT64 cases above, or, if passed by pointer,
- is handled by the callee. */
-
-done:
- /* all done, return */
- copy %r4, %sp /* pop arg stack */
- ldw 12(%r3), %r4
- ldwm -64(%sp), %r3 /* .. and pop stack */
- ldw -20(%sp), %rp
- bv %r0(%rp)
- nop
- .exit
- .procend
-.LFE1:
-
- /* void ffi_closure_LINUX(void);
- Called with closure argument in %r21 */
- .export ffi_closure_LINUX,code
- .import ffi_closure_inner_LINUX,code
-
- .type ffi_closure_LINUX, @function
-.LFB2:
-ffi_closure_LINUX:
- .proc
- .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
- .entry
-
- stw %rp, -20(%sp)
-.LCFI20:
- copy %r3, %r1
-.LCFI21:
- copy %sp, %r3
-.LCFI22:
- stwm %r1, 64(%sp)
-
- /* Put arguments onto the stack and call ffi_closure_inner. */
- stw %arg0, -36(%r3)
- stw %arg1, -40(%r3)
- stw %arg2, -44(%r3)
- stw %arg3, -48(%r3)
-
- copy %r21, %arg0
- bl ffi_closure_inner_LINUX, %r2
- copy %r3, %arg1
-
- ldwm -64(%sp), %r3
- ldw -20(%sp), %rp
- ldw -36(%sp), %ret0
- bv %r0(%r2)
- ldw -40(%sp), %ret1
-
- .exit
- .procend
-.LFE2:
-
- .section ".eh_frame",EH_FRAME_FLAGS,@progbits
-.Lframe1:
- .word .LECIE1-.LSCIE1 ;# Length of Common Information Entry
-.LSCIE1:
- .word 0x0 ;# CIE Identifier Tag
- .byte 0x1 ;# CIE Version
- .ascii "\0" ;# CIE Augmentation
- .uleb128 0x1 ;# CIE Code Alignment Factor
- .sleb128 4 ;# CIE Data Alignment Factor
- .byte 0x2 ;# CIE RA Column
- .byte 0xc ;# DW_CFA_def_cfa
- .uleb128 0x1e
- .uleb128 0x0
- .align 4
-.LECIE1:
-.LSFDE1:
- .word .LEFDE1-.LASFDE1 ;# FDE Length
-.LASFDE1:
- .word .LASFDE1-.Lframe1 ;# FDE CIE offset
- .word .LFB1 ;# FDE initial location
- .word .LFE1-.LFB1 ;# FDE address range
-
- .byte 0x4 ;# DW_CFA_advance_loc4
- .word .LCFI11-.LFB1
- .byte 0x83 ;# DW_CFA_offset, column 0x3
- .uleb128 0x0
- .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
- .uleb128 0x2
- .sleb128 -5
-
- .byte 0x4 ;# DW_CFA_advance_loc4
- .word .LCFI12-.LCFI11
- .byte 0xd ;# DW_CFA_def_cfa_register = r3
- .uleb128 0x3
-
- .byte 0x4 ;# DW_CFA_advance_loc4
- .word .LCFI13-.LCFI12
- .byte 0x84 ;# DW_CFA_offset, column 0x4
- .uleb128 0x3
-
- .align 4
-.LEFDE1:
-
-.LSFDE2:
- .word .LEFDE2-.LASFDE2 ;# FDE Length
-.LASFDE2:
- .word .LASFDE2-.Lframe1 ;# FDE CIE offset
- .word .LFB2 ;# FDE initial location
- .word .LFE2-.LFB2 ;# FDE address range
- .byte 0x4 ;# DW_CFA_advance_loc4
- .word .LCFI21-.LFB2
- .byte 0x83 ;# DW_CFA_offset, column 0x3
- .uleb128 0x0
- .byte 0x11 ;# DW_CFA_offset_extended_sf
- .uleb128 0x2
- .sleb128 -5
-
- .byte 0x4 ;# DW_CFA_advance_loc4
- .word .LCFI12-.LCFI11
- .byte 0xd ;# DW_CFA_def_cfa_register = r3
- .uleb128 0x3
-
- .align 4
-.LEFDE2: