1 /* -----------------------------------------------------------------------
2 sysv.S - Copyright (c) 2013 Tensilica, Inc.
4 XTENSA Foreign Function Interface
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 ``Software''), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be included
15 in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 DEALINGS IN THE SOFTWARE.
25 ----------------------------------------------------------------------- */
28 #include <fficonfig.h>
31 #define ENTRY(name) .text; .globl name; .type name,@function; .align 4; name:
32 #define END(name) .size name , . - name
34 /* Assert that the table below is in sync with ffi.h. */
36 #if FFI_TYPE_UINT8 != 5 \
37 || FFI_TYPE_SINT8 != 6 \
38 || FFI_TYPE_UINT16 != 7 \
39 || FFI_TYPE_SINT16 != 8 \
40 || FFI_TYPE_UINT32 != 9 \
41 || FFI_TYPE_SINT32 != 10 \
42 || FFI_TYPE_UINT64 != 11
43 #error "xtensa/sysv.S out of sync with ffi.h"
47 /* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif)
49 unsigned long rbytes; a3
52 unsigned long bytes; a6
53 extended_cif* ecif) a7
58 entry a1, 32 # 32 byte frame for using call8 below
60 mov a10, a7 # a10(->arg0): ecif
61 sub a11, a1, a6 # a11(->arg1): stack pointer
63 movsp a1, a11 # set new sp = old_sp - bytes
65 movi a8, ffi_prep_args
66 callx8 a8 # ffi_prep_args(ecif, stack)
68 # prepare to move stack pointer back up to 6 arguments
69 # note that 'bytes' is already aligned
77 # we can pass up to 6 arguments in registers
78 # for simplicity, just load 6 arguments
79 # (the stack size is at least 32 bytes, so no risk to cross boundaries)
92 callx8 a5 # (*fn)(args...)
94 # Handle return value(s)
98 movi a5, FFI_TYPE_STRUCT
115 addi a4, a4, -FFI_TYPE_UINT8
116 bgei a4, 7, .Lexit # should never happen
119 addx4 a6, a4, a6 # store_table + idx * 8
163 * void ffi_cacheflush (unsigned long start, unsigned long end)
166 #define EXTRA_ARGS_SIZE 24
168 ENTRY(ffi_cacheflush)
181 /* ffi_trampoline is copied to the stack */
183 ENTRY(ffi_trampoline)
185 entry a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4) # [ 0]
189 2: l32r a15, 1b # [12]
199 * a14: return address (a0)
202 ENTRY(ffi_closure_SYSV)
204 /* intentionally omitting entry here */
206 # restore return address (a0) and move pointer to closure to a10
210 # allow up to 4 arguments as return values
213 # save up to 6 arguments to stack (allocated by entry below)
221 movi a8, ffi_closure_SYSV_inner
223 callx8 a8 # .._inner(*closure, **avalue, *rvalue)
225 # load up to four return arguments
231 # (sign-)extend return value
232 movi a11, FFI_TYPE_UINT8
237 1: movi a11, FFI_TYPE_SINT8
242 1: movi a11, FFI_TYPE_UINT16
247 1: movi a11, FFI_TYPE_SINT16
253 END(ffi_closure_SYSV)