aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/s390/sysv.S
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/s390/sysv.S')
-rw-r--r--libffi/src/s390/sysv.S161
1 files changed, 161 insertions, 0 deletions
diff --git a/libffi/src/s390/sysv.S b/libffi/src/s390/sysv.S
new file mode 100644
index 00000000000..afaf1ea1ca3
--- /dev/null
+++ b/libffi/src/s390/sysv.S
@@ -0,0 +1,161 @@
+/* -----------------------------------------------------------------------
+ sysv.S - Copyright (c) 2000 Software AG
+
+ S390 Foreign Function Interface
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <ffi.h>
+#ifdef HAVE_MACHINE_ASM_H
+#include <machine/asm.h>
+#endif
+
+.text
+
+ # r2: ffi_prep_args
+ # r3: &ecif
+ # r4: cif->bytes
+ # r5: fig->flags
+ # r6: ecif.rvalue
+ # sp+0: fn
+
+ # This assumes we are using gas.
+ .globl ffi_call_SYSV
+ .type ffi_call_SYSV,%function
+ffi_call_SYSV:
+ # Save registers
+ stm %r7,%r15,28(%r15)
+ l %r7,96(%r15) # Get A(fn)
+ lr %r0,%r15
+ ahi %r15,-128 # Make room for my args
+ st %r0,0(%r15) # Set backchain
+ lr %r11,%r15 # Establish my stack register
+ sr %r15,%r4 # Make room for fn args
+ ahi %r15,-96 # Make room for new frame
+ lr %r10,%r15 # Establish stack build area
+ ahi %r15,-96 # Stack for next call
+ lr %r1,%r7
+ stm %r2,%r7,96(%r11) # Save args on my stack
+
+#------------------------------------------------------------------
+# move first 3 parameters in registers
+#------------------------------------------------------------------
+ lr %r9,%r2 # r9: &ffi_prep_args
+ lr %r2,%r10 # Parm 1: &stack Parm 2: &ecif
+ basr %r14,%r9 # call ffi_prep_args
+
+#------------------------------------------------------------------
+# load first 5 parameter registers
+#------------------------------------------------------------------
+ lm %r2,%r6,24(%r10)
+
+#------------------------------------------------------------------
+# load fp parameter registers
+#------------------------------------------------------------------
+ ld %f0,48(%r10)
+ ld %f2,56(%r10)
+
+#------------------------------------------------------------------
+# call function
+#------------------------------------------------------------------
+ lr %r15,%r10 # Set new stack
+ l %r9,116(%r11) # Get &fn
+ basr %r14,%r9 # Call function
+
+#------------------------------------------------------------------
+# On return:
+# r2: Return value (r3: Return value + 4 for long long)
+#------------------------------------------------------------------
+
+#------------------------------------------------------------------
+# If the return value pointer is NULL, assume no return value.
+#------------------------------------------------------------------
+ icm %r6,15,112(%r11)
+ jz .Lepilogue
+
+ l %r5,108(%r11) # Get return type
+#------------------------------------------------------------------
+# return INT
+#------------------------------------------------------------------
+ chi %r5,FFI_TYPE_INT
+ jne .Lchk64
+
+ st %r2,0(%r6)
+ j .Lepilogue
+
+.Lchk64:
+#------------------------------------------------------------------
+# return LONG LONG (signed/unsigned)
+#------------------------------------------------------------------
+ chi %r5,FFI_TYPE_UINT64
+ je .LdoLongLong
+
+ chi %r5,FFI_TYPE_SINT64
+ jne .LchkFloat
+
+.LdoLongLong:
+ stm %r2,%r3,0(%r6)
+ j .Lepilogue
+
+.LchkFloat:
+#------------------------------------------------------------------
+# return FLOAT
+#------------------------------------------------------------------
+ chi %r5,FFI_TYPE_FLOAT
+ jne .LchkDouble
+
+ std %f0,0(%r6)
+ j .Lepilogue
+
+.LchkDouble:
+#------------------------------------------------------------------
+# return DOUBLE or LONGDOUBLE
+#------------------------------------------------------------------
+ chi %r5,FFI_TYPE_DOUBLE
+ jne .LchkStruct
+
+ std %f0,0(%r6)
+ std %f2,8(%r6)
+ j .Lepilogue
+
+.LchkStruct:
+#------------------------------------------------------------------
+# Structure - rvalue already set as sent as 1st parm to routine
+#------------------------------------------------------------------
+ chi %r5,FFI_TYPE_STRUCT
+ je .Lepilogue
+
+.Ldefault:
+#------------------------------------------------------------------
+# return a pointer
+#------------------------------------------------------------------
+ st %r2,0(%r6)
+ j .Lepilogue
+
+.Lepilogue:
+ l %r15,0(%r11)
+ l %r4,56(%r15)
+ lm %r7,%r15,28(%r15)
+ br %r4
+
+.ffi_call_SYSV_end:
+ .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV