2009-05-22 Dave Korn <dave.korn.cygwin@gmail.com>
[libffi.git] / libffi / src / sparc / v8.S
1 /* -----------------------------------------------------------------------
2    v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc.
3    
4    SPARC 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 STACKFRAME 96           /* Minimum stack framesize for SPARC */
32 #define ARGS (64+4)             /* Offset of register area in frame */
33
34 .text
35         .align 8
36 .globl ffi_call_v8
37 .globl _ffi_call_v8
38
39 ffi_call_v8:
40 _ffi_call_v8:
41 .LLFB1:
42         save    %sp, -STACKFRAME, %sp
43 .LLCFI0:
44         
45         sub     %sp, %i2, %sp   ! alloca() space in stack for frame to set up
46         add     %sp, STACKFRAME, %l0    ! %l0 has start of 
47                                         ! frame to set up
48
49         mov     %l0, %o0        ! call routine to set up frame
50         call    %i0
51         mov     %i1, %o1        ! (delay)
52
53         ld      [%l0+ARGS], %o0 ! call foreign function
54         ld      [%l0+ARGS+4], %o1
55         ld      [%l0+ARGS+8], %o2
56         ld      [%l0+ARGS+12], %o3
57         ld      [%l0+ARGS+16], %o4
58         ld      [%l0+ARGS+20], %o5
59         call    %i5
60         mov     %l0, %sp        ! (delay) switch to frame
61         nop                     ! STRUCT returning functions skip 12 instead of 8 bytes
62
63         ! If the return value pointer is NULL, assume no return value.
64         tst     %i4
65         bz      done
66         nop
67
68         cmp     %i3, FFI_TYPE_INT
69         be,a    done
70         st      %o0, [%i4]      ! (delay)
71
72         cmp     %i3, FFI_TYPE_FLOAT
73         be,a    done
74         st      %f0, [%i4+0]    ! (delay)
75
76         cmp     %i3, FFI_TYPE_DOUBLE
77         be,a    double
78         st      %f0, [%i4+0]    ! (delay)
79
80         cmp     %i3, FFI_TYPE_SINT8
81         be,a    sint8
82         sll     %o0, 24, %o0    ! (delay)
83
84         cmp     %i3, FFI_TYPE_UINT8
85         be,a    uint8
86         sll     %o0, 24, %o0    ! (delay)
87
88         cmp     %i3, FFI_TYPE_SINT16
89         be,a    sint16
90         sll     %o0, 16, %o0    ! (delay)
91
92         cmp     %i3, FFI_TYPE_UINT16
93         be,a    uint16
94         sll     %o0, 16, %o0    ! (delay)
95
96         cmp     %i3, FFI_TYPE_SINT64
97         be,a    longlong
98         st      %o0, [%i4+0]    ! (delay)
99 done:
100         ret
101         restore
102
103 double:
104         st      %f1, [%i4+4]
105         ret
106         restore
107
108 sint8:
109         sra     %o0, 24, %o0
110         st      %o0, [%i4+0]
111         ret
112         restore
113
114 uint8:
115         srl     %o0, 24, %o0
116         st      %o0, [%i4+0]
117         ret
118         restore
119
120 sint16:
121         sra     %o0, 16, %o0
122         st      %o0, [%i4+0]
123         ret
124         restore
125
126 uint16:
127         srl     %o0, 16, %o0
128         st      %o0, [%i4+0]
129         ret
130         restore
131
132 longlong:
133         st      %o1, [%i4+4]
134         ret
135         restore
136 .LLFE1:
137
138 .ffi_call_v8_end:
139         .size   ffi_call_v8,.ffi_call_v8_end-ffi_call_v8
140
141
142 #undef STACKFRAME
143 #define STACKFRAME      104     /* 16*4 register window +
144                                    1*4 struct return +  
145                                    6*4 args backing store +
146                                    3*4 locals */
147
148 /* ffi_closure_v8(...)
149
150    Receives the closure argument in %g2.   */
151
152         .text
153         .align 8
154         .globl ffi_closure_v8
155
156 ffi_closure_v8:
157 #ifdef HAVE_AS_REGISTER_PSEUDO_OP
158                 .register       %g2, #scratch
159 #endif
160 .LLFB2:
161         ! Reserve frame space for all arguments in case
162         ! we need to align them on a 8-byte boundary.
163         ld      [%g2+FFI_TRAMPOLINE_SIZE], %g1
164         ld      [%g1+4], %g1
165         sll     %g1, 3, %g1
166         add     %g1, STACKFRAME, %g1
167         ! %g1 == STACKFRAME + 8*nargs
168         neg     %g1
169         save    %sp, %g1, %sp
170 .LLCFI1:
171
172         ! Store all of the potential argument registers in va_list format.
173         st      %i0, [%fp+68+0]
174         st      %i1, [%fp+68+4]
175         st      %i2, [%fp+68+8]
176         st      %i3, [%fp+68+12]
177         st      %i4, [%fp+68+16]
178         st      %i5, [%fp+68+20]
179
180         ! Call ffi_closure_sparc_inner to do the bulk of the work.
181         mov     %g2, %o0
182         add     %fp, -8, %o1
183         add     %fp,  64, %o2
184         call    ffi_closure_sparc_inner_v8
185          add    %fp, -16, %o3
186
187         ! Load up the return value in the proper type.
188         ! See ffi_prep_cif_machdep for the list of cases.
189         cmp     %o0, FFI_TYPE_VOID
190         be      done1
191
192         cmp     %o0, FFI_TYPE_INT
193         be      done1
194          ld     [%fp-8], %i0
195
196         cmp     %o0, FFI_TYPE_FLOAT
197         be,a    done1
198          ld     [%fp-8], %f0
199
200         cmp     %o0, FFI_TYPE_DOUBLE
201         be,a    done1
202          ldd    [%fp-8], %f0
203
204 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
205         cmp     %o0, FFI_TYPE_LONGDOUBLE
206         be      done2
207 #endif
208
209         cmp     %o0, FFI_TYPE_STRUCT
210         be      done2
211
212         cmp     %o0, FFI_TYPE_SINT64
213         be,a    done1
214          ldd    [%fp-8], %i0
215
216         ld      [%fp-8], %i0
217 done1:
218         jmp     %i7+8
219          restore
220 done2:
221         ! Skip 'unimp'.
222         jmp     %i7+12
223          restore
224 .LLFE2:
225
226 .ffi_closure_v8_end:
227         .size   ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8
228
229 #ifdef SPARC64
230 #define WS 8
231 #define nword   xword
232 #define uanword uaxword
233 #else
234 #define WS 4
235 #define nword   long
236 #define uanword uaword
237 #endif
238
239 #ifdef HAVE_RO_EH_FRAME
240         .section        ".eh_frame",#alloc
241 #else
242         .section        ".eh_frame",#alloc,#write
243 #endif
244 .LLframe1:
245         .uaword .LLECIE1-.LLSCIE1       ! Length of Common Information Entry
246 .LLSCIE1:
247         .uaword 0x0     ! CIE Identifier Tag
248         .byte   0x1     ! CIE Version
249         .ascii "zR\0"   ! CIE Augmentation
250         .byte   0x1     ! uleb128 0x1; CIE Code Alignment Factor
251         .byte   0x80-WS ! sleb128 -WS; CIE Data Alignment Factor
252         .byte   0xf     ! CIE RA Column
253         .byte   0x1     ! uleb128 0x1; Augmentation size
254 #ifdef HAVE_AS_SPARC_UA_PCREL
255         .byte   0x1b    ! FDE Encoding (pcrel sdata4)
256 #else
257         .byte   0x50    ! FDE Encoding (aligned absolute)
258 #endif
259         .byte   0xc     ! DW_CFA_def_cfa
260         .byte   0xe     ! uleb128 0xe
261         .byte   0x0     ! uleb128 0x0
262         .align  WS
263 .LLECIE1:
264 .LLSFDE1:
265         .uaword .LLEFDE1-.LLASFDE1      ! FDE Length
266 .LLASFDE1:
267         .uaword .LLASFDE1-.LLframe1     ! FDE CIE offset
268 #ifdef HAVE_AS_SPARC_UA_PCREL
269         .uaword %r_disp32(.LLFB1)
270         .uaword .LLFE1-.LLFB1   ! FDE address range
271 #else
272         .align  WS
273         .nword  .LLFB1
274         .uanword .LLFE1-.LLFB1  ! FDE address range
275 #endif
276         .byte   0x0     ! uleb128 0x0; Augmentation size
277         .byte   0x4     ! DW_CFA_advance_loc4
278         .uaword .LLCFI0-.LLFB1
279         .byte   0xd     ! DW_CFA_def_cfa_register
280         .byte   0x1e    ! uleb128 0x1e
281         .byte   0x2d    ! DW_CFA_GNU_window_save
282         .byte   0x9     ! DW_CFA_register
283         .byte   0xf     ! uleb128 0xf
284         .byte   0x1f    ! uleb128 0x1f
285         .align  WS
286 .LLEFDE1:
287 .LLSFDE2:
288         .uaword .LLEFDE2-.LLASFDE2      ! FDE Length
289 .LLASFDE2:
290         .uaword .LLASFDE2-.LLframe1     ! FDE CIE offset
291 #ifdef HAVE_AS_SPARC_UA_PCREL
292         .uaword %r_disp32(.LLFB2)
293         .uaword .LLFE2-.LLFB2   ! FDE address range
294 #else
295         .align  WS
296         .nword  .LLFB2
297         .uanword .LLFE2-.LLFB2  ! FDE address range
298 #endif
299         .byte   0x0     ! uleb128 0x0; Augmentation size
300         .byte   0x4     ! DW_CFA_advance_loc4
301         .uaword .LLCFI1-.LLFB2
302         .byte   0xd     ! DW_CFA_def_cfa_register
303         .byte   0x1e    ! uleb128 0x1e
304         .byte   0x2d    ! DW_CFA_GNU_window_save
305         .byte   0x9     ! DW_CFA_register
306         .byte   0xf     ! uleb128 0xf
307         .byte   0x1f    ! uleb128 0x1f
308         .align  WS
309 .LLEFDE2:
310
311 #if defined __ELF__ && defined __linux__
312         .section        .note.GNU-stack,"",@progbits
313 #endif