]> git.ipfire.org Git - thirdparty/gcc.git/blob - libffi/src/sparc/v9.S
Merge with upstream libffi db1b34b7e1f5e473d17557e454a29933dfecd1af
[thirdparty/gcc.git] / libffi / src / sparc / v9.S
1 /* -----------------------------------------------------------------------
2 v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc.
3
4 SPARC 64-bit 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 #include "internal.h"
31
32 #ifdef SPARC64
33
34 #define C2(X, Y) X ## Y
35 #define C1(X, Y) C2(X, Y)
36
37 #ifdef __USER_LABEL_PREFIX__
38 # define C(Y) C1(__USER_LABEL_PREFIX__, Y)
39 #else
40 # define C(Y) Y
41 #endif
42 #define L(Y) C1(.L, Y)
43
44 #if defined(__sun__) && defined(__svr4__)
45 # define E(INDEX) .align 16
46 #else
47 # define E(INDEX) .align 16; .org 2b + INDEX * 16
48 #endif
49
50 #define STACK_BIAS 2047
51
52 .text
53 .align 8
54 .globl C(ffi_call_v9)
55 .type C(ffi_call_v9),#function
56 FFI_HIDDEN(C(ffi_call_v9))
57
58 C(ffi_call_v9):
59 .LUW0:
60 save %sp, %o4, %sp
61 .LUW1:
62 mov %i0, %o0 ! copy cif
63 add %sp, STACK_BIAS+128+48, %o1 ! load args area
64 mov %i2, %o2 ! copy rvalue
65 call C(ffi_prep_args_v9)
66 mov %i3, %o3 ! copy avalue
67
68 andcc %o0, SPARC_FLAG_FP_ARGS, %g0 ! need fp regs?
69 add %sp, 48, %sp ! deallocate prep frame
70 be,pt %xcc, 1f
71 mov %o0, %l0 ! save flags
72
73 ldd [%sp+STACK_BIAS+128], %f0 ! load all fp arg regs
74 ldd [%sp+STACK_BIAS+128+8], %f2
75 ldd [%sp+STACK_BIAS+128+16], %f4
76 ldd [%sp+STACK_BIAS+128+24], %f6
77 ldd [%sp+STACK_BIAS+128+32], %f8
78 ldd [%sp+STACK_BIAS+128+40], %f10
79 ldd [%sp+STACK_BIAS+128+48], %f12
80 ldd [%sp+STACK_BIAS+128+56], %f14
81 ldd [%sp+STACK_BIAS+128+64], %f16
82 ldd [%sp+STACK_BIAS+128+72], %f18
83 ldd [%sp+STACK_BIAS+128+80], %f20
84 ldd [%sp+STACK_BIAS+128+88], %f22
85 ldd [%sp+STACK_BIAS+128+96], %f24
86 ldd [%sp+STACK_BIAS+128+104], %f26
87 ldd [%sp+STACK_BIAS+128+112], %f28
88 ldd [%sp+STACK_BIAS+128+120], %f30
89
90 1: ldx [%sp+STACK_BIAS+128], %o0 ! load all int arg regs
91 ldx [%sp+STACK_BIAS+128+8], %o1
92 ldx [%sp+STACK_BIAS+128+16], %o2
93 ldx [%sp+STACK_BIAS+128+24], %o3
94 ldx [%sp+STACK_BIAS+128+32], %o4
95 ldx [%sp+STACK_BIAS+128+40], %o5
96 call %i1
97 mov %i5, %g5 ! load static chain
98
99 0: call 1f ! load pc in %o7
100 and %l0, SPARC_FLAG_RET_MASK, %l1
101 1: sll %l1, 4, %l1
102 add %o7, %l1, %o7 ! o7 = 0b + ret_type*16
103 jmp %o7+(2f-0b)
104 nop
105
106 .align 16
107 2:
108 E(SPARC_RET_VOID)
109 return %i7+8
110 nop
111 E(SPARC_RET_STRUCT)
112 add %sp, STACK_BIAS-64+128+48, %l2
113 sub %sp, 64, %sp
114 b 8f
115 stx %o0, [%l2]
116 E(SPARC_RET_UINT8)
117 and %o0, 0xff, %i0
118 return %i7+8
119 stx %o0, [%o2]
120 E(SPARC_RET_SINT8)
121 sll %o0, 24, %o0
122 sra %o0, 24, %i0
123 return %i7+8
124 stx %o0, [%o2]
125 E(SPARC_RET_UINT16)
126 sll %o0, 16, %o0
127 srl %o0, 16, %i0
128 return %i7+8
129 stx %o0, [%o2]
130 E(SPARC_RET_SINT16)
131 sll %o0, 16, %o0
132 sra %o0, 16, %i0
133 return %i7+8
134 stx %o0, [%o2]
135 E(SPARC_RET_UINT32)
136 srl %o0, 0, %i0
137 return %i7+8
138 stx %o0, [%o2]
139 E(SP_V9_RET_SINT32)
140 sra %o0, 0, %i0
141 return %i7+8
142 stx %o0, [%o2]
143 E(SPARC_RET_INT64)
144 stx %o0, [%i2]
145 return %i7+8
146 nop
147 E(SPARC_RET_INT128)
148 stx %o0, [%i2]
149 stx %o1, [%i2+8]
150 return %i7+8
151 nop
152 E(SPARC_RET_F_8)
153 st %f7, [%i2+7*4]
154 nop
155 st %f6, [%i2+6*4]
156 nop
157 E(SPARC_RET_F_6)
158 st %f5, [%i2+5*4]
159 nop
160 st %f4, [%i2+4*4]
161 nop
162 E(SPARC_RET_F_4)
163 std %f2, [%i2+2*4]
164 return %i7+8
165 std %f0, [%o2]
166 E(SPARC_RET_F_2)
167 return %i7+8
168 std %f0, [%o2]
169 E(SP_V9_RET_F_3)
170 st %f2, [%i2+2*4]
171 nop
172 st %f1, [%i2+1*4]
173 nop
174 E(SPARC_RET_F_1)
175 return %i7+8
176 st %f0, [%o2]
177
178 ! Finish the SPARC_RET_STRUCT sequence.
179 .align 8
180 8: stx %o1, [%l2+8]
181 stx %o2, [%l2+16]
182 stx %o3, [%l2+24]
183 std %f0, [%l2+32]
184 std %f2, [%l2+40]
185 std %f4, [%l2+48]
186 std %f6, [%l2+56]
187
188 ! Copy the structure into place.
189 srl %l0, SPARC_SIZEMASK_SHIFT, %o0 ! load size_mask
190 mov %i2, %o1 ! load dst
191 mov %l2, %o2 ! load src_gp
192 call C(ffi_struct_float_copy)
193 add %l2, 32, %o3 ! load src_fp
194
195 return %i7+8
196 nop
197
198 .LUW2:
199 .size C(ffi_call_v9), . - C(ffi_call_v9)
200
201
202 #undef STACKFRAME
203 #define STACKFRAME 336 /* 16*8 register window +
204 6*8 args backing store +
205 20*8 locals */
206 #define FP %fp+STACK_BIAS
207
208 /* ffi_closure_v9(...)
209
210 Receives the closure argument in %g1. */
211
212 .align 8
213 .globl C(ffi_go_closure_v9)
214 .type C(ffi_go_closure_v9),#function
215 FFI_HIDDEN(C(ffi_go_closure_v9))
216
217 C(ffi_go_closure_v9):
218 .LUW3:
219 save %sp, -STACKFRAME, %sp
220 .LUW4:
221 ldx [%g5+8], %o0
222 ldx [%g5+16], %o1
223 b 0f
224 mov %g5, %o2
225
226 .LUW5:
227 .size C(ffi_go_closure_v9), . - C(ffi_go_closure_v9)
228
229 .align 8
230 .globl C(ffi_closure_v9)
231 .type C(ffi_closure_v9),#function
232 FFI_HIDDEN(C(ffi_closure_v9))
233
234 C(ffi_closure_v9):
235 .LUW6:
236 save %sp, -STACKFRAME, %sp
237 .LUW7:
238 ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0
239 ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1
240 ldx [%g1+FFI_TRAMPOLINE_SIZE+16], %o2
241 0:
242 ! Store all of the potential argument registers in va_list format.
243 stx %i0, [FP+128+0]
244 stx %i1, [FP+128+8]
245 stx %i2, [FP+128+16]
246 stx %i3, [FP+128+24]
247 stx %i4, [FP+128+32]
248 stx %i5, [FP+128+40]
249
250 ! Store possible floating point argument registers too.
251 std %f0, [FP-128]
252 std %f2, [FP-120]
253 std %f4, [FP-112]
254 std %f6, [FP-104]
255 std %f8, [FP-96]
256 std %f10, [FP-88]
257 std %f12, [FP-80]
258 std %f14, [FP-72]
259 std %f16, [FP-64]
260 std %f18, [FP-56]
261 std %f20, [FP-48]
262 std %f22, [FP-40]
263 std %f24, [FP-32]
264 std %f26, [FP-24]
265 std %f28, [FP-16]
266 std %f30, [FP-8]
267
268 ! Call ffi_closure_sparc_inner to do the bulk of the work.
269 add %fp, STACK_BIAS-160, %o3
270 add %fp, STACK_BIAS+128, %o4
271 call C(ffi_closure_sparc_inner_v9)
272 add %fp, STACK_BIAS-128, %o5
273
274 0: call 1f ! load pc in %o7
275 and %o0, SPARC_FLAG_RET_MASK, %o0
276 1: sll %o0, 4, %o0 ! o2 = i2 * 16
277 add %o7, %o0, %o7 ! o7 = 0b + i2*16
278 jmp %o7+(2f-0b)
279 nop
280
281 ! Note that we cannot load the data in the delay slot of
282 ! the return insn because the data is in the stack frame
283 ! that is deallocated by the return.
284 .align 16
285 2:
286 E(SPARC_RET_VOID)
287 return %i7+8
288 nop
289 E(SPARC_RET_STRUCT)
290 ldx [FP-160], %i0
291 ldd [FP-160], %f0
292 b 8f
293 ldx [FP-152], %i1
294 E(SPARC_RET_UINT8)
295 ldub [FP-160+7], %i0
296 return %i7+8
297 nop
298 E(SPARC_RET_SINT8)
299 ldsb [FP-160+7], %i0
300 return %i7+8
301 nop
302 E(SPARC_RET_UINT16)
303 lduh [FP-160+6], %i0
304 return %i7+8
305 nop
306 E(SPARC_RET_SINT16)
307 ldsh [FP-160+6], %i0
308 return %i7+8
309 nop
310 E(SPARC_RET_UINT32)
311 lduw [FP-160+4], %i0
312 return %i7+8
313 nop
314 E(SP_V9_RET_SINT32)
315 ldsw [FP-160+4], %i0
316 return %i7+8
317 nop
318 E(SPARC_RET_INT64)
319 ldx [FP-160], %i0
320 return %i7+8
321 nop
322 E(SPARC_RET_INT128)
323 ldx [FP-160], %i0
324 ldx [FP-160+8], %i1
325 return %i7+8
326 nop
327 E(SPARC_RET_F_8)
328 ld [FP-160+7*4], %f7
329 nop
330 ld [FP-160+6*4], %f6
331 nop
332 E(SPARC_RET_F_6)
333 ld [FP-160+5*4], %f5
334 nop
335 ld [FP-160+4*4], %f4
336 nop
337 E(SPARC_RET_F_4)
338 ldd [FP-160], %f0
339 ldd [FP-160+8], %f2
340 return %i7+8
341 nop
342 E(SPARC_RET_F_2)
343 ldd [FP-160], %f0
344 return %i7+8
345 nop
346 E(SP_V9_RET_F_3)
347 ld [FP-160+2*4], %f2
348 nop
349 ld [FP-160+1*4], %f1
350 nop
351 E(SPARC_RET_F_1)
352 ld [FP-160], %f0
353 return %i7+8
354 nop
355
356 ! Finish the SPARC_RET_STRUCT sequence.
357 .align 8
358 8: ldd [FP-152], %f2
359 ldx [FP-144], %i2
360 ldd [FP-144], %f4
361 ldx [FP-136], %i3
362 ldd [FP-136], %f6
363 return %i7+8
364 nop
365
366 .LUW8:
367 .size C(ffi_closure_v9), . - C(ffi_closure_v9)
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_RANGE(B, E) .long %r_disp32(B), E - B
377 #else
378 # define FDE_RANGE(B, E) .align 8; .xword B, E - B
379 #endif
380
381 .align 8
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 0x78 ! 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, 0xff, 0xf ! DW_CFA_def_cfa, %o6, offset 0x7ff
398 .align 8
399 .LECIE:
400
401 .long .LEFDE1 - .LSFDE1 ! FDE Length
402 .LSFDE1:
403 .long .LSFDE1 - .LCIE ! FDE CIE offset
404 FDE_RANGE(.LUW0, .LUW2)
405 .byte 0 ! Augmentation size
406 .byte 0x40+1 ! DW_CFA_advance_loc 4
407 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
408 .byte 0x2d ! DW_CFA_GNU_window_save
409 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
410 .align 8
411 .LEFDE1:
412
413 .long .LEFDE2 - .LSFDE2 ! FDE Length
414 .LSFDE2:
415 .long .LSFDE2 - .LCIE ! FDE CIE offset
416 FDE_RANGE(.LUW3, .LUW5)
417 .byte 0 ! Augmentation size
418 .byte 0x40+1 ! DW_CFA_advance_loc 4
419 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
420 .byte 0x2d ! DW_CFA_GNU_window_save
421 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
422 .align 8
423 .LEFDE2:
424
425 .long .LEFDE3 - .LSFDE3 ! FDE Length
426 .LSFDE3:
427 .long .LSFDE3 - .LCIE ! FDE CIE offset
428 FDE_RANGE(.LUW6, .LUW8)
429 .byte 0 ! Augmentation size
430 .byte 0x40+1 ! DW_CFA_advance_loc 4
431 .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6
432 .byte 0x2d ! DW_CFA_GNU_window_save
433 .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7
434 .align 8
435 .LEFDE3:
436
437 #endif /* SPARC64 */
438 #ifdef __linux__
439 .section .note.GNU-stack,"",@progbits
440 #endif