From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12504 invoked by alias); 18 Dec 2014 21:33:50 -0000 Mailing-List: contact libffi-discuss-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libffi-discuss-owner@sourceware.org Received: (qmail 12434 invoked by uid 89); 18 Dec 2014 21:33:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL,BAYES_00,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qc0-f180.google.com Received: from mail-qc0-f180.google.com (HELO mail-qc0-f180.google.com) (209.85.216.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Thu, 18 Dec 2014 21:33:43 +0000 Received: by mail-qc0-f180.google.com with SMTP id i8so1609795qcq.11 for ; Thu, 18 Dec 2014 13:33:41 -0800 (PST) X-Received: by 10.224.24.129 with SMTP id v1mr4249595qab.31.1418938421158; Thu, 18 Dec 2014 13:33:41 -0800 (PST) Received: from pike.twiddle.home.com (187-254-17-144-cable.cybercable.net.mx. [187.254.17.144]) by mx.google.com with ESMTPSA id f11sm1579590qga.42.2014.12.18.13.33.38 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 18 Dec 2014 13:33:39 -0800 (PST) From: Richard Henderson To: libffi-discuss@sourceware.org Cc: Ulrich.Weigand@de.ibm.com, vogt@linux.vnet.ibm.com, krebbel@linux.vnet.ibm.com, Richard Henderson Subject: [PATCH 3/4] s390: Reorganize assembly Date: Thu, 18 Dec 2014 21:33:00 -0000 Message-Id: <1418938403-15836-4-git-send-email-rth@twiddle.net> In-Reply-To: <1418938403-15836-1-git-send-email-rth@twiddle.net> References: <1418938403-15836-1-git-send-email-rth@twiddle.net> X-SW-Source: 2014/txt/msg00269.txt.bz2 From: Richard Henderson Avoid using ffi_prep_args as a callback; do all the work setting up the frame within ffi_call_int directly. Save fewer registers in ffi_closure_SYSV. --- src/s390/ffi.c | 153 +++++++------- src/s390/internal.h | 11 + src/s390/sysv.S | 578 ++++++++++++++++++---------------------------------- 3 files changed, 286 insertions(+), 456 deletions(-) create mode 100644 src/s390/internal.h diff --git a/src/s390/ffi.c b/src/s390/ffi.c index c06b79e..1189f7b 100644 --- a/src/s390/ffi.c +++ b/src/s390/ffi.c @@ -30,9 +30,7 @@ #include #include - -#include -#include +#include "internal.h" /*====================== End of Includes =============================*/ @@ -54,14 +52,6 @@ /* Round to multiple of 16. */ #define ROUND_SIZE(size) (((size) + 15) & ~15) -/* If these values change, sysv.S must be adapted! */ -#define FFI390_RET_VOID 0 -#define FFI390_RET_STRUCT 1 -#define FFI390_RET_FLOAT 2 -#define FFI390_RET_DOUBLE 3 -#define FFI390_RET_INT32 4 -#define FFI390_RET_INT64 5 - /*===================== End of Defines ===============================*/ /*====================================================================*/ @@ -69,12 +59,17 @@ /* --------- */ /*====================================================================*/ -extern void ffi_call_SYSV(unsigned, - extended_cif *, - void (*)(unsigned char *, extended_cif *), - unsigned, - void *, - void (*fn)(void), void *); +struct call_frame +{ + void *back_chain; + void *eos; + unsigned long gpr_args[5]; + unsigned long gpr_save[9]; + unsigned long long fpr_args[4]; +}; + +extern void FFI_HIDDEN ffi_call_SYSV(struct call_frame *, unsigned, void *, + void (*fn)(void), void *); extern void ffi_closure_SYSV(void); extern void ffi_go_closure_SYSV(void); @@ -145,54 +140,29 @@ ffi_check_struct_type (ffi_type *arg) /*====================================================================*/ static void -ffi_prep_args (unsigned char *stack, extended_cif *ecif) +ffi_prep_args (ffi_cif *cif, void *rvalue, void **p_argv, + unsigned long *p_ov, struct call_frame *p_frame) { - /* The stack space will be filled with those areas: - - FPR argument register save area (highest addresses) - GPR argument register save area - temporary struct copies - overflow argument area (lowest addresses) - - We set up the following pointers: - - p_fpr: bottom of the FPR area (growing upwards) - p_gpr: bottom of the GPR area (growing upwards) - p_ov: bottom of the overflow area (growing upwards) - p_struct: top of the struct copy area (growing downwards) - - All areas are kept aligned to twice the word size. */ - - int gpr_off = ecif->cif->bytes; - int fpr_off = gpr_off + ROUND_SIZE (MAX_GPRARGS * sizeof (long)); - - unsigned long long *p_fpr = (unsigned long long *)(stack + fpr_off); - unsigned long *p_gpr = (unsigned long *)(stack + gpr_off); - unsigned char *p_struct = (unsigned char *)p_gpr; - unsigned long *p_ov = (unsigned long *)stack; - + unsigned char *p_struct = (unsigned char *)p_frame; + unsigned long *p_gpr = p_frame->gpr_args; + unsigned long long *p_fpr = p_frame->fpr_args; int n_fpr = 0; int n_gpr = 0; int n_ov = 0; - ffi_type **ptr; - void **p_argv = ecif->avalue; int i; /* If we returning a structure then we set the first parameter register to the address of where we are returning this structure. */ - - if (ecif->cif->flags == FFI390_RET_STRUCT) - p_gpr[n_gpr++] = (unsigned long) ecif->rvalue; + if (cif->flags & FFI390_RET_IN_MEM) + p_gpr[n_gpr++] = (unsigned long) rvalue; /* Now for the arguments. */ - - for (ptr = ecif->cif->arg_types, i = ecif->cif->nargs; - i > 0; - i--, ptr++, p_argv++) + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++, p_argv++) { + ffi_type *ty = *ptr; void *arg = *p_argv; - int type = (*ptr)->type; + int type = ty->type; #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE /* 16-byte long double is passed like a struct. */ @@ -206,13 +176,13 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) if (type == FFI_TYPE_COMPLEX) type = FFI_TYPE_POINTER; else - type = ffi_check_struct_type (*ptr); + type = ffi_check_struct_type (ty); /* If we pass the struct via pointer, copy the data. */ if (type == FFI_TYPE_POINTER) { - p_struct -= ROUND_SIZE ((*ptr)->size); - memcpy (p_struct, (char *)arg, (*ptr)->size); + p_struct -= ROUND_SIZE (ty->size); + memcpy (p_struct, (char *)arg, ty->size); arg = &p_struct; } } @@ -234,7 +204,7 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) case FFI_TYPE_FLOAT: if (n_fpr < MAX_FPRARGS) - p_fpr[n_fpr++] = (long long) *(unsigned int *) arg << 32; + p_fpr[n_fpr++] = (unsigned long long)*(unsigned int *) arg << 32; else p_ov[n_ov++] = *(unsigned int *) arg; break; @@ -325,7 +295,7 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) /* */ /*====================================================================*/ -ffi_status +ffi_status FFI_HIDDEN ffi_prep_cif_machdep(ffi_cif *cif) { size_t struct_size = 0; @@ -498,32 +468,55 @@ ffi_call_int(ffi_cif *cif, void *closure) { int ret_type = cif->flags; - extended_cif ecif; + size_t rsize = 0, bytes = cif->bytes; + unsigned char *stack; + struct call_frame *frame; - ecif.cif = cif; - ecif.avalue = avalue; - ecif.rvalue = rvalue; + FFI_ASSERT (cif->abi == FFI_SYSV); /* If we don't have a return value, we need to fake one. */ if (rvalue == NULL) { - if (ret_type == FFI390_RET_STRUCT) - ecif.rvalue = alloca (cif->rtype->size); + if (ret_type & FFI390_RET_IN_MEM) + rsize = cif->rtype->size; else ret_type = FFI390_RET_VOID; } - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args, - ret_type, ecif.rvalue, fn, closure); - break; + /* The stack space will be filled with those areas: - default: - FFI_ASSERT (0); - break; - } + dummy structure return (highest addresses) + FPR argument register save area + GPR argument register save area + stack frame for ffi_call_SYSV + temporary struct copies + overflow argument area (lowest addresses) + + We set up the following pointers: + + p_fpr: bottom of the FPR area (growing upwards) + p_gpr: bottom of the GPR area (growing upwards) + p_ov: bottom of the overflow area (growing upwards) + p_struct: top of the struct copy area (growing downwards) + + All areas are kept aligned to twice the word size. */ + + stack = alloca (bytes + sizeof(struct call_frame) + rsize); + frame = (struct call_frame *)(stack + bytes); + if (rsize) + rvalue = frame + 1; + + /* Assuming that the current function has the standard call frame, + we can maintain the linked list like so. */ + frame->back_chain = __builtin_dwarf_cfa() - sizeof(struct call_frame); + + /* Pass the outgoing stack frame in the r15 save slot. */ + frame->gpr_save[8] = (unsigned long)(stack - sizeof(struct call_frame)); + + /* Fill in all of the argument stuff. */ + ffi_prep_args (cif, rvalue, avalue, (unsigned long *)stack, frame); + + ffi_call_SYSV (frame, ret_type & FFI360_RET_MASK, rvalue, fn, closure); } void @@ -549,8 +542,7 @@ ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, /* */ /*====================================================================*/ -FFI_HIDDEN -void +void FFI_HIDDEN ffi_closure_helper_SYSV (ffi_cif *cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, @@ -572,18 +564,15 @@ ffi_closure_helper_SYSV (ffi_cif *cif, int i; /* Allocate buffer for argument list pointers. */ - p_arg = avalue = alloca (cif->nargs * sizeof (void *)); /* 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 (cif->flags == FFI390_RET_STRUCT) + if (cif->flags & FFI390_RET_IN_MEM) rvalue = (void *) p_gpr[n_gpr++]; /* Now for the arguments. */ - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, p_arg++, ptr++) { int deref_struct_pointer = 0; @@ -611,11 +600,13 @@ ffi_closure_helper_SYSV (ffi_cif *cif, /* Pointers are passed like UINTs of the same size. */ if (type == FFI_TYPE_POINTER) + { #ifdef __s390x__ - type = FFI_TYPE_UINT64; + type = FFI_TYPE_UINT64; #else - type = FFI_TYPE_UINT32; + type = FFI_TYPE_UINT32; #endif + } /* Now handle all primitive int/float data types. */ switch (type) diff --git a/src/s390/internal.h b/src/s390/internal.h new file mode 100644 index 0000000..b875578 --- /dev/null +++ b/src/s390/internal.h @@ -0,0 +1,11 @@ +/* If these values change, sysv.S must be adapted! */ +#define FFI390_RET_DOUBLE 0 +#define FFI390_RET_FLOAT 1 +#define FFI390_RET_INT64 2 +#define FFI390_RET_INT32 3 +#define FFI390_RET_VOID 4 + +#define FFI360_RET_MASK 7 +#define FFI390_RET_IN_MEM 8 + +#define FFI390_RET_STRUCT (FFI390_RET_VOID | FFI390_RET_IN_MEM) diff --git a/src/s390/sysv.S b/src/s390/sysv.S index b01a7eb..df9083e 100644 --- a/src/s390/sysv.S +++ b/src/s390/sysv.S @@ -29,221 +29,140 @@ #include #include -#ifndef __s390x__ + .text -.text +#ifndef __s390x__ - # r2: cif->bytes - # r3: &ecif - # r4: ffi_prep_args - # r5: ret_type - # r6: ecif.rvalue - # ov: fn - # ov+8: closure + # r2: frame + # r3: ret_type + # r4: ret_addr + # r5: fun + # r6: closure # This assumes we are using gas. + .balign 8 .globl ffi_call_SYSV FFI_HIDDEN(ffi_call_SYSV) .type ffi_call_SYSV,%function ffi_call_SYSV: .cfi_startproc - stm %r6,%r15,24(%r15) # Save registers - .cfi_offset r6, -72 - .cfi_offset r7, -68 - .cfi_offset r8, -64 - .cfi_offset r9, -60 - .cfi_offset r10, -56 - .cfi_offset r11, -52 - .cfi_offset r12, -48 - .cfi_offset r13, -44 - .cfi_offset r14, -40 - .cfi_offset r15, -36 - basr %r13,0 # Set up base register + st %r6,44(%r2) # Save registers + stm %r12,%r14,48(%r2) + lr %r13,%r2 # Install frame pointer + .cfi_rel_offset r6, 44 + .cfi_rel_offset r12, 48 + .cfi_rel_offset r13, 52 + .cfi_rel_offset r14, 56 + .cfi_def_cfa_register r13 + l %r15,60(%r2) # Set up outgoing stack + basr %r14,0 # Set up base register .Lbase: - lr %r11,%r15 # Set up frame pointer - .cfi_def_cfa_register r11 - sr %r15,%r2 - ahi %r15,-96-48 # Allocate stack - lr %r8,%r6 # Save ecif.rvalue - sr %r9,%r9 - ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address - l %r7,96(%r11) # Load function address - st %r11,0(%r15) # Set up back chain - ahi %r11,-48 # Register save area - .cfi_adjust_cfa_offset 48 - - la %r2,96(%r15) # Save area - # r3 already holds &ecif - basr %r14,%r4 # Call ffi_prep_args - - l %r0,96+48+4(%r11) # Go closure -> static chain - lm %r2,%r6,0(%r11) # Load arguments - ld %f0,32(%r11) - ld %f2,40(%r11) - la %r14,0(%r13,%r9) # Set return address - br %r7 # ... and call function - -.LretNone: # Return void - l %r4,48+56(%r11) - lm %r6,%r15,48+24(%r11) - .cfi_remember_state - .cfi_restore 15 - .cfi_restore 14 - .cfi_restore 13 - .cfi_restore 12 - .cfi_restore 11 - .cfi_restore 10 - .cfi_restore 9 - .cfi_restore 8 - .cfi_restore 7 - .cfi_restore 6 - .cfi_def_cfa r15, 96 - br %r4 - .cfi_restore_state - # This nopr is necessary so that the .cfi instructions between the br - # above and the label below get executed. See execute_cfa_program() in - # the Gcc source code, libgcc/unwind-dw2.c. - nopr - -.LretFloat: - l %r4,48+56(%r11) - ste %f0,0(%r8) # Return float - lm %r6,%r15,48+24(%r11) - .cfi_remember_state - .cfi_restore 15 - .cfi_restore 14 - .cfi_restore 13 - .cfi_restore 12 - .cfi_restore 11 - .cfi_restore 10 - .cfi_restore 9 - .cfi_restore 8 - .cfi_restore 7 - .cfi_restore 6 - .cfi_def_cfa r15, 96 - br %r4 - .cfi_restore_state - # See comment on the nopr above. - nopr - -.LretDouble: - l %r4,48+56(%r11) - std %f0,0(%r8) # Return double - lm %r6,%r15,48+24(%r11) - .cfi_remember_state - .cfi_restore 15 - .cfi_restore 14 - .cfi_restore 13 - .cfi_restore 12 - .cfi_restore 11 - .cfi_restore 10 - .cfi_restore 9 - .cfi_restore 8 - .cfi_restore 7 - .cfi_restore 6 - .cfi_def_cfa r15, 96 - br %r4 - .cfi_restore_state - # See comment on the nopr above. - nopr - -.LretInt32: - l %r4,48+56(%r11) - st %r2,0(%r8) # Return int - lm %r6,%r15,48+24(%r11) - .cfi_remember_state - .cfi_restore 15 - .cfi_restore 14 - .cfi_restore 13 - .cfi_restore 12 - .cfi_restore 11 - .cfi_restore 10 - .cfi_restore 9 - .cfi_restore 8 - .cfi_restore 7 - .cfi_restore 6 - .cfi_def_cfa r15, 96 - br %r4 - .cfi_restore_state - # See comment on the nopr above. - nopr - -.LretInt64: - l %r4,48+56(%r11) - stm %r2,%r3,0(%r8) # Return long long - lm %r6,%r15,48+24(%r11) - .cfi_remember_state - .cfi_restore 15 + sla %r3,3 # ret_type *= 8 + lr %r12,%r4 # Save ret_addr + lr %r1,%r5 # Save fun + lr %r0,%r6 # Install static chain + la %r14,.Ltable-.Lbase(%r14,%r3) # Set return address + lm %r2,%r6,8(%r13) # Load arguments + ld %f0,64(%r13) + ld %f2,72(%r13) + st %r13,0(%r15) # Set up back chain + br %r1 # ... and call function + + .balign 8 +.Ltable: +# FFI390_RET_DOUBLE + std %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_FLOAT + ste %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_INT64 + st %r3,4(%r12) + nop + # fallthru + + .balign 8 +# FFI390_RET_INT32 + st %r2,0(%r12) + nop + # fallthru + + .balign 8 +# FFI390_RET_VOID +.Ldone: + l %r14,56(%r13) + l %r12,48(%r13) + l %r6,44(%r13) + l %r13,52(%r13) .cfi_restore 14 .cfi_restore 13 .cfi_restore 12 - .cfi_restore 11 - .cfi_restore 10 - .cfi_restore 9 - .cfi_restore 8 - .cfi_restore 7 .cfi_restore 6 .cfi_def_cfa r15, 96 - br %r4 + br %r14 .cfi_endproc + .size ffi_call_SYSV,.-ffi_call_SYSV -.Ltable: - .byte .LretNone-.Lbase # FFI390_RET_VOID - .byte .LretNone-.Lbase # FFI390_RET_STRUCT - .byte .LretFloat-.Lbase # FFI390_RET_FLOAT - .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE - .byte .LretInt32-.Lbase # FFI390_RET_INT32 - .byte .LretInt64-.Lbase # FFI390_RET_INT64 - -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV + .balign 8 + .globl ffi_go_closure_SYSV + FFI_HIDDEN(ffi_go_closure_SYSV) + .type ffi_go_closure_SYSV,%function +ffi_go_closure_SYSV: + .cfi_startproc + stm %r2,%r6,8(%r15) # Save arguments + lr %r4,%r0 # Load closure -> user_data + l %r2,4(%r4) # ->cif + l %r3,8(%r4) # ->fun + j .Ldoclosure + .cfi_endproc + .balign 8 .globl ffi_closure_SYSV FFI_HIDDEN(ffi_closure_SYSV) .type ffi_closure_SYSV,%function ffi_closure_SYSV: .cfi_startproc stm %r2,%r6,8(%r15) # Save arguments - .cfi_offset r6, -72 lr %r4,%r0 # Closure l %r2,16(%r4) # ->cif l %r3,20(%r4) # ->fun l %r4,24(%r4) # ->user_data .Ldoclosure: stm %r12,%r15,48(%r15) # Save registers - .cfi_offset r12, -48 - .cfi_offset r13, -44 - .cfi_offset r14, -40 - .cfi_offset r15, -36 + lr %r12,%r15 + .cfi_def_cfa_register r12 + .cfi_rel_offset r6, 24 + .cfi_rel_offset r12, 48 + .cfi_rel_offset r13, 52 + .cfi_rel_offset r14, 56 + .cfi_rel_offset r15, 60 basr %r13,0 # Set up base register .Lcbase: - std %f0,64(%r15) - std %f2,72(%r15) - lr %r1,%r15 # Set up stack frame - ahi %r15,-104 - .cfi_adjust_cfa_offset 104 - l %r12,.Lchelper-.Lcbase(%r13) # Get helper function - la %r5,96(%r1) - st %r5,96(%r15) # Overflow - la %r5,8(%r1) # GPRs - la %r6,64(%r1) # FPRs - st %r1,0(%r15) # Set up back chain - - bas %r14,0(%r12,%r13) # Call helper - - l %r4,104+56(%r15) - ld %f0,104+64(%r15) # Load return registers - lm %r2,%r3,104+8(%r15) - l %r6,104+24(%r15) # Restore saved registers - .cfi_restore r6 - lm %r12,%r15,104+48(%r15) - .cfi_adjust_cfa_offset -104 - .cfi_restore r12 - .cfi_restore r13 - .cfi_restore r14 - .cfi_restore r15 - br %r4 + ahi %r15,-96-8 # Set up stack frame + l %r1,.Lchelper-.Lcbase(%r13) # Get helper function + st %r12,0(%r15) # Set up back chain + + std %f0,64(%r12) # Save fp arguments + std %f2,72(%r12) + + la %r5,96(%r12) # Overflow + st %r5,96(%r15) + la %r6,64(%r12) # FPRs + la %r5,8(%r12) # GPRs + bas %r14,0(%r1,%r13) # Call helper + + lr %r15,%r12 + .cfi_def_cfa_register r15 + lm %r12,%r14,48(%r12) # Restore saved registers + l %r6,24(%r15) + ld %f0,64(%r15) # Load return registers + lm %r2,%r3,8(%r15) + br %r14 .cfi_endproc .align 4 @@ -251,234 +170,143 @@ ffi_closure_SYSV: .long ffi_closure_helper_SYSV-.Lcbase -.ffi_closure_SYSV_end: - .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV - - - .globl ffi_go_closure_SYSV - FFI_HIDDEN(ffi_go_closure_SYSV) - .type ffi_go_closure_SYSV,%function -ffi_go_closure_SYSV: - .cfi_startproc - stm %r2,%r6,8(%r15) # Save arguments - .cfi_offset r6, -72 - lr %r4,%r0 # Load closure -> user_data - l %r2,4(%r4) # ->cif - l %r3,8(%r4) # ->fun - j .Ldoclosure - .cfi_endproc + .size ffi_closure_SYSV,.-ffi_closure_SYSV #else -.text - - # r2: cif->bytes - # r3: &ecif - # r4: ffi_prep_args - # r5: ret_type - # r6: ecif.rvalue - # ov: fn - # ov+8: closure + # r2: frame + # r3: ret_type + # r4: ret_addr + # r5: fun + # r6: closure # This assumes we are using gas. + .balign 8 .globl ffi_call_SYSV FFI_HIDDEN(ffi_call_SYSV) .type ffi_call_SYSV,%function ffi_call_SYSV: .cfi_startproc - stmg %r6,%r15,48(%r15) # Save registers - .cfi_offset r6, -112 - .cfi_offset r7, -104 - .cfi_offset r8, -96 - .cfi_offset r9, -88 - .cfi_offset r10, -80 - .cfi_offset r11, -72 - .cfi_offset r12, -64 - .cfi_offset r13, -56 - .cfi_offset r14, -48 - .cfi_offset r15, -40 - larl %r13,.Lbase # Set up base register - lgr %r11,%r15 # Set up frame pointer - .cfi_def_cfa_register r11 - sgr %r15,%r2 - aghi %r15,-160-80 # Allocate stack - lgr %r8,%r6 # Save ecif.rvalue - llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address - lg %r7,160(%r11) # Load function address - stg %r11,0(%r15) # Set up back chain - aghi %r11,-80 # Register save area - .cfi_adjust_cfa_offset 80 - - la %r2,160(%r15) # Save area - # r3 already holds &ecif - basr %r14,%r4 # Call ffi_prep_args - - lg %r0,160+80+8(%r11) # Go closure -> static chain - lmg %r2,%r6,0(%r11) # Load arguments - ld %f0,48(%r11) - ld %f2,56(%r11) - ld %f4,64(%r11) - ld %f6,72(%r11) - la %r14,0(%r13,%r9) # Set return address - br %r7 # ... and call function - -.Lbase: -.LretNone: # Return void - lg %r4,80+112(%r11) - lmg %r6,%r15,80+48(%r11) - .cfi_remember_state - .cfi_restore r15 - .cfi_restore r14 - .cfi_restore r13 - .cfi_restore r12 - .cfi_restore r11 - .cfi_restore r10 - .cfi_restore r9 - .cfi_restore r8 - .cfi_restore r7 - .cfi_restore r6 - .cfi_def_cfa r15, 160 - br %r4 - .cfi_restore_state - # This nopr is necessary so that the .cfi instructions between the br - # above and the label below get executed. See execute_cfa_program() in - # the Gcc source code, libgcc/unwind-dw2.c. - nopr - -.LretFloat: - lg %r4,80+112(%r11) - ste %f0,0(%r8) # Return float - lmg %r6,%r15,80+48(%r11) - .cfi_remember_state - .cfi_restore r6 - .cfi_restore r7 - .cfi_restore r8 - .cfi_restore r9 - .cfi_restore r10 - .cfi_restore r11 - .cfi_restore r12 - .cfi_restore r13 - .cfi_restore r14 - .cfi_restore r15 - .cfi_def_cfa r15, 160 - br %r4 - .cfi_restore_state - # See comment on the nopr above. - nopr - -.LretDouble: - lg %r4,80+112(%r11) - std %f0,0(%r8) # Return double - lmg %r6,%r15,80+48(%r11) - .cfi_remember_state - .cfi_restore r15 - .cfi_restore r14 - .cfi_restore r13 - .cfi_restore r12 - .cfi_restore r11 - .cfi_restore r10 - .cfi_restore r9 - .cfi_restore r8 - .cfi_restore r7 - .cfi_restore r6 - .cfi_def_cfa r15, 160 - br %r4 - .cfi_restore_state - # See comment on the nopr above. - nopr - -.LretInt64: - lg %r4,80+112(%r11) - stg %r2,0(%r8) # Return long - lmg %r6,%r15,80+48(%r11) - .cfi_restore r15 + stg %r6,88(%r2) # Save registers + stmg %r12,%r14,96(%r2) + lgr %r13,%r2 # Install frame pointer + .cfi_rel_offset r6, 88 + .cfi_rel_offset r12, 96 + .cfi_rel_offset r13, 104 + .cfi_rel_offset r14, 112 + .cfi_def_cfa_register r13 + lg %r15,120(%r2) # Set up outgoing stack + larl %r14,.Ltable # Set up return address + slag %r3,%r3,3 # ret_type *= 8 + lgr %r12,%r4 # Save ret_addr + lgr %r1,%r5 # Save fun + lgr %r0,%r6 # Install static chain + agr %r14,%r3 + lmg %r2,%r6,16(%r13) # Load arguments + ld %f0,128(%r13) + ld %f2,136(%r13) + ld %f4,144(%r13) + ld %f6,152(%r13) + stg %r13,0(%r15) # Set up back chain + br %r1 # ... and call function + + .balign 8 +.Ltable: +# FFI390_RET_DOUBLE + std %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_DOUBLE + ste %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_INT64 + stg %r2,0(%r12) + + .balign 8 +# FFI390_RET_INT32 + # Never used, as we always store type ffi_arg. + # But the stg above is 6 bytes and we cannot + # jump around this case, so fall through. + nop + nop + + .balign 8 +# FFI390_RET_VOID +.Ldone: + lg %r14,112(%r13) + lg %r12,96(%r13) + lg %r6,88(%r13) + lg %r13,104(%r13) .cfi_restore r14 .cfi_restore r13 .cfi_restore r12 - .cfi_restore r11 - .cfi_restore r10 - .cfi_restore r9 - .cfi_restore r8 - .cfi_restore r7 .cfi_restore r6 .cfi_def_cfa r15, 160 - br %r4 + br %r14 .cfi_endproc + .size ffi_call_SYSV,.-ffi_call_SYSV -.Ltable: - .byte .LretNone-.Lbase # FFI390_RET_VOID - .byte .LretNone-.Lbase # FFI390_RET_STRUCT - .byte .LretFloat-.Lbase # FFI390_RET_FLOAT - .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE - .byte 0 # int32 retval not supported - .byte .LretInt64-.Lbase # FFI390_RET_INT64 -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV + .balign 8 + .globl ffi_go_closure_SYSV + FFI_HIDDEN(ffi_go_closure_SYSV) + .type ffi_go_closure_SYSV,%function +ffi_go_closure_SYSV: + .cfi_startproc + stmg %r2,%r6,16(%r15) # Save arguments + lgr %r4,%r0 # Load closure -> user_data + lg %r2,8(%r4) # ->cif + lg %r3,16(%r4) # ->fun + j .Ldoclosure + .cfi_endproc + .size ffi_go_closure_SYSV,.-ffi_go_closure_SYSV + .balign 8 .globl ffi_closure_SYSV FFI_HIDDEN(ffi_closure_SYSV) .type ffi_closure_SYSV,%function ffi_closure_SYSV: .cfi_startproc stmg %r2,%r6,16(%r15) # Save arguments - .cfi_offset r6, -112 lgr %r4,%r0 # Load closure lg %r2,32(%r4) # ->cif lg %r3,40(%r4) # ->fun lg %r4,48(%r4) # ->user_data .Ldoclosure: - stmg %r14,%r15,112(%r15) # Save registers - .cfi_offset r14, -48 - .cfi_offset r15, -40 - std %f0,128(%r15) # Save arguments - std %f2,136(%r15) - std %f4,144(%r15) - std %f6,152(%r15) - lgr %r1,%r15 # Set up stack frame - aghi %r15,-168 - .cfi_adjust_cfa_offset 168 - la %r5,160(%r1) - stg %r5,160(%r15) # Overflow - la %r5,16(%r1) # GPRs - la %r6,128(%r1) # FPRs - stg %r1,0(%r15) # Set up back chain - + stmg %r13,%r15,104(%r15) # Save registers + lgr %r13,%r15 + .cfi_def_cfa_register r13 + .cfi_rel_offset r6, 48 + .cfi_rel_offset r13, 104 + .cfi_rel_offset r14, 112 + .cfi_rel_offset r15, 120 + aghi %r15,-160-16 # Set up stack frame + stg %r13,0(%r15) # Set up back chain + + std %f0,128(%r13) # Save fp arguments + std %f2,136(%r13) + std %f4,144(%r13) + std %f6,152(%r13) + la %r5,160(%r13) # Overflow + stg %r5,160(%r15) + la %r6,128(%r13) # FPRs + la %r5,16(%r13) # GPRs brasl %r14,ffi_closure_helper_SYSV # Call helper - ld %f0,168+128(%r15) # Load return registers - lg %r2,168+16(%r15) - lg %r6,168+48(%r15) # Restore saved registers - .cfi_restore r6 - lmg %r14,%r15,168+112(%r15) - .cfi_restore r14 - .cfi_restore r15 - .cfi_adjust_cfa_offset -168 + lgr %r15,%r13 + .cfi_def_cfa_register r15 + lmg %r13,%r14,104(%r13) # Restore saved registers + lg %r6,48(%r15) + ld %f0,128(%r15) # Load return registers + lg %r2,16(%r15) br %r14 .cfi_endproc - -.ffi_closure_SYSV_end: - .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV - - - .globl ffi_go_closure_SYSV - FFI_HIDDEN(ffi_go_closure_SYSV) - .type ffi_go_closure_SYSV,%function -ffi_go_closure_SYSV: - .cfi_startproc - stmg %r2,%r6,16(%r15) # Save arguments - .cfi_offset r6, -112 - lgr %r4,%r0 # Load closure -> user_data - lg %r2,8(%r4) # ->cif - lg %r3,16(%r4) # ->fun - j .Ldoclosure - .cfi_endproc - -.ffi_go_closure_SYSV_end: - .size ffi_go_closure_SYSV,.ffi_go_closure_SYSV_end-ffi_go_closure_SYSV - -#endif + .size ffi_closure_SYSV,.-ffi_closure_SYSV +#endif /* !s390x */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits -- 2.1.0