LWG 3035. std::allocator's constructors should be constexpr
[official-gcc.git] / libffi / src / xtensa / sysv.S
blob64e6a0918d0248d9d19177769ccf8fc91c6cb872
1 /* -----------------------------------------------------------------------
2    sysv.S - Copyright (c) 2013 Tensilica, Inc.
3    
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    ----------------------------------------------------------------------- */
27 #define LIBFFI_ASM
28 #include <fficonfig.h>
29 #include <ffi.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"
44 #endif
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
56 ENTRY(ffi_call_SYSV)
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
62         mov     a7, a1              # fp
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
71         movi    a10, 6*4 
72         sub     a11, a6, a10
73         movgez  a6, a10, a11
74         add     a6, a1, a6
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)
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
88         # move stack pointer
90         movsp   a1, a6
92         callx8  a5                  # (*fn)(args...)
94         # Handle return value(s)
96         beqz    a2, .Lexit
98         movi    a5, FFI_TYPE_STRUCT
99         bne     a4, a5, .Lstore
100         movi    a5, 16
101         blt     a5, a3, .Lexit
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
112 .Lexit: retw
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
122         .align  8
123 store_calls:
124         # UINT8
125         s8i     a10, a2, 0
126         retw
128         # SINT8
129         .align  8
130         s8i     a10, a2, 0
131         retw
133         # UINT16
134         .align  8
135         s16i    a10, a2, 0
136         retw
138         # SINT16
139         .align  8
140         s16i    a10, a2, 0
141         retw
143         # UINT32
144         .align  8
145         s32i    a10, a2, 0
146         retw
148         # SINT32
149         .align  8
150         s32i    a10, a2, 0
151         retw
153         # UINT64
154         .align  8
155         s32i    a10, a2, 0
156         s32i    a11, a2, 4
157         retw
159 END(ffi_call_SYSV)
163  * void ffi_cacheflush (unsigned long start, unsigned long end)
164  */
166 #define EXTRA_ARGS_SIZE 24
168 ENTRY(ffi_cacheflush)
170         entry   a1, 16
172 1:      dhwbi   a2, 0
173         ihi     a2, 0
174         addi    a2, a2, 4
175         blt     a2, a3, 1b
177         retw
179 END(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]
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)
196  * ffi_closure()
198  * a0:  closure + 21
199  * a14: return address (a0)
200  */
202 ENTRY(ffi_closure_SYSV)
204         /* intentionally omitting entry here */
206         # restore return address (a0) and move pointer to closure to a10
207         addi    a10, a0, -21
208         mov     a0, a14
210         # allow up to 4 arguments as return values
211         addi    a11, a1, 4 * 4
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
221         movi    a8, ffi_closure_SYSV_inner
222         mov     a12, a1
223         callx8  a8                      # .._inner(*closure, **avalue, *rvalue)
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
231         # (sign-)extend return value
232         movi    a11, FFI_TYPE_UINT8
233         bne     a10, a11, 1f
234         extui   a2, a2, 0, 8
235         retw
237 1:      movi    a11, FFI_TYPE_SINT8
238         bne     a10, a11, 1f
239         sext    a2, a2, 7
240         retw
242 1:      movi    a11, FFI_TYPE_UINT16
243         bne     a10, a11, 1f
244         extui   a2, a2, 0, 16
245         retw
247 1:      movi    a11, FFI_TYPE_SINT16
248         bne     a10, a11, 1f
249         sext    a2, a2, 15
251 1:      retw
253 END(ffi_closure_SYSV)