From d8da1e284e5f11d2ceb6b3f346ac90e2f2ed2d84 Mon Sep 17 00:00:00 2001 From: Austin Wells Date: Wed, 8 May 2024 11:43:15 -0400 Subject: [PATCH] Update struct support in embedded libffi Adds support for passing struct type arguments and receiving struct type returns in libffi - Struct arguments are now properly loaded into registers and the argument area in sys64z.s - Struct returns are now appropriately handled in sys64z.s - Doesn't pad argument buffer in ffi_prep_args to save space. Signed-off-by: Austin Wells --- runtime/libffi/z/ffi64.c | 225 +++++++------ runtime/libffi/z/sysvz64.s | 638 +++++++++++++++++++++++++++++++------ 2 files changed, 654 insertions(+), 209 deletions(-) diff --git a/runtime/libffi/z/ffi64.c b/runtime/libffi/z/ffi64.c index 139946ce7bd..c76ef5b24ed 100644 --- a/runtime/libffi/z/ffi64.c +++ b/runtime/libffi/z/ffi64.c @@ -2,9 +2,9 @@ ffi64.c - Copyright (c) 2000, 2007 Software AG Copyright (c) 2008 Red Hat, Inc Copyright IBM Corp. 2016 - + 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 @@ -12,10 +12,10 @@ 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. @@ -28,24 +28,24 @@ /* Includes */ /* -------- */ /*====================================================================*/ - + #include #include - + #include #include - + /*====================== End of Includes =============================*/ - + /*====================================================================*/ /* Defines */ /* ------- */ /*====================================================================*/ -/* Maximum number of GPRs available for argument passing. */ +/* Maximum number of GPRs available for argument passing. */ #define MAX_GPRARGS 3 -/* Maximum number of FPRs available for argument passing. */ +/* Maximum number of FPRs available for argument passing. */ #define MAX_FPRARGS 4 /* Round to multiple of 16. */ @@ -100,28 +100,28 @@ typedef struct ffi_cel4ro31_control_block { } ffi_cel4ro31_control_block; /*===================== End of Defines ===============================*/ - + /*====================================================================*/ /* Prototypes */ /* ---------- */ /*====================================================================*/ - + /*Making it extern to call this from sysvz.S*/ #pragma map(ffi_prep_args, "PREPARGS") void ffi_prep_args (unsigned char *, extended_cif *); -void ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, +void ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, unsigned long long *, unsigned long *); /*====================== End of Prototypes ===========================*/ - + /*====================================================================*/ /* Externals */ /* --------- */ /*====================================================================*/ - + #pragma map(ffi_call_SYSV, "FFISYS") -extern void ffi_call_SYSV(void (*fn)(void), extended_cif *, +extern void ffi_call_SYSV(void (*fn)(void), extended_cif *, unsigned, unsigned *, unsigned, unsigned, unsigned); extern void ffi_closure_SYSV(void); @@ -145,7 +145,7 @@ typedef void celqgipb_cwi_func(uint32_t*, ffi_cel4ro31_control_block**, uint32_t #define FFI390_CEL4RO31_CEEPCB_3164_MASK 0x4 /*====================== End of Externals ============================*/ - + /*====================================================================*/ /* */ /* Name - ffi_check_struct_type. */ @@ -154,7 +154,7 @@ typedef void celqgipb_cwi_func(uint32_t*, ffi_cel4ro31_control_block**, uint32_t /* general purpose or floating point register. */ /* */ /*====================================================================*/ - + static int ffi_check_struct_type (ffi_type *arg) { @@ -162,7 +162,7 @@ ffi_check_struct_type (ffi_type *arg) /* If the struct has just one element, look at that element to find out whether to consider the struct as floating point. */ - while (arg->type == FFI_TYPE_STRUCT + while (arg->type == FFI_TYPE_STRUCT && arg->elements[0] && !arg->elements[1]) arg = arg->elements[0]; @@ -172,17 +172,17 @@ ffi_check_struct_type (ffi_type *arg) { case 1: case 2: - return FFI_TYPE_UINT32; + return FFI_TYPE_UINT32; case 4: if (arg->type == FFI_TYPE_FLOAT) return FFI_TYPE_FLOAT; else - return FFI_TYPE_UINT32; + return FFI_TYPE_UINT32; case 8: if (arg->type == FFI_TYPE_DOUBLE) return FFI_TYPE_DOUBLE; else - return FFI_TYPE_UINT64; + return FFI_TYPE_UINT64; default: break; } @@ -632,7 +632,7 @@ ffi_call_CEL4RO31(void (*fn)(void), extended_cif *ecif) /* has been allocated for the function's arguments. */ /* */ /*====================================================================*/ - + void ffi_prep_args (unsigned char *stack, extended_cif *ecif) { @@ -641,29 +641,29 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) ------------------------------------ <- Low Addresses Guard Page (4KB) - ------------------------------------ + ------------------------------------ Stack Frame for Called functions ------------------------------------ <- Stack Ptr (r4) Backchain |+2048 ------------------------------------ | Environment | ------------------------------------ | - Entry Point | Savearea + Entry Point | Savearea ------------------------------------ | 48 bytes Return Address | ------------------------------------ | R8 - R15 | ------------------------------------ <- Reserved (8 bytes) +2096 - ------------------------------------ + ------------------------------------ Debug Area (4 bytes) +2104 - ------------------------------------ + ------------------------------------ Arg area prefix (4 bytes) +2108 - ------------------------------------ + ------------------------------------ Argument area: Parm1 ... ParmN +2112 - ------------------------------------ + ------------------------------------ Local (automatic storage) - Saved FPRs Saved ARs Saved VRs + Saved FPRs Saved ARs Saved VRs ------------------------------------ <- High Addresses */ @@ -677,8 +677,8 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) #endif /* If we returning a structure larger than 12bytes, we set the first parameter register - to the address of where we are returning this structure. - */ + to the address of where we are returning this structure. + */ if (ecif->cif->flags == FFI_TYPE_STRUCT && (ecif->cif->rtype->size > 12)){ @@ -686,7 +686,7 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) } /*Now for the arguments. */ - + for (type_ptr = ecif->cif->arg_types, i = ecif->cif->nargs; i > 0; i--, type_ptr++, p_argv++) @@ -695,18 +695,15 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) int type = (*type_ptr)->type; int size = (*type_ptr)->size; - /* Check how a structure type is passed. */ - if (type == FFI_TYPE_STRUCT) { - memcpy(arg_ptr, (char*)p_argv, (*type_ptr)->size); - arg_ptr += (*type_ptr)->size; - continue; - } - /* Now handle all primitive int/pointer/float data types. */ - switch (type) + switch (type) { -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: + case FFI_TYPE_STRUCT: + memcpy(arg_ptr, *p_argv, size); + break; + +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: *(long double *) arg_ptr = * (long double *) (*p_argv); break; #endif @@ -715,15 +712,15 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) case FFI_TYPE_COMPLEX: *(double *) arg_ptr = * (double *) (*p_argv); break; - + case FFI_TYPE_FLOAT: *(float *) arg_ptr = * (float *) (*p_argv); break; case FFI_TYPE_POINTER: - *(void **) arg_ptr = * (void**) (* p_argv); + *(void **) arg_ptr = * (void**) (* p_argv); break; - + case FFI_TYPE_SINT64: *(signed long long *) arg_ptr = * (signed long long *) (* p_argv); break; @@ -731,37 +728,32 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) case FFI_TYPE_UINT64: *(unsigned long long *) arg_ptr = * (unsigned long long *) (* p_argv); break; - + case FFI_TYPE_UINT32: *(unsigned int *) arg_ptr = * (unsigned int *) (*p_argv); break; - + case FFI_TYPE_SINT32: case FFI_TYPE_INT: *(signed int *) arg_ptr = * (signed int *) (*p_argv); break; - + case FFI_TYPE_UINT16: *(unsigned short *) arg_ptr = * (unsigned short *) (* p_argv); - arg_ptr += 2; break; - + case FFI_TYPE_SINT16: *(signed short *) arg_ptr = * (signed short *) (* p_argv); - arg_ptr += 2; break; case FFI_TYPE_UINT8: *(unsigned char *) arg_ptr = * (unsigned char *) (* p_argv); - arg_ptr += 3; break; - + case FFI_TYPE_SINT8: *(signed char *) arg_ptr = * (signed char*) (* p_argv); - - arg_ptr += 3; break; - + default: FFI_ASSERT (0); break; @@ -773,7 +765,7 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) } /*======================== End of Routine ============================*/ - + /*====================================================================*/ /* */ /* Name - ffi_prep_cif_machdep. */ @@ -781,7 +773,7 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) /* Function - Perform machine dependent CIF processing. */ /* */ /*====================================================================*/ - + ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { @@ -800,16 +792,16 @@ ffi_prep_cif_machdep(ffi_cif *cif) /* 64-bit XPLINK handling below */ - /* Determine return value handling. - Integral values <=4bytes are widened and put in GPR3 - Integral values >4bytes and <=8bytes are widened and put in - GPR2 (left most 32-bits) and GPR3 (right most 32-bits) - Floating point values, including complex type, are returned in + /* Determine return value handling. + Integral values <=8bytes are widened and put in GPR3 + Integral values >8bytes and <=16bytes are widened and put in + GPR2 (left most 64-bits) and GPR3 (right most 64-bits) + Floating point values, including complex type, are returned in FPR0, FPR2, FPR4, FPR6 (as many registers as required) - Aggregates size of <=4 are returned GPR1 (left adjusted) - Aggregates size between 5bytes-8bytes are returned in GPR1 and + Aggregates size of <=8 are returned GPR1 (left adjusted) + Aggregates size between 9bytes-16bytes are returned in GPR1 and GPR2 (left adjusted) - Aggregates size between 9bytes-12bytes are returned in GPR1, GPR2, + Aggregates size between 17bytes-24bytes are returned in GPR1, GPR2, and GPR3 (left adjusted) Anything greater in size and anyother type is returned in a buffer, the buffer is passed in as hidden first argument. @@ -825,13 +817,11 @@ ffi_prep_cif_machdep(ffi_cif *cif) /* Structures are returned in GPR or buffer depending on size. */ case FFI_TYPE_STRUCT: struct_size = cif->rtype->size; - if (struct_size <= 8) - cif->flags = FFI390_RET_INT64; - else if (struct_size <= 12) + if (struct_size <= 24) cif->flags = FFI390_RET_STRUCT; else - n_ov = struct_size; - break; + n_gpr++; + break; /* Floating point and complex values are returned in fpr0, 2, 4, 6 */ case FFI_TYPE_FLOAT: @@ -866,14 +856,14 @@ ffi_prep_cif_machdep(ffi_cif *cif) - + default: FFI_ASSERT (0); break; } /* Now for the arguments. */ - + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) @@ -881,7 +871,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) int type = (*ptr)->type; /* Check how a structure type is passed. */ - if (type == FFI_TYPE_STRUCT) + if (type == FFI_TYPE_STRUCT) { type = ffi_check_struct_type (*ptr); @@ -892,18 +882,18 @@ ffi_prep_cif_machdep(ffi_cif *cif) } /* Now handle all primitive int/float data types. */ - switch (type) + switch (type) { /* The first MAX_FPRARGS floating point arguments - go in FPRs, the rest overflow to the stack. */ - + go in FPRs, the rest overflow to the stack. */ + case FFI_TYPE_LONGDOUBLE: if (n_fpr < MAX_FPRARGS) n_fpr+=2; else n_ov += sizeof(long double) / sizeof(long); - break; - + break; + case FFI_TYPE_COMPLEX: case FFI_TYPE_DOUBLE: case FFI_TYPE_FLOAT: @@ -911,13 +901,13 @@ ffi_prep_cif_machdep(ffi_cif *cif) n_fpr++; else n_ov += sizeof (double) / sizeof (long); - break; - + break; + /* On 31-bit machines, 64-bit integers are passed in GPR pairs, if one is still available, or else on the stack. If only one - register is free, skip the register (it won't be used for any - subsequent argument either). */ - + register is free, skip the register (it won't be used for any + subsequent argument either). */ + case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: if (n_gpr == MAX_GPRARGS-1) @@ -926,12 +916,12 @@ ffi_prep_cif_machdep(ffi_cif *cif) n_gpr += 2; else n_ov += 2; - break; - + break; + /* Everything else is passed in GPRs (until MAX_GPRARGS - have been used) or overflows to the stack. */ - - default: + have been used) or overflows to the stack. */ + + default: if (n_gpr < MAX_GPRARGS) n_gpr++; else @@ -947,12 +937,12 @@ ffi_prep_cif_machdep(ffi_cif *cif) cif->bytes = ROUND_SIZE ((n_ov * sizeof (long)) + (n_fpr * sizeof (long long)) + (n_gpr * sizeof (long)) ) + struct_size; /* printf("prep_cif_machdep_cif_bytes: %d n_gpr=%d n_ov=%d n_fpr=%d\n",cif->bytes,n_gpr,n_ov,n_fpr); */ - + return FFI_OK; } - + /*======================== End of Routine ============================*/ - + /*====================================================================*/ /* */ /* Name - ffi_call. */ @@ -960,7 +950,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) /* Function - Call the FFI routine. */ /* */ /*====================================================================*/ - + void ffi_call(ffi_cif *cif, void (*fn)(void), @@ -969,7 +959,7 @@ ffi_call(ffi_cif *cif, { int ret_type = cif->flags; extended_cif ecif; - + ecif.cif = cif; ecif.avalue = avalue; ecif.rvalue = rvalue; @@ -980,14 +970,17 @@ ffi_call(ffi_cif *cif, /* if (ret_type == FFI_TYPE_STRUCT) ecif.rvalue = alloca (cif->rtype->size); else - */ + */ ret_type = FFI_TYPE_VOID; - } + } switch (cif->abi) { case FFI_SYSV: - ffi_call_SYSV(fn, &ecif, cif->flags, ecif.rvalue, cif->bytes, cif->nargs, (*cif->arg_types)->size); + if (cif->arg_types != NULL) + ffi_call_SYSV(fn, &ecif, cif->flags, ecif.rvalue, cif->bytes, cif->nargs, (*cif->arg_types)->size); + else + ffi_call_SYSV(fn, &ecif, cif->flags, ecif.rvalue, cif->bytes, cif->nargs, 0); #ifdef FFI_DEBUG printf("called_ffi_call_sysv nargs=%d\n",cif->nargs); #endif @@ -1000,7 +993,7 @@ ffi_call(ffi_cif *cif, break; } } - + /*======================== End of Routine ============================*/ /*====================================================================*/ @@ -1010,7 +1003,7 @@ ffi_call(ffi_cif *cif, /* Function - Call a FFI closure target function. */ /* */ /*====================================================================*/ - + void ffi_closure_helper_SYSV (ffi_closure *closure, unsigned long *p_gpr, @@ -1034,8 +1027,8 @@ ffi_closure_helper_SYSV (ffi_closure *closure, p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *)); - /* If we returning a structure, pass the structure address - directly to the target function. Otherwise, have the target + /* If we returning a structure, pass the structure address + directly to the target function. Otherwise, have the target function store the return value to the GPR save area. */ if (closure->cif->flags == FFI_TYPE_STRUCT) @@ -1064,7 +1057,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, else type = ffi_check_struct_type (*ptr); - /* If we pass the struct via pointer, remember to + /* If we pass the struct via pointer, remember to retrieve the pointer later. */ if (type == FFI_TYPE_POINTER) deref_struct_pointer = 1; @@ -1079,23 +1072,23 @@ ffi_closure_helper_SYSV (ffi_closure *closure, #endif /* Now handle all primitive int/float data types. */ - switch (type) + switch (type) { case FFI_TYPE_DOUBLE: if (n_fpr < MAX_FPRARGS) *p_arg = &p_fpr[n_fpr++]; else - *p_arg = &p_ov[n_ov], + *p_arg = &p_ov[n_ov], n_ov += sizeof (double) / sizeof (long); break; - + case FFI_TYPE_FLOAT: if (n_fpr < MAX_FPRARGS) *p_arg = &p_fpr[n_fpr++]; else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; break; - + case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: #ifdef __s390x__ @@ -1112,7 +1105,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, *p_arg = &p_ov[n_ov], n_ov += 2; #endif break; - + case FFI_TYPE_INT: case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: @@ -1121,7 +1114,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; break; - + case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: if (n_gpr < MAX_GPRARGS) @@ -1137,7 +1130,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1; break; - + default: FFI_ASSERT (0); break; @@ -1205,7 +1198,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, break; } } - + /*======================== End of Routine ============================*/ /*====================================================================*/ @@ -1215,7 +1208,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, /* Function - Prepare a FFI closure. */ /* */ /*====================================================================*/ - + ffi_status ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, @@ -1241,14 +1234,14 @@ ffi_prep_closure_loc (ffi_closure *closure, *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */ *(long *)&closure->tramp[16] = (long)codeloc; *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV; -#endif - +#endif + closure->cif = cif; closure->user_data = user_data; closure->fun = fun; - + return FFI_OK; } /*======================== End of Routine ============================*/ - + diff --git a/runtime/libffi/z/sysvz64.s b/runtime/libffi/z/sysvz64.s index 20b70457b09..e540ca320c1 100644 --- a/runtime/libffi/z/sysvz64.s +++ b/runtime/libffi/z/sysvz64.s @@ -13,6 +13,12 @@ FFISYS CELQPRLG DSASIZE=DSASZ,PSECT=ASP *@2136(,4) <- cif->arg_types->size (+52)? USING CEEDSAHP,4 + +*Store argument registers on the stack + STG 1,(2176+(((DSASZ+31)/32)*32))(,4) + STG 2,(2176+(((DSASZ+31)/32)*32)+8)(,4) + STG 3,(2176+(((DSASZ+31)/32)*32)+16)(,4) + LG 14,0(,2) ecif->cif LG 14,8(,14) cif->arg_types *What: Storing arguments in this routine's @@ -21,10 +27,10 @@ FFISYS CELQPRLG DSASIZE=DSASZ,PSECT=ASP *Input: stack, extended_cif *Output: void *Action: Is an external call to C-XPLINK routine -* It saves function's arguments in this +* It saves function's arguments in this * routine's local storage - LA 1,LSTOR - LGR 13,1 + LA 1,LSTOR + LGR 13,1 CELQCALL PREPARGS,WORKREG=10 LGR 5,14 Copy of parameter types @@ -40,19 +46,43 @@ FFISYS CELQPRLG DSASIZE=DSASZ,PSECT=ASP * SR 6,6 Offset in stored parm values LA 6,0 +*bytes, we need to allocate space for the dummy argument +*that holds the return value pointer + LG 15,(2176+(((DSASZ+31)/32)*32)+8)(,4) + LG 15,0(,15) ecif->cif + LG 15,16(,15) cif->rtype + LG 15,0(,15) rtype->size + CGIJNH 15,24,GETNARGS size>24, means we need to use gpr1 + + LG 1,(2176+(((DSASZ+31)/32)*32)+24)(,4) + AHI 0,1 One less gpr to work with + AHI 7,8 reserve space in arg area + +GETNARGS DS 0H *Get the cif->nargs from caller's stack - L 9,(2176+(((DSASZ+31)/32)*32)+44)(,4) + L 9,(2176+(((DSASZ+31)/32)*32)+44)(,4) + CIJE 9,0,CALL *Place arguments passed to the foreign function based on type ARGLOOP LG 11,0(10,5) Get pointer to current ffi_type LLGC 11,11(11) ffi_type->type SLL 11,2 Find offset in branch tabel - LA 15,ATABLE - L 15,0(11,15) + LA 15,ATABLE + L 15,0(11,15) + AFI 7,7 args in arg area need to be + N 7,=X'FFFFFFF8' 8-byte aligned so we round BR 15 - + *Following code prepares ffi arguments, according to xplink +* technically, this isn't allowed +* but openJ9 uses ffi_type_void for void functions +* so we support it since it doesn't break anything +* assuming we don't have something weird like a void type +* followed by real parameters +VOID DS 0H ffi_type_void + B CALL + I DS 0H ffi_type_int UI32 DS 0H ffi_type_uint32 LA 15,I32 @@ -71,24 +101,28 @@ J DS 0H IGPR1 DS 0H INT/UI32 type passed in gpr1 L 1,0(6,13) AHI 7,8 Advance to next word in arg area + AHI 6,4 Advance to next word in parm value B CONT Next parameter IGPR2 DS 0H INT/UI32 type passed in gpr2 L 2,0(6,13) AHI 7,8 Advance to next word in arg area + AHI 6,4 Advance to next word in parm value B CONT Next parameter IGPR3 DS 0H INT/UI32 type passed in gpr3 L 3,0(6,13) AHI 7,8 Advance to next word in arg area + AHI 6,4 Advance to next word in parm value B CONT Next parameter IARGA DS 0H INT/UI32 stored in arg area L 11,0(6,13) Argument value LA 15,2176(,4) Start of arg area STG 11,0(7,15) Store in next word in arg area AHI 7,8 Bump to the next word in arg area + AHI 6,4 Advance to next word in parm value B CONT Next parameter UI8 DS 0H ffi_type_uint8 -SI8 DS 0H ffi_type_sint8 +SI8 DS 0H ffi_type_sint8 LA 15,I8 LR 11,0 SLL 11,2 Pass this parm in gpr or arg area @@ -100,25 +134,29 @@ SI8 DS 0H ffi_type_sint8 INC2 DS 0H AHI 0,1 Now we have one less gpr left J2 DS 0H - BR 15 + BR 15 I8GPR1 DS 0H Char type passed in gpr1 LLC 1,0(6,13) AHI 7,8 Advance to next word in arg area + AHI 6,1 Advance the first byte of parm value B CONT Next parameter I8GPR2 DS 0H Char type passed in gpr2 LLC 2,0(6,13) AHI 7,8 Advance to next word in arg area + AHI 6,1 Advance the first byte of parm value B CONT Next parameter I8GPR3 DS 0H Char type passed in gpr3 - LLC 3,0(6,13) + LLC 3,0(6,13) AHI 7,8 Advance to the next word in arg area + AHI 6,1 Advance the first byte of parm value B CONT I8ARGA DS 0H Char stored in arg area LLC 11,0(6,13) Argument value LA 15,2176(,4) Start of arg area STG 11,0(7,15) Store in next word in arg area AHI 7,8 Bump to the next word in arg area + AHI 6,1 Advance the first byte of parm value B CONT Next parameter UI16 DS 0H ffi_type_uint16 @@ -133,58 +171,66 @@ UI16 DS 0H ffi_type_uint16 INC3 DS 0H AHI 0,1 Now we have one less gpr left J3 DS 0H - BR 15 + BR 15 U16GPR1 DS 0H u_short type passed in gpr1 LLH 1,0(6,13) AHI 7,8 Advance to the next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter U16GPR2 DS 0H u_short type passed in gpr2 LLH 2,0(6,13) AHI 7,8 Advance to the next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter U16GPR3 DS 0H u_short passed in gpr3 LLH 3,0(6,13) AHI 7,8 Advance to the next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter U16ARGA DS 0H u_short in arg area LLH 11,0(6,13) Argument value LA 15,2176(,4) Start of arg area STG 11,0(7,15) Store in next word in arg area AHI 7,8 Bump to the next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter SI16 DS 0H ffi_type_sint16 LA 15,S16 LR 11,0 SLL 11,2 Pass this parm in gpr or arg area - L 15,0(11,15) + L 15,0(11,15) CFI 0,3 GPRs left to pass parms in? BL INC4 LA 0,3 Reached max gprs - B J4 + B J4 INC4 DS 0H AHI 0,1 Now we have one less gpr left J4 DS 0H - BR 15 + BR 15 S16GPR1 DS 0H s_SHORT type passsed in gpr1 - LH 1,0(6,13) + LH 1,0(6,13) AHI 7,8 Advance to the next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter S16GPR2 DS 0H s_SHORT type passed in gpr2 LH 2,0(6,13) AHI 7,8 Advance to the next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter S16GPR3 DS 0H s_SHORT type passed in gpr3 LH 3,0(6,13) AHI 7,8 Advance to next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter S16ARGA DS 0H s_SHORT in arg area LH 11,0(6,13) Argument value LA 15,2176(,4) Start of arg area STG 11,0(7,15) Store in next word in arg area AHI 7,8 Bump to the next word in arg area + AHI 6,2 Advance the first 2 bytes of parm value B CONT Next parameter SI64 DS 0H ffi_type_sint64 @@ -199,36 +245,36 @@ SI64 DS 0H ffi_type_sint64 INC5 DS 0H AHI 0,1 Now we have two less gpr left J5 DS 0H - BR 15 + BR 15 S64GPR1 DS 0H INT64 type passed in gpr1 LG 1,0(6,13) AHI 7,8 Advance next two words in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter S64GPR2 DS 0H INT64 type passed in gpr2,gpr3 LG 2,0(6,13) AHI 7,8 Advance next two words in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter S64GPR3 DS 0H INT64 type passed in gpr2 LG 3,0(6,13) AHI 7,8 Advance next two words in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter S64ARGA DS 0H INT64 in arg area LG 11,0(6,13) Argument value LA 15,2176(,4) Start of arg area STG 11,0(7,15) Store in next word in arg area AHI 7,8 Bump one word in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter PTR DS 0H ffi_type_pointer LA 15,PTRS LR 11,0 SLL 11,2 Pass this parm in gpr or arg area - L 15,0(11,15) + L 15,0(11,15) CFI 0,3 GPRs left to pass parms in? BL INC6 LA 0,3 Reached max gprs @@ -236,29 +282,29 @@ PTR DS 0H ffi_type_pointer INC6 DS 0H AHI 0,1 Now we have one less gpr left J6 DS 0H - BR 15 + BR 15 PTRG1 DS 0H PTR type passed in gpr1 LG 1,0(6,13) AHI 7,8 Advance to the next word in arg area - AHI 6,4 + AHI 6,8 B CONT Next parameter PTRG2 DS 0H PTR type passed in gpr2 LG 2,0(6,13) AHI 7,8 Advance to the next word in arg area - AHI 6,4 + AHI 6,8 B CONT Next parameter PTRG3 DS 0H PTR type passed in gpr3 LG 3,0(6,13) AHI 7,8 Advance to the next word in arg area - AHI 6,4 + AHI 6,8 B CONT Next parameter PTRARG DS 0H PTR in arg area LG 11,0(6,13) Argument value LA 15,2176(,4) Start of arg area - STG 11,0(7,15) Store in next word in arg area + STG 11,0(7,15) Store in next word in arg area AHI 7,8 Bump to the next word in arg area - AHI 6,4 + AHI 6,8 B CONT Next parameter UI64 DS 0H ffi_type_uint64 @@ -276,34 +322,34 @@ J64 DS 0H BR 15 U64GP1 DS 0H u_INT64 passed in gpr1, gpr2 - LG 1,0(6,13) + LG 1,0(6,13) AHI 7,8 Advance two slots in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter U64GP2 DS 0H u_INT64 passed in gpr2, gpr3 - LG 2,0(6,13) + LG 2,0(6,13) AHI 7,8 Advance two slots in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter U64GP3 DS 0H u_INT64 passed in gpr2 LG 3,0(6,13) AHI 7,8 Advance next word in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter U64ARGA DS 0H u_INT64 in arg area LG 11,0(6,13) Argument value LA 15,2176(,4) Start of arg area STG 11,0(7,15) Store in next two words in arg area AHI 7,8 Bump one word in arg area - AHI 6,4 Advance the first 4 bytes of parm value + AHI 6,8 Advance the first 8 bytes of parm value B CONT Next parameter - + FLT DS 0H ffi_type_float LA 15,FLTS LR 11,14 SLL 11,2 Pass in fpr or arg area L 15,0(11,15) - CFI 14,4 FPRs left to pass parms in? + CFI 14,4 FPRs left to pass parms in? BL INC7L LA 14,4 Reached max fprs B JL7 @@ -340,6 +386,7 @@ FLTSTR DS 0H LA 15,2176(,4) Start of arg area STE 11,0(7,15) Store in next word in arg area AHI 7,8 Bump to the next word in arg area + AHI 6,4 Advance the first 4 bytes of parm value B CONT Next parameter D DS 0H ffi_type_double @@ -358,9 +405,9 @@ INC7 DS 0H LA 0,3 B J7 INCGD DS 0H - AHI 0,2 + AHI 0,1 J7 DS 0H - BR 15 + BR 15 FLDR0 DS 0H DOUBLE passed in fpr0 LD 0,0(6,13) @@ -384,7 +431,7 @@ DBLSTR DS 0H LA 15,2176(,4) Start of arg area STD 11,0(7,15) Store in next two words in arg area AHI 7,8 Bump to the next two words in arg area - AHI 6,4 Bump stack twice, cuz double is 8byte + AHI 6,8 Bump stack twice, cuz double is 8byte B CONT Next parameter LD DS 0H ffi_type_longdouble @@ -397,7 +444,7 @@ LD DS 0H ffi_type_longdouble BH 0(11,15) Pass l_DOUBLE in arg area LA 11,4 L 15,0(11,15) Pass l_DOUBLE in fpr4-fpr6 - BR 15 + BR 15 DFPR0 DS 0H l_DOUBLE passed in fpr0-fpr2 LD 0,0(6,13) @@ -407,11 +454,11 @@ DFPR0 DS 0H l_DOUBLE passed in fpr0-fpr2 LD 2,0(6,13) l_DOUBLE passed in fpr0-fpr2 STD 2,8(7,15) Store the second 8bytes in arg area AHI 6,4 Bump stack once here, once at end - AHI 7,16 Advance two slots + AHI 7,16 Advance two slots AHI 14,2 Now we have two less fprs left B CONT Next Parameter DFPR4 DS 0H l_DOUBLE passed in fpr4-fpr6 - LD 4,0(6,13) + LD 4,0(6,13) LA 15,2176(,4) Start of arg area STD 4,0(7,15) Store the first 8bytes in arg area AHI 6,8 Bump stack to next parameter @@ -432,65 +479,351 @@ DARGF DS 0H l_DOUBLE in arg area LA 14,4 We reached max fprs B CONT Next parameter -*If we have spare gprs, pass up to 12bytes -*in GPRs. -*TODO: Store left over struct to argument area -* +*If we have spare gprs, pass up to 24 bytes in GPRs. STRCT DS 0H - L WRKREG,(2176+(((DSASZ+31)/32)*32)+24)(,4) - CFI WRKREG,12 - BL STRCT2 - B CONT -STRCT2 DS 0H - LA 15,STRCTS - LR WRKREG,GPX - SLL WRKREG,2 - L 15,0(WRKREG,15) - BR 15 + LG 11,0(10,5) -BYTE4 DS 0H - L 1,0(6,STKREG) - AHI GPX,1 - B CONT +*check if first element is float or double +STFPCHK DS 0H + LG 15,16(,11) type->elements + LG 15,0(,15) type->elements[0] + LH 15,10(,15) type->elements[0]->type + CFI 15,11 is it a float? + BE STFPCHKF + CFI 15,1 is it a double? + BE STFPCHKD + B STRCT2 -BYTE8 DS 0H - L 1,0(6,STKREG) - L 2,4(6,STKREG) - AHI GPX,2 - AHI 6,4 - B CONT +*first arg is a float +STFPCHKF DS 0H + LG 15,16(,11) type->elements + LA 15,8(,15) type->elements[0] + LG 15,0(,15) + LH 15,10(,15) type->elements[0]->type + CFI 15,11 is it a float? + BE STFPCHKF2 + B STRCT2 + +*first arg is a double +STFPCHKD DS 0H + LG 15,16(,11) type->elements + LA 15,8(,15) type->elements[1] + LG 15,0(,15) + LH 15,10(,15) type->elements[1]->type + CFI 15,1 is it a double? + BE STFPCHKD2 + B STRCT2 + + +*check if there are more elements +*if not we have a special case +*this is to handle complex types +*in languages that don't support +*complex types natively +*in this case we pass the struct +*in the first 2 free FPRs, just check this +*against r14 the free FPR counter +STFPCHKF2 DS 0H + LG 15,16(,11) type->elements + LA 15,16(,15) type->elements[0] + LG 15,0(,15) + CFI 15,0 + BNE STRCT2 if no, not special case + + LG 11,0(10,5) + LG 15,0(,11) type->size + + CFI 14,4 no FPRs are available + BNL STRCT2 if yes, not special case + + CFI 14,3 1 FPR is available + BNL STFPCHKF26 use fpr6 + memory + + CFI 14,2 2 FPRs available + BE STFPCHKF246 use fpr4 + fpr6 + + CFI 14,1 3 FPRs available + BE STFPCHKF224 use fpr2 + fpr4 + + CFI 14,0 4 FPRs available + BE STFPCHKF202 use fpr0 + fpr2 + + +STFPCHKF26 DS 0H + LE 6,0(6,13) first float will go in fpr + AFI 0,1 one less GPR available + AFI 14,1 one less FPR available + + AFI 6,4 bump local store 4 bytes + AFI 15,-4 we've handled 4 bytes + AFI 7,4 advance 4 bytes into argarea + + B STRCTLP copy rest of struct + + +STFPCHKF202 DS 0H + LE 0,0(6,13) first float + LE 2,4(6,13) second float + AFI 0,2 one less GPR available + AFI 14,2 two less FPRs available + + AFI 6,8 bump arg area by 8 bytes + AFI 15,-8 we've handled 8 bytes (all the struct) + AFI 7,8 bump local storage by 8 bytes + + B STRCTLP + +STFPCHKF224 DS 0H + LE 2,0(6,13) first float + LE 4,4(6,13) second float + AFI 0,2 one less GPR available + AFI 14,2 two less FPRs available + + AFI 6,8 bump arg area by 8 bytes + AFI 15,-8 we've handled 8 bytes (all the struct) + AFI 7,8 bump local storage by 8 bytes + + B STRCTLP + + +STFPCHKF246 DS 0H + LE 4,0(6,13) first float + LE 6,4(6,13) second float + AFI 0,2 one less GPR available + AFI 14,2 two less FPRs available + + AFI 6,8 bump arg area by 8 bytes + AFI 15,-8 we've handled 8 bytes (all the struct) + AFI 7,8 bump local storage by 8 bytes + + B STRCTLP + + + +*same as the float case (STFPCHKF2) above but for doubles +STFPCHKD2 DS 0H + LG 15,16(,11) type->elements + LA 15,16(,15) type->elements + 1 + LG 15,0(,15) *(type->elements + 1) + CFI 15,0 is NULL? + BNE STRCT2 if no, not special case + + LG 11,0(10,5) ensure we have size + LG 15,0(,11) ready for labels we branch to + + CFI 14,4 no FPRs are available + BNL STRCT2 if yes, not special case + + CFI 14,3 1 FPR is available + BNL STFPCHKD26 use fpr6+memory + + CFI 14,2 2 FPRs are available + BE STFPCHKD246 use fpr4+fpr6 + + CFI 14,1 3 FPRs are available + BE STFPCHKD224 use fpr2+fpr4 + + CFI 14,0 4 FPRs are available + BE STFPCHKD202 use fpr0+fpr2 + + +STFPCHKD26 DS 0H + LD 6,0(6,13) first double + AFI 0,1 one less GPR available + AFI 14,1 one less FPRs available + + AFI 6,8 + AFI 15,-8 + AFI 7,8 + + B STRCTLP + +STFPCHKD202 DS 0H + LD 0,0(6,13) first double + LD 2,8(6,13) second double + AFI 0,2 one less GPR available + AFI 14,2 two less FPRs available + + AFI 6,16 + AFI 15,-16 + AFI 7,16 + + B STRCTLP + +STFPCHKD224 DS 0H + LD 2,0(6,13) first double + LD 4,8(6,13) second double + AFI 0,2 one less GPR available + AFI 14,2 two less FPRs available + + AFI 6,16 + AFI 15,-16 + AFI 7,16 + + B STRCTLP + + +STFPCHKD246 DS 0H + LD 4,0(6,13) first double + LD 6,8(6,13) second double + AFI 0,2 one less GPR available + AFI 14,2 two less FPRs available + + AFI 6,16 + AFI 15,-16 + AFI 7,16 + + B STRCTLP + + +*determine how to pass the struct based on size +*at this point we've weeded out all the float/double +*pair structs that get passed purely in FPRs +STRCT2 DS 0H + LG 15,0(,11) type->size + CFI 15,8 Struct <= 8 bytes? + BNH BYTE8 + CFI 15,16 Struct <= 16 bytes? + BNH BYTE16 + CFI 15,24 Struct <= 24 bytes? + B BYTE24 + +BYTE8 DS 0H Struct <= 8 bytes + +*Since a struct here can be <8 bytes +*we need to pad it to 8 bytes in the arg area +*since saves in the arg area always assume 8 bytes for register +*so even on a for example 1 byte struct, the arg area has 8 bytes +*this is true for all cases where +*max struct size < register storage used +*so <8 byte sturcts regardless of register storage used, will be padded +*similarly with <16 byte structs using 2 registers, +*and <24 byte structs +*using all 3 registers +*I assume this is because the first 24 bytes of the arg area are +*technically the save area for the first 3 registers +BYTE8R1 DS 0H Struct goes in R1 + CFI 0,1 is R1 available? + BNL BYTE8R2 + + LG 1,0(6,13) + + LA 0,1 + B STRCTLP + +BYTE8R2 DS 0H Struct goes in R2 + CFI 0,2 is R2 available? + BH BYTE8R3 + + LG 2,0(6,13) + + LA 0,2 + B STRCTLP + + +BYTE8R3 DS 0H Struct goes in R3 + CFI 0,3 is R3 available? + BNL STRCTLP + + LG 3,0(6,13) + + LA 0,3 + B STRCTLP + +BYTE16 DS 0H Struct <= 16 bytes + +BYTE16R1 DS 0H Struct goes in R1-R2 + CFI 0,1 are R1+R2 available? + BNL BYTE16R2 + + LG 1,0(6,13) + LG 2,8(6,13) + + LA 0,2 + B STRCTLP + + +BYTE16R2 DS 0H Struct goes in R2-R3 + CFI 0,2 are R2+R3 available? + BNL BYTE16R3 + + LG 2,0(6,13) + LG 3,8(6,13) + + LA 0,3 + B STRCTLP + + +BYTE16R3 DS 0H Struct goes in R3+Memory + CFI 0,3 are R3 available? + BNL STRCTLP + LG 3,0(6,13) + + LA 0,3 + B STRCTLP + +BYTE24 DS 0H Struct <= 24 bytes + + +BYTE24R1 DS 0H Struct goes in R1-R3 + CFI 0,1 are R1+R2+R3 available? + BNL BYTE24R2 + LG 1,0(6,13) + LG 2,8(6,13) + LG 3,16(6,13) + + LA 0,3 + B STRCTLP + +BYTE24R2 DS 0H Struct goes in R2,R3 and Memory + CFI 0,2 are R2+R3 available? + BNL BYTE24R3 + LG 2,0(6,13) + LG 3,8(6,13) + + LA 0,3 + B STRCTLP + +BYTE24R3 DS 0H Struct goes in R3 and Memory + CFI 0,3 is R3 available? + BNL STRCTLP + LG 3,0(6,13) + + LA 0,3 + B STRCTLP + +STRCTLP DS 0H Rest of struct goes in Memory + CFI 15,0 Size remaining > 0? + BNH CONT + + LB 12,0(6,13) Load the byte of the struct + STC 12,2176(7,4) Store in next byte in arg area + + AFI 6,1 Move to next byte in struct + AFI 7,1 Move to next byte in arg area + AFI 15,-1 Decrement size of struct + B STRCTLP -BYTE12 DS 0H - L 1,0(6,STKREG) - L 2,4(6,STKREG) - L 3,8(6,STKREG) - LA GPX,3 - AHI 6,8 - B CONT CONT DS 0H End of processing curr_param AHI 10,8 Next parameter type - AHI 6,4 Next parameter value stored - BCT 9,ARGLOOP - + BCT 9,ARGLOOP + *Get function address, first argument passed, *and return type, third argument passed from caller's *argument area. - -* SR 11,11 +CALL DS 0H LA 11,0 LG 6,(2176+(((DSASZ+31)/32)*32))(,4) L 11,(2176+(((DSASZ+31)/32)*32)+20)(,4) - -*Call the foreign function using its address given + +*Call the foreign function using its address given *to us from an xplink compiled routine -* L 5,16(,6) -* L 6,20(,6) LMG 5,6,0(6) BASR 7,6 DC X'0700' - + *What: Processing the return value based * on information in cif->flags, 3rd * parameter passed to this routine @@ -527,14 +860,133 @@ RLL DS 0H B RET RV DS 0H + B RET + RS DS 0H + LG 7,(2176+(((DSASZ+31)/32)*32)+24)(,4) + LG 14,(2176+(((DSASZ+31)/32)*32)+8)(,4) + LG 14,0(,14) ecif->cif + LG 9,16(,14) cif->rtype + LG 14,0(,9) rtype->size + CGIBH 14,24,RSP + +* now we need to determine how to return the struct +* the rules for return types are +* integral types <= 8 bytes returned in gpr3 +* floating point type returned in fpr0-fpr6 (left adjusted) +* using as many registers as needed +* ie. 1 for double +* 2 for long double or complex double +* structures containing exactly 2 floating point types are returned +* in fprs 0-6 using as many as needed +* structures of size > 24 bytes +* are returned using a pointer passed in gpr1 +* structures <= 24 bytes are returned in gprs 1-3 (left adjusted) +* size <= 8 bytes are returned in gpr3 +* size <= 16 bytes are returned in gpr2 and gpr3 +* size <= 24 bytes are returned in gpr1, gpr2 and gpr3 + +* currently we have +* r9 = cif->rtype +* r7 = ecif->rvalue +RSREG DS 0H + LG 11,16(,9) rtype->elements + LA 15,0 number of floats seen + LA 0,0 number of doubles seen + LA 6,0 number of elements in struct + +RSLOOP DS 0H + LG 12,0(,11) load the current element, we update +* this register in NEXT so it's technically +* actually rtype->elements + i + CGIJE 12,0,RSFPR if we have NULL, we are done +* this means we have all float types + LA 13,10(,12) address of rtype->elements[i]->type + LLGH 10,0(,13) load the type (halfword) + CFI 10,11 if type == FFI_TYPE_FLOAT + BE NEXTF check next element + CFI 10,1 if type == FFI_TYPE_DOUBLE + BE NEXTD check next element + B RSGPR we have an integral type, use GPRs + +NEXTF DS 0H + LA 11,8(,11) increment the pointer to the next element + LA 15,1 we have seen a float + AFI 6,1 + CGIJE 0,1,RSGPR we have a mix of float/double use GPRs + B RSLOOP loop back to the top + +NEXTD DS 0H + LA 11,8(,11) increment the pointer to the next element + LA 0,1 we have seen a double + AFI 6,1 + CGIJE 15,1,RSGPR we have a mix of float/double use GPRs + B RSLOOP loop back to the top + +* label if we're using FPRs +RSFPR DS 0H + CFI 6,2 + BNE RSGPR + LA 5,0 + LA 15,SSTOR + LG 11,16(,9) + LG 12,0(,11) + CGIJE 12,0,RSCPY + LA 13,10(,12) address of rtype->elements[i]->type + LLGH 10,0(,13) load the type (halfword) + CFI 10,11 if type == FFI_TYPE_FLOAT + BE STOREF1 store the float in the return area + CFI 10,1 if type == FFI_TYPE_DOUBLE + BE STORED1 + +STOREF1 DS 0H + STE 0,0(5,15) + STE 2,4(5,15) + AGFI 5,4 + B RSCPY + +STORED1 DS 0H + STD 0,0(5,15) + STD 2,8(5,15) + AGFI 5,8 + B RSCPY + +* label if we're using GPRs +RSGPR DS 0H +* so to save us from having to figure out +* how many regs to save, we'll just save them all +* into some local storage, then copy the right amount + LA 15,SSTOR + STG 1,0(,15) + STG 2,8(,15) + STG 3,16(,15) + B RSCPY + +* label to copy the struct to the return area +* just move one byte at a time from r15 to r7 +* while r14 is non-zero + +RSCPY DS 0H + CGIJNH 14,0,RET + LB 1,0(,15) + STC 1,0(,7) + LA 15,1(,15) + LA 7,1(,7) + AFI 14,-1 + B RSCPY + +* return struct in pointer passed as dummy first argument +* this should be the same pointer passed to ffi_call +* and should have been set up in prep_args +* only using an explicit label for clarity +RSP DS 0H B RET -RET DS 0H +RET DS 0H CELQEPLG ATABLE DC A(I) Labels for parm types - DC A(D) + DC A(D) DC A(LD) DC A(UI8) DC A(SI8) @@ -542,11 +994,11 @@ ATABLE DC A(I) Labels for parm types DC A(SI16) DC A(UI32) DC A(SI64) - DC A(PTR) + DC A(PTR) DC A(UI64) DC A(FLT) DC A(STRCT) - DC A(0) + DC A(VOID) DC A(I) DC A(D) I32 DC A(IGPR1) Labels for passing INT in gpr @@ -581,7 +1033,7 @@ FLD DC A(FLDR0) Labels to store DOUBLE in fpr LDD DC A(DFPR0) Labels to store l_DOUBLE in fpr DC A(DFPR4) DC A(DARGF) Label to store l_DOUBLE in arg area -UI64S DC A(U64GP1) Labels to store u_INT64 in gpr +UI64S DC A(U64GP1) Labels to store u_INT64 in gpr DC A(U64GP2) DC A(U64GP3) DC A(U64ARGA) Label to store u_INT64 in arg area @@ -590,16 +1042,13 @@ FLTS DC A(FLTR0) Labels to store FLOAT in fpr DC A(FLTR4) DC A(FLTR6) DC A(ARGAFT) Label to store FLOAT in arg area -STRCTS DC A(BYTE4) - DC A(BYTE8) - DC A(BYTE12) RTABLE DC A(RV) DC A(RS) DC A(RF) DC A(RD) DC A(RLD) DC A(RI) - DC A(RLL) + DC A(RLL) RETVOID EQU X'0' RETSTRT EQU X'1' RETFLOT EQU X'2' @@ -609,12 +1058,15 @@ RETINT6 EQU X'5' OFFSET EQU 7 BASEREG EQU 8 GPX EQU 0 -WRKREG EQU 11 -IDXREG EQU 10 +WRKREG EQU 11 +IDXREG EQU 10 STKREG EQU 13 FPX EQU 14 CEEDSAHP CEEDSA SECTYPE=XPLINK ARGSL DS XL800 LSTOR DS XL800 +* storage space for the returns regs maximum 4*8 fpr +SSTOR DS XL32 +SSIZE DS XL8 DSASZ EQU (*-CEEDSAHP_FIXED) END FFISYS