diff options
author | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-04-29 04:14:44 +0000 |
---|---|---|
committer | bryce <bryce@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-04-29 04:14:44 +0000 |
commit | ea1f83c547ade869a8ac885d061426c4b0e77fb0 (patch) | |
tree | f39e5328a9363e97902877aab9e253339d93ad1c /libffi/src/s390 | |
parent | 6f0ae5446034ae364d9599e051a1f81ae9b61e1f (diff) | |
download | gcc-ea1f83c547ade869a8ac885d061426c4b0e77fb0.tar.gz |
2002-04-29 Gerhard Tonn <GerhardTonn@swol.de>
* Makefile.am: Add Linux for S/390 support.
* Makefile.in: Regenerate.
* configure.in: Add Linux for S/390 support.
* configure: Regenerate.
* include/ffi.h.in: Add Linux for S/390 support.
* src/s390/ffi.c: New file from libffi CVS tree.
* src/s390/sysv.S: New file from libffi CVS tree.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52873 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libffi/src/s390')
-rw-r--r-- | libffi/src/s390/ffi.c | 589 | ||||
-rw-r--r-- | libffi/src/s390/sysv.S | 161 |
2 files changed, 750 insertions, 0 deletions
diff --git a/libffi/src/s390/ffi.c b/libffi/src/s390/ffi.c new file mode 100644 index 00000000000..8b514e36c26 --- /dev/null +++ b/libffi/src/s390/ffi.c @@ -0,0 +1,589 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2000 Software AG + + S390 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 THE AUTHOR 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. + ----------------------------------------------------------------------- */ +/*====================================================================*/ +/* Includes */ +/* -------- */ +/*====================================================================*/ + +#include <ffi.h> +#include <ffi_common.h> + +#include <stdlib.h> +#include <stdio.h> + +/*====================== End of Includes =============================*/ + +/*====================================================================*/ +/* Defines */ +/* ------- */ +/*====================================================================*/ + +#define MAX_GPRARGS 5 /* Max. no. of GPR available */ +#define MAX_FPRARGS 2 /* Max. no. of FPR available */ + +#define STR_GPR 1 /* Structure will fit in 1 or 2 GPR */ +#define STR_FPR 2 /* Structure will fit in a FPR */ +#define STR_STACK 3 /* Structure needs to go on stack */ + +/*===================== End of Defines ===============================*/ + +/*====================================================================*/ +/* Types */ +/* ----- */ +/*====================================================================*/ + +typedef struct stackLayout +{ + int *backChain; + int *endOfStack; + int glue[2]; + int scratch[2]; + int gprArgs[MAX_GPRARGS]; + int notUsed; + union + { + float f; + double d; + } fprArgs[MAX_FPRARGS]; + int unUsed[8]; + int outArgs[100]; +} stackLayout; + +/*======================== End of Types ==============================*/ + +/*====================================================================*/ +/* Prototypes */ +/* ---------- */ +/*====================================================================*/ + +void ffi_prep_args(stackLayout *, extended_cif *); +static int ffi_check_struct(ffi_type *, unsigned int *); +static void ffi_insert_int(int, stackLayout *, int *, int *); +static void ffi_insert_int64(long long, stackLayout *, int *, int *); +static void ffi_insert_double(double, stackLayout *, int *, int *); + +/*====================== End of Prototypes ===========================*/ + +/*====================================================================*/ +/* Externals */ +/* --------- */ +/*====================================================================*/ + +extern void ffi_call_SYSV(void (*)(stackLayout *, extended_cif *), + extended_cif *, + unsigned, unsigned, + unsigned *, + void (*fn)()); + +/*====================== End of Externals ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_check_struct. */ +/* */ +/* Function - Determine if a structure can be passed within a */ +/* general or floating point register. */ +/* */ +/*====================================================================*/ + +int +ffi_check_struct(ffi_type *arg, unsigned int *strFlags) +{ + ffi_type *element; + int i_Element; + + for (i_Element = 0; arg->elements[i_Element]; i_Element++) { + element = arg->elements[i_Element]; + switch (element->type) { + case FFI_TYPE_DOUBLE : + *strFlags |= STR_FPR; + break; + + case FFI_TYPE_STRUCT : + *strFlags |= ffi_check_struct(element, strFlags); + break; + + default : + *strFlags |= STR_GPR; + } + } + return (*strFlags); +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_insert_int. */ +/* */ +/* Function - Insert an integer parameter in a register if there are */ +/* spares else on the stack. */ +/* */ +/*====================================================================*/ + +void +ffi_insert_int(int gprValue, stackLayout *stack, + int *intArgC, int *outArgC) +{ + if (*intArgC < MAX_GPRARGS) { + stack->gprArgs[*intArgC] = gprValue; + *intArgC += 1; + } + else { + stack->outArgs[*outArgC++] = gprValue; + *outArgC += 1; + } +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_insert_int64. */ +/* */ +/* Function - Insert a long long parameter in registers if there are */ +/* spares else on the stack. */ +/* */ +/*====================================================================*/ + +void +ffi_insert_int64(long long llngValue, stackLayout *stack, + int *intArgC, int *outArgC) +{ + + if (*intArgC < (MAX_GPRARGS-1)) { + memcpy(&stack->gprArgs[*intArgC], + &llngValue, sizeof(long long)); + *intArgC += 2; + } + else { + memcpy(&stack->outArgs[*outArgC], + &llngValue, sizeof(long long)); + *outArgC += 2; + } + +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_insert_double. */ +/* */ +/* Function - Insert a double parameter in a FP register if there is */ +/* a spare else on the stack. */ +/* */ +/*====================================================================*/ + +void +ffi_insert_double(double dblValue, stackLayout *stack, + int *fprArgC, int *outArgC) +{ + + if (*fprArgC < MAX_FPRARGS) { + stack->fprArgs[*fprArgC].d = dblValue; + *fprArgC += 1; + } + else { + memcpy(&stack->outArgs[*outArgC], + &dblValue,sizeof(double)); + *outArgC += 2; + } + +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_prep_args. */ +/* */ +/* Function - Prepare parameters for call to function. */ +/* */ +/* ffi_prep_args is called by the assembly routine once stack space */ +/* has been allocated for the function's arguments. */ +/* */ +/* The stack layout we want looks like this: */ +/* *------------------------------------------------------------* */ +/* | 0 | Back chain (a 0 here signifies end of back chain) | */ +/* +--------+---------------------------------------------------+ */ +/* | 4 | EOS (end of stack, not used on Linux for S390) | */ +/* +--------+---------------------------------------------------+ */ +/* | 8 | Glue used in other linkage formats | */ +/* +--------+---------------------------------------------------+ */ +/* | 12 | Glue used in other linkage formats | */ +/* +--------+---------------------------------------------------+ */ +/* | 16 | Scratch area | */ +/* +--------+---------------------------------------------------+ */ +/* | 20 | Scratch area | */ +/* +--------+---------------------------------------------------+ */ +/* | 24 | GPR parameter register 1 | */ +/* +--------+---------------------------------------------------+ */ +/* | 28 | GPR parameter register 2 | */ +/* +--------+---------------------------------------------------+ */ +/* | 32 | GPR parameter register 3 | */ +/* +--------+---------------------------------------------------+ */ +/* | 36 | GPR parameter register 4 | */ +/* +--------+---------------------------------------------------+ */ +/* | 40 | GPR parameter register 5 | */ +/* +--------+---------------------------------------------------+ */ +/* | 44 | Unused | */ +/* +--------+---------------------------------------------------+ */ +/* | 48 | FPR parameter register 1 | */ +/* +--------+---------------------------------------------------+ */ +/* | 56 | FPR parameter register 2 | */ +/* +--------+---------------------------------------------------+ */ +/* | 64 | Unused | */ +/* +--------+---------------------------------------------------+ */ +/* | 96 | Outgoing args (length x) | */ +/* +--------+---------------------------------------------------+ */ +/* | 96+x | Copy area for structures (length y) | */ +/* +--------+---------------------------------------------------+ */ +/* | 96+x+y | Possible stack alignment | */ +/* *------------------------------------------------------------* */ +/* */ +/*====================================================================*/ + +void +ffi_prep_args(stackLayout *stack, extended_cif *ecif) +{ + const unsigned bytes = ecif->cif->bytes; + const unsigned flags = ecif->cif->flags; + + /*----------------------------------------------------------*/ + /* Pointer to the copy area on stack for structures */ + /*----------------------------------------------------------*/ + char *copySpace = (char *) stack + bytes + sizeof(stackLayout); + + /*----------------------------------------------------------*/ + /* Count of general and floating point register usage */ + /*----------------------------------------------------------*/ + int intArgC = 0, + fprArgC = 0, + outArgC = 0; + + int i; + ffi_type **ptr; + void **p_argv; + size_t structCopySize; + unsigned gprValue, strFlags = 0; + unsigned long long llngValue; + double dblValue; + + /* Now for the arguments. */ + p_argv = ecif->avalue; + + /*----------------------------------------------------------------------*/ + /* If we returning a structure then we set the first parameter register */ + /* to the address of where we are returning this structure */ + /*----------------------------------------------------------------------*/ + if (flags == FFI_TYPE_STRUCT) + stack->gprArgs[intArgC++] = (int) ecif->rvalue; + + for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; + i > 0; + i--, ptr++, p_argv++) + { + switch ((*ptr)->type) { + + case FFI_TYPE_FLOAT: + if (fprArgC < MAX_FPRARGS) + stack->fprArgs[fprArgC++].f = *(float *) *p_argv; + else + stack->outArgs[outArgC++] = *(int *) *p_argv; + break; + + case FFI_TYPE_DOUBLE: + dblValue = *(double *) *p_argv; + ffi_insert_double(dblValue, stack, &fprArgC, &outArgC); + break; + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + llngValue = *(unsigned long long *) *p_argv; + ffi_insert_int64(llngValue, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_UINT8: + gprValue = *(unsigned char *)*p_argv; + ffi_insert_int(gprValue, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_SINT8: + gprValue = *(signed char *)*p_argv; + ffi_insert_int(gprValue, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_UINT16: + gprValue = *(unsigned short *)*p_argv; + ffi_insert_int(gprValue, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_SINT16: + gprValue = *(signed short *)*p_argv; + ffi_insert_int(gprValue, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_STRUCT: + /*--------------------------------------------------*/ + /* If structure > 8 bytes then it goes on the stack */ + /*--------------------------------------------------*/ + if (((*ptr)->size > 8) || + ((*ptr)->size > 4 && + (*ptr)->size < 8)) + strFlags = STR_STACK; + else + strFlags = ffi_check_struct((ffi_type *) *ptr, &strFlags); + + switch (strFlags) { + /*-------------------------------------------*/ + /* Structure that will fit in one or two GPR */ + /*-------------------------------------------*/ + case STR_GPR : + if ((*ptr)->size <= 4) { + gprValue = *(unsigned int *) *p_argv; + gprValue = gprValue >> ((4 - (*ptr)->size) * 8); + ffi_insert_int(gprValue, stack, &intArgC, &outArgC); + } + else { + llngValue = *(unsigned long long *) *p_argv; + ffi_insert_int64(llngValue, stack, &intArgC, &outArgC); + } + break; + + /*-------------------------------------------*/ + /* Structure that will fit in one FPR */ + /*-------------------------------------------*/ + case STR_FPR : + dblValue = *(double *) *p_argv; + ffi_insert_double(dblValue, stack, &fprArgC, &outArgC); + break; + + /*-------------------------------------------*/ + /* Structure that must be copied to stack */ + /*-------------------------------------------*/ + default : + structCopySize = (((*ptr)->size + 15) & ~0xF); + copySpace -= structCopySize; + memcpy(copySpace, (char *)*p_argv, (*ptr)->size); + gprValue = (unsigned) copySpace; + if (intArgC < MAX_GPRARGS) + stack->gprArgs[intArgC++] = gprValue; + else + stack->outArgs[outArgC++] = gprValue; + } + break; + +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + structCopySize = (((*ptr)->size + 15) & ~0xF); + copySpace -= structCopySize; + memcpy(copySpace, (char *)*p_argv, (*ptr)->size); + gprValue = (unsigned) copySpace; + if (intArgC < MAX_GPRARGS) + stack->gprArgs[intArgC++] = gprValue; + else + stack->outArgs[outArgC++] = gprValue; + break; +#endif + + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_POINTER: + gprValue = *(unsigned *)*p_argv; + if (intArgC < MAX_GPRARGS) + stack->gprArgs[intArgC++] = gprValue; + else + stack->outArgs[outArgC++] = gprValue; + break; + + } + } +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_prep_cif_machdep. */ +/* */ +/* Function - Perform machine dependent CIF processing. */ +/* */ +/*====================================================================*/ + +ffi_status +ffi_prep_cif_machdep(ffi_cif *cif) +{ + int i; + ffi_type **ptr; + unsigned bytes; + int fpArgC = 0, + intArgC = 0; + unsigned flags = 0; + unsigned structCopySize = 0; + + /*-----------------------------------------------------------------*/ + /* Extra space required in stack for overflow parameters. */ + /*-----------------------------------------------------------------*/ + bytes = 0; + + /*--------------------------------------------------------*/ + /* Return value handling. The rules are as follows: */ + /* - 32-bit (or less) integer values are returned in gpr2 */ + /* - Structures are returned as pointers in gpr2 */ + /* - 64-bit integer values are returned in gpr2 and 3 */ + /* - Single/double FP values are returned in fpr0 */ + /*--------------------------------------------------------*/ + flags = cif->rtype->type; + + /*------------------------------------------------------------------------*/ + /* The first MAX_GPRARGS words of integer arguments, and the */ + /* first MAX_FPRARGS floating point arguments, go in registers; the rest */ + /* goes on the stack. Structures and long doubles (if not equivalent */ + /* to double) are passed as a pointer to a copy of the structure. */ + /* Stuff on the stack needs to keep proper alignment. */ + /*------------------------------------------------------------------------*/ + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) + { + switch ((*ptr)->type) + { + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + fpArgC++; + if (fpArgC > MAX_FPRARGS && intArgC%2 != 0) + intArgC++; + break; + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + /*----------------------------------------------------*/ + /* 'long long' arguments are passed as two words, but */ + /* either both words must fit in registers or both go */ + /* on the stack. If they go on the stack, they must */ + /* be 8-byte-aligned. */ + /*----------------------------------------------------*/ + if ((intArgC == MAX_GPRARGS-1) || + (intArgC >= MAX_GPRARGS) && + (intArgC%2 != 0)) + intArgC++; + intArgC += 2; + break; + + case FFI_TYPE_STRUCT: +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: +#endif + /*----------------------------------------------------*/ + /* We must allocate space for a copy of these to */ + /* enforce pass-by-value. Pad the space up to a */ + /* multiple of 16 bytes (the maximum alignment */ + /* required for anything under the SYSV ABI). */ + /*----------------------------------------------------*/ + structCopySize += ((*ptr)->size + 15) & ~0xF; + /*----------------------------------------------------*/ + /* Fall through (allocate space for the pointer). */ + /*----------------------------------------------------*/ + + default: + /*----------------------------------------------------*/ + /* Everything else is passed as a 4-byte word in a */ + /* GPR either the object itself or a pointer to it. */ + /*----------------------------------------------------*/ + intArgC++; + break; + } + } + + /*-----------------------------------------------------------------*/ + /* Stack space. */ + /*-----------------------------------------------------------------*/ + if (intArgC > MAX_GPRARGS) + bytes += (intArgC - MAX_GPRARGS) * sizeof(int); + if (fpArgC > MAX_FPRARGS) + bytes += (fpArgC - MAX_FPRARGS) * sizeof(double); + + /*-----------------------------------------------------------------*/ + /* The stack space allocated needs to be a multiple of 16 bytes. */ + /*-----------------------------------------------------------------*/ + bytes = (bytes + 15) & ~0xF; + + /*-----------------------------------------------------------------*/ + /* Add in the space for the copied structures. */ + /*-----------------------------------------------------------------*/ + bytes += structCopySize; + + cif->flags = flags; + cif->bytes = bytes; + + return FFI_OK; +} + +/*======================== End of Routine ============================*/ + +/*====================================================================*/ +/* */ +/* Name - ffi_call. */ +/* */ +/* Function - Call the FFI routine. */ +/* */ +/*====================================================================*/ + +void +ffi_call(ffi_cif *cif, + void (*fn)(), + void *rvalue, + 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)) + ecif.rvalue = alloca(cif->rtype->size); + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_SYSV: + ffi_call_SYSV(ffi_prep_args, + &ecif, cif->bytes, + cif->flags, ecif.rvalue, fn); + break; + + default: + FFI_ASSERT(0); + break; + } +} + +/*======================== End of Routine ============================*/ diff --git a/libffi/src/s390/sysv.S b/libffi/src/s390/sysv.S new file mode 100644 index 00000000000..afaf1ea1ca3 --- /dev/null +++ b/libffi/src/s390/sysv.S @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2000 Software AG + + S390 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 <ffi.h> +#ifdef HAVE_MACHINE_ASM_H +#include <machine/asm.h> +#endif + +.text + + # r2: ffi_prep_args + # r3: &ecif + # r4: cif->bytes + # r5: fig->flags + # r6: ecif.rvalue + # sp+0: fn + + # This assumes we are using gas. + .globl ffi_call_SYSV + .type ffi_call_SYSV,%function +ffi_call_SYSV: + # Save registers + stm %r7,%r15,28(%r15) + l %r7,96(%r15) # Get A(fn) + lr %r0,%r15 + ahi %r15,-128 # Make room for my args + st %r0,0(%r15) # Set backchain + lr %r11,%r15 # Establish my stack register + sr %r15,%r4 # Make room for fn args + ahi %r15,-96 # Make room for new frame + lr %r10,%r15 # Establish stack build area + ahi %r15,-96 # Stack for next call + lr %r1,%r7 + stm %r2,%r7,96(%r11) # Save args on my stack + +#------------------------------------------------------------------ +# move first 3 parameters in registers +#------------------------------------------------------------------ + lr %r9,%r2 # r9: &ffi_prep_args + lr %r2,%r10 # Parm 1: &stack Parm 2: &ecif + basr %r14,%r9 # call ffi_prep_args + +#------------------------------------------------------------------ +# load first 5 parameter registers +#------------------------------------------------------------------ + lm %r2,%r6,24(%r10) + +#------------------------------------------------------------------ +# load fp parameter registers +#------------------------------------------------------------------ + ld %f0,48(%r10) + ld %f2,56(%r10) + +#------------------------------------------------------------------ +# call function +#------------------------------------------------------------------ + lr %r15,%r10 # Set new stack + l %r9,116(%r11) # Get &fn + basr %r14,%r9 # Call function + +#------------------------------------------------------------------ +# On return: +# r2: Return value (r3: Return value + 4 for long long) +#------------------------------------------------------------------ + +#------------------------------------------------------------------ +# If the return value pointer is NULL, assume no return value. +#------------------------------------------------------------------ + icm %r6,15,112(%r11) + jz .Lepilogue + + l %r5,108(%r11) # Get return type +#------------------------------------------------------------------ +# return INT +#------------------------------------------------------------------ + chi %r5,FFI_TYPE_INT + jne .Lchk64 + + st %r2,0(%r6) + j .Lepilogue + +.Lchk64: +#------------------------------------------------------------------ +# return LONG LONG (signed/unsigned) +#------------------------------------------------------------------ + chi %r5,FFI_TYPE_UINT64 + je .LdoLongLong + + chi %r5,FFI_TYPE_SINT64 + jne .LchkFloat + +.LdoLongLong: + stm %r2,%r3,0(%r6) + j .Lepilogue + +.LchkFloat: +#------------------------------------------------------------------ +# return FLOAT +#------------------------------------------------------------------ + chi %r5,FFI_TYPE_FLOAT + jne .LchkDouble + + std %f0,0(%r6) + j .Lepilogue + +.LchkDouble: +#------------------------------------------------------------------ +# return DOUBLE or LONGDOUBLE +#------------------------------------------------------------------ + chi %r5,FFI_TYPE_DOUBLE + jne .LchkStruct + + std %f0,0(%r6) + std %f2,8(%r6) + j .Lepilogue + +.LchkStruct: +#------------------------------------------------------------------ +# Structure - rvalue already set as sent as 1st parm to routine +#------------------------------------------------------------------ + chi %r5,FFI_TYPE_STRUCT + je .Lepilogue + +.Ldefault: +#------------------------------------------------------------------ +# return a pointer +#------------------------------------------------------------------ + st %r2,0(%r6) + j .Lepilogue + +.Lepilogue: + l %r15,0(%r11) + l %r4,56(%r15) + lm %r7,%r15,28(%r15) + br %r4 + +.ffi_call_SYSV_end: + .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV |