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