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