Copyright (c) 2013 Miodrag Vallat. <miod@openbsd.org> 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.
/*
vax Foreign Function Interface /
define LIBFFI_ASM
include <fficonfig.h> include <ffi.h>
.text
/*
void * %r0 ffi_call_elfbsd(extended_cif *ecif, 4(%ap) unsigned bytes, 8(%ap) unsigned flags, 12(%ap) void *rvalue, 16(%ap) void (*fn)()); 20(%ap) / .globl ffi_call_elfbsd .type ffi_call_elfbsd,@function .align 2
ffi_call_elfbsd:
.word 0x00c # save R2 and R3 # Allocate stack space for the args subl2 8(%ap), %sp # Call ffi_prep_args pushl %sp pushl 4(%ap) calls $2, ffi_prep_args # Get function pointer movl 20(%ap), %r1 # Build a CALLS frame ashl $-2, 8(%ap), %r0 pushl %r0 # argument stack usage movl %sp, %r0 # future %ap # saved registers bbc $11, 0(%r1), 1f pushl %r11
1: bbc $10, 0(%r1), 1f
pushl %r10
1: bbc $9, 0(%r1), 1f
pushl %r9
1: bbc $8, 0(%r1), 1f
pushl %r8
1: bbc $7, 0(%r1), 1f
pushl %r7
1: bbc $6, 0(%r1), 1f
pushl %r6
1: bbc $5, 0(%r1), 1f
pushl %r5
1: bbc $4, 0(%r1), 1f
pushl %r4
1: bbc $3, 0(%r1), 1f
pushl %r3
1: bbc $2, 0(%r1), 1f
pushl %r2
1:
pushal 9f pushl %fp pushl %ap movl 16(%ap), %r3 # struct return address, if needed movl %r0, %ap movzwl 4(%fp), %r0 # previous PSW, without the saved registers mask bisl2 $0x20000000, %r0 # calls frame movzwl 0(%r1), %r2 bicw2 $0xf003, %r2 # only keep R11-R2 ashl $16, %r2, %r2 bisl2 %r2, %r0 # saved register mask of the called function pushl %r0 pushl $0 movl %sp, %fp # Invoke the function pushal 2(%r1) # skip procedure entry mask movl %r3, %r1 bicpsw $0x000f rsb
9:
# Copy return value if necessary tstl 16(%ap) jeql 9f movl 16(%ap), %r2 bbc $0, 12(%ap), 1f # CIF_FLAGS_CHAR movb %r0, 0(%r2) brb 9f
1:
bbc $1, 12(%ap), 1f # CIF_FLAGS_SHORT movw %r0, 0(%r2) brb 9f
1:
bbc $2, 12(%ap), 1f # CIF_FLAGS_INT movl %r0, 0(%r2) brb 9f
1:
bbc $3, 12(%ap), 1f # CIF_FLAGS_DINT movq %r0, 0(%r2) brb 9f
1:
movl %r1, %r0 # might have been a struct #brb 9f
9:
ret
/*
ffi_closure_elfbsd(void); invoked with %r0: ffi_closure *closure / .globl ffi_closure_elfbsd .type ffi_closure_elfbsd, @function .align 2
ffi_closure_elfbsd:
.word 0 # Allocate room on stack for return value subl2 $8, %sp # Invoke the closure function pushal 4(%ap) # calling stack pushal 4(%sp) # return value pushl %r0 # closure calls $3, ffi_closure_elfbsd_inner # Copy return value if necessary bitb $1, %r0 # CIF_FLAGS_CHAR beql 1f movb 0(%sp), %r0 brb 9f
1:
bitb $2, %r0 # CIF_FLAGS_SHORT beql 1f movw 0(%sp), %r0 brb 9f
1:
bitb $4, %r0 # CIF_FLAGS_INT beql 1f movl 0(%sp), %r0 brb 9f
1:
bitb $8, %r0 # CIF_FLAGS_DINT beql 1f movq 0(%sp), %r0 #brb 9f
1:
9:
ret
/*
ffi_closure_struct_elfbsd(void); invoked with %r0: ffi_closure *closure %r1: struct return address / .globl ffi_closure_struct_elfbsd .type ffi_closure_struct_elfbsd, @function .align 2
ffi_closure_struct_elfbsd:
.word 0 # Invoke the closure function pushal 4(%ap) # calling stack pushl %r1 # return value pushl %r0 # closure calls $3, ffi_closure_elfbsd_inner ret