| /* ----------------------------------------------------------------------- |
| 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__ */ |