1 /* ----------------------------------------------------------------------- 2 osf.S - Copyright (c) 1998, 2001, 2007, 2008 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 .section .eh_frame,EH_FRAME_FLAGS,@progbits 303 __FRAME_BEGIN__: 304 .4byte $LECIE1-$LSCIE1 # Length of Common Information Entry 305 $LSCIE1: 306 .4byte 0x0 # CIE Identifier Tag 307 .byte 0x1 # CIE Version 308 .ascii "zR\0" # CIE Augmentation 309 .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor 310 .byte 0x78 # sleb128 -8; CIE Data Alignment Factor 311 .byte 26 # CIE RA Column 312 .byte 0x1 # uleb128 0x1; Augmentation size 313 .byte 0x1b # FDE Encoding (pcrel sdata4) 314 .byte 0xc # DW_CFA_def_cfa 315 .byte 30 # uleb128 column 30 316 .byte 0 # uleb128 offset 0 317 .align 3 318 $LECIE1: 319 $LSFDE1: 320 .4byte $LEFDE1-$LASFDE1 # FDE Length 321 $LASFDE1: 322 .4byte $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset 323 .4byte $LFB1-. # FDE initial location 324 .4byte $LFE1-$LFB1 # FDE address range 325 .byte 0x0 # uleb128 0x0; Augmentation size 326 327 .byte 0x4 # DW_CFA_advance_loc4 328 .4byte $LCFI1-$LFB1 329 .byte 0x9a # DW_CFA_offset, column 26 330 .byte 4 # uleb128 4*-8 331 .byte 0x8f # DW_CFA_offset, column 15 332 .byte 0x3 # uleb128 3*-8 333 .byte 0xc # DW_CFA_def_cfa 334 .byte 15 # uleb128 column 15 335 .byte 32 # uleb128 offset 32 336 337 .byte 0x4 # DW_CFA_advance_loc4 338 .4byte $LCFI2-$LCFI1 339 .byte 0xda # DW_CFA_restore, column 26 340 .align 3 341 $LEFDE1: 342 343 $LSFDE3: 344 .4byte $LEFDE3-$LASFDE3 # FDE Length 345 $LASFDE3: 346 .4byte $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset 347 .4byte $LFB2-. # FDE initial location 348 .4byte $LFE2-$LFB2 # FDE address range 349 .byte 0x0 # uleb128 0x0; Augmentation size 350 351 .byte 0x4 # DW_CFA_advance_loc4 352 .4byte $LCFI5-$LFB2 353 .byte 0xe # DW_CFA_def_cfa_offset 354 .byte 0x80,0x1 # uleb128 128 355 356 .byte 0x4 # DW_CFA_advance_loc4 357 .4byte $LCFI6-$LCFI5 358 .byte 0x9a # DW_CFA_offset, column 26 359 .byte 16 # uleb128 offset 16*-8 360 .align 3 361 $LEFDE3: 362 363 #ifdef __linux__ 364 .section .note.GNU-stack,"",@progbits 365 #endif 366 #endif 367