1 /* ----------------------------------------------------------------------- 2 osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat 3 4 Alpha/OSF 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 #define LIBFFI_ASM 28 #include <fficonfig.h> 29 #include <ffi.h> 30 31 .arch ev6 32 .text 33 34 /* ffi_call_osf (void *args, unsigned long bytes, unsigned flags, 35 void *raddr, void (*fnaddr)(void)); 36 37 Bit o trickiness here -- ARGS+BYTES is the base of the stack frame 38 for this function. This has been allocated by ffi_call. We also 39 deallocate some of the stack that has been alloca'd. */ 40 41 .align 3 42 .globl ffi_call_osf 43 .ent ffi_call_osf 44 FFI_HIDDEN(ffi_call_osf) 45 46 ffi_call_osf: 47 .frame $15, 32, $26, 0 48 .mask 0x4008000, -32 49 $LFB1: 50 addq $16,$17,$1 51 mov $16, $30 52 stq $26, 0($1) 53 stq $15, 8($1) 54 stq $18, 16($1) 55 mov $1, $15 56 $LCFI1: 57 .prologue 0 58 59 stq $19, 24($1) 60 mov $20, $27 61 62 # Load up all of the (potential) argument registers. 63 ldq $16, 0($30) 64 ldt $f16, 0($30) 65 ldt $f17, 8($30) 66 ldq $17, 8($30) 67 ldt $f18, 16($30) 68 ldq $18, 16($30) 69 ldt $f19, 24($30) 70 ldq $19, 24($30) 71 ldt $f20, 32($30) 72 ldq $20, 32($30) 73 ldt $f21, 40($30) 74 ldq $21, 40($30) 75 76 # Deallocate the register argument area. 77 lda $30, 48($30) 78 79 jsr $26, ($27), 0 80 ldgp $29, 0($26) 81 82 # If the return value pointer is NULL, assume no return value. 83 ldq $19, 24($15) 84 ldq $18, 16($15) 85 ldq $26, 0($15) 86 $LCFI2: 87 beq $19, $noretval 88 89 # Store the return value out in the proper type. 90 cmpeq $18, FFI_TYPE_INT, $1 91 bne $1, $retint 92 cmpeq $18, FFI_TYPE_FLOAT, $2 93 bne $2, $retfloat 94 cmpeq $18, FFI_TYPE_DOUBLE, $3 95 bne $3, $retdouble 96 97 .align 3 98 $noretval: 99 ldq $15, 8($15) 100 ret 101 102 .align 4 103 $retint: 104 stq $0, 0($19) 105 nop 106 ldq $15, 8($15) 107 ret 108 109 .align 4 110 $retfloat: 111 sts $f0, 0($19) 112 nop 113 ldq $15, 8($15) 114 ret 115 116 .align 4 117 $retdouble: 118 stt $f0, 0($19) 119 nop 120 ldq $15, 8($15) 121 ret 122 $LFE1: 123 124 .end ffi_call_osf 125 126 /* ffi_closure_osf(...) 127 128 Receives the closure argument in $1. */ 129 130 .align 3 131 .globl ffi_closure_osf 132 .ent ffi_closure_osf 133 FFI_HIDDEN(ffi_closure_osf) 134 135 ffi_closure_osf: 136 .frame $30, 16*8, $26, 0 137 .mask 0x4000000, -16*8 138 $LFB2: 139 ldgp $29, 0($27) 140 subq $30, 16*8, $30 141 $LCFI5: 142 stq $26, 0($30) 143 $LCFI6: 144 .prologue 1 145 146 # Store all of the potential argument registers in va_list format. 147 stt $f16, 4*8($30) 148 stt $f17, 5*8($30) 149 stt $f18, 6*8($30) 150 stt $f19, 7*8($30) 151 stt $f20, 8*8($30) 152 stt $f21, 9*8($30) 153 stq $16, 10*8($30) 154 stq $17, 11*8($30) 155 stq $18, 12*8($30) 156 stq $19, 13*8($30) 157 stq $20, 14*8($30) 158 stq $21, 15*8($30) 159 160 # Call ffi_closure_osf_inner to do the bulk of the work. 161 mov $1, $16 162 lda $17, 2*8($30) 163 lda $18, 10*8($30) 164 jsr $26, ffi_closure_osf_inner 165 ldgp $29, 0($26) 166 ldq $26, 0($30) 167 168 # Load up the return value in the proper type. 169 lda $1, $load_table 170 s4addq $0, $1, $1 171 ldl $1, 0($1) 172 addq $1, $29, $1 173 jmp $31, ($1), $load_32 174 175 .align 4 176 $load_none: 177 addq $30, 16*8, $30 178 ret 179 180 .align 4 181 $load_float: 182 lds $f0, 16($30) 183 nop 184 addq $30, 16*8, $30 185 ret 186 187 .align 4 188 $load_double: 189 ldt $f0, 16($30) 190 nop 191 addq $30, 16*8, $30 192 ret 193 194 .align 4 195 $load_u8: 196 #ifdef __alpha_bwx__ 197 ldbu $0, 16($30) 198 nop 199 #else 200 ldq $0, 16($30) 201 and $0, 255, $0 202 #endif 203 addq $30, 16*8, $30 204 ret 205 206 .align 4 207 $load_s8: 208 #ifdef __alpha_bwx__ 209 ldbu $0, 16($30) 210 sextb $0, $0 211 #else 212 ldq $0, 16($30) 213 sll $0, 56, $0 214 sra $0, 56, $0 215 #endif 216 addq $30, 16*8, $30 217 ret 218 219 .align 4 220 $load_u16: 221 #ifdef __alpha_bwx__ 222 ldwu $0, 16($30) 223 nop 224 #else 225 ldq $0, 16($30) 226 zapnot $0, 3, $0 227 #endif 228 addq $30, 16*8, $30 229 ret 230 231 .align 4 232 $load_s16: 233 #ifdef __alpha_bwx__ 234 ldwu $0, 16($30) 235 sextw $0, $0 236 #else 237 ldq $0, 16($30) 238 sll $0, 48, $0 239 sra $0, 48, $0 240 #endif 241 addq $30, 16*8, $30 242 ret 243 244 .align 4 245 $load_32: 246 ldl $0, 16($30) 247 nop 248 addq $30, 16*8, $30 249 ret 250 251 .align 4 252 $load_64: 253 ldq $0, 16($30) 254 nop 255 addq $30, 16*8, $30 256 ret 257 $LFE2: 258 259 .end ffi_closure_osf 260 261 #ifdef __ELF__ 262 .section .rodata 263 #else 264 .rdata 265 #endif 266 $load_table: 267 .gprel32 $load_none # FFI_TYPE_VOID 268 .gprel32 $load_32 # FFI_TYPE_INT 269 .gprel32 $load_float # FFI_TYPE_FLOAT 270 .gprel32 $load_double # FFI_TYPE_DOUBLE 271 .gprel32 $load_none # FFI_TYPE_LONGDOUBLE 272 .gprel32 $load_u8 # FFI_TYPE_UINT8 273 .gprel32 $load_s8 # FFI_TYPE_SINT8 274 .gprel32 $load_u16 # FFI_TYPE_UINT16 275 .gprel32 $load_s16 # FFI_TYPE_SINT16 276 .gprel32 $load_32 # FFI_TYPE_UINT32 277 .gprel32 $load_32 # FFI_TYPE_SINT32 278 .gprel32 $load_64 # FFI_TYPE_UINT64 279 .gprel32 $load_64 # FFI_TYPE_SINT64 280 .gprel32 $load_none # FFI_TYPE_STRUCT 281 .gprel32 $load_64 # FFI_TYPE_POINTER 282 283 /* Assert that the table above is in sync with ffi.h. */ 284 285 #if FFI_TYPE_FLOAT != 2 \ 286 || FFI_TYPE_DOUBLE != 3 \ 287 || FFI_TYPE_UINT8 != 5 \ 288 || FFI_TYPE_SINT8 != 6 \ 289 || FFI_TYPE_UINT16 != 7 \ 290 || FFI_TYPE_SINT16 != 8 \ 291 || FFI_TYPE_UINT32 != 9 \ 292 || FFI_TYPE_SINT32 != 10 \ 293 || FFI_TYPE_UINT64 != 11 \ 294 || FFI_TYPE_SINT64 != 12 \ 295 || FFI_TYPE_STRUCT != 13 \ 296 || FFI_TYPE_POINTER != 14 \ 297 || FFI_TYPE_LAST != 14 298 #error "osf.S out of sync with ffi.h" 299 #endif 300 301 #ifdef __ELF__ 302 # define UA_SI .4byte 303 # define FDE_ENCODING 0x1b /* pcrel sdata4 */ 304 # define FDE_ENCODE(X) .4byte X-. 305 # define FDE_ARANGE(X) .4byte X 306 #elif defined __osf__ 307 # define UA_SI .align 0; .long 308 # define FDE_ENCODING 0x50 /* aligned absolute */ 309 # define FDE_ENCODE(X) .align 3; .quad X 310 # define FDE_ARANGE(X) .align 0; .quad X 311 #endif 312 313 #ifdef __ELF__ 314 .section .eh_frame,EH_FRAME_FLAGS,@progbits 315 #elif defined __osf__ 316 .data 317 .align 3 318 .globl _GLOBAL__F_ffi_call_osf 319 _GLOBAL__F_ffi_call_osf: 320 #endif 321 __FRAME_BEGIN__: 322 UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry 323 $LSCIE1: 324 UA_SI 0x0 # CIE Identifier Tag 325 .byte 0x1 # CIE Version 326 .ascii "zR\0" # CIE Augmentation 327 .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor 328 .byte 0x78 # sleb128 -8; CIE Data Alignment Factor 329 .byte 26 # CIE RA Column 330 .byte 0x1 # uleb128 0x1; Augmentation size 331 .byte FDE_ENCODING # FDE Encoding 332 .byte 0xc # DW_CFA_def_cfa 333 .byte 30 # uleb128 column 30 334 .byte 0 # uleb128 offset 0 335 .align 3 336 $LECIE1: 337 $LSFDE1: 338 UA_SI $LEFDE1-$LASFDE1 # FDE Length 339 $LASFDE1: 340 UA_SI $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset 341 FDE_ENCODE($LFB1) # FDE initial location 342 FDE_ARANGE($LFE1-$LFB1) # FDE address range 343 .byte 0x0 # uleb128 0x0; Augmentation size 344 345 .byte 0x4 # DW_CFA_advance_loc4 346 UA_SI $LCFI1-$LFB1 347 .byte 0x9a # DW_CFA_offset, column 26 348 .byte 4 # uleb128 4*-8 349 .byte 0x8f # DW_CFA_offset, column 15 350 .byte 0x3 # uleb128 3*-8 351 .byte 0xc # DW_CFA_def_cfa 352 .byte 15 # uleb128 column 15 353 .byte 32 # uleb128 offset 32 354 355 .byte 0x4 # DW_CFA_advance_loc4 356 UA_SI $LCFI2-$LCFI1 357 .byte 0xda # DW_CFA_restore, column 26 358 .align 3 359 $LEFDE1: 360 361 $LSFDE3: 362 UA_SI $LEFDE3-$LASFDE3 # FDE Length 363 $LASFDE3: 364 UA_SI $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset 365 FDE_ENCODE($LFB2) # FDE initial location 366 FDE_ARANGE($LFE2-$LFB2) # FDE address range 367 .byte 0x0 # uleb128 0x0; Augmentation size 368 369 .byte 0x4 # DW_CFA_advance_loc4 370 UA_SI $LCFI5-$LFB2 371 .byte 0xe # DW_CFA_def_cfa_offset 372 .byte 0x80,0x1 # uleb128 128 373 374 .byte 0x4 # DW_CFA_advance_loc4 375 UA_SI $LCFI6-$LCFI5 376 .byte 0x9a # DW_CFA_offset, column 26 377 .byte 16 # uleb128 offset 16*-8 378 .align 3 379 $LEFDE3: 380 #if defined __osf__ 381 .align 0 382 .long 0 # End of Table 383 #endif 384 385 #if defined __ELF__ && defined __linux__ 386 .section .note.GNU-stack,"",@progbits 387 #endif 388