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 #ifndef GSTREAMER_LITE 174 jmp SHORT ret_void$ 175 #else 176 jmp ret_void$ 177 #endif // GSTREAMER_LITE 178 179 ret_sint16$: 180 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT16 181 jne ret_uint32$ 182 183 mov rcx, QWORD PTR RVALUE[rbp] 184 movsx rax, ax 185 mov QWORD PTR [rcx], rax 186 #ifndef GSTREAMER_LITE 187 jmp SHORT ret_void$ 188 #else 189 jmp ret_void$ 190 #endif // GSTREAMER_LITE 191 192 ret_uint32$: 193 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT32 194 jne ret_sint32$ 195 196 mov rcx, QWORD PTR RVALUE[rbp] 197 mov eax, eax 198 mov QWORD PTR [rcx], rax 199 jmp SHORT ret_void$ 200 201 ret_sint32$: 202 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32 203 jne ret_float$ 204 205 mov rcx, QWORD PTR RVALUE[rbp] 206 cdqe 207 mov QWORD PTR [rcx], rax 208 jmp SHORT ret_void$ 209 210 ret_float$: 211 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT 212 jne SHORT ret_double$ 213 214 mov rax, QWORD PTR RVALUE[rbp] 215 movss DWORD PTR [rax], xmm0 216 jmp SHORT ret_void$ 217 218 ret_double$: 219 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE 220 jne SHORT ret_uint64$ 221 222 mov rax, QWORD PTR RVALUE[rbp] 223 movlpd QWORD PTR [rax], xmm0 224 jmp SHORT ret_void$ 225 226 ret_uint64$: 227 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT64 228 jne SHORT ret_sint64$ 229 230 mov rcx, QWORD PTR RVALUE[rbp] 231 mov QWORD PTR [rcx], rax 232 jmp SHORT ret_void$ 233 234 ret_sint64$: 235 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64 236 jne SHORT ret_pointer$ 237 238 mov rcx, QWORD PTR RVALUE[rbp] 239 mov QWORD PTR [rcx], rax 240 jmp SHORT ret_void$ 241 242 ret_pointer$: 243 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_POINTER 244 jne SHORT ret_int$ 245 246 mov rcx, QWORD PTR RVALUE[rbp] 247 mov QWORD PTR [rcx], rax 248 jmp SHORT ret_void$ 249 250 ret_int$: 251 cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT 252 jne SHORT ret_void$ 253 254 mov rcx, QWORD PTR RVALUE[rbp] 255 cdqe 256 mov QWORD PTR [rcx], rax 257 jmp SHORT ret_void$ 258 259 ret_void$: 260 xor rax, rax 261 262 lea rsp, QWORD PTR [rbp+16] 263 pop rbp 264 ret 0 265 ffi_call_win64 ENDP 266 _TEXT ENDS 267 END 268 269 #else 270 271 #ifdef SYMBOL_UNDERSCORE 272 #define SYMBOL_NAME(name) _##name 273 #else 274 #define SYMBOL_NAME(name) name 275 #endif 276 277 .text 278 279 .extern SYMBOL_NAME(ffi_closure_win64_inner) 280 281 # ffi_closure_win64 will be called with these registers set: 282 # rax points to 'closure' 283 # r11 contains a bit mask that specifies which of the 284 # first four parameters are float or double 285 # 286 # It must move the parameters passed in registers to their stack location, 287 # call ffi_closure_win64_inner for the actual work, then return the result. 288 # 289 .balign 16 290 .globl SYMBOL_NAME(ffi_closure_win64) 291 .seh_proc SYMBOL_NAME(ffi_closure_win64) 292 SYMBOL_NAME(ffi_closure_win64): 293 # copy register arguments onto stack 294 test $1,%r11 295 jne .Lfirst_is_float 296 mov %rcx, 8(%rsp) 297 jmp .Lsecond 298 .Lfirst_is_float: 299 movlpd %xmm0, 8(%rsp) 300 301 .Lsecond: 302 test $2, %r11 303 jne .Lsecond_is_float 304 mov %rdx, 16(%rsp) 305 jmp .Lthird 306 .Lsecond_is_float: 307 movlpd %xmm1, 16(%rsp) 308 309 .Lthird: 310 test $4, %r11 311 jne .Lthird_is_float 312 mov %r8,24(%rsp) 313 jmp .Lfourth 314 .Lthird_is_float: 315 movlpd %xmm2, 24(%rsp) 316 317 .Lfourth: 318 test $8, %r11 319 jne .Lfourth_is_float 320 mov %r9, 32(%rsp) 321 jmp .Ldone 322 .Lfourth_is_float: 323 movlpd %xmm3, 32(%rsp) 324 325 .Ldone: 326 .seh_stackalloc 40 327 sub $40, %rsp 328 .seh_endprologue 329 mov %rax, %rcx # context is first parameter 330 mov %rsp, %rdx # stack is second parameter 331 add $48, %rdx # point to start of arguments 332 leaq SYMBOL_NAME(ffi_closure_win64_inner)(%rip), %rax 333 callq *%rax # call the real closure function 334 add $40, %rsp 335 movq %rax, %xmm0 # If the closure returned a float, 336 # ffi_closure_win64_inner wrote it to rax 337 retq 338 .seh_endproc 339 340 .balign 16 341 .globl SYMBOL_NAME(ffi_call_win64) 342 .seh_proc SYMBOL_NAME(ffi_call_win64) 343 SYMBOL_NAME(ffi_call_win64): 344 # copy registers onto stack 345 mov %r9,32(%rsp) 346 mov %r8,24(%rsp) 347 mov %rdx,16(%rsp) 348 mov %rcx,8(%rsp) 349 .seh_pushreg rbp 350 push %rbp 351 .seh_stackalloc 48 352 sub $48,%rsp 353 .seh_setframe rbp, 32 354 lea 32(%rsp),%rbp 355 .seh_endprologue 356 357 mov CIF_BYTES(%rbp),%eax 358 add $15, %rax 359 and $-16, %rax 360 cmpq $0x1000, %rax 361 jb Lch_done 362 Lch_probe: 363 subq $0x1000,%rsp 364 orl $0x0, (%rsp) 365 subq $0x1000,%rax 366 cmpq $0x1000,%rax 367 ja Lch_probe 368 Lch_done: 369 subq %rax, %rsp 370 orl $0x0, (%rsp) 371 lea 32(%rsp), %rax 372 mov %rax, STACK(%rbp) 373 374 mov ECIF(%rbp), %rdx 375 mov STACK(%rbp), %rcx 376 callq *PREP_ARGS_FN(%rbp) 377 378 mov STACK(%rbp), %rsp 379 380 movlpd 24(%rsp), %xmm3 381 movd %xmm3, %r9 382 383 movlpd 16(%rsp), %xmm2 384 movd %xmm2, %r8 385 386 movlpd 8(%rsp), %xmm1 387 movd %xmm1, %rdx 388 389 movlpd (%rsp), %xmm0 390 movd %xmm0, %rcx 391 392 callq *FN(%rbp) 393 .Lret_struct4b: 394 cmpl $FFI_TYPE_SMALL_STRUCT_4B, CIF_FLAGS(%rbp) 395 jne .Lret_struct2b 396 397 mov RVALUE(%rbp), %rcx 398 mov %eax, (%rcx) 399 jmp .Lret_void 400 401 .Lret_struct2b: 402 cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp) 403 jne .Lret_struct1b 404 405 mov RVALUE(%rbp), %rcx 406 mov %ax, (%rcx) 407 jmp .Lret_void 408 409 .Lret_struct1b: 410 cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp) 411 jne .Lret_uint8 412 413 mov RVALUE(%rbp), %rcx 414 mov %al, (%rcx) 415 jmp .Lret_void 416 417 .Lret_uint8: 418 cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp) 419 jne .Lret_sint8 420 421 mov RVALUE(%rbp), %rcx 422 movzbq %al, %rax 423 movq %rax, (%rcx) 424 jmp .Lret_void 425 426 .Lret_sint8: 427 cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp) 428 jne .Lret_uint16 429 430 mov RVALUE(%rbp), %rcx 431 movsbq %al, %rax 432 movq %rax, (%rcx) 433 jmp .Lret_void 434 435 .Lret_uint16: 436 cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp) 437 jne .Lret_sint16 438 439 mov RVALUE(%rbp), %rcx 440 movzwq %ax, %rax 441 movq %rax, (%rcx) 442 jmp .Lret_void 443 444 .Lret_sint16: 445 cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp) 446 jne .Lret_uint32 447 448 mov RVALUE(%rbp), %rcx 449 movswq %ax, %rax 450 movq %rax, (%rcx) 451 jmp .Lret_void 452 453 .Lret_uint32: 454 cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp) 455 jne .Lret_sint32 456 457 mov RVALUE(%rbp), %rcx 458 movl %eax, %eax 459 movq %rax, (%rcx) 460 jmp .Lret_void 461 462 .Lret_sint32: 463 cmpl $FFI_TYPE_SINT32, CIF_FLAGS(%rbp) 464 jne .Lret_float 465 466 mov RVALUE(%rbp), %rcx 467 cltq 468 movq %rax, (%rcx) 469 jmp .Lret_void 470 471 .Lret_float: 472 cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp) 473 jne .Lret_double 474 475 mov RVALUE(%rbp), %rax 476 movss %xmm0, (%rax) 477 jmp .Lret_void 478 479 .Lret_double: 480 cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp) 481 jne .Lret_uint64 482 483 mov RVALUE(%rbp), %rax 484 movlpd %xmm0, (%rax) 485 jmp .Lret_void 486 487 .Lret_uint64: 488 cmpl $FFI_TYPE_UINT64, CIF_FLAGS(%rbp) 489 jne .Lret_sint64 490 491 mov RVALUE(%rbp), %rcx 492 mov %rax, (%rcx) 493 jmp .Lret_void 494 495 .Lret_sint64: 496 cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp) 497 jne .Lret_pointer 498 499 mov RVALUE(%rbp), %rcx 500 mov %rax, (%rcx) 501 jmp .Lret_void 502 503 .Lret_pointer: 504 cmpl $FFI_TYPE_POINTER, CIF_FLAGS(%rbp) 505 jne .Lret_int 506 507 mov RVALUE(%rbp), %rcx 508 mov %rax, (%rcx) 509 jmp .Lret_void 510 511 .Lret_int: 512 cmpl $FFI_TYPE_INT, CIF_FLAGS(%rbp) 513 jne .Lret_void 514 515 mov RVALUE(%rbp), %rcx 516 cltq 517 movq %rax, (%rcx) 518 jmp .Lret_void 519 520 .Lret_void: 521 xor %rax, %rax 522 523 lea 16(%rbp), %rsp 524 pop %rbp 525 retq 526 .seh_endproc 527 #endif /* !_MSC_VER */ 528