| /* ----------------------------------------------------------------------- | |
| sysv.S - Copyright (c) 2003, 2004, 2006, 2008 Kaz Kojima | |
| SuperH SHmedia 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> | |
| #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 | |
| #ifdef __LITTLE_ENDIAN__ | |
| #define OFS_FLT 0 | |
| #else | |
| #define OFS_FLT 4 | |
| #endif | |
| .section .text..SHmedia32,"ax" | |
| # r2: ffi_prep_args | |
| # r3: &ecif | |
| # r4: bytes | |
| # r5: flags | |
| # r6: flags2 | |
| # r7: rvalue | |
| # r8: fn | |
| # This assumes we are using gas. | |
| .align 5 | |
| ENTRY(ffi_call_SYSV) | |
| # Save registers | |
| .LFB1: | |
| addi.l r15, -48, r15 | |
| .LCFI0: | |
| st.q r15, 40, r32 | |
| st.q r15, 32, r31 | |
| st.q r15, 24, r30 | |
| st.q r15, 16, r29 | |
| st.q r15, 8, r28 | |
| st.l r15, 4, r18 | |
| st.l r15, 0, r14 | |
| .LCFI1: | |
| add.l r15, r63, r14 | |
| .LCFI2: | |
| # add r4, r63, r28 | |
| add r5, r63, r29 | |
| add r6, r63, r30 | |
| add r7, r63, r31 | |
| add r8, r63, r32 | |
| addi r4, (64 + 7), r4 | |
| andi r4, ~7, r4 | |
| sub.l r15, r4, r15 | |
| ptabs/l r2, tr0 | |
| add r15, r63, r2 | |
| blink tr0, r18 | |
| addi r15, 64, r22 | |
| movi 0, r0 | |
| movi 0, r1 | |
| movi -1, r23 | |
| pt/l 1f, tr1 | |
| bnei/l r29, FFI_TYPE_STRUCT, tr1 | |
| ld.l r15, 0, r19 | |
| addi r15, 8, r15 | |
| addi r0, 1, r0 | |
| 1: | |
| .L_pass: | |
| andi r30, 3, r20 | |
| shlri r30, 2, r30 | |
| pt/l .L_call_it, tr0 | |
| pt/l .L_pass_i, tr1 | |
| pt/l .L_pass_f, tr2 | |
| beqi/l r20, FFI_TYPE_VOID, tr0 | |
| beqi/l r20, FFI_TYPE_INT, tr1 | |
| beqi/l r20, FFI_TYPE_FLOAT, tr2 | |
| .L_pass_d: | |
| addi r0, 1, r0 | |
| pt/l 3f, tr0 | |
| movi 12, r20 | |
| bge/l r1, r20, tr0 | |
| pt/l .L_pop_d, tr1 | |
| pt/l 2f, tr0 | |
| blink tr1, r63 | |
| 2: | |
| addi.l r15, 8, r15 | |
| 3: | |
| pt/l .L_pass, tr0 | |
| addi r1, 2, r1 | |
| blink tr0, r63 | |
| .L_pop_d: | |
| pt/l .L_pop_d_tbl, tr1 | |
| gettr tr1, r20 | |
| shlli r1, 2, r21 | |
| add r20, r21, r20 | |
| ptabs/l r20, tr1 | |
| blink tr1, r63 | |
| .L_pop_d_tbl: | |
| fld.d r15, 0, dr0 | |
| blink tr0, r63 | |
| fld.d r15, 0, dr2 | |
| blink tr0, r63 | |
| fld.d r15, 0, dr4 | |
| blink tr0, r63 | |
| fld.d r15, 0, dr6 | |
| blink tr0, r63 | |
| fld.d r15, 0, dr8 | |
| blink tr0, r63 | |
| fld.d r15, 0, dr10 | |
| blink tr0, r63 | |
| .L_pass_f: | |
| addi r0, 1, r0 | |
| pt/l 3f, tr0 | |
| movi 12, r20 | |
| bge/l r1, r20, tr0 | |
| pt/l .L_pop_f, tr1 | |
| pt/l 2f, tr0 | |
| blink tr1, r63 | |
| 2: | |
| addi.l r15, 8, r15 | |
| 3: | |
| pt/l .L_pass, tr0 | |
| blink tr0, r63 | |
| .L_pop_f: | |
| pt/l .L_pop_f_tbl, tr1 | |
| pt/l 5f, tr2 | |
| gettr tr1, r20 | |
| bge/l r23, r63, tr2 | |
| add r1, r63, r23 | |
| shlli r1, 3, r21 | |
| addi r1, 2, r1 | |
| add r20, r21, r20 | |
| ptabs/l r20, tr1 | |
| blink tr1, r63 | |
| 5: | |
| addi r23, 1, r21 | |
| movi -1, r23 | |
| shlli r21, 3, r21 | |
| add r20, r21, r20 | |
| ptabs/l r20, tr1 | |
| blink tr1, r63 | |
| .L_pop_f_tbl: | |
| fld.s r15, OFS_FLT, fr0 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr1 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr2 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr3 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr4 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr5 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr6 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr7 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr8 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr9 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr10 | |
| blink tr0, r63 | |
| fld.s r15, OFS_FLT, fr11 | |
| blink tr0, r63 | |
| .L_pass_i: | |
| pt/l 3f, tr0 | |
| movi 8, r20 | |
| bge/l r0, r20, tr0 | |
| pt/l .L_pop_i, tr1 | |
| pt/l 2f, tr0 | |
| blink tr1, r63 | |
| 2: | |
| addi.l r15, 8, r15 | |
| 3: | |
| pt/l .L_pass, tr0 | |
| addi r0, 1, r0 | |
| blink tr0, r63 | |
| .L_pop_i: | |
| pt/l .L_pop_i_tbl, tr1 | |
| gettr tr1, r20 | |
| shlli r0, 3, r21 | |
| add r20, r21, r20 | |
| ptabs/l r20, tr1 | |
| blink tr1, r63 | |
| .L_pop_i_tbl: | |
| ld.q r15, 0, r2 | |
| blink tr0, r63 | |
| ld.q r15, 0, r3 | |
| blink tr0, r63 | |
| ld.q r15, 0, r4 | |
| blink tr0, r63 | |
| ld.q r15, 0, r5 | |
| blink tr0, r63 | |
| ld.q r15, 0, r6 | |
| blink tr0, r63 | |
| ld.q r15, 0, r7 | |
| blink tr0, r63 | |
| ld.q r15, 0, r8 | |
| blink tr0, r63 | |
| ld.q r15, 0, r9 | |
| blink tr0, r63 | |
| .L_call_it: | |
| # call function | |
| pt/l 1f, tr1 | |
| bnei/l r29, FFI_TYPE_STRUCT, tr1 | |
| add r19, r63, r2 | |
| 1: | |
| add r22, r63, r15 | |
| ptabs/l r32, tr0 | |
| blink tr0, r18 | |
| pt/l .L_ret_i, tr0 | |
| pt/l .L_ret_ll, tr1 | |
| pt/l .L_ret_d, tr2 | |
| pt/l .L_ret_f, tr3 | |
| pt/l .L_epilogue, tr4 | |
| beqi/l r29, FFI_TYPE_INT, tr0 | |
| beqi/l r29, FFI_TYPE_UINT32, tr0 | |
| beqi/l r29, FFI_TYPE_SINT64, tr1 | |
| beqi/l r29, FFI_TYPE_UINT64, tr1 | |
| beqi/l r29, FFI_TYPE_DOUBLE, tr2 | |
| beqi/l r29, FFI_TYPE_FLOAT, tr3 | |
| pt/l .L_ret_q, tr0 | |
| pt/l .L_ret_h, tr1 | |
| beqi/l r29, FFI_TYPE_UINT8, tr0 | |
| beqi/l r29, FFI_TYPE_UINT16, tr1 | |
| blink tr4, r63 | |
| .L_ret_d: | |
| fst.d r31, 0, dr0 | |
| blink tr4, r63 | |
| .L_ret_ll: | |
| st.q r31, 0, r2 | |
| blink tr4, r63 | |
| .L_ret_f: | |
| fst.s r31, OFS_FLT, fr0 | |
| blink tr4, r63 | |
| .L_ret_q: | |
| st.b r31, 0, r2 | |
| blink tr4, r63 | |
| .L_ret_h: | |
| st.w r31, 0, r2 | |
| blink tr4, r63 | |
| .L_ret_i: | |
| st.l r31, 0, r2 | |
| # Fall | |
| .L_epilogue: | |
| # Remove the space we pushed for the args | |
| add r14, r63, r15 | |
| ld.l r15, 0, r14 | |
| ld.l r15, 4, r18 | |
| ld.q r15, 8, r28 | |
| ld.q r15, 16, r29 | |
| ld.q r15, 24, r30 | |
| ld.q r15, 32, r31 | |
| ld.q r15, 40, r32 | |
| addi.l r15, 48, r15 | |
| ptabs r18, tr0 | |
| blink tr0, r63 | |
| .LFE1: | |
| .ffi_call_SYSV_end: | |
| .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) | |
| .align 5 | |
| ENTRY(ffi_closure_SYSV) | |
| .LFB2: | |
| addi.l r15, -136, r15 | |
| .LCFI3: | |
| st.l r15, 12, r18 | |
| st.l r15, 8, r14 | |
| st.l r15, 4, r12 | |
| .LCFI4: | |
| add r15, r63, r14 | |
| .LCFI5: | |
| /* Stack layout: | |
| ... | |
| 64 bytes (register parameters) | |
| 48 bytes (floating register parameters) | |
| 8 bytes (result) | |
| 4 bytes (r18) | |
| 4 bytes (r14) | |
| 4 bytes (r12) | |
| 4 bytes (for align) | |
| <- new stack pointer | |
| */ | |
| fst.d r14, 24, dr0 | |
| fst.d r14, 32, dr2 | |
| fst.d r14, 40, dr4 | |
| fst.d r14, 48, dr6 | |
| fst.d r14, 56, dr8 | |
| fst.d r14, 64, dr10 | |
| st.q r14, 72, r2 | |
| st.q r14, 80, r3 | |
| st.q r14, 88, r4 | |
| st.q r14, 96, r5 | |
| st.q r14, 104, r6 | |
| st.q r14, 112, r7 | |
| st.q r14, 120, r8 | |
| st.q r14, 128, r9 | |
| add r1, r63, r2 | |
| addi r14, 16, r3 | |
| addi r14, 72, r4 | |
| addi r14, 24, r5 | |
| addi r14, 136, r6 | |
| #ifdef PIC | |
| movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12 | |
| shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12 | |
| .LPCS0: ptrel/u r12, tr0 | |
| movi ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1 | |
| gettr tr0, r12 | |
| ldx.l r1, r12, r1 | |
| ptabs r1, tr0 | |
| #else | |
| pt/l ffi_closure_helper_SYSV, tr0 | |
| #endif | |
| blink tr0, r18 | |
| shlli r2, 1, r1 | |
| movi (((datalabel .L_table) >> 16) & 65535), r2 | |
| shori ((datalabel .L_table) & 65535), r2 | |
| ldx.w r2, r1, r1 | |
| add r1, r2, r1 | |
| pt/l .L_case_v, tr1 | |
| ptabs r1, tr0 | |
| blink tr0, r63 | |
| .align 2 | |
| .L_table: | |
| .word .L_case_v - datalabel .L_table /* FFI_TYPE_VOID */ | |
| .word .L_case_i - datalabel .L_table /* FFI_TYPE_INT */ | |
| .word .L_case_f - datalabel .L_table /* FFI_TYPE_FLOAT */ | |
| .word .L_case_d - datalabel .L_table /* FFI_TYPE_DOUBLE */ | |
| .word .L_case_d - datalabel .L_table /* FFI_TYPE_LONGDOUBLE */ | |
| .word .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */ | |
| .word .L_case_q - datalabel .L_table /* FFI_TYPE_SINT8 */ | |
| .word .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */ | |
| .word .L_case_h - datalabel .L_table /* FFI_TYPE_SINT16 */ | |
| .word .L_case_i - datalabel .L_table /* FFI_TYPE_UINT32 */ | |
| .word .L_case_i - datalabel .L_table /* FFI_TYPE_SINT32 */ | |
| .word .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */ | |
| .word .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */ | |
| .word .L_case_v - datalabel .L_table /* FFI_TYPE_STRUCT */ | |
| .word .L_case_i - datalabel .L_table /* FFI_TYPE_POINTER */ | |
| .align 2 | |
| .L_case_d: | |
| fld.d r14, 16, dr0 | |
| blink tr1, r63 | |
| .L_case_f: | |
| fld.s r14, 16, fr0 | |
| blink tr1, r63 | |
| .L_case_ll: | |
| ld.q r14, 16, r2 | |
| blink tr1, r63 | |
| .L_case_i: | |
| ld.l r14, 16, r2 | |
| blink tr1, r63 | |
| .L_case_q: | |
| ld.b r14, 16, r2 | |
| blink tr1, r63 | |
| .L_case_uq: | |
| ld.ub r14, 16, r2 | |
| blink tr1, r63 | |
| .L_case_h: | |
| ld.w r14, 16, r2 | |
| blink tr1, r63 | |
| .L_case_uh: | |
| ld.uw r14, 16, r2 | |
| blink tr1, r63 | |
| .L_case_v: | |
| add.l r14, r63, r15 | |
| ld.l r15, 4, r12 | |
| ld.l r15, 8, r14 | |
| ld.l r15, 12, r18 | |
| addi.l r15, 136, r15 | |
| ptabs r18, tr0 | |
| blink tr0, r63 | |
| .LFE2: | |
| .ffi_closure_SYSV_end: | |
| .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) | |
| #if defined __ELF__ && defined __linux__ | |
| .section .note.GNU-stack,"",@progbits | |
| #endif | |
| .section ".eh_frame","aw",@progbits | |
| __FRAME_BEGIN__: | |
| .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ | |
| .LSCIE1: | |
| .4byte 0x0 /* CIE Identifier Tag */ | |
| .byte 0x1 /* CIE Version */ | |
| #ifdef PIC | |
| .ascii "zR\0" /* CIE Augmentation */ | |
| #else | |
| .byte 0x0 /* CIE Augmentation */ | |
| #endif | |
| .uleb128 0x1 /* CIE Code Alignment Factor */ | |
| .sleb128 -4 /* CIE Data Alignment Factor */ | |
| .byte 0x12 /* CIE RA Column */ | |
| #ifdef PIC | |
| .uleb128 0x1 /* Augmentation size */ | |
| .byte 0x10 /* FDE Encoding (pcrel) */ | |
| #endif | |
| .byte 0xc /* DW_CFA_def_cfa */ | |
| .uleb128 0xf | |
| .uleb128 0x0 | |
| .align 2 | |
| .LECIE1: | |
| .LSFDE1: | |
| .4byte datalabel .LEFDE1-datalabel .LASFDE1 /* FDE Length */ | |
| .LASFDE1: | |
| .4byte datalabel .LASFDE1-datalabel __FRAME_BEGIN__ | |
| #ifdef PIC | |
| .4byte .LFB1-. /* FDE initial location */ | |
| #else | |
| .4byte .LFB1 /* FDE initial location */ | |
| #endif | |
| .4byte datalabel .LFE1-datalabel .LFB1 /* FDE address range */ | |
| #ifdef PIC | |
| .uleb128 0x0 /* Augmentation size */ | |
| #endif | |
| .byte 0x4 /* DW_CFA_advance_loc4 */ | |
| .4byte datalabel .LCFI0-datalabel .LFB1 | |
| .byte 0xe /* DW_CFA_def_cfa_offset */ | |
| .uleb128 0x30 | |
| .byte 0x4 /* DW_CFA_advance_loc4 */ | |
| .4byte datalabel .LCFI1-datalabel .LCFI0 | |
| .byte 0x8e /* DW_CFA_offset, column 0xe */ | |
| .uleb128 0xc | |
| .byte 0x92 /* DW_CFA_offset, column 0x12 */ | |
| .uleb128 0xb | |
| .byte 0x9c /* DW_CFA_offset, column 0x1c */ | |
| .uleb128 0xa | |
| .byte 0x9d /* DW_CFA_offset, column 0x1d */ | |
| .uleb128 0x8 | |
| .byte 0x9e /* DW_CFA_offset, column 0x1e */ | |
| .uleb128 0x6 | |
| .byte 0x9f /* DW_CFA_offset, column 0x1f */ | |
| .uleb128 0x4 | |
| .byte 0xa0 /* DW_CFA_offset, column 0x20 */ | |
| .uleb128 0x2 | |
| .byte 0x4 /* DW_CFA_advance_loc4 */ | |
| .4byte datalabel .LCFI2-datalabel .LCFI1 | |
| .byte 0xd /* DW_CFA_def_cfa_register */ | |
| .uleb128 0xe | |
| .align 2 | |
| .LEFDE1: | |
| .LSFDE3: | |
| .4byte datalabel .LEFDE3-datalabel .LASFDE3 /* FDE Length */ | |
| .LASFDE3: | |
| .4byte datalabel .LASFDE3-datalabel __FRAME_BEGIN__ | |
| #ifdef PIC | |
| .4byte .LFB2-. /* FDE initial location */ | |
| #else | |
| .4byte .LFB2 /* FDE initial location */ | |
| #endif | |
| .4byte datalabel .LFE2-datalabel .LFB2 /* FDE address range */ | |
| #ifdef PIC | |
| .uleb128 0x0 /* Augmentation size */ | |
| #endif | |
| .byte 0x4 /* DW_CFA_advance_loc4 */ | |
| .4byte datalabel .LCFI3-datalabel .LFB2 | |
| .byte 0xe /* DW_CFA_def_cfa_offset */ | |
| .uleb128 0x88 | |
| .byte 0x4 /* DW_CFA_advance_loc4 */ | |
| .4byte datalabel .LCFI4-datalabel .LCFI3 | |
| .byte 0x8c /* DW_CFA_offset, column 0xc */ | |
| .uleb128 0x21 | |
| .byte 0x8e /* DW_CFA_offset, column 0xe */ | |
| .uleb128 0x20 | |
| .byte 0x92 /* DW_CFA_offset, column 0x12 */ | |
| .uleb128 0x1f | |
| .byte 0x4 /* DW_CFA_advance_loc4 */ | |
| .4byte datalabel .LCFI5-datalabel .LCFI4 | |
| .byte 0xd /* DW_CFA_def_cfa_register */ | |
| .uleb128 0xe | |
| .align 2 | |
| .LEFDE3: |