OSDN Git Service

2009-09-28 Kai Tietz <kai.tietz@onevision.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 _ffi_closure_win64_inner
239
240 # ffi_closure_win64 will be called with these registers set:
241 #    rax points to 'closure'
242 #    r11 contains a bit mask that specifies which of the
243 #    first four parameters are float or double
244 #
245 # It must move the parameters passed in registers to their stack location,
246 # call ffi_closure_win64_inner for the actual work, then return the result.
247
248         .balign 16
249         .globl _ffi_closure_win64       
250 _ffi_closure_win64:     
251         # copy register arguments onto stack
252         test    $1,%r11
253         jne     .Lfirst_is_float        
254         mov     %rcx, 8(%rsp)
255         jmp     .Lsecond
256 .Lfirst_is_float:
257         movlpd  %xmm0, 8(%rsp)
258
259 .Lsecond:
260         test    $2, %r11
261         jne     .Lsecond_is_float       
262         mov     %rdx, 16(%rsp)
263         jmp     .Lthird
264 .Lsecond_is_float:
265         movlpd  %xmm1, 16(%rsp)
266
267 .Lthird:
268         test    $4, %r11
269         jne     .Lthird_is_float        
270         mov     %r8,24(%rsp)
271         jmp     .Lfourth
272 .Lthird_is_float:
273         movlpd  %xmm2, 24(%rsp)
274
275 .Lfourth:
276         test    $8, %r11
277         jne     .Lfourth_is_float       
278         mov     %r9, 32(%rsp)
279         jmp     .Ldone
280 .Lfourth_is_float:
281         movlpd  %xmm3, 32(%rsp)
282
283 .Ldone:
284 #.ALLOCSTACK 40
285         sub     $40, %rsp
286 #.ENDPROLOG
287         mov     %rax, %rcx      # context is first parameter
288         mov     %rsp, %rdx      # stack is second parameter
289         add     $48, %rdx       # point to start of arguments
290         mov     $_ffi_closure_win64_inner, %rax
291         callq   *%rax           # call the real closure function
292         add     $40, %rsp
293         movq    %rax, %xmm0     # If the closure returned a float,
294                                 # ffi_closure_win64_inner wrote it to rax
295         retq
296 .ffi_closure_win64_end:
297
298         .balign 16
299         .globl  _ffi_call_win64
300 _ffi_call_win64:        
301         # copy registers onto stack
302         mov     %r9,32(%rsp)
303         mov     %r8,24(%rsp)
304         mov     %rdx,16(%rsp)
305         mov     %rcx,8(%rsp)
306         #.PUSHREG rbp
307         push    %rbp
308         #.ALLOCSTACK 48
309         sub     $48,%rsp
310         #.SETFRAME rbp, 32
311         lea     32(%rsp),%rbp
312         #.ENDPROLOG
313
314         mov     CIF_BYTES(%rbp),%eax
315         add     $15, %rax
316         and     $-16, %rax
317         cmpq    $0x1000, %rax
318         jb      Lch_done
319 Lch_probe:
320         subq    $0x1000,%rsp
321         orl     $0x0, (%rsp)
322         subq    $0x1000,%rax
323         cmpq    $0x1000,%rax
324         ja      Lch_probe
325 Lch_done:
326         subq    %rax, %rsp
327         orl     $0x0, (%rsp)
328         lea     32(%rsp), %rax
329         mov     %rax, STACK(%rbp)
330
331         mov     ECIF(%rbp), %rdx
332         mov     STACK(%rbp), %rcx
333         callq   *PREP_ARGS_FN(%rbp)
334
335         mov     STACK(%rbp), %rsp
336
337         movlpd  24(%rsp), %xmm3
338         movd    %xmm3, %r9
339
340         movlpd  16(%rsp), %xmm2
341         movd    %xmm2, %r8
342
343         movlpd  8(%rsp), %xmm1
344         movd    %xmm1, %rdx
345
346         movlpd  (%rsp), %xmm0
347         movd    %xmm0, %rcx
348
349         callq   *FN(%rbp)
350 .Lret_struct4b:
351         cmpl    $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp)
352         jne .Lret_struct2b
353
354         mov     RVALUE(%rbp), %rcx
355         mov     %eax, (%rcx)
356         jmp     .Lret_void
357
358 .Lret_struct2b:
359         cmpl    $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp)
360         jne .Lret_struct1b
361         
362         mov     RVALUE(%rbp), %rcx
363         mov     %ax, (%rcx)
364         jmp .Lret_void
365         
366 .Lret_struct1b:
367         cmpl    $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp)
368         jne .Lret_uint8
369         
370         mov     RVALUE(%rbp), %rcx
371         mov     %al, (%rcx)
372         jmp .Lret_void
373
374 .Lret_uint8:
375         cmpl    $FFI_TYPE_UINT8, CIF_FLAGS(%rbp)
376         jne .Lret_sint8
377         
378         mov     RVALUE(%rbp), %rcx
379         movzbq  %al, %rax
380         movq    %rax, (%rcx)
381         jmp .Lret_void
382
383 .Lret_sint8:
384         cmpl    $FFI_TYPE_SINT8, CIF_FLAGS(%rbp)
385         jne .Lret_uint16
386         
387         mov     RVALUE(%rbp), %rcx
388         movsbq  %al, %rax
389         movq    %rax, (%rcx)
390         jmp .Lret_void
391
392 .Lret_uint16:
393         cmpl    $FFI_TYPE_UINT16, CIF_FLAGS(%rbp)
394         jne .Lret_sint16
395         
396         mov     RVALUE(%rbp), %rcx
397         movzwq  %ax, %rax
398         movq    %rax, (%rcx)
399         jmp .Lret_void
400
401 .Lret_sint16:
402         cmpl    $FFI_TYPE_SINT16, CIF_FLAGS(%rbp)
403         jne .Lret_uint32
404         
405         mov     RVALUE(%rbp), %rcx
406         movswq  %ax, %rax
407         movq    %rax, (%rcx)
408         jmp .Lret_void
409
410 .Lret_uint32:
411         cmpl    $FFI_TYPE_UINT32, CIF_FLAGS(%rbp)
412         jne .Lret_sint32
413         
414         mov     RVALUE(%rbp), %rcx
415         movl    %eax, %eax
416         movq    %rax, (%rcx)
417         jmp .Lret_void
418
419 .Lret_sint32:
420         cmpl    $FFI_TYPE_SINT32, CIF_FLAGS(%rbp)
421         jne     .Lret_float
422
423         mov     RVALUE(%rbp), %rcx
424         cltq
425         movq    %rax, (%rcx)
426         jmp     .Lret_void
427
428 .Lret_float:
429         cmpl    $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp)
430         jne     .Lret_double
431
432         mov     RVALUE(%rbp), %rax
433         movss   %xmm0, (%rax)
434         jmp     .Lret_void
435
436 .Lret_double:
437         cmpl    $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp)
438         jne     .Lret_sint64
439
440         mov     RVALUE(%rbp), %rax
441         movlpd  %xmm0, (%rax)
442         jmp     .Lret_void
443
444 .Lret_sint64:
445         cmpl    $FFI_TYPE_SINT64, CIF_FLAGS(%rbp)
446         jne     .Lret_void
447
448         mov     RVALUE(%rbp), %rcx
449         mov     %rax, (%rcx)
450         jmp     .Lret_void
451         
452 .Lret_void:
453         xor     %rax, %rax
454
455         lea     16(%rbp), %rsp
456         pop     %rbp
457         retq
458 .ffi_call_win64_end:
459 #endif /* !_MSC_VER */
460