Update ChangeLog and version files for release
[official-gcc.git] / libffi / src / sparc / v8.S
bloba2e4908fd417a707260994f2ffbf9e31355eccaa
1 /* -----------------------------------------------------------------------
2    v8.S - Copyright (c) 2013  The Written Word, Inc.
3           Copyright (c) 1996, 1997, 2003, 2004, 2008  Red Hat, Inc.
5    SPARC Foreign Function Interface
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:
15    The above copyright notice and this permission notice shall be included
16    in all copies or substantial portions of the Software.
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    ----------------------------------------------------------------------- */
28 #define LIBFFI_ASM
29 #include <fficonfig.h>
30 #include <ffi.h>
31 #include "internal.h"
33 #ifndef SPARC64
35 #define C2(X, Y)  X ## Y
36 #define C1(X, Y)  C2(X, Y)
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)
45         .text
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))
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
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
72         .align 8
73         .globl  C(ffi_call_v8)
74         .type   C(ffi_call_v8),#function
75         FFI_HIDDEN(C(ffi_call_v8))
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
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
100         ! Call foreign function
101         call    %i1
102          mov    %i5, %g2                ! load static chain
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
110         ! Note that each entry is 4 insns, enforced by the E macro.
111         .align  16
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
182         .align  8
183 9:      sth     %o0, [%i2]
184         ret
185          restore
186         .align  8
187 0:      stb     %o0, [%i2]
188         ret
189          restore
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
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
213 #define rept16                          \
214         rept1; rept1; rept1; rept1;     \
215         rept1; rept1; rept1; rept1;     \
216         rept1; rept1; rept1; rept1;     \
217         rept1; rept1; rept1; rept1
219 #define rept256                         \
220         rept16; rept16; rept16; rept16; \
221         rept16; rept16; rept16; rept16; \
222         rept16; rept16; rept16; rept16; \
223         rept16; rept16; rept16; rept16
225         rept256; rept256; rept256; rept256
226         rept256; rept256; rept256; rept256
227         rept256; rept256; rept256; rept256
228         rept256; rept256; rept256; rept256
230 .LUW2:
231         .size   C(ffi_call_v8),. - C(ffi_call_v8)
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)
238 /* ffi_closure_v8(...)
240    Receives the closure argument in %g2.   */
242 #ifdef HAVE_AS_REGISTER_PSEUDO_OP
243         .register       %g2, #scratch
244 #endif
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))
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)
262         .align 8
263         .globl  C(ffi_closure_v8)
264         .type   C(ffi_closure_v8),#function
265         FFI_HIDDEN(C(ffi_closure_v8))
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
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]
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
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
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
366 .LUW8:
367         .size   C(ffi_closure_v8), . - C(ffi_closure_v8)
369 #ifdef HAVE_RO_EH_FRAME
370         .section        ".eh_frame",#alloc
371 #else
372         .section        ".eh_frame",#alloc,#write
373 #endif
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
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:
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:
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:
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:
440 #endif /* !SPARC64 */
441 #if defined __ELF__ && defined __linux__
442         .section        .note.GNU-stack,"",@progbits
443 #endif