aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/s390/ffi.c
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/s390/ffi.c')
-rw-r--r--libffi/src/s390/ffi.c589
1 files changed, 0 insertions, 589 deletions
diff --git a/libffi/src/s390/ffi.c b/libffi/src/s390/ffi.c
deleted file mode 100644
index 8b514e36c26..00000000000
--- a/libffi/src/s390/ffi.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/* -----------------------------------------------------------------------
- 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 ============================*/