|  | /* | 
|  | * 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 |