summaryrefslogtreecommitdiff
path: root/libffi/src/sh/sysv.S
diff options
context:
space:
mode:
Diffstat (limited to 'libffi/src/sh/sysv.S')
-rw-r--r--libffi/src/sh/sysv.S674
1 files changed, 674 insertions, 0 deletions
diff --git a/libffi/src/sh/sysv.S b/libffi/src/sh/sysv.S
new file mode 100644
index 00000000000..b6a06b8d15e
--- /dev/null
+++ b/libffi/src/sh/sysv.S
@@ -0,0 +1,674 @@
+/* -----------------------------------------------------------------------
+ sysv.S - Copyright (c) 2002 Kaz Kojima
+
+ SuperH 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>
+#else
+/* XXX these lose for some platforms, I'm sure. */
+#define CNAME(x) x
+#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
+#endif
+
+#if defined(__HITACHI__)
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 1
+#else
+#define STRUCT_VALUE_ADDRESS_WITH_ARG 0
+#endif
+
+.text
+
+ # r4: ffi_prep_args
+ # r5: &ecif
+ # r6: bytes
+ # r7: flags
+ # sp+0: rvalue
+ # sp+4: fn
+
+ # This assumes we are using gas.
+ENTRY(ffi_call_SYSV)
+#if defined(__SH4__)
+ # Save registers
+ mov.l r8,@-r15
+ mov.l r9,@-r15
+ mov.l r10,@-r15
+ mov.l r12,@-r15
+ mov.l r14,@-r15
+ sts.l pr,@-r15
+ mov r15,r14
+
+ mov r6,r8
+ mov r7,r9
+
+ sub r6,r15
+ add #-16,r15
+ mov #~7,r0
+ and r0,r15
+
+ mov r4,r0
+ jsr @r0
+ mov r15,r4
+
+ mov r9,r1
+ shlr8 r9
+ shlr8 r9
+ shlr8 r9
+
+ mov #FFI_TYPE_STRUCT,r2
+ cmp/eq r2,r9
+ bf 1f
+#if STRUCT_VALUE_ADDRESS_WITH_ARG
+ mov.l @r15+,r4
+ bra 2f
+ mov #5,r2
+#else
+ mov.l @r15+,r10
+#endif
+1:
+ mov #4,r2
+2:
+ mov #4,r3
+
+L_pass:
+ cmp/pl r8
+ bf L_call_it
+
+ mov r1,r0
+ and #3,r0
+
+L_pass_d:
+ cmp/eq #FFI_TYPE_DOUBLE,r0
+ bf L_pass_f
+
+ mov r3,r0
+ and #1,r0
+ tst r0,r0
+ bt 1f
+ add #1,r3
+1:
+ mov r15,r0
+ and #7,r0
+ tst r0,r0
+ bt 2f
+ add #4,r15
+2:
+ mov #12,r0
+ cmp/hs r0,r3
+ bt/s 3f
+ shlr2 r1
+ bsr L_pop_d
+ nop
+3:
+ add #2,r3
+ bra L_pass
+ add #-8,r8
+
+L_pop_d:
+ mov r3,r0
+ add r0,r0
+ add r3,r0
+ add #-12,r0
+ braf r0
+ nop
+#ifdef __LITTLE_ENDIAN__
+ fmov.s @r15+,fr5
+ rts
+ fmov.s @r15+,fr4
+ fmov.s @r15+,fr7
+ rts
+ fmov.s @r15+,fr6
+ fmov.s @r15+,fr9
+ rts
+ fmov.s @r15+,fr8
+ fmov.s @r15+,fr11
+ rts
+ fmov.s @r15+,fr10
+#else
+ fmov.s @r15+,fr4
+ rts
+ fmov.s @r15+,fr5
+ fmov.s @r15+,fr6
+ rts
+ fmov.s @r15+,fr7
+ fmov.s @r15+,fr8
+ rts
+ fmov.s @r15+,fr9
+ fmov.s @r15+,fr10
+ rts
+ fmov.s @r15+,fr11
+#endif
+
+L_pass_f:
+ cmp/eq #FFI_TYPE_FLOAT,r0
+ bf L_pass_i
+
+ mov #12,r0
+ cmp/hs r0,r3
+ bt/s 2f
+ shlr2 r1
+ bsr L_pop_f
+ nop
+2:
+ add #1,r3
+ bra L_pass
+ add #-4,r8
+
+L_pop_f:
+ mov r3,r0
+ shll2 r0
+ add #-16,r0
+ braf r0
+ nop
+#ifdef __LITTLE_ENDIAN__
+ rts
+ fmov.s @r15+,fr5
+ rts
+ fmov.s @r15+,fr4
+ rts
+ fmov.s @r15+,fr7
+ rts
+ fmov.s @r15+,fr6
+ rts
+ fmov.s @r15+,fr9
+ rts
+ fmov.s @r15+,fr8
+ rts
+ fmov.s @r15+,fr11
+ rts
+ fmov.s @r15+,fr10
+#else
+ rts
+ fmov.s @r15+,fr4
+ rts
+ fmov.s @r15+,fr5
+ rts
+ fmov.s @r15+,fr6
+ rts
+ fmov.s @r15+,fr7
+ rts
+ fmov.s @r15+,fr8
+ rts
+ fmov.s @r15+,fr9
+ rts
+ fmov.s @r15+,fr10
+ rts
+ fmov.s @r15+,fr11
+#endif
+
+L_pass_i:
+ cmp/eq #FFI_TYPE_INT,r0
+ bf L_call_it
+
+ mov #8,r0
+ cmp/hs r0,r2
+ bt/s 2f
+ shlr2 r1
+ bsr L_pop_i
+ nop
+2:
+ add #1,r2
+ bra L_pass
+ add #-4,r8
+
+L_pop_i:
+ mov r2,r0
+ shll2 r0
+ add #-16,r0
+ braf r0
+ nop
+ rts
+ mov.l @r15+,r4
+ rts
+ mov.l @r15+,r5
+ rts
+ mov.l @r15+,r6
+ rts
+ mov.l @r15+,r7
+
+L_call_it:
+ # call function
+#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
+ mov r10, r2
+#endif
+ mov.l @(28,r14),r1
+ jsr @r1
+ nop
+
+L_ret_d:
+ mov #FFI_TYPE_DOUBLE,r2
+ cmp/eq r2,r9
+ bf L_ret_ll
+
+ mov.l @(24,r14),r1
+#ifdef __LITTLE_ENDIAN__
+ fmov.s fr1,@r1
+ add #4,r1
+ bra L_epilogue
+ fmov.s fr0,@r1
+#else
+ fmov.s fr0,@r1
+ add #4,r1
+ bra L_epilogue
+ fmov.s fr1,@r1
+#endif
+
+L_ret_ll:
+ mov #FFI_TYPE_SINT64,r2
+ cmp/eq r2,r9
+ bt/s 1f
+ mov #FFI_TYPE_UINT64,r2
+ cmp/eq r2,r9
+ bf L_ret_f
+
+1:
+ mov.l @(24,r14),r2
+ mov.l r0,@r2
+ bra L_epilogue
+ mov.l r1,@(4,r2)
+
+L_ret_f:
+ mov #FFI_TYPE_FLOAT,r2
+ cmp/eq r2,r9
+ bf L_ret_i
+
+ mov.l @(24,r14),r1
+ bra L_epilogue
+ fmov.s fr0,@r1
+
+L_ret_i:
+ mov #FFI_TYPE_INT,r2
+ cmp/eq r2,r9
+ bf L_epilogue
+
+ mov.l @(24,r14),r1
+ bra L_epilogue
+ mov.l r0,@r1
+
+L_epilogue:
+ # Remove the space we pushed for the args
+ mov r14,r15
+
+ lds.l @r15+,pr
+ mov.l @r15+,r14
+ mov.l @r15+,r12
+ mov.l @r15+,r10
+ mov.l @r15+,r9
+ rts
+ mov.l @r15+,r8
+#else
+ # Save registers
+ mov.l r8,@-r15
+ mov.l r9,@-r15
+ mov.l r10,@-r15
+ mov.l r12,@-r15
+ mov.l r14,@-r15
+ sts.l pr,@-r15
+ mov r15,r14
+
+ mov r6,r8
+ mov r7,r9
+
+ sub r6,r15
+ add #-16,r15
+ mov #~7,r0
+ and r0,r15
+
+ mov r4,r0
+ jsr @r0
+ mov r15,r4
+
+ mov r9,r3
+ shlr8 r9
+ shlr8 r9
+ shlr8 r9
+
+ mov #FFI_TYPE_STRUCT,r2
+ cmp/eq r2,r9
+ bf 1f
+#if STRUCT_VALUE_ADDRESS_WITH_ARG
+ mov.l @r15+,r4
+ bra 2f
+ mov #5,r2
+#else
+ mov.l @r15+,r10
+#endif
+1:
+ mov #4,r2
+2:
+
+L_pass:
+ cmp/pl r8
+ bf L_call_it
+
+ mov r3,r0
+ and #3,r0
+
+L_pass_d:
+ cmp/eq #FFI_TYPE_DOUBLE,r0
+ bf L_pass_i
+
+ mov r15,r0
+ and #7,r0
+ tst r0,r0
+ bt 1f
+ add #4,r15
+1:
+ mov #8,r0
+ cmp/hs r0,r2
+ bt/s 2f
+ shlr2 r3
+ bsr L_pop_d
+ nop
+2:
+ add #2,r2
+ bra L_pass
+ add #-8,r8
+
+L_pop_d:
+ mov r2,r0
+ add r0,r0
+ add r2,r0
+ add #-12,r0
+ add r0,r0
+ braf r0
+ nop
+ mov.l @r15+,r4
+ rts
+ mov.l @r15+,r5
+ mov.l @r15+,r5
+ rts
+ mov.l @r15+,r6
+ mov.l @r15+,r6
+ rts
+ mov.l @r15+,r7
+ rts
+ mov.l @r15+,r7
+
+L_pass_i:
+ mov #8,r0
+ cmp/hs r0,r2
+ bt/s 2f
+ shlr2 r3
+ bsr L_pop_i
+ nop
+2:
+ add #1,r2
+ bra L_pass
+ add #-4,r8
+
+L_pop_i:
+ mov r2,r0
+ shll2 r0
+ add #-16,r0
+ braf r0
+ nop
+ rts
+ mov.l @r15+,r4
+ rts
+ mov.l @r15+,r5
+ rts
+ mov.l @r15+,r6
+ rts
+ mov.l @r15+,r7
+
+L_call_it:
+ # call function
+#if (! STRUCT_VALUE_ADDRESS_WITH_ARG)
+ mov r10, r2
+#endif
+ mov.l @(28,r14),r1
+ jsr @r1
+ nop
+
+L_ret_d:
+ mov #FFI_TYPE_DOUBLE,r2
+ cmp/eq r2,r9
+ bf L_ret_ll
+
+ mov.l @(24,r14),r2
+ mov.l r0,@r2
+ bra L_epilogue
+ mov.l r1,@(4,r2)
+
+L_ret_ll:
+ mov #FFI_TYPE_SINT64,r2
+ cmp/eq r2,r9
+ bt/s 1f
+ mov #FFI_TYPE_UINT64,r2
+ cmp/eq r2,r9
+ bf L_ret_i
+
+1:
+ mov.l @(24,r14),r2
+ mov.l r0,@r2
+ bra L_epilogue
+ mov.l r1,@(4,r2)
+
+L_ret_i:
+ mov #FFI_TYPE_FLOAT,r2
+ cmp/eq r2,r9
+ bt 1f
+ mov #FFI_TYPE_INT,r2
+ cmp/eq r2,r9
+ bf L_epilogue
+1:
+ mov.l @(24,r14),r1
+ bra L_epilogue
+ mov.l r0,@r1
+
+L_epilogue:
+ # Remove the space we pushed for the args
+ mov r14,r15
+
+ lds.l @r15+,pr
+ mov.l @r15+,r14
+ mov.l @r15+,r12
+ mov.l @r15+,r10
+ mov.l @r15+,r9
+ rts
+ mov.l @r15+,r8
+#endif
+
+.ffi_call_SYSV_end:
+ .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
+
+.globl ffi_closure_helper_SYSV
+
+ENTRY(ffi_closure_SYSV)
+ mov.l r14,@-r15
+ sts.l pr,@-r15
+
+ /* Stack layout:
+ ...
+ 32 bytes (floating register parameters, SH-4 only)
+ 16 bytes (register parameters)
+ 4 bytes (result)
+ 4 bytes (5th arg)
+ <- new stack pointer
+ */
+#if defined(__SH4__)
+ add #-56,r15
+#else
+ add #-24,r15
+#endif
+ mov r15,r14
+
+ mov r14,r1
+ add #24,r1
+ mov.l r7,@-r1
+ mov.l r6,@-r1
+ mov.l r5,@-r1
+ mov.l r4,@-r1
+ mov r1,r6
+
+#if defined(__SH4__)
+ mov r14,r1
+ add #56,r1
+#ifdef __LITTLE_ENDIAN__
+ fmov.s fr10,@-r1
+ fmov.s fr11,@-r1
+ fmov.s fr8,@-r1
+ fmov.s fr9,@-r1
+ fmov.s fr6,@-r1
+ fmov.s fr7,@-r1
+ fmov.s fr4,@-r1
+ fmov.s fr5,@-r1
+#else
+ fmov.s fr11,@-r1
+ fmov.s fr10,@-r1
+ fmov.s fr9,@-r1
+ fmov.s fr8,@-r1
+ fmov.s fr7,@-r1
+ fmov.s fr6,@-r1
+ fmov.s fr5,@-r1
+ fmov.s fr4,@-r1
+#endif
+ mov r1,r7
+#endif
+
+ mov r14,r1
+ add #4,r1
+ mov r1,r5
+
+ mov r14,r1
+#if defined(__SH4__)
+ add #64,r1
+#else
+ add #32,r1
+#endif
+ mov.l r1,@r14
+
+ mov.l L_helper,r0
+ jsr @r0
+ mov r3,r4
+
+ shll r0
+ mov r0,r1
+ mova L_table,r0
+ add r1,r0
+ mov.w @r0,r0
+ mov r14,r2
+ braf r0
+ add #4,r2
+0:
+ .align 2
+L_helper:
+ .long ffi_closure_helper_SYSV
+L_table:
+ .short L_case_v - 0b /* FFI_TYPE_VOID */
+ .short L_case_i - 0b /* FFI_TYPE_INT */
+#if defined(__SH4__)
+ .short L_case_f - 0b /* FFI_TYPE_FLOAT */
+ .short L_case_d - 0b /* FFI_TYPE_DOUBLE */
+ .short L_case_d - 0b /* FFI_TYPE_LONGDOUBLE */
+#else
+ .short L_case_i - 0b /* FFI_TYPE_FLOAT */
+ .short L_case_ll - 0b /* FFI_TYPE_DOUBLE */
+ .short L_case_ll - 0b /* FFI_TYPE_LONGDOUBLE */
+#endif
+ .short L_case_uq - 0b /* FFI_TYPE_UINT8 */
+ .short L_case_q - 0b /* FFI_TYPE_SINT8 */
+ .short L_case_uh - 0b /* FFI_TYPE_UINT16 */
+ .short L_case_h - 0b /* FFI_TYPE_SINT16 */
+ .short L_case_i - 0b /* FFI_TYPE_UINT32 */
+ .short L_case_i - 0b /* FFI_TYPE_SINT32 */
+ .short L_case_ll - 0b /* FFI_TYPE_UINT64 */
+ .short L_case_ll - 0b /* FFI_TYPE_SINT64 */
+ .short L_case_v - 0b /* FFI_TYPE_STRUCT */
+ .short L_case_i - 0b /* FFI_TYPE_POINTER */
+
+#if defined(__SH4__)
+L_case_d:
+#ifdef __LITTLE_ENDIAN__
+ fmov.s @r2+,fr1
+ bra L_case_v
+ fmov.s @r2,fr0
+#else
+ fmov.s @r2+,fr0
+ bra L_case_v
+ fmov.s @r2,fr1
+#endif
+
+L_case_f:
+ bra L_case_v
+ fmov.s @r2,fr0
+#endif
+
+L_case_ll:
+ mov.l @r2+,r0
+ bra L_case_v
+ mov.l @r2,r1
+
+L_case_i:
+ bra L_case_v
+ mov.l @r2,r0
+
+L_case_q:
+#ifdef __LITTLE_ENDIAN__
+#else
+ add #3,r2
+#endif
+ bra L_case_v
+ mov.b @r2,r0
+
+L_case_uq:
+#ifdef __LITTLE_ENDIAN__
+#else
+ add #3,r2
+#endif
+ mov.b @r2,r0
+ bra L_case_v
+ extu.b r0,r0
+
+L_case_h:
+#ifdef __LITTLE_ENDIAN__
+#else
+ add #2,r2
+#endif
+ bra L_case_v
+ mov.w @r2,r0
+
+L_case_uh:
+#ifdef __LITTLE_ENDIAN__
+#else
+ add #2,r2
+#endif
+ mov.w @r2,r0
+ extu.w r0,r0
+ /* fall through */
+
+L_case_v:
+#if defined(__SH4__)
+ add #56,r15
+#else
+ add #24,r15
+#endif
+ lds.l @r15+,pr
+ rts
+ mov.l @r15+,r14
+
+.ffi_closure_SYSV_end:
+ .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)