1/* ----------------------------------------------------------------------- 2 sysv.S - Copyright (c) 2013 The Written Word, Inc. 3 - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. 4 5 X86 Foreign Function Interface 6 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: 14 15 The above copyright notice and this permission notice shall be included 16 in all copies or substantial portions of the Software. 17 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 ----------------------------------------------------------------------- */ 27 28#ifndef __x86_64__ 29 30#define LIBFFI_ASM 31#include <fficonfig.h> 32#include <ffi.h> 33 34.text 35 36.globl ffi_prep_args 37 38 .align 4 39.globl ffi_call_SYSV 40 .type ffi_call_SYSV,@function 41 42ffi_call_SYSV: 43.LFB1: 44 pushl %ebp 45.LCFI0: 46 movl %esp,%ebp 47.LCFI1: 48 /* Make room for all of the new args. */ 49 movl 16(%ebp),%ecx 50 subl %ecx,%esp 51 52 /* Align the stack pointer to 16-bytes */ 53 andl $0xfffffff0, %esp 54 55 movl %esp,%eax 56 57 /* Place all of the ffi_prep_args in position */ 58 pushl 12(%ebp) 59 pushl %eax 60 call *8(%ebp) 61 62 /* Return stack to previous state and call the function */ 63 addl $8,%esp 64 65 call *28(%ebp) 66 67 /* Load %ecx with the return type code */ 68 movl 20(%ebp),%ecx 69 70 /* Protect %esi. We're going to pop it in the epilogue. */ 71 pushl %esi 72 73 /* If the return value pointer is NULL, assume no return value. */ 74 cmpl $0,24(%ebp) 75 jne 0f 76 77 /* Even if there is no space for the return value, we are 78 obliged to handle floating-point values. */ 79 cmpl $FFI_TYPE_FLOAT,%ecx 80 jne noretval 81 fstp %st(0) 82 83 jmp epilogue 84 850: 86 call 1f 87 88.Lstore_table: 89 .long noretval-.Lstore_table /* FFI_TYPE_VOID */ 90 .long retint-.Lstore_table /* FFI_TYPE_INT */ 91 .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */ 92 .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ 93 .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ 94 .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */ 95 .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */ 96 .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */ 97 .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */ 98 .long retint-.Lstore_table /* FFI_TYPE_UINT32 */ 99 .long retint-.Lstore_table /* FFI_TYPE_SINT32 */ 100 .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */ 101 .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */ 102 .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */ 103 .long retint-.Lstore_table /* FFI_TYPE_POINTER */ 104 1051: 106 pop %esi 107 add (%esi, %ecx, 4), %esi 108 jmp *%esi 109 110 /* Sign/zero extend as appropriate. */ 111retsint8: 112 movsbl %al, %eax 113 jmp retint 114 115retsint16: 116 movswl %ax, %eax 117 jmp retint 118 119retuint8: 120 movzbl %al, %eax 121 jmp retint 122 123retuint16: 124 movzwl %ax, %eax 125 jmp retint 126 127retfloat: 128 /* Load %ecx with the pointer to storage for the return value */ 129 movl 24(%ebp),%ecx 130 fstps (%ecx) 131 jmp epilogue 132 133retdouble: 134 /* Load %ecx with the pointer to storage for the return value */ 135 movl 24(%ebp),%ecx 136 fstpl (%ecx) 137 jmp epilogue 138 139retlongdouble: 140 /* Load %ecx with the pointer to storage for the return value */ 141 movl 24(%ebp),%ecx 142 fstpt (%ecx) 143 jmp epilogue 144 145retint64: 146 /* Load %ecx with the pointer to storage for the return value */ 147 movl 24(%ebp),%ecx 148 movl %eax,0(%ecx) 149 movl %edx,4(%ecx) 150 jmp epilogue 151 152retint: 153 /* Load %ecx with the pointer to storage for the return value */ 154 movl 24(%ebp),%ecx 155 movl %eax,0(%ecx) 156 157retstruct: 158 /* Nothing to do! */ 159 160noretval: 161epilogue: 162 popl %esi 163 movl %ebp,%esp 164 popl %ebp 165 ret 166.LFE1: 167.ffi_call_SYSV_end: 168 .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV 169 170 .align 4 171FFI_HIDDEN (ffi_closure_SYSV) 172.globl ffi_closure_SYSV 173 .type ffi_closure_SYSV, @function 174 175ffi_closure_SYSV: 176.LFB2: 177 pushl %ebp 178.LCFI2: 179 movl %esp, %ebp 180.LCFI3: 181 subl $40, %esp 182 leal -24(%ebp), %edx 183 movl %edx, -12(%ebp) /* resp */ 184 leal 8(%ebp), %edx 185#ifdef __SUNPRO_C 186 /* The SUNPRO compiler doesn't support GCC's regparm function 187 attribute, so we have to pass all three arguments to 188 ffi_closure_SYSV_inner on the stack. */ 189 movl %edx, 8(%esp) /* args = __builtin_dwarf_cfa () */ 190 leal -12(%ebp), %edx 191 movl %edx, 4(%esp) /* &resp */ 192 movl %eax, (%esp) /* closure */ 193#else 194 movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ 195 leal -12(%ebp), %edx 196 movl %edx, (%esp) /* &resp */ 197#endif 198#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__ 199 call ffi_closure_SYSV_inner 200#else 201 movl %ebx, 8(%esp) 202.LCFI7: 203 call 1f 2041: popl %ebx 205 addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx 206 call ffi_closure_SYSV_inner@PLT 207 movl 8(%esp), %ebx 208#endif 209 movl -12(%ebp), %ecx 210 cmpl $FFI_TYPE_INT, %eax 211 je .Lcls_retint 212 213 /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, 214 FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ 215 cmpl $FFI_TYPE_UINT64, %eax 216 jge 0f 217 cmpl $FFI_TYPE_UINT8, %eax 218 jge .Lcls_retint 219 2200: cmpl $FFI_TYPE_FLOAT, %eax 221 je .Lcls_retfloat 222 cmpl $FFI_TYPE_DOUBLE, %eax 223 je .Lcls_retdouble 224 cmpl $FFI_TYPE_LONGDOUBLE, %eax 225 je .Lcls_retldouble 226 cmpl $FFI_TYPE_SINT64, %eax 227 je .Lcls_retllong 228 cmpl $FFI_TYPE_STRUCT, %eax 229 je .Lcls_retstruct 230.Lcls_epilogue: 231 movl %ebp, %esp 232 popl %ebp 233 ret 234.Lcls_retint: 235 movl (%ecx), %eax 236 jmp .Lcls_epilogue 237.Lcls_retfloat: 238 flds (%ecx) 239 jmp .Lcls_epilogue 240.Lcls_retdouble: 241 fldl (%ecx) 242 jmp .Lcls_epilogue 243.Lcls_retldouble: 244 fldt (%ecx) 245 jmp .Lcls_epilogue 246.Lcls_retllong: 247 movl (%ecx), %eax 248 movl 4(%ecx), %edx 249 jmp .Lcls_epilogue 250.Lcls_retstruct: 251 movl %ebp, %esp 252 popl %ebp 253 ret $4 254.LFE2: 255 .size ffi_closure_SYSV, .-ffi_closure_SYSV 256 257#if !FFI_NO_RAW_API 258 259/* Precalculate for e.g. the Solaris 10/x86 assembler. */ 260#if FFI_TRAMPOLINE_SIZE == 10 261#define RAW_CLOSURE_CIF_OFFSET 12 262#define RAW_CLOSURE_FUN_OFFSET 16 263#define RAW_CLOSURE_USER_DATA_OFFSET 20 264#elif FFI_TRAMPOLINE_SIZE == 24 265#define RAW_CLOSURE_CIF_OFFSET 24 266#define RAW_CLOSURE_FUN_OFFSET 28 267#define RAW_CLOSURE_USER_DATA_OFFSET 32 268#else 269#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) 270#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) 271#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) 272#endif 273#define CIF_FLAGS_OFFSET 20 274 275 .align 4 276FFI_HIDDEN (ffi_closure_raw_SYSV) 277.globl ffi_closure_raw_SYSV 278 .type ffi_closure_raw_SYSV, @function 279 280ffi_closure_raw_SYSV: 281.LFB3: 282 pushl %ebp 283.LCFI4: 284 movl %esp, %ebp 285.LCFI5: 286 pushl %esi 287.LCFI6: 288 subl $36, %esp 289 movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ 290 movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ 291 movl %edx, 12(%esp) /* user_data */ 292 leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ 293 movl %edx, 8(%esp) /* raw_args */ 294 leal -24(%ebp), %edx 295 movl %edx, 4(%esp) /* &res */ 296 movl %esi, (%esp) /* cif */ 297 call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ 298 movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ 299 cmpl $FFI_TYPE_INT, %eax 300 je .Lrcls_retint 301 302 /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, 303 FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ 304 cmpl $FFI_TYPE_UINT64, %eax 305 jge 0f 306 cmpl $FFI_TYPE_UINT8, %eax 307 jge .Lrcls_retint 3080: 309 cmpl $FFI_TYPE_FLOAT, %eax 310 je .Lrcls_retfloat 311 cmpl $FFI_TYPE_DOUBLE, %eax 312 je .Lrcls_retdouble 313 cmpl $FFI_TYPE_LONGDOUBLE, %eax 314 je .Lrcls_retldouble 315 cmpl $FFI_TYPE_SINT64, %eax 316 je .Lrcls_retllong 317.Lrcls_epilogue: 318 addl $36, %esp 319 popl %esi 320 popl %ebp 321 ret 322.Lrcls_retint: 323 movl -24(%ebp), %eax 324 jmp .Lrcls_epilogue 325.Lrcls_retfloat: 326 flds -24(%ebp) 327 jmp .Lrcls_epilogue 328.Lrcls_retdouble: 329 fldl -24(%ebp) 330 jmp .Lrcls_epilogue 331.Lrcls_retldouble: 332 fldt -24(%ebp) 333 jmp .Lrcls_epilogue 334.Lrcls_retllong: 335 movl -24(%ebp), %eax 336 movl -20(%ebp), %edx 337 jmp .Lrcls_epilogue 338.LFE3: 339 .size ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV 340#endif 341 342#if defined __GNUC__ 343/* Only emit dwarf unwind info when building with GNU toolchain. */ 344 345#if defined __PIC__ 346# if defined __sun__ && defined __svr4__ 347/* 32-bit Solaris 2/x86 uses datarel encoding for PIC. GNU ld before 2.22 348 doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this. */ 349# define FDE_ENCODING 0x30 /* datarel */ 350# define FDE_ENCODE(X) X@GOTOFF 351# else 352# define FDE_ENCODING 0x1b /* pcrel sdata4 */ 353# if defined HAVE_AS_X86_PCREL 354# define FDE_ENCODE(X) X-. 355# else 356# define FDE_ENCODE(X) X@rel 357# endif 358# endif 359#else 360# define FDE_ENCODING 0 /* absolute */ 361# define FDE_ENCODE(X) X 362#endif 363 364 .section .eh_frame,EH_FRAME_FLAGS,@progbits 365.Lframe1: 366 .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */ 367.LSCIE1: 368 .long 0x0 /* CIE Identifier Tag */ 369 .byte 0x1 /* CIE Version */ 370#ifdef HAVE_AS_ASCII_PSEUDO_OP 371#ifdef __PIC__ 372 .ascii "zR\0" /* CIE Augmentation */ 373#else 374 .ascii "\0" /* CIE Augmentation */ 375#endif 376#elif defined HAVE_AS_STRING_PSEUDO_OP 377#ifdef __PIC__ 378 .string "zR" /* CIE Augmentation */ 379#else 380 .string "" /* CIE Augmentation */ 381#endif 382#else 383#error missing .ascii/.string 384#endif 385 .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ 386 .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ 387 .byte 0x8 /* CIE RA Column */ 388#ifdef __PIC__ 389 .byte 0x1 /* .uleb128 0x1; Augmentation size */ 390 .byte FDE_ENCODING 391#endif 392 .byte 0xc /* DW_CFA_def_cfa */ 393 .byte 0x4 /* .uleb128 0x4 */ 394 .byte 0x4 /* .uleb128 0x4 */ 395 .byte 0x88 /* DW_CFA_offset, column 0x8 */ 396 .byte 0x1 /* .uleb128 0x1 */ 397 .align 4 398.LECIE1: 399.LSFDE1: 400 .long .LEFDE1-.LASFDE1 /* FDE Length */ 401.LASFDE1: 402 .long .LASFDE1-.Lframe1 /* FDE CIE offset */ 403 .long FDE_ENCODE(.LFB1) /* FDE initial location */ 404 .long .LFE1-.LFB1 /* FDE address range */ 405#ifdef __PIC__ 406 .byte 0x0 /* .uleb128 0x0; Augmentation size */ 407#endif 408 .byte 0x4 /* DW_CFA_advance_loc4 */ 409 .long .LCFI0-.LFB1 410 .byte 0xe /* DW_CFA_def_cfa_offset */ 411 .byte 0x8 /* .uleb128 0x8 */ 412 .byte 0x85 /* DW_CFA_offset, column 0x5 */ 413 .byte 0x2 /* .uleb128 0x2 */ 414 .byte 0x4 /* DW_CFA_advance_loc4 */ 415 .long .LCFI1-.LCFI0 416 .byte 0xd /* DW_CFA_def_cfa_register */ 417 .byte 0x5 /* .uleb128 0x5 */ 418 .align 4 419.LEFDE1: 420.LSFDE2: 421 .long .LEFDE2-.LASFDE2 /* FDE Length */ 422.LASFDE2: 423 .long .LASFDE2-.Lframe1 /* FDE CIE offset */ 424 .long FDE_ENCODE(.LFB2) /* FDE initial location */ 425 .long .LFE2-.LFB2 /* FDE address range */ 426#ifdef __PIC__ 427 .byte 0x0 /* .uleb128 0x0; Augmentation size */ 428#endif 429 .byte 0x4 /* DW_CFA_advance_loc4 */ 430 .long .LCFI2-.LFB2 431 .byte 0xe /* DW_CFA_def_cfa_offset */ 432 .byte 0x8 /* .uleb128 0x8 */ 433 .byte 0x85 /* DW_CFA_offset, column 0x5 */ 434 .byte 0x2 /* .uleb128 0x2 */ 435 .byte 0x4 /* DW_CFA_advance_loc4 */ 436 .long .LCFI3-.LCFI2 437 .byte 0xd /* DW_CFA_def_cfa_register */ 438 .byte 0x5 /* .uleb128 0x5 */ 439#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__ 440 .byte 0x4 /* DW_CFA_advance_loc4 */ 441 .long .LCFI7-.LCFI3 442 .byte 0x83 /* DW_CFA_offset, column 0x3 */ 443 .byte 0xa /* .uleb128 0xa */ 444#endif 445 .align 4 446.LEFDE2: 447 448#if !FFI_NO_RAW_API 449 450.LSFDE3: 451 .long .LEFDE3-.LASFDE3 /* FDE Length */ 452.LASFDE3: 453 .long .LASFDE3-.Lframe1 /* FDE CIE offset */ 454 .long FDE_ENCODE(.LFB3) /* FDE initial location */ 455 .long .LFE3-.LFB3 /* FDE address range */ 456#ifdef __PIC__ 457 .byte 0x0 /* .uleb128 0x0; Augmentation size */ 458#endif 459 .byte 0x4 /* DW_CFA_advance_loc4 */ 460 .long .LCFI4-.LFB3 461 .byte 0xe /* DW_CFA_def_cfa_offset */ 462 .byte 0x8 /* .uleb128 0x8 */ 463 .byte 0x85 /* DW_CFA_offset, column 0x5 */ 464 .byte 0x2 /* .uleb128 0x2 */ 465 .byte 0x4 /* DW_CFA_advance_loc4 */ 466 .long .LCFI5-.LCFI4 467 .byte 0xd /* DW_CFA_def_cfa_register */ 468 .byte 0x5 /* .uleb128 0x5 */ 469 .byte 0x4 /* DW_CFA_advance_loc4 */ 470 .long .LCFI6-.LCFI5 471 .byte 0x86 /* DW_CFA_offset, column 0x6 */ 472 .byte 0x3 /* .uleb128 0x3 */ 473 .align 4 474.LEFDE3: 475 476#endif 477#endif 478 479#endif /* ifndef __x86_64__ */ 480 481#if defined __ELF__ && defined __linux__ 482 .section .note.GNU-stack,"",@progbits 483#endif 484