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