--- ./boehm-gc/include/private/gcconfig.h.orig 2002-04-22 02:05:04.000000000 -0400 +++ ./boehm-gc/include/private/gcconfig.h 2003-05-07 23:12:28.000000000 -0400 @@ -369,7 +369,7 @@ # define mach_type_known # endif # if defined(__s390__) && defined(LINUX) -# define S370 +# define S390 # define mach_type_known # endif # if defined(__GNU__) @@ -418,7 +418,8 @@ /* (CX_UX and DGUX) */ /* S370 ==> 370-like machine */ /* running Amdahl UTS4 */ - /* or a 390 running LINUX */ + /* S390 ==> 390-line machine */ + /* running LINUX */ /* ARM32 ==> Intel StrongARM */ /* IA64 ==> Intel IPF */ /* (e.g. Itanium) */ @@ -1528,12 +1529,29 @@ # define DATAEND (_end) # define HEURISTIC2 # endif +# endif + +# ifdef S390 +# define MACH_TYPE "S390" +# define USE_GENERIC_PUSH_REGS +# ifndef __s390x__ +# define ALIGNMENT 4 +# define CPP_WORDSZ 32 +# else +# define ALIGNMENT 8 +# define CPP_WORDSZ 64 +# define HBLKSIZE 4096 +# endif # ifdef LINUX # define OS_TYPE "LINUX" # define HEURISTIC1 # define DYNAMIC_LOADING extern int __data_start[]; # define DATASTART ((ptr_t)(__data_start)) + extern int _end[]; +# define DATAEND (_end) +# define CACHE_LINE_SIZE 256 +# define GETPAGESIZE() 4096 # endif # endif @@ -1818,7 +1836,7 @@ # define CAN_SAVE_CALL_STACKS # define CAN_SAVE_CALL_ARGS #endif -#if defined(I386) && defined(LINUX) +#if (defined(I386) || defined(S390)) && defined(LINUX) /* SAVE_CALL_CHAIN is supported if the code is compiled to save */ /* frame pointers by default, i.e. no -fomit-frame-pointer flag. */ # define CAN_SAVE_CALL_STACKS --- ./boehm-gc/include/private/gc_locks.h.orig 2001-10-16 05:01:39.000000000 -0400 +++ ./boehm-gc/include/private/gc_locks.h 2003-05-07 23:12:28.000000000 -0400 @@ -209,6 +209,21 @@ } # define GC_TEST_AND_SET_DEFINED # endif /* ARM32 */ +# ifdef S390 + inline static int GC_test_and_set(volatile unsigned int *spinlock) { + int ret; + /* See linuxthreads/sysdeps/s390/s390-32/pt-machine.h in glibc-2.2 */ + __asm__ __volatile__( + " la 1,%1\n" + " lhi 0,1\n" + " l %0,%1\n" + "0: cs %0,0,0(1)\n" + " jl 0b" + : "=&d" (ret), "+m" (*spinlock) + : : "0", "1", "cc"); + return(ret); + } +# endif # endif /* __GNUC__ */ # if (defined(ALPHA) && !defined(__GNUC__)) # define GC_test_and_set(addr) __cxx_test_and_set_atomic(addr, 1) @@ -326,6 +341,42 @@ } # endif /* 0 */ # endif /* IA64 */ +# if defined(S390) +# if !defined(GENERIC_COMPARE_AND_SWAP) +# ifndef __s390x__ + inline static GC_bool GC_compare_and_exchange(volatile C_word *addr, + GC_word old, GC_word new_val) { + int retval; + + __asm__ __volatile ( + " lr 0,%2\n" + " cs 0,%3,%1\n" + " ipm %0\n" + " srl %0,28\n" + : "=&d" (retval), "+m" (*addr) + : "d" (old), "d" (new_val) + : "0", "cc"); + return(retval == 0); + } +# else + inline static GC_bool GC_compare_and_exchange(volatile C_word *addr, + GC_word old, GC_word new_v +al) { + int retval; + + __asm__ __volatile ( + " lgr 0,%2\n" + " csg 0,%3,%1\n" + " ipm %0\n" + " srl %0,28\n" + : "=&d" (retval), "+m" (*addr) + : "d" (old), "d" (new_val) + : "0", "cc"); + return(retval == 0) + } +# endif +# endif +# endif # if !defined(GENERIC_COMPARE_AND_SWAP) /* Returns the original value of *addr. */ inline static GC_word GC_atomic_add(volatile GC_word *addr, --- ./libffi/include/ffi.h.in.orig 2002-03-12 17:35:56.000000000 -0500 +++ ./libffi/include/ffi.h.in 2003-05-07 23:12:28.000000000 -0400 @@ -251,6 +251,13 @@ FFI_DEFAULT_ABI = FFI_SYSV, #endif + /* ---- S390 - 31 & 64-bit ------ */ + +#if defined(S390) || defined(S390X) + FFI_SYSV, + FFI_DEFAULT_ABI = FFI_SYSV, +#endif + /* Leave this for debugging purposes */ FFI_LAST_ABI --- ./libffi/src/s390/ffi.c.orig 1969-12-31 19:00:00.000000000 -0500 +++ ./libffi/src/s390/ffi.c 2003-05-07 23:12:28.000000000 -0400 @@ -0,0 +1,591 @@ +#ifndef __s390x__ +/* ----------------------------------------------------------------------- + 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 +#include + +#include +#include + +/*====================== 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 ============================*/ +#endif /* #ifndef __s390x__ */ --- ./libffi/src/s390/sysv.S.orig 1969-12-31 19:00:00.000000000 -0500 +++ ./libffi/src/s390/sysv.S 2003-05-07 23:12:28.000000000 -0400 @@ -0,0 +1,184 @@ +#ifndef __s390x__ +/* ----------------------------------------------------------------------- + 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 +#ifdef HAVE_MACHINE_ASM_H +#include +#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 %r6,%r15,24(%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 + sll %r5,2 /* Form displacement */ + basr %r1,0 /* Establish base */ + la %r1,.LretTable-ffi_call_SYSV(%r1) + alr %r5,%r1 /* Address actual entry */ + br %r5 /* Branch to the jump */ + +.LretTable: + j .LretPointer /* Void */ + j .LretInt /* Integer */ + j .LretFloat /* Float */ + j .LretDouble /* Double */ + j .LretLongDouble /* Long Double */ + j .LretByte /* Unsigned Byte */ + j .LretByte /* Signed Byte */ + j .LretShort /* Unsigned Short */ + j .LretShort /* Signed Short */ + j .LretInt /* Unsigned Integer */ + j .LretInt /* Signed Integer */ + j .LretLong /* Unsigned Long */ + j .LretLong /* Signed Long */ + j .Lepilogue /* Structure */ + j .LretPointer /* Pointer */ + +#------------------------------------------------------------------ +# return BYTE +#------------------------------------------------------------------ +.LretByte: + stc %r2,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return SHORT +#------------------------------------------------------------------ +.LretShort: + stcm %r2,3,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return INT +#------------------------------------------------------------------ +.LretInt: + st %r2,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return LONG LONG (signed/unsigned) +#------------------------------------------------------------------ +.LretLong: + stm %r2,%r3,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return FLOAT +#------------------------------------------------------------------ +.LretFloat: + ste %f0,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return DOUBLE or LONGDOUBLE +#------------------------------------------------------------------ +.LretDouble: +.LretLongDouble: + std %f0,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# Structure - rvalue already set as sent as 1st parm to routine +#------------------------------------------------------------------ +.LretStruct: + j .Lepilogue + +#------------------------------------------------------------------ +# return a pointer +#------------------------------------------------------------------ +.LretPointer: + st %r2,0(%r6) + j .Lepilogue + +.Lepilogue: + l %r15,0(%r11) + l %r4,56(%r15) + lm %r6,%r15,24(%r15) + br %r4 + +.ffi_call_SYSV_end: + .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV +#endif /* #ifndef __s390x__ */ --- ./libffi/src/types.c.orig 2001-03-26 21:39:16.000000000 -0500 +++ ./libffi/src/types.c 2003-05-07 23:12:28.000000000 -0400 @@ -42,7 +42,7 @@ FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); -#if defined ALPHA || defined SPARC64 +#if defined ALPHA || defined SPARC64 || defined S390X FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); --- ./libffi/src/s390/ffi64.c.orig 1969-12-31 19:00:00.000000000 -0500 +++ ./libffi/src/s390/ffi64.c 2003-05-07 23:12:28.000000000 -0400 @@ -0,0 +1,585 @@ +#ifdef __s390x__ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2000 Software AG + + S390 Foreign Function Interface + + $Id: $ + + 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 +#include + +#include +#include +#include + +/*====================== End of Includes =============================*/ + +/*====================================================================*/ +/* Defines */ +/* ------- */ +/*====================================================================*/ + +#define MAX_GPRARGS 5 /* Max. no. of GPR available */ +#define MAX_FPRARGS 4 /* 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 +{ + uint64_t *backChain; /* 0 */ + uint64_t *endOfStack; /* 8 */ + uint64_t glue[2]; /* 16 */ + uint64_t scratch[2]; /* 32 */ + uint64_t gprArgs[MAX_GPRARGS]; /* 48 */ + uint64_t notUsed; /* 88 */ + uint64_t fprArgs[MAX_FPRARGS]; /* 96 */ + uint64_t unUsed[4]; /* 128 */ + uint64_t outArgs[44]; /* 160 */ + } stackLayout; /* 512 */ + +/*======================== End of Types ==============================*/ + +/*====================================================================*/ +/* Prototypes */ +/* ---------- */ +/*====================================================================*/ + +void ffi_prep_args(stackLayout *, extended_cif *); +static int ffi_check_struct(ffi_type *, unsigned 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 or long parameter in a register if */ +/* there are spares else on the stack. */ +/* */ +/*====================================================================*/ + +static inline void +ffi_insert_int(uint64_t 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_float. */ +/* */ +/* Function - Insert a float parameter in a FP register if there is */ +/* a spare else on the stack. */ +/* */ +/*====================================================================*/ + +static inline void +ffi_insert_float(uint64_t fltValue, stackLayout *stack, + int *fprArgC, int *outArgC) +{ + + if (*fprArgC < MAX_FPRARGS) { + stack->fprArgs[*fprArgC] = fltValue << 32; + *fprArgC += 1; + } + else { + stack->outArgs[*outArgC] = fltValue; + *outArgC += 1; + } + +} + +/*======================== 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. */ +/* */ +/*====================================================================*/ + +static inline void +ffi_insert_double(uint64_t dblValue, stackLayout *stack, + int *fprArgC, int *outArgC) +{ + + if (*fprArgC < MAX_FPRARGS) { + stack->fprArgs[*fprArgC] = dblValue; + *fprArgC += 1; + } + else { + stack->outArgs[*outArgC] = dblValue; + *outArgC += 1; + } + +} + +/*======================== 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) | */ +/* +--------+---------------------------------------------------+ */ +/* | 8 | EOS (end of stack, not used on Linux for S390) | */ +/* +--------+---------------------------------------------------+ */ +/* | 16 | Glue used in other linkage formats | */ +/* +--------+---------------------------------------------------+ */ +/* | 24 | Glue used in other linkage formats | */ +/* +--------+---------------------------------------------------+ */ +/* | 32 | Scratch area | */ +/* +--------+---------------------------------------------------+ */ +/* | 40 | Scratch area | */ +/* +--------+---------------------------------------------------+ */ +/* | 48 | GPR parameter register 1 | */ +/* +--------+---------------------------------------------------+ */ +/* | 56 | GPR parameter register 2 | */ +/* +--------+---------------------------------------------------+ */ +/* | 64 | GPR parameter register 3 | */ +/* +--------+---------------------------------------------------+ */ +/* | 72 | GPR parameter register 4 | */ +/* +--------+---------------------------------------------------+ */ +/* | 80 | GPR parameter register 5 | */ +/* +--------+---------------------------------------------------+ */ +/* | 88 | Unused | */ +/* +--------+---------------------------------------------------+ */ +/* | 96 | FPR parameter register 1 | */ +/* +--------+---------------------------------------------------+ */ +/* | 112 | FPR parameter register 2 | */ +/* +--------+---------------------------------------------------+ */ +/* | 120 | FPR parameter register 3 | */ +/* +--------+---------------------------------------------------+ */ +/* | 128 | FPR parameter register 4 | */ +/* +--------+---------------------------------------------------+ */ +/* | 136 | Unused | */ +/* +--------+---------------------------------------------------+ */ +/* | 160 | Outgoing args (length x) | */ +/* +--------+---------------------------------------------------+ */ +/* | 160+x | Copy area for structures (length y) | */ +/* +--------+---------------------------------------------------+ */ +/* | 160+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 strFlags = 0; + uint64_t lngValue; + union + { + uint32_t i[2]; + float f[2]; + uint64_t l; + } prmData; + + prmData.l = 0; + + /* 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: + prmData.f[1] = *(float *) *p_argv; + ffi_insert_float(prmData.l, stack, &fprArgC, &outArgC); + break; + + case FFI_TYPE_DOUBLE: + lngValue = *(uint64_t *) *p_argv; + ffi_insert_double(lngValue, stack, &fprArgC, &outArgC); + break; + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: + lngValue = *(uint64_t *) *p_argv; + ffi_insert_int(lngValue, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_UINT8: + prmData.i[1] = *(unsigned char *) *p_argv; + ffi_insert_int(prmData.l, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_SINT8: + prmData.i[1] = *(signed char *) *p_argv; + ffi_insert_int(prmData.l, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_UINT16: + prmData.i[1] = *(unsigned short *) *p_argv; + ffi_insert_int(prmData.l, stack, &intArgC, &outArgC); + break; + + case FFI_TYPE_SINT16: + prmData.i[1] = *(signed short *) *p_argv; + ffi_insert_int(prmData.l, 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 a GPR */ + /*-------------------------------------------*/ + case STR_GPR : + if ((*ptr)->size <= 8) { + lngValue = *(uint64_t *) *p_argv; + lngValue = lngValue >> ((8 - (*ptr)->size) * 8); + ffi_insert_int(lngValue, stack, &intArgC, &outArgC); + } + else { + lngValue = *(uint64_t *) *p_argv; + ffi_insert_int(lngValue, stack, &intArgC, &outArgC); + } + break; + + /*-------------------------------------------*/ + /* Structure that will fit in one FPR */ + /*-------------------------------------------*/ + case STR_FPR : + lngValue = *(uint64_t *) *p_argv; + ffi_insert_double(lngValue, 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); + lngValue = (uint64_t) copySpace; + ffi_insert_int(lngValue, stack, &intArgC, &outArgC); + } + 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); + lngValue = (unsigned) copySpace; + if (intArgC < MAX_GPRARGS) + stack->gprArgs[intArgC++] = lngValue; + else + stack->outArgs[outArgC++] = lngValue; + break; +#endif + + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + prmData.i[1] = *(uint32_t *) *p_argv; + ffi_insert_int(prmData.l, stack, &intArgC, &outArgC); + 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: */ + /* - 64-bit (or less) integer values are returned in gpr2 */ + /* - Structures are returned as pointers in gpr2 */ + /* - 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++; + 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) + intArgC++; + 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(uint64_t); + 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 ============================*/ +#endif /* ifdef __s390x__ */ --- ./libffi/src/s390/unix64.S.orig 1969-12-31 19:00:00.000000000 -0500 +++ ./libffi/src/s390/unix64.S 2003-05-07 23:12:28.000000000 -0400 @@ -0,0 +1,188 @@ +#ifdef __s390x__ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2000 Software AG + + S390 Foreign Function Interface + + $Id: sysv.S,v 1.1.1.1 1998/10/07 04:27:22 toshok Exp $ + + 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 +#ifdef HAVE_MACHINE_ASM_H +#include +#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 + stmg %r6,%r15,48(%r15) + lg %r7,160(%r15) # Get A(fn) + lgr %r0,%r15 + aghi %r15,-256 # Make room for my args + stg %r0,0(%r15) # Set backchain + lgr %r11,%r15 # Establish my stack register + sgr %r15,%r4 # Make room for fn args + aghi %r15,-256 # Make room for new frame + lgr %r10,%r15 # Establish stack build area + aghi %r15,-512 # Stack for next call + lgr %r1,%r7 + stmg %r2,%r7,160(%r11) # Save args on my stack + +#------------------------------------------------------------------ +# move first 3 parameters in registers +#------------------------------------------------------------------ + lgr %r9,%r2 # r9: &ffi_prep_args + lgr %r2,%r10 # Parm 1: &stack Parm 2: &ecif + basr %r14,%r9 # call ffi_prep_args + +#------------------------------------------------------------------ +# load first 5 parameter registers +#------------------------------------------------------------------ + lmg %r2,%r6,48(%r10) + +#------------------------------------------------------------------ +# load fp parameter registers +#------------------------------------------------------------------ + ld %f0,96(%r10) + ld %f2,104(%r10) + ld %f4,112(%r10) + ld %f6,120(%r10) + +#------------------------------------------------------------------ +# call function +#------------------------------------------------------------------ + lgr %r15,%r10 # Set new stack + lg %r9,200(%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. +#------------------------------------------------------------------ + lg %r6,192(%r11) + ltgr %r6,%r6 + jz .Lepilogue + + lg %r5,184(%r11) # Get return type + sllg %r5,%r5,2 /* Form displacement */ + larl %r1,.LretTable /* Establish base register */ + algr %r5,%r1 /* Address actual entry */ + br %r5 /* Branch to the jump */ + +.LretTable: + j .LretPointer /* Void */ + j .LretInt /* Integer */ + j .LretFloat /* Float */ + j .LretDouble /* Double */ + j .LretLongDouble /* Long Double */ + j .LretByte /* Unsigned Byte */ + j .LretByte /* Signed Byte */ + j .LretShort /* Unsigned Short */ + j .LretShort /* Signed Short */ + j .LretInt /* Unsigned Integer */ + j .LretInt /* Signed Integer */ + j .LretLong /* Unsigned Long */ + j .LretLong /* Signed Long */ + j .Lepilogue /* Structure */ + j .LretPointer /* Pointer */ + +#------------------------------------------------------------------ +# return BYTE +#------------------------------------------------------------------ +.LretByte: + stc %r2,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return SHORT +#------------------------------------------------------------------ +.LretShort: + stcm %r2,3,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return INT +#------------------------------------------------------------------ +.LretInt: + st %r2,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return LONG LONG (signed/unsigned) +#------------------------------------------------------------------ +.LretLong: + stg %r2,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return FLOAT +#------------------------------------------------------------------ +.LretFloat: + ste %f0,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# return DOUBLE or LONGDOUBLE +#------------------------------------------------------------------ +.LretDouble: +.LretLongDouble: + std %f0,0(%r6) + j .Lepilogue + +#------------------------------------------------------------------ +# Structure: rvalue already set as sent as 1st parm to routine +#------------------------------------------------------------------ +.LretStruct: + j .Lepilogue + +#------------------------------------------------------------------ +# return a pointer +#------------------------------------------------------------------ +.LretPointer: + stg %r2,0(%r6) + j .Lepilogue + +.Lepilogue: + lg %r15,0(%r11) + lg %r4,112(%r15) + lmg %r6,%r15,48(%r15) + br %r4 + +.ffi_call_SYSV_end: + .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV +#endif /* ifdef __s390x__ */ --- ./libffi/configure.in.orig 2003-01-27 20:43:56.000000000 -0500 +++ ./libffi/configure.in 2003-05-07 23:12:28.000000000 -0400 @@ -67,6 +67,8 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;; +s390-*-linux*) TARGET=S390; TARGETDIR=s390;; +s390x-*-linux*) TARGET=S390X; TARGETDIR=s390;; esac if test $TARGETDIR = unknown; then @@ -85,6 +87,8 @@ AM_CONDITIONAL(POWERPC_AIX, test x$TARGET = xPOWERPC_AIX) AM_CONDITIONAL(POWERPC_DARWIN, test x$TARGET = xPOWERPC_DARWIN) AM_CONDITIONAL(ARM, test x$TARGET = xARM) +AM_CONDITIONAL(S390, test x$TARGET = xS390) +AM_CONDITIONAL(S390X, test x$TARGET = xS390X) AC_HEADER_STDC AC_CHECK_FUNCS(memcpy) --- ./libffi/configure.orig 2003-01-28 17:59:05.000000000 -0500 +++ ./libffi/configure 2003-05-07 23:12:28.000000000 -0400 @@ -2392,6 +2392,8 @@ powerpc-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; rs6000-*-aix*) TARGET=POWERPC_AIX; TARGETDIR=powerpc;; arm*-*-linux-*) TARGET=ARM; TARGETDIR=arm;; +s390-*-linux-*) TARGET=S390; TARGETDIR=s390;; +s390x-*-linux-*) TARGET=S390X; TARGETDIR=s390;; esac if test $TARGETDIR = unknown; then @@ -2507,6 +2509,24 @@ ARM_FALSE= fi + +if test x$TARGET = xS390; then + S390_TRUE= + S390_FALSE='#' +else + S390_TRUE='#' + S390_FALSE= +fi + + +if test x$TARGET = xS390X; then + S390X_TRUE= + S390X_FALSE='#' +else + S390X_TRUE='#' + S390X_FALSE= +fi + echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:2512: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. @@ -3729,6 +3749,10 @@ s%@POWERPC_DARWIN_FALSE@%$POWERPC_DARWIN_FALSE%g s%@ARM_TRUE@%$ARM_TRUE%g s%@ARM_FALSE@%$ARM_FALSE%g +s%@S390_TRUE@%$S390_TRUE%g +s%@S390_FALSE@%$S390_FALSE%g +s%@S390X_TRUE@%$S390X_TRUE%g +s%@S390X_FALSE@%$S390X_FALSE%g s%@CPP@%$CPP%g s%@ALLOCA@%$ALLOCA%g s%@TARGET@%$TARGET%g --- ./libffi/Makefile.am.orig 2003-01-27 20:43:56.000000000 -0500 +++ ./libffi/Makefile.am 2003-05-07 23:12:28.000000000 -0400 @@ -15,7 +15,9 @@ src/powerpc/ffi_darwin.c \ src/powerpc/darwin.S src/powerpc/aix.S \ src/powerpc/darwin_closure.S src/powerpc/aix_closures.S \ - src/arm/ffi.c src/arm/sysv.S + src/arm/ffi.c src/arm/sysv.S \ + src/s390/ffi.c src/s390/sysv.S \ + src/s390/ffi64.c src/s390/unix64.S VPATH = @srcdir@:@srcdir@/src:@srcdir@/src/@TARGETDIR@ @@ -94,6 +96,8 @@ TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closures.S TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c +TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c +TARGET_SRC_S390X = $(TARGET_SRC_S390) src/s390/unix64.S src/s390/ffi64.c ##libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c $(TARGET_SRC_@TARGET@) ## Work around automake deficiency @@ -147,6 +151,14 @@ libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) libffi_convenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) endif +if S390 +libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390) +libfficonvenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390) +endif +if S390X +libffi_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390X) +libfficonvenience_la_SOURCES = $(libffi_la_common_SOURCES) $(TARGET_SRC_S390X) +endif AM_CFLAGS = -fexceptions --- ./libffi/Makefile.in.orig 2003-01-28 17:59:05.000000000 -0500 +++ ./libffi/Makefile.in 2003-05-07 23:12:28.000000000 -0400 @@ -173,6 +173,8 @@ TARGET_SRC_POWERPC_AIX = src/powerpc/ffi_darwin.c src/powerpc/aix.S src/powerpc/aix_closures.S TARGET_SRC_POWERPC_DARWIN = src/powerpc/ffi_darwin.c src/powerpc/darwin.S src/powerpc/darwin_closure.S TARGET_SRC_ARM = src/arm/sysv.S src/arm/ffi.c +TARGET_SRC_S390 = src/s390/sysv.S src/s390/ffi.c +TARGET_SRC_S390X = $(TARGET_SRC_S390) src/s390/unix64.S src/s390/ffi64.c libffi_la_common_SOURCES = src/debug.c src/prep_cif.c src/types.c \ src/raw_api.c src/java_raw_api.c @@ -189,6 +191,8 @@ @POWERPC_AIX_TRUE@libffi_la_SOURCES = @POWERPC_AIX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_AIX) @POWERPC_DARWIN_TRUE@libffi_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN) @ARM_TRUE@libffi_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) +@S390_TRUE@libffi_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390) +@S390X_TRUE@libffi_la_SOURCES = @S390X_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390X) @MIPS_GCC_TRUE@libffi_convenience_la_SOURCES = @MIPS_GCC_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_GCC) @MIPS_SGI_TRUE@libffi_convenience_la_SOURCES = @MIPS_SGI_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_MIPS_SGI) @X86_TRUE@libffi_convenience_la_SOURCES = @X86_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_X86) @@ -201,6 +205,8 @@ @POWERPC_AIX_TRUE@libffi_convenience_la_SOURCES = @POWERPC_AIX_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_AIX) @POWERPC_DARWIN_TRUE@libffi_convenience_la_SOURCES = @POWERPC_DARWIN_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_POWERPC_DARWIN) @ARM_TRUE@libffi_convenience_la_SOURCES = @ARM_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_ARM) +@S390_TRUE@libffi_convenience_la_SOURCES = @S390_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390) +@S390X_TRUE@libffi_convenience_la_SOURCES = @S390X_TRUE@$(libffi_la_common_SOURCES) $(TARGET_SRC_S390X) AM_CFLAGS = -fexceptions @@ -254,6 +260,13 @@ @ARM_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \ @ARM_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ @ARM_TRUE@src/arm/sysv.lo src/arm/ffi.lo +@S390_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \ +@S390_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ +@S390_TRUE@src/s390/sysv.lo src/s390/ffi.lo +@S390X_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo src/prep_cif.lo \ +@S390X_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ +@S390X_TRUE@src/s390/sysv.lo src/s390/ffi.lo \ +@S390X_TRUE@src/s390/unix64.lo src/s390/ffi64.lo @POWERPC_DARWIN_TRUE@libffi_convenience_la_OBJECTS = src/debug.lo \ @POWERPC_DARWIN_TRUE@src/prep_cif.lo src/types.lo src/raw_api.lo \ @POWERPC_DARWIN_TRUE@src/java_raw_api.lo src/powerpc/ffi_darwin.lo \ @@ -296,6 +309,13 @@ @ARM_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ @ARM_TRUE@src/raw_api.lo src/java_raw_api.lo src/arm/sysv.lo \ @ARM_TRUE@src/arm/ffi.lo +@S390_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ +@S390_TRUE@src/raw_api.lo src/java_raw_api.lo src/s390/sysv.lo \ +@S390_TRUE@src/s390/ffi.lo +@S390X_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ +@S390X_TRUE@src/raw_api.lo src/java_raw_api.lo src/s390/unix64.lo \ +@S390X_TRUE@src/s390/ffi64.lo \ +@S390X_TRUE@src/s390/sysv.lo src/s390/ffi.lo @POWERPC_DARWIN_TRUE@libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo \ @POWERPC_DARWIN_TRUE@src/types.lo src/raw_api.lo src/java_raw_api.lo \ @POWERPC_DARWIN_TRUE@src/powerpc/ffi_darwin.lo src/powerpc/darwin.lo \