| /* ----------------------------------------------------------------------- | |
| osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat | |
| Alpha/OSF Foreign Function Interface | |
| Permission is hereby granted, free of charge, to any person obtaining | |
| a copy of this software and associated documentation files (the | |
| ``Software''), to deal in the Software without restriction, including | |
| without limitation the rights to use, copy, modify, merge, publish, | |
| distribute, sublicense, and/or sell copies of the Software, and to | |
| permit persons to whom the Software is furnished to do so, subject to | |
| the following conditions: | |
| The above copyright notice and this permission notice shall be included | |
| in all copies or substantial portions of the Software. | |
| THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, | |
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
| HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| DEALINGS IN THE SOFTWARE. | |
| ----------------------------------------------------------------------- */ | |
| #define LIBFFI_ASM | |
| #include <fficonfig.h> | |
| #include <ffi.h> | |
| #include <ffi_cfi.h> | |
| #include "internal.h" | |
| .arch ev6 | |
| .text | |
| /* Aid in building a direct addressed jump table, 4 insns per entry. */ | |
| .macro E index | |
| .align 4 | |
| .org 99b + \index * 16 | |
| .endm | |
| /* ffi_call_osf (void *stack, void *frame, unsigned flags, | |
| void *raddr, void (*fnaddr)(void), void *closure) | |
| Bit o trickiness here -- FRAME is the base of the stack frame | |
| for this function. This has been allocated by ffi_call. We also | |
| deallocate some of the stack that has been alloca'd. */ | |
| .align 4 | |
| .globl ffi_call_osf | |
| .ent ffi_call_osf | |
| FFI_HIDDEN(ffi_call_osf) | |
| ffi_call_osf: | |
| cfi_startproc | |
| cfi_def_cfa($17, 32) | |
| mov $16, $30 | |
| stq $26, 0($17) | |
| stq $15, 8($17) | |
| mov $17, $15 | |
| .prologue 0 | |
| cfi_def_cfa_register($15) | |
| cfi_rel_offset($26, 0) | |
| cfi_rel_offset($15, 8) | |
| stq $18, 16($17) # save flags into frame | |
| stq $19, 24($17) # save rvalue into frame | |
| mov $20, $27 # fn into place for call | |
| mov $21, $1 # closure into static chain | |
| # Load up all of the (potential) argument registers. | |
| ldq $16, 0($30) | |
| ldt $f16, 0($30) | |
| ldt $f17, 8($30) | |
| ldq $17, 8($30) | |
| ldt $f18, 16($30) | |
| ldq $18, 16($30) | |
| ldt $f19, 24($30) | |
| ldq $19, 24($30) | |
| ldt $f20, 32($30) | |
| ldq $20, 32($30) | |
| ldt $f21, 40($30) | |
| ldq $21, 40($30) | |
| # Deallocate the register argument area. | |
| lda $30, 48($30) | |
| jsr $26, ($27), 0 | |
| 0: | |
| ldah $29, 0($26) !gpdisp!1 | |
| ldq $2, 24($15) # reload rvalue | |
| lda $29, 0($29) !gpdisp!1 | |
| ldq $3, 16($15) # reload flags | |
| lda $1, 99f-0b($26) | |
| ldq $26, 0($15) | |
| ldq $15, 8($15) | |
| cfi_restore($26) | |
| cfi_restore($15) | |
| cfi_def_cfa($sp, 0) | |
| cmoveq $2, ALPHA_ST_VOID, $3 # mash null rvalue to void | |
| addq $3, $3, $3 | |
| s8addq $3, $1, $1 # 99f + stcode * 16 | |
| jmp $31, ($1), $st_int | |
| .align 4 | |
| 99: | |
| E ALPHA_ST_VOID | |
| ret | |
| E ALPHA_ST_INT | |
| $st_int: | |
| stq $0, 0($2) | |
| ret | |
| E ALPHA_ST_FLOAT | |
| sts $f0, 0($2) | |
| ret | |
| E ALPHA_ST_DOUBLE | |
| stt $f0, 0($2) | |
| ret | |
| E ALPHA_ST_CPLXF | |
| sts $f0, 0($2) | |
| sts $f1, 4($2) | |
| ret | |
| E ALPHA_ST_CPLXD | |
| stt $f0, 0($2) | |
| stt $f1, 8($2) | |
| ret | |
| cfi_endproc | |
| .end ffi_call_osf | |
| /* ffi_closure_osf(...) | |
| Receives the closure argument in $1. */ | |
| #define CLOSURE_FS (16*8) | |
| .align 4 | |
| .globl ffi_go_closure_osf | |
| .ent ffi_go_closure_osf | |
| FFI_HIDDEN(ffi_go_closure_osf) | |
| ffi_go_closure_osf: | |
| cfi_startproc | |
| ldgp $29, 0($27) | |
| subq $30, CLOSURE_FS, $30 | |
| cfi_adjust_cfa_offset(CLOSURE_FS) | |
| stq $26, 0($30) | |
| .prologue 1 | |
| cfi_rel_offset($26, 0) | |
| stq $16, 10*8($30) | |
| stq $17, 11*8($30) | |
| stq $18, 12*8($30) | |
| ldq $16, 8($1) # load cif | |
| ldq $17, 16($1) # load fun | |
| mov $1, $18 # closure is user_data | |
| br $do_closure | |
| cfi_endproc | |
| .end ffi_go_closure_osf | |
| .align 4 | |
| .globl ffi_closure_osf | |
| .ent ffi_closure_osf | |
| FFI_HIDDEN(ffi_closure_osf) | |
| ffi_closure_osf: | |
| cfi_startproc | |
| ldgp $29, 0($27) | |
| subq $30, CLOSURE_FS, $30 | |
| cfi_adjust_cfa_offset(CLOSURE_FS) | |
| stq $26, 0($30) | |
| .prologue 1 | |
| cfi_rel_offset($26, 0) | |
| # Store all of the potential argument registers in va_list format. | |
| stq $16, 10*8($30) | |
| stq $17, 11*8($30) | |
| stq $18, 12*8($30) | |
| ldq $16, 24($1) # load cif | |
| ldq $17, 32($1) # load fun | |
| ldq $18, 40($1) # load user_data | |
| $do_closure: | |
| stq $19, 13*8($30) | |
| stq $20, 14*8($30) | |
| stq $21, 15*8($30) | |
| stt $f16, 4*8($30) | |
| stt $f17, 5*8($30) | |
| stt $f18, 6*8($30) | |
| stt $f19, 7*8($30) | |
| stt $f20, 8*8($30) | |
| stt $f21, 9*8($30) | |
| # Call ffi_closure_osf_inner to do the bulk of the work. | |
| lda $19, 2*8($30) | |
| lda $20, 10*8($30) | |
| jsr $26, ffi_closure_osf_inner | |
| 0: | |
| ldah $29, 0($26) !gpdisp!2 | |
| lda $2, 99f-0b($26) | |
| s4addq $0, 0, $1 # ldcode * 4 | |
| ldq $0, 16($30) # preload return value | |
| s4addq $1, $2, $1 # 99f + ldcode * 16 | |
| lda $29, 0($29) !gpdisp!2 | |
| ldq $26, 0($30) | |
| cfi_restore($26) | |
| jmp $31, ($1), $load_32 | |
| .macro epilogue | |
| addq $30, CLOSURE_FS, $30 | |
| cfi_adjust_cfa_offset(-CLOSURE_FS) | |
| ret | |
| .align 4 | |
| cfi_adjust_cfa_offset(CLOSURE_FS) | |
| .endm | |
| .align 4 | |
| 99: | |
| E ALPHA_LD_VOID | |
| epilogue | |
| E ALPHA_LD_INT64 | |
| epilogue | |
| E ALPHA_LD_INT32 | |
| $load_32: | |
| sextl $0, $0 | |
| epilogue | |
| E ALPHA_LD_UINT16 | |
| zapnot $0, 3, $0 | |
| epilogue | |
| E ALPHA_LD_SINT16 | |
| #ifdef __alpha_bwx__ | |
| sextw $0, $0 | |
| #else | |
| sll $0, 48, $0 | |
| sra $0, 48, $0 | |
| #endif | |
| epilogue | |
| E ALPHA_LD_UINT8 | |
| and $0, 0xff, $0 | |
| epilogue | |
| E ALPHA_LD_SINT8 | |
| #ifdef __alpha_bwx__ | |
| sextb $0, $0 | |
| #else | |
| sll $0, 56, $0 | |
| sra $0, 56, $0 | |
| #endif | |
| epilogue | |
| E ALPHA_LD_FLOAT | |
| lds $f0, 16($sp) | |
| epilogue | |
| E ALPHA_LD_DOUBLE | |
| ldt $f0, 16($sp) | |
| epilogue | |
| E ALPHA_LD_CPLXF | |
| lds $f0, 16($sp) | |
| lds $f1, 20($sp) | |
| epilogue | |
| E ALPHA_LD_CPLXD | |
| ldt $f0, 16($sp) | |
| ldt $f1, 24($sp) | |
| epilogue | |
| cfi_endproc | |
| .end ffi_closure_osf | |
| #if defined __ELF__ && defined __linux__ | |
| .section .note.GNU-stack,"",@progbits | |
| #endif |