aboutsummaryrefslogtreecommitdiff
path: root/libffi/src/csky/sysv.S
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/csky/sysv.S')
-rw-r--r--libffi/src/csky/sysv.S371
1 files changed, 371 insertions, 0 deletions
diff --git a/libffi/src/csky/sysv.S b/libffi/src/csky/sysv.S
new file mode 100644
index 0000000..21670bf
--- /dev/null
+++ b/libffi/src/csky/sysv.S
@@ -0,0 +1,371 @@
+/* -----------------------------------------------------------------------
+ sysv.S
+
+ CSKY 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 AUTHORS OR COPYRIGHT
+ HOLDERS 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 <fficonfig.h>
+#include <ffi.h>
+
+.macro CSKY_FUNC_START name
+ .text
+ .align 2
+ .globl \name
+ .type \name, @function
+ \name:
+.endm
+
+#ifdef __CSKYABIV2__
+
+ /*
+ * a0: fn
+ * a1: &ecif
+ * a2: cif->bytes
+ * a3: fig->flags
+ * sp+0: ecif.rvalue
+ */
+CSKY_FUNC_START ffi_call_SYSV
+ /* Save registers */
+ .cfi_startproc
+ subi sp, 28
+ .cfi_def_cfa_offset 28
+ stw a0, (sp, 0x0)
+ .cfi_offset 0, -28
+ stw a1, (sp, 0x4)
+ .cfi_offset 1, -24
+ stw a2, (sp, 0x8)
+ .cfi_offset 2, -20
+ stw a3, (sp, 0xC)
+ .cfi_offset 3, -16
+ stw l0, (sp, 0x10)
+ .cfi_offset 4, -12
+ stw l1, (sp, 0x14)
+ .cfi_offset 5, -8
+ stw lr, (sp, 0x18)
+ .cfi_offset 15, -4
+
+ mov l0, sp
+ .cfi_def_cfa_register 4
+
+ /* Make room for all of the new args. */
+ subu sp, sp, a2
+
+ /* Place all of the ffi_prep_args in position */
+ mov a0, sp
+ /* a1 already set */
+
+ /* Call ffi_prep_args(stack, &ecif) */
+ jsri ffi_prep_args
+
+ /* move first 4 parameters in registers */
+ ldw a0, (sp, 0x0)
+ ldw a1, (sp, 0x4)
+ ldw a2, (sp, 0x8)
+ ldw a3, (sp, 0xC)
+
+ /* and adjust stack */
+ subu lr, l0, sp /* cif->bytes == l0 - sp */
+ cmphsi lr, 16
+ movi l1, 16
+ movt lr, l1
+ addu sp, sp, lr
+
+ ldw l1, (l0, 0) /* load fn() in advance */
+
+ /* call (fn) (...) */
+ jsr l1
+
+ /* Remove the space we pushed for the args */
+ mov sp, l0
+
+ /* Load r2 with the pointer to storage for the return value */
+ ldw a2, (sp, 0x1C)
+
+ /* Load r3 with the return type code */
+ ldw a3, (sp, 0xC)
+
+ /* If the return value pointer is NULL, assume no return value. */
+ cmpnei a2, 0
+ bf .Lepilogue
+
+ cmpnei a3, FFI_TYPE_STRUCT
+ bf .Lepilogue
+
+ /* return INT64 */
+ cmpnei a3, FFI_TYPE_SINT64
+ bt .Lretint
+ /* stw a0, (a2, 0x0) at .Lretint */
+ stw a1, (a2, 0x4)
+
+.Lretint:
+ /* return INT */
+ stw a0, (a2, 0x0)
+
+.Lepilogue:
+ ldw a0, (sp, 0x0)
+ ldw a1, (sp, 0x4)
+ ldw a2, (sp, 0x8)
+ ldw a3, (sp, 0xC)
+ ldw l0, (sp, 0x10)
+ ldw l1, (sp, 0x14)
+ ldw lr, (sp, 0x18)
+ addi sp, sp, 28
+ rts
+ .cfi_endproc
+ .size ffi_call_SYSV, .-ffi_call_SYSV
+
+
+ /*
+ * unsigned int FFI_HIDDEN
+ * ffi_closure_SYSV_inner (closure, respp, args)
+ * ffi_closure *closure;
+ * void **respp;
+ * void *args;
+ */
+CSKY_FUNC_START ffi_closure_SYSV
+ .cfi_startproc
+ mov a2, sp
+ addi a1, sp, 16
+ subi sp, sp, 24
+ .cfi_def_cfa_offset 40
+ stw a1, (sp, 0x10)
+ .cfi_offset 1, -24
+ stw lr, (sp, 0x14)
+ .cfi_offset 15, -20
+ stw sp, (sp, 0x8)
+ addi a1, sp, 8
+ jsri ffi_closure_SYSV_inner
+ ldw a0, (sp, 0x0)
+ /*
+ * if FFI_TYPE_SINT64, need a1.
+ * if FFI_TYPE_INT, ignore a1.
+ */
+ ldw a1, (sp, 0x4)
+
+ ldw lr, (sp, 0x14)
+ addi sp, sp, 40
+ rts
+ .cfi_endproc
+ .size ffi_closure_SYSV, .-ffi_closure_SYSV
+
+CSKY_FUNC_START ffi_csky_trampoline
+ subi sp, sp, 16
+ stw a0, (sp, 0x0)
+ stw a1, (sp, 0x4)
+ stw a2, (sp, 0x8)
+ stw a3, (sp, 0xC)
+ lrw a0, [.Lctx]
+ lrw a1, [.Lfun]
+ jmp a1
+.Lctx:
+ mov a0, a0
+ mov a0, a0
+.Lfun:
+
+ .size ffi_csky_trampoline, .-ffi_csky_trampoline
+
+CSKY_FUNC_START ffi_csky_cacheflush
+ mov t0, r7
+ movi r7, 123
+ trap 0
+ mov r7, t0
+ rts
+
+ .size ffi_csky_cacheflush, .-ffi_csky_cacheflush
+
+#else /* !__CSKYABIV2__ */
+
+ /*
+ * a0: fn
+ * a1: &ecif
+ * a2: cif->bytes
+ * a3: fig->flags
+ * a4: ecif.rvalue
+ */
+CSKY_FUNC_START ffi_call_SYSV
+ /* Save registers */
+ .cfi_startproc
+ subi sp, 32
+ subi sp, 8
+ .cfi_def_cfa_offset 40
+ stw a0, (sp, 0x0)
+ .cfi_offset 2, -40
+ stw a1, (sp, 0x4)
+ .cfi_offset 3, -36
+ stw a2, (sp, 0x8)
+ .cfi_offset 4, -32
+ stw a3, (sp, 0xC)
+ .cfi_offset 5, -28
+ stw a4, (sp, 0x10)
+ .cfi_offset 6, -24
+ stw a5, (sp, 0x14)
+ .cfi_offset 7, -20
+ stw l0, (sp, 0x18)
+ .cfi_offset 8, -16
+ stw l1, (sp, 0x1C)
+ .cfi_offset 9, -12
+ stw lr, (sp, 0x20)
+ .cfi_offset 15, -8
+
+ mov l0, sp
+ .cfi_def_cfa_register 8
+
+ /* Make room for all of the new args. */
+ subu sp, sp, a2
+
+ /* Place all of the ffi_prep_args in position */
+ mov a0, sp
+ /* a1 already set */
+
+ /* Call ffi_prep_args(stack, &ecif) */
+ jsri ffi_prep_args
+
+ /* move first 4 parameters in registers */
+ ldw a0, (sp, 0x0)
+ ldw a1, (sp, 0x4)
+ ldw a2, (sp, 0x8)
+ ldw a3, (sp, 0xC)
+ ldw a4, (sp, 0x10)
+ ldw a5, (sp, 0x14)
+
+ /* and adjust stack */
+ mov lr, l0
+ subu lr, sp /* cif->bytes == l0 - sp */
+ movi l1, 24
+ cmphs lr, l1
+ movt lr, l1
+ addu sp, sp, lr
+
+ ldw l1, (l0, 0) /* load fn() in advance */
+
+ /* call (fn) (...) */
+ jsr l1
+
+ /* Remove the space we pushed for the args */
+ mov sp, l0
+
+ /* Load r2 with the pointer to storage for the return value */
+ ldw a2, (sp, 0x10)
+
+ /* Load r3 with the return type code */
+ ldw a3, (sp, 0xC)
+
+ /* If the return value pointer is NULL, assume no return value. */
+ cmpnei a2, 0
+ bf .Lepilogue
+
+ cmpnei a3, FFI_TYPE_STRUCT
+ bf .Lepilogue
+
+ /* return INT64 */
+ cmpnei a3, FFI_TYPE_SINT64
+ bt .Lretint
+ /* stw a0, (a2, 0x0) at .Lretint */
+ stw a1, (a2, 0x4)
+
+.Lretint:
+ /* return INT */
+ stw a0, (a2, 0x0)
+
+.Lepilogue:
+ ldw a0, (sp, 0x0)
+ ldw a1, (sp, 0x4)
+ ldw a2, (sp, 0x8)
+ ldw a3, (sp, 0xC)
+ ldw a4, (sp, 0x10)
+ ldw a5, (sp, 0x14)
+ ldw l0, (sp, 0x18)
+ ldw l1, (sp, 0x1C)
+ ldw lr, (sp, 0x20)
+ addi sp, sp, 32
+ addi sp, sp, 8
+ rts
+ .cfi_endproc
+
+ .size ffi_call_SYSV, .-ffi_call_SYSV
+
+
+ /*
+ * unsigned int FFI_HIDDEN
+ * ffi_closure_SYSV_inner (closure, respp, args)
+ * ffi_closure *closure;
+ * void **respp;
+ * void *args;
+ */
+CSKY_FUNC_START ffi_closure_SYSV
+ .cfi_startproc
+ mov a2, sp
+ mov a1, sp
+ addi a1, 24
+ subi sp, sp, 24
+ .cfi_def_cfa_offset 48
+ stw a1, (sp, 0x10)
+ .cfi_offset 3, -32
+ stw lr, (sp, 0x14)
+ .cfi_offset 15, -28
+ stw sp, (sp, 0x8)
+ mov a1, sp
+ addi a1, 8
+ jsri ffi_closure_SYSV_inner
+ ldw a0, (sp, 0x0)
+ /*
+ * if FFI_TYPE_SINT64, need a1.
+ * if FFI_TYPE_INT, ignore a1.
+ */
+ ldw a1, (sp, 0x4)
+
+ ldw lr, (sp, 0x14)
+ addi sp, sp, 24
+ addi sp, sp, 24
+ rts
+ .cfi_endproc
+
+ .size ffi_closure_SYSV, .-ffi_closure_SYSV
+
+CSKY_FUNC_START ffi_csky_trampoline
+ subi sp, 24
+ stw a0, (sp, 0x0)
+ stw a1, (sp, 0x4)
+ stw a2, (sp, 0x8)
+ stw a3, (sp, 0xC)
+ stw a4, (sp, 0x10)
+ stw a5, (sp, 0x14)
+ lrw a0, [.Lctx]
+ lrw a1, [.Lfun]
+ jmp a1
+.Lctx:
+ mov a0, a0
+ mov a0, a0
+.Lfun:
+
+ .size ffi_csky_trampoline, .-ffi_csky_trampoline
+
+CSKY_FUNC_START ffi_csky_cacheflush
+ lrw r1, 123
+ trap 0
+ rts
+
+ .size ffi_csky_cacheflush, .-ffi_csky_cacheflush
+
+#endif /* __CSKYABIV2__ */