111
|
1 /* -----------------------------------------------------------------------
|
|
2 sysv.S - Copyright (c) 2013 Tensilica, Inc.
|
|
3
|
|
4 XTENSA Foreign Function Interface
|
|
5
|
|
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:
|
|
13
|
|
14 The above copyright notice and this permission notice shall be included
|
|
15 in all copies or substantial portions of the Software.
|
|
16
|
|
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 ----------------------------------------------------------------------- */
|
|
26
|
|
27 #define LIBFFI_ASM
|
|
28 #include <fficonfig.h>
|
|
29 #include <ffi.h>
|
|
30
|
|
31 #define ENTRY(name) .text; .globl name; .type name,@function; .align 4; name:
|
|
32 #define END(name) .size name , . - name
|
|
33
|
|
34 /* Assert that the table below is in sync with ffi.h. */
|
|
35
|
|
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"
|
|
44 #endif
|
|
45
|
|
46
|
|
47 /* ffi_call_SYSV (rvalue, rbytes, flags, (*fnaddr)(), bytes, ecif)
|
|
48 void *rvalue; a2
|
|
49 unsigned long rbytes; a3
|
|
50 unsigned flags; a4
|
|
51 void (*fnaddr)(); a5
|
|
52 unsigned long bytes; a6
|
|
53 extended_cif* ecif) a7
|
|
54 */
|
|
55
|
|
56 ENTRY(ffi_call_SYSV)
|
|
57
|
|
58 entry a1, 32 # 32 byte frame for using call8 below
|
|
59
|
|
60 mov a10, a7 # a10(->arg0): ecif
|
|
61 sub a11, a1, a6 # a11(->arg1): stack pointer
|
|
62 mov a7, a1 # fp
|
|
63 movsp a1, a11 # set new sp = old_sp - bytes
|
|
64
|
|
65 movi a8, ffi_prep_args
|
|
66 callx8 a8 # ffi_prep_args(ecif, stack)
|
|
67
|
|
68 # prepare to move stack pointer back up to 6 arguments
|
|
69 # note that 'bytes' is already aligned
|
|
70
|
|
71 movi a10, 6*4
|
|
72 sub a11, a6, a10
|
|
73 movgez a6, a10, a11
|
|
74 add a6, a1, a6
|
|
75
|
|
76
|
|
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)
|
|
80
|
|
81 l32i a10, a1, 0
|
|
82 l32i a11, a1, 4
|
|
83 l32i a12, a1, 8
|
|
84 l32i a13, a1, 12
|
|
85 l32i a14, a1, 16
|
|
86 l32i a15, a1, 20
|
|
87
|
|
88 # move stack pointer
|
|
89
|
|
90 movsp a1, a6
|
|
91
|
|
92 callx8 a5 # (*fn)(args...)
|
|
93
|
|
94 # Handle return value(s)
|
|
95
|
|
96 beqz a2, .Lexit
|
|
97
|
|
98 movi a5, FFI_TYPE_STRUCT
|
|
99 bne a4, a5, .Lstore
|
|
100 movi a5, 16
|
|
101 blt a5, a3, .Lexit
|
|
102
|
|
103 s32i a10, a2, 0
|
|
104 blti a3, 5, .Lexit
|
|
105 addi a3, a3, -1
|
|
106 s32i a11, a2, 4
|
|
107 blti a3, 8, .Lexit
|
|
108 s32i a12, a2, 8
|
|
109 blti a3, 12, .Lexit
|
|
110 s32i a13, a2, 12
|
|
111
|
|
112 .Lexit: retw
|
|
113
|
|
114 .Lstore:
|
|
115 addi a4, a4, -FFI_TYPE_UINT8
|
|
116 bgei a4, 7, .Lexit # should never happen
|
|
117 movi a6, store_calls
|
|
118 add a4, a4, a4
|
|
119 addx4 a6, a4, a6 # store_table + idx * 8
|
|
120 jx a6
|
|
121
|
|
122 .align 8
|
|
123 store_calls:
|
|
124 # UINT8
|
|
125 s8i a10, a2, 0
|
|
126 retw
|
|
127
|
|
128 # SINT8
|
|
129 .align 8
|
|
130 s8i a10, a2, 0
|
|
131 retw
|
|
132
|
|
133 # UINT16
|
|
134 .align 8
|
|
135 s16i a10, a2, 0
|
|
136 retw
|
|
137
|
|
138 # SINT16
|
|
139 .align 8
|
|
140 s16i a10, a2, 0
|
|
141 retw
|
|
142
|
|
143 # UINT32
|
|
144 .align 8
|
|
145 s32i a10, a2, 0
|
|
146 retw
|
|
147
|
|
148 # SINT32
|
|
149 .align 8
|
|
150 s32i a10, a2, 0
|
|
151 retw
|
|
152
|
|
153 # UINT64
|
|
154 .align 8
|
|
155 s32i a10, a2, 0
|
|
156 s32i a11, a2, 4
|
|
157 retw
|
|
158
|
|
159 END(ffi_call_SYSV)
|
|
160
|
|
161
|
|
162 /*
|
|
163 * void ffi_cacheflush (unsigned long start, unsigned long end)
|
|
164 */
|
|
165
|
|
166 #define EXTRA_ARGS_SIZE 24
|
|
167
|
|
168 ENTRY(ffi_cacheflush)
|
|
169
|
|
170 entry a1, 16
|
|
171
|
|
172 1: dhwbi a2, 0
|
|
173 ihi a2, 0
|
|
174 addi a2, a2, 4
|
|
175 blt a2, a3, 1b
|
|
176
|
|
177 retw
|
|
178
|
|
179 END(ffi_cacheflush)
|
|
180
|
|
181 /* ffi_trampoline is copied to the stack */
|
|
182
|
|
183 ENTRY(ffi_trampoline)
|
|
184
|
|
185 entry a1, 16 + (FFI_REGISTER_NARGS * 4) + (4 * 4) # [ 0]
|
|
186 j 2f # [ 3]
|
|
187 .align 4 # [ 6]
|
|
188 1: .long 0 # [ 8]
|
|
189 2: l32r a15, 1b # [12]
|
|
190 _mov a14, a0 # [15]
|
|
191 callx0 a15 # [18]
|
|
192 # [21]
|
|
193 END(ffi_trampoline)
|
|
194
|
|
195 /*
|
|
196 * ffi_closure()
|
|
197 *
|
|
198 * a0: closure + 21
|
|
199 * a14: return address (a0)
|
|
200 */
|
|
201
|
|
202 ENTRY(ffi_closure_SYSV)
|
|
203
|
|
204 /* intentionally omitting entry here */
|
|
205
|
|
206 # restore return address (a0) and move pointer to closure to a10
|
|
207 addi a10, a0, -21
|
|
208 mov a0, a14
|
|
209
|
|
210 # allow up to 4 arguments as return values
|
|
211 addi a11, a1, 4 * 4
|
|
212
|
|
213 # save up to 6 arguments to stack (allocated by entry below)
|
|
214 s32i a2, a11, 0
|
|
215 s32i a3, a11, 4
|
|
216 s32i a4, a11, 8
|
|
217 s32i a5, a11, 12
|
|
218 s32i a6, a11, 16
|
|
219 s32i a7, a11, 20
|
|
220
|
|
221 movi a8, ffi_closure_SYSV_inner
|
|
222 mov a12, a1
|
|
223 callx8 a8 # .._inner(*closure, **avalue, *rvalue)
|
|
224
|
|
225 # load up to four return arguments
|
|
226 l32i a2, a1, 0
|
|
227 l32i a3, a1, 4
|
|
228 l32i a4, a1, 8
|
|
229 l32i a5, a1, 12
|
|
230
|
|
231 # (sign-)extend return value
|
|
232 movi a11, FFI_TYPE_UINT8
|
|
233 bne a10, a11, 1f
|
|
234 extui a2, a2, 0, 8
|
|
235 retw
|
|
236
|
|
237 1: movi a11, FFI_TYPE_SINT8
|
|
238 bne a10, a11, 1f
|
|
239 sext a2, a2, 7
|
|
240 retw
|
|
241
|
|
242 1: movi a11, FFI_TYPE_UINT16
|
|
243 bne a10, a11, 1f
|
|
244 extui a2, a2, 0, 16
|
|
245 retw
|
|
246
|
|
247 1: movi a11, FFI_TYPE_SINT16
|
|
248 bne a10, a11, 1f
|
|
249 sext a2, a2, 15
|
|
250
|
|
251 1: retw
|
|
252
|
|
253 END(ffi_closure_SYSV)
|