]> git.ipfire.org Git - thirdparty/gcc.git/blob - libffi/src/sparc/v8.S
Merge with upstream libffi db1b34b7e1f5e473d17557e454a29933dfecd1af
[thirdparty/gcc.git] / libffi / src / sparc / v8.S
1 /* -----------------------------------------------------------------------
2 v8.S - Copyright (c) 2013 The Written Word, Inc.
3 Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
4
5 SPARC Foreign Function Interface
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 ``Software''), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 DEALINGS IN THE SOFTWARE.
26 ----------------------------------------------------------------------- */
27
28 #define LIBFFI_ASM
29 #include <fficonfig.h>
30 #include <ffi.h>
31 #include "internal.h"
32
33 #ifndef SPARC64
34
35 #define C2(X, Y) X ## Y
36 #define C1(X, Y) C2(X, Y)
37
38 #ifdef __USER_LABEL_PREFIX__
39 # define C(Y) C1(__USER_LABEL_PREFIX__, Y)
40 #else
41 # define C(Y) Y
42 #endif
43 #define L(Y) C1(.L, Y)
44
45 .text
46
47 #ifndef __GNUC__
48 .align 8
49 .globl C(ffi_flush_icache)
50 .type C(ffi_flush_icache),#function
51 FFI_HIDDEN(C(ffi_flush_icache))
52
53 C(ffi_flush_icache):
54 1: iflush %o0
55 iflush %o+8
56 nop
57 nop
58 nop
59 nop
60 nop
61 retl
62 nop
63 .size C(ffi_flush_icache), . - C(ffi_flush_icache)
64 #endif
65
66 #if defined(__sun__) && defined(__svr4__)
67 # define E(INDEX) .align 16
68 #else
69 # define E(INDEX) .align 16; .org 2b + INDEX * 16
70 #endif
71
72 .align 8
73 .globl C(ffi_call_v8)
74 .type C(ffi_call_v8),#function
75 FFI_HIDDEN(C(ffi_call_v8))
76
77 C(ffi_call_v8):
78 .LUW0:
79 ! Allocate a stack frame sized by ffi_call.
80 save %sp, %o4, %sp
81 .LUW1:
82 mov %i0, %o0 ! copy cif
83 add %sp, 64+32, %o1 ! load args area
84 mov %i2, %o2 ! copy rvalue
85 call C(ffi_prep_args_v8)
86 mov %i3, %o3 ! copy avalue
87
88 add %sp, 32, %sp ! deallocate prep frame
89 and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type
90 srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size
91 ld [%sp+64+4], %o0 ! load all argument registers
92 ld [%sp+64+8], %o1
93 ld [%sp+64+12], %o2
94 ld [%sp+64+16], %o3
95 cmp %l0, SPARC_RET_STRUCT ! struct return needs an unimp 4
96 ld [%sp+64+20], %o4
97 be 8f
98 ld [%sp+64+24], %o5
99
100 ! Call foreign function
101 call %i1
102 mov %i5, %g2 ! load static chain
103
104 0: call 1f ! load pc in %o7
105 sll %l0, 4, %l0
106 1: add %o7, %l0, %o7 ! o7 = 0b + ret_type*16
107 jmp %o7+(2f-0b)
108 nop
109
110 ! Note that each entry is 4 insns, enforced by the E macro.
111 .align 16
112 2:
113 E(SPARC_RET_VOID)
114 ret
115 restore
116 E(SPARC_RET_STRUCT)
117 unimp
118 E(SPARC_RET_UINT8)
119 and %o0, 0xff, %o0
120 st %o0, [%i2]
121 ret
122 restore
123 E(SPARC_RET_SINT8)
124 sll %o0, 24, %o0
125 b 7f
126 sra %o0, 24, %o0
127 E(SPARC_RET_UINT16)
128 sll %o0, 16, %o0
129 b 7f
130 srl %o0, 16, %o0
131 E(SPARC_RET_SINT16)
132 sll %o0, 16, %o0
133 b 7f
134 sra %o0, 16, %o0
135 E(SPARC_RET_UINT32)
136 7: st %o0, [%i2]
137 ret
138 restore
139 E(SP_V8_RET_CPLX16)
140 sth %o0, [%i2+2]
141 b 9f
142 srl %o0, 16, %o0
143 E(SPARC_RET_INT64)
144 st %o0, [%i2]
145 st %o1, [%i2+4]
146 ret
147 restore
148 E(SPARC_RET_INT128)
149 std %o0, [%i2]
150 std %o2, [%i2+8]
151 ret
152 restore
153 E(SPARC_RET_F_8)
154 st %f7, [%i2+7*4]
155 nop
156 st %f6, [%i2+6*4]
157 nop
158 E(SPARC_RET_F_6)
159 st %f5, [%i2+5*4]
160 nop
161 st %f4, [%i2+4*4]
162 nop
163 E(SPARC_RET_F_4)
164 st %f3, [%i2+3*4]
165 nop
166 st %f2, [%i2+2*4]
167 nop
168 E(SPARC_RET_F_2)
169 st %f1, [%i2+4]
170 st %f0, [%i2]
171 ret
172 restore
173 E(SP_V8_RET_CPLX8)
174 stb %o0, [%i2+1]
175 b 0f
176 srl %o0, 8, %o0
177 E(SPARC_RET_F_1)
178 st %f0, [%i2]
179 ret
180 restore
181
182 .align 8
183 9: sth %o0, [%i2]
184 ret
185 restore
186 .align 8
187 0: stb %o0, [%i2]
188 ret
189 restore
190
191 ! Struct returning functions expect and skip the unimp here.
192 ! To make it worse, conforming callees examine the unimp and
193 ! make sure the low 12 bits of the unimp match the size of
194 ! the struct being returned.
195 .align 8
196 8: call 1f ! load pc in %o7
197 sll %l1, 2, %l0 ! size * 4
198 1: sll %l1, 4, %l1 ! size * 16
199 add %l0, %l1, %l0 ! size * 20
200 add %o7, %l0, %o7 ! o7 = 8b + size*20
201 jmp %o7+(2f-8b)
202 mov %i5, %g2 ! load static chain
203 2:
204
205 /* The Sun assembler doesn't understand .rept 0x1000. */
206 #define rept1 \
207 call %i1; \
208 nop; \
209 unimp (. - 2b) / 20; \
210 ret; \
211 restore
212
213 #define rept16 \
214 rept1; rept1; rept1; rept1; \
215 rept1; rept1; rept1; rept1; \
216 rept1; rept1; rept1; rept1; \
217 rept1; rept1; rept1; rept1
218
219 #define rept256 \
220 rept16; rept16; rept16; rept16; \
221 rept16; rept16; rept16; rept16; \
222 rept16; rept16; rept16; rept16; \
223 rept16; rept16; rept16; rept16
224
225 rept256; rept256; rept256; rept256
226 rept256; rept256; rept256; rept256
227 rept256; rept256; rept256; rept256
228 rept256; rept256; rept256; rept256
229
230 .LUW2:
231 .size C(ffi_call_v8),. - C(ffi_call_v8)
232
233
234 /* 16*4 register window + 1*4 struct return + 6*4 args backing store
235 + 8*4 return storage + 1*4 alignment. */
236 #define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4)
237
238 /* ffi_closure_v8(...)
239
240 Receives the closure argument in %g2. */
241
242 #ifdef HAVE_AS_REGISTER_PSEUDO_OP
243 .register %g2, #scratch
244 #endif
245
246 .align 8
247 .globl C(ffi_go_closure_v8)
248 .type C(ffi_go_closure_v8),#function
249 FFI_HIDDEN(C(ffi_go_closure_v8))
250
251 C(ffi_go_closure_v8):
252 .LUW3:
253 save %sp, -STACKFRAME, %sp
254 .LUW4:
255 ld [%g2+4], %o0 ! load cif
256 ld [%g2+8], %o1 ! load fun
257 b 0f
258 mov %g2, %o2 ! load user_data
259 .LUW5:
260 .size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8)
261
262 .align 8
263 .globl C(ffi_closure_v8)
264 .type C(ffi_closure_v8),#function
265 FFI_HIDDEN(C(ffi_closure_v8))
266
267 C(ffi_closure_v8):
268 .LUW6:
269 save %sp, -STACKFRAME, %sp
270 .LUW7:
271 ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif
272 ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun
273 ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data
274 0:
275 ! Store all of the potential argument registers in va_list format.
276 st %i0, [%fp+68+0]
277 st %i1, [%fp+68+4]
278 st %i2, [%fp+68+8]
279 st %i3, [%fp+68+12]
280 st %i4, [%fp+68+16]
281 st %i5, [%fp+68+20]
282
283 ! Call ffi_closure_sparc_inner to do the bulk of the work.
284 add %fp, -8*4, %o3
285 call ffi_closure_sparc_inner_v8
286 add %fp, 64, %o4
287
288 0: call 1f
289 and %o0, SPARC_FLAG_RET_MASK, %o0
290 1: sll %o0, 4, %o0 ! o0 = o0 * 16
291 add %o7, %o0, %o7 ! o7 = 0b + o0*16
292 jmp %o7+(2f-0b)
293 add %fp, -8*4, %i2
294
295 ! Note that each entry is 4 insns, enforced by the E macro.
296 .align 16
297 2:
298 E(SPARC_RET_VOID)
299 ret
300 restore
301 E(SPARC_RET_STRUCT)
302 ld [%i2], %i0
303 jmp %i7+12
304 restore
305 E(SPARC_RET_UINT8)
306 ldub [%i2+3], %i0
307 ret
308 restore
309 E(SPARC_RET_SINT8)
310 ldsb [%i2+3], %i0
311 ret
312 restore
313 E(SPARC_RET_UINT16)
314 lduh [%i2+2], %i0
315 ret
316 restore
317 E(SPARC_RET_SINT16)
318 ldsh [%i2+2], %i0
319 ret
320 restore
321 E(SPARC_RET_UINT32)
322 ld [%i2], %i0
323 ret
324 restore
325 E(SP_V8_RET_CPLX16)
326 ld [%i2], %i0
327 ret
328 restore
329 E(SPARC_RET_INT64)
330 ldd [%i2], %i0
331 ret
332 restore
333 E(SPARC_RET_INT128)
334 ldd [%i2], %i0
335 ldd [%i2+8], %i2
336 ret
337 restore
338 E(SPARC_RET_F_8)
339 ld [%i2+7*4], %f7
340 nop
341 ld [%i2+6*4], %f6
342 nop
343 E(SPARC_RET_F_6)
344 ld [%i2+5*4], %f5
345 nop
346 ld [%i2+4*4], %f4
347 nop
348 E(SPARC_RET_F_4)
349 ld [%i2+3*4], %f3
350 nop
351 ld [%i2+2*4], %f2
352 nop
353 E(SPARC_RET_F_2)
354 ldd [%i2], %f0
355 ret
356 restore
357 E(SP_V8_RET_CPLX8)
358 lduh [%i2], %i0
359 ret
360 restore
361 E(SPARC_RET_F_1)
362 ld [%i2], %f0
363 ret
364 restore
365
366 .LUW8:
367 .size C(ffi_closure_v8), . - C(ffi_closure_v8)
368
369 #ifdef HAVE_RO_EH_FRAME
370 .section ".eh_frame",#alloc
371 #else
372 .section ".eh_frame",#alloc,#write
373 #endif
374
375 #ifdef HAVE_AS_SPARC_UA_PCREL
376 # define FDE_ADDR(X) %r_disp32(X)
377 #else
378 # define FDE_ADDR(X) X
379 #endif
380
381 .align 4
382 .LCIE:
383 .long .LECIE - .LSCIE ! CIE Length
384 .LSCIE:
385 .long 0 ! CIE Identifier Tag
386 .byte 1 ! CIE Version
387 .ascii "zR\0" ! CIE Augmentation
388 .byte 4 ! CIE Code Alignment Factor
389 .byte 0x7c ! CIE Data Alignment Factor
390 .byte 15 ! CIE RA Column
391 .byte 1 ! Augmentation size
392 #ifdef HAVE_AS_SPARC_UA_PCREL
393 .byte 0x1b ! FDE Encoding (pcrel sdata4)
394 #else
395 .byte 0x50 ! FDE Encoding (aligned absolute)
396 #endif
397 .byte 0xc, 14, 0 ! DW_CFA_def_cfa, %o6, offset 0
398 .align 4
399 .LECIE:
400
401 .long .LEFDE1 - .LSFDE1 ! FDE Length
402 .LSFDE1:
403 .long .LSFDE1 - .LCIE ! FDE CIE offset
404 .long FDE_ADDR(.LUW0) ! Initial location
405 .long .LUW2 - .LUW0 ! Address range
406 .byte 0 ! Augmentation size
407 .byte 0x40+1 ! DW_CFA_advance_loc 4
408 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
409 .byte 0x2d ! DW_CFA_GNU_window_save
410 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
411 .align 4
412 .LEFDE1:
413
414 .long .LEFDE2 - .LSFDE2 ! FDE Length
415 .LSFDE2:
416 .long .LSFDE2 - .LCIE ! FDE CIE offset
417 .long FDE_ADDR(.LUW3) ! Initial location
418 .long .LUW5 - .LUW3 ! Address range
419 .byte 0 ! Augmentation size
420 .byte 0x40+1 ! DW_CFA_advance_loc 4
421 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
422 .byte 0x2d ! DW_CFA_GNU_window_save
423 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
424 .align 4
425 .LEFDE2:
426
427 .long .LEFDE3 - .LSFDE3 ! FDE Length
428 .LSFDE3:
429 .long .LSFDE3 - .LCIE ! FDE CIE offset
430 .long FDE_ADDR(.LUW6) ! Initial location
431 .long .LUW8 - .LUW6 ! Address range
432 .byte 0 ! Augmentation size
433 .byte 0x40+1 ! DW_CFA_advance_loc 4
434 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
435 .byte 0x2d ! DW_CFA_GNU_window_save
436 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
437 .align 4
438 .LEFDE3:
439
440 #endif /* !SPARC64 */
441 #if defined __ELF__ && defined __linux__
442 .section .note.GNU-stack,"",@progbits
443 #endif