OSDN Git Service

2009-06-12 Andrew Haley <aph@redhat.com>
[pf3gnuchains/gcc-fork.git] / libffi / src / x86 / win64.S
1 #define LIBFFI_ASM
2 #include <fficonfig.h>
3 #include <ffi.h>
4         
5 /* Constants for ffi_call_win64 */      
6 #define STACK 0
7 #define PREP_ARGS_FN 32
8 #define ECIF 40
9 #define CIF_BYTES 48
10 #define CIF_FLAGS 56
11 #define RVALUE 64
12 #define FN 72
13
14 /* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *),
15                    extended_cif *ecif, unsigned bytes, unsigned flags,
16                    unsigned *rvalue, void (*fn)());
17  */
18
19 #ifdef _MSC_VER
20 PUBLIC  ffi_call_win64
21
22 EXTRN   __chkstk:NEAR
23 EXTRN   ffi_closure_win64_inner:NEAR
24
25 _TEXT   SEGMENT
26
27 ;;; ffi_closure_win64 will be called with these registers set:
28 ;;;    rax points to 'closure'
29 ;;;    r11 contains a bit mask that specifies which of the
30 ;;;    first four parameters are float or double
31 ;;;
32 ;;; It must move the parameters passed in registers to their stack location,
33 ;;; call ffi_closure_win64_inner for the actual work, then return the result.
34 ;;; 
35 ffi_closure_win64 PROC FRAME
36         ;; copy register arguments onto stack
37         test    r11, 1
38         jne     first_is_float  
39         mov     QWORD PTR [rsp+8], rcx
40         jmp     second
41 first_is_float:
42         movlpd  QWORD PTR [rsp+8], xmm0
43
44 second:
45         test    r11, 2
46         jne     second_is_float 
47         mov     QWORD PTR [rsp+16], rdx
48         jmp     third
49 second_is_float:
50         movlpd  QWORD PTR [rsp+16], xmm1
51
52 third:
53         test    r11, 4
54         jne     third_is_float  
55         mov     QWORD PTR [rsp+24], r8
56         jmp     fourth
57 third_is_float:
58         movlpd  QWORD PTR [rsp+24], xmm2
59
60 fourth:
61         test    r11, 8
62         jne     fourth_is_float 
63         mov     QWORD PTR [rsp+32], r9
64         jmp     done
65 fourth_is_float:
66         movlpd  QWORD PTR [rsp+32], xmm3
67
68 done:
69         .ALLOCSTACK 40
70         sub     rsp, 40
71         .ENDPROLOG
72         mov     rcx, rax        ; context is first parameter
73         mov     rdx, rsp        ; stack is second parameter
74         add     rdx, 48         ; point to start of arguments
75         mov     rax, ffi_closure_win64_inner
76         call    rax             ; call the real closure function
77         add     rsp, 40
78         movd    xmm0, rax       ; If the closure returned a float,
79                                 ; ffi_closure_win64_inner wrote it to rax
80         ret     0
81 ffi_closure_win64 ENDP
82
83 ffi_call_win64 PROC FRAME
84         ;; copy registers onto stack
85         mov     QWORD PTR [rsp+32], r9
86         mov     QWORD PTR [rsp+24], r8
87         mov     QWORD PTR [rsp+16], rdx
88         mov     QWORD PTR [rsp+8], rcx
89         .PUSHREG rbp
90         push    rbp
91         .ALLOCSTACK 48
92         sub     rsp, 48                                 ; 00000030H
93         .SETFRAME rbp, 32
94         lea     rbp, QWORD PTR [rsp+32]
95         .ENDPROLOG
96
97         mov     eax, DWORD PTR CIF_BYTES[rbp]
98         add     rax, 15
99         and     rax, -16
100         call    __chkstk
101         sub     rsp, rax
102         lea     rax, QWORD PTR [rsp+32]
103         mov     QWORD PTR STACK[rbp], rax
104
105         mov     rdx, QWORD PTR ECIF[rbp]
106         mov     rcx, QWORD PTR STACK[rbp]
107         call    QWORD PTR PREP_ARGS_FN[rbp]
108
109         mov     rsp, QWORD PTR STACK[rbp]
110
111         movlpd  xmm3, QWORD PTR [rsp+24]
112         movd    r9, xmm3
113
114         movlpd  xmm2, QWORD PTR [rsp+16]
115         movd    r8, xmm2
116
117         movlpd  xmm1, QWORD PTR [rsp+8]
118         movd    rdx, xmm1
119
120         movlpd  xmm0, QWORD PTR [rsp]
121         movd    rcx, xmm0
122
123         call    QWORD PTR FN[rbp]
124 ret_struct4b$:
125         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_4B
126         jne     ret_struct2b$
127
128         mov     rcx, QWORD PTR RVALUE[rbp]
129         mov     DWORD PTR [rcx], eax
130         jmp     ret_void$
131
132 ret_struct2b$:
133         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
134         jne     ret_struct1b$
135
136         mov     rcx, QWORD PTR RVALUE[rbp]
137         mov     WORD PTR [rcx], ax
138         jmp     ret_void$
139
140 ret_struct1b$:
141         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
142         jne     ret_uint8$
143
144         mov     rcx, QWORD PTR RVALUE[rbp]
145         mov     BYTE PTR [rcx], al
146         jmp     ret_void$
147
148 ret_uint8$:
149         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
150         jne     ret_sint8$
151
152         mov     rcx, QWORD PTR RVALUE[rbp]
153         movzx   rax, al
154         mov     QWORD PTR [rcx], rax
155         jmp     ret_void$
156
157 ret_sint8$:
158         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
159         jne     ret_uint16$
160
161         mov     rcx, QWORD PTR RVALUE[rbp]
162         movsx   rax, al
163         mov     QWORD PTR [rcx], rax
164         jmp     ret_void$
165
166 ret_uint16$:
167         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
168         jne     ret_sint16$
169
170         mov     rcx, QWORD PTR RVALUE[rbp]
171         movzx   rax, ax
172         mov     QWORD PTR [rcx], rax
173         jmp     SHORT ret_void$
174
175 ret_sint16$:
176         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16
177         jne     ret_uint32$
178
179         mov     rcx, QWORD PTR RVALUE[rbp]
180         movsx   rax, ax
181         mov     QWORD PTR [rcx], rax
182         jmp     SHORT ret_void$
183
184 ret_uint32$:
185         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32
186         jne     ret_sint32$
187
188         mov     rcx, QWORD PTR RVALUE[rbp]
189         mov     eax, eax
190         mov     QWORD PTR [rcx], rax
191         jmp     SHORT ret_void$
192
193 ret_sint32$:
194         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
195         jne     ret_float$
196
197         mov     rcx, QWORD PTR RVALUE[rbp]
198         cdqe
199         mov     QWORD PTR [rcx], rax
200         jmp     SHORT ret_void$
201
202 ret_float$:
203         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT
204         jne     SHORT ret_double$
205
206         mov     rax, QWORD PTR RVALUE[rbp]
207         movss   DWORD PTR [rax], xmm0
208         jmp     SHORT ret_void$
209
210 ret_double$:
211         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE
212         jne     SHORT ret_sint64$
213
214         mov     rax, QWORD PTR RVALUE[rbp]
215         movlpd  QWORD PTR [rax], xmm0
216         jmp     SHORT ret_void$
217
218 ret_sint64$:
219         cmp     DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64
220         jne     ret_void$
221
222         mov     rcx, QWORD PTR RVALUE[rbp]
223         mov     QWORD PTR [rcx], rax
224         jmp     SHORT ret_void$
225         
226 ret_void$:
227         xor     rax, rax
228
229         lea     rsp, QWORD PTR [rbp+16]
230         pop     rbp
231         ret     0
232 ffi_call_win64 ENDP
233 _TEXT   ENDS
234 END
235 #else        
236 .text
237
238 .extern ___chkstk
239 .extern _ffi_closure_win64_inner
240
241 # ffi_closure_win64 will be called with these registers set:
242 #    rax points to 'closure'
243 #    r11 contains a bit mask that specifies which of the
244 #    first four parameters are float or double
245 #
246 # It must move the parameters passed in registers to their stack location,
247 # call ffi_closure_win64_inner for the actual work, then return the result.
248
249         .balign 16
250         .globl _ffi_closure_win64       
251 _ffi_closure_win64:     
252         # copy register arguments onto stack
253         test    $1,%r11
254         jne     .Lfirst_is_float        
255         mov     %rcx, 8(%rsp)
256         jmp     .Lsecond
257 .Lfirst_is_float:
258         movlpd  %xmm0, 8(%rsp)
259
260 .Lsecond:
261         test    $2, %r11
262         jne     .Lsecond_is_float       
263         mov     %rdx, 16(%rsp)
264         jmp     .Lthird
265 .Lsecond_is_float:
266         movlpd  %xmm1, 16(%rsp)
267
268 .Lthird:
269         test    $4, %r11
270         jne     .Lthird_is_float        
271         mov     %r8,24(%rsp)
272         jmp     .Lfourth
273 .Lthird_is_float:
274         movlpd  %xmm2, 24(%rsp)
275
276 .Lfourth:
277         test    $8, %r11
278         jne     .Lfourth_is_float       
279         mov     %r9, 32(%rsp)
280         jmp     .Ldone
281 .Lfourth_is_float:
282         movlpd  %xmm3, 32(%rsp)
283
284 .Ldone:
285 #.ALLOCSTACK 40
286         sub     $40, %rsp
287 #.ENDPROLOG
288         mov     %rax, %rcx      # context is first parameter
289         mov     %rsp, %rdx      # stack is second parameter
290         add     $48, %rdx       # point to start of arguments
291         mov     $_ffi_closure_win64_inner, %rax
292         callq   *%rax           # call the real closure function
293         add     $40, %rsp
294         movq    %rax, %xmm0     # If the closure returned a float,
295                                 # ffi_closure_win64_inner wrote it to rax
296         retq
297 .ffi_closure_win64_end:
298
299         .balign 16
300         .globl  _ffi_call_win64
301 _ffi_call_win64:        
302         # copy registers onto stack
303         mov     %r9,32(%rsp)
304         mov     %r8,24(%rsp)
305         mov     %rdx,16(%rsp)
306         mov     %rcx,8(%rsp)
307         #.PUSHREG rbp
308         push    %rbp
309         #.ALLOCSTACK 48
310         sub     $48,%rsp
311         #.SETFRAME rbp, 32
312         lea     32(%rsp),%rbp
313         #.ENDPROLOG
314
315         mov     CIF_BYTES(%rbp),%eax
316         add     $15, %rax
317         and     $-16, %rax
318         callq   ___chkstk
319         cmpq    $0x1000, %rax
320         jb      Lch_done
321 Lch_probe:
322         subq    $0x1000,%rsp
323         orl     $0x0, (%rsp)
324         subq    $0x1000,%rax
325         cmpq    $0x1000,%rax
326         ja      Lch_probe
327 Lch_done:
328         subq    %rax, %rsp
329         orl     $0x0, (%rsp)
330         lea     32(%rsp), %rax
331         mov     %rax, STACK(%rbp)
332
333         mov     ECIF(%rbp), %rdx
334         mov     STACK(%rbp), %rcx
335         callq   *PREP_ARGS_FN(%rbp)
336
337         mov     STACK(%rbp), %rsp
338
339         movlpd  24(%rsp), %xmm3
340         movd    %xmm3, %r9
341
342         movlpd  16(%rsp), %xmm2
343         movd    %xmm2, %r8
344
345         movlpd  8(%rsp), %xmm1
346         movd    %xmm1, %rdx
347
348         movlpd  (%rsp), %xmm0
349         movd    %xmm0, %rcx
350
351         callq   *FN(%rbp)
352 .Lret_struct4b:
353         cmpl    $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
354         jne .Lret_struct2b
355
356         mov     RVALUE(%rbp), %rcx
357         mov     %eax, (%rcx)
358         jmp     .Lret_void
359
360 .Lret_struct2b:
361         cmpl    $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
362         jne .Lret_struct1b
363         
364         mov     RVALUE(%rbp), %rcx
365         mov     %ax, (%rcx)
366         jmp .Lret_void
367         
368 .Lret_struct1b:
369         cmpl    $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
370         jne .Lret_uint8
371         
372         mov     RVALUE(%rbp), %rcx
373         mov     %al, (%rcx)
374         jmp .Lret_void
375
376 .Lret_uint8:
377         cmpl    $FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
378         jne .Lret_sint8
379         
380         mov     RVALUE(%rbp), %rcx
381         movzbq  %al, %rax
382         movq    %rax, (%rcx)
383         jmp .Lret_void
384
385 .Lret_sint8:
386         cmpl    $FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
387         jne .Lret_uint16
388         
389         mov     RVALUE(%rbp), %rcx
390         movsbq  %al, %rax
391         movq    %rax, (%rcx)
392         jmp .Lret_void
393
394 .Lret_uint16:
395         cmpl    $FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
396         jne .Lret_sint16
397         
398         mov     RVALUE(%rbp), %rcx
399         movzwq  %ax, %rax
400         movq    %rax, (%rcx)
401         jmp .Lret_void
402
403 .Lret_sint16:
404         cmpl    $FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
405         jne .Lret_uint32
406         
407         mov     RVALUE(%rbp), %rcx
408         movswq  %ax, %rax
409         movq    %rax, (%rcx)
410         jmp .Lret_void
411
412 .Lret_uint32:
413         cmpl    $FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
414         jne .Lret_sint32
415         
416         mov     RVALUE(%rbp), %rcx
417         movl    %eax, %eax
418         movq    %rax, (%rcx)
419         jmp .Lret_void
420
421 .Lret_sint32:
422         cmpl    $FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
423         jne     .Lret_float
424
425         mov     RVALUE(%rbp), %rcx
426         cltq
427         movq    %rax, (%rcx)
428         jmp     .Lret_void
429
430 .Lret_float:
431         cmpl    $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
432         jne     .Lret_double
433
434         mov     RVALUE(%rbp), %rax
435         movss   %xmm0, (%rax)
436         jmp     .Lret_void
437
438 .Lret_double:
439         cmpl    $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
440         jne     .Lret_sint64
441
442         mov     RVALUE(%rbp), %rax
443         movlpd  %xmm0, (%rax)
444         jmp     .Lret_void
445
446 .Lret_sint64:
447         cmpl    $FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
448         jne     .Lret_void
449
450         mov     RVALUE(%rbp), %rcx
451         mov     %rax, (%rcx)
452         jmp     .Lret_void
453         
454 .Lret_void:
455         xor     %rax, %rax
456
457         lea     16(%rbp), %rsp
458         pop     %rbp
459         retq
460 .ffi_call_win64_end:
461 #endif /* !_MSC_VER */
462