1/*
2 * Copyright (c) 2013 Miodrag Vallat.  <miod@openbsd.org>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * ``Software''), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24/*
25 * vax Foreign Function Interface
26 */
27
28#define LIBFFI_ASM
29#include <fficonfig.h>
30#include <ffi.h>
31
32	.text
33
34/*
35 * void *					%r0
36 * ffi_call_elfbsd(extended_cif *ecif,		4(%ap)
37 *		   unsigned bytes,		8(%ap)
38 *		   unsigned flags,		12(%ap)
39 *		   void *rvalue,		16(%ap)
40 *		   void (*fn)());		20(%ap)
41 */
42	.globl	ffi_call_elfbsd
43	.type	ffi_call_elfbsd,@function
44	.align	2
45ffi_call_elfbsd:
46	.word	0x00c		# save R2 and R3
47
48	# Allocate stack space for the args
49	subl2	8(%ap), %sp
50
51	# Call ffi_prep_args
52	pushl	%sp
53	pushl	4(%ap)
54	calls	$2, ffi_prep_args
55
56	# Get function pointer
57	movl	20(%ap), %r1
58
59	# Build a CALLS frame
60	ashl	$-2, 8(%ap), %r0
61	pushl	%r0		# argument stack usage
62	movl	%sp, %r0	# future %ap
63	# saved registers
64	bbc	$11, 0(%r1), 1f
65	pushl	%r11
661:	bbc	$10, 0(%r1), 1f
67	pushl	%r10
681:	bbc	$9, 0(%r1), 1f
69	pushl	%r9
701:	bbc	$8, 0(%r1), 1f
71	pushl	%r8
721:	bbc	$7, 0(%r1), 1f
73	pushl	%r7
741:	bbc	$6, 0(%r1), 1f
75	pushl	%r6
761:	bbc	$5, 0(%r1), 1f
77	pushl	%r5
781:	bbc	$4, 0(%r1), 1f
79	pushl	%r4
801:	bbc	$3, 0(%r1), 1f
81	pushl	%r3
821:	bbc	$2, 0(%r1), 1f
83	pushl	%r2
841:
85	pushal	9f
86	pushl	%fp
87	pushl	%ap
88	movl	16(%ap), %r3	# struct return address, if needed
89	movl	%r0, %ap
90	movzwl	4(%fp), %r0	# previous PSW, without the saved registers mask
91	bisl2	$0x20000000, %r0 # calls frame
92	movzwl	0(%r1), %r2
93	bicw2	$0xf003, %r2	# only keep R11-R2
94	ashl	$16, %r2, %r2
95	bisl2	%r2, %r0	# saved register mask of the called function
96	pushl	%r0
97	pushl	$0
98	movl	%sp, %fp
99
100	# Invoke the function
101	pushal	2(%r1)		# skip procedure entry mask
102	movl	%r3, %r1
103	bicpsw	$0x000f
104	rsb
105
1069:
107	# Copy return value if necessary
108	tstl	16(%ap)
109	jeql	9f
110	movl	16(%ap), %r2
111
112	bbc	$0, 12(%ap), 1f	# CIF_FLAGS_CHAR
113	movb	%r0, 0(%r2)
114	brb	9f
1151:
116	bbc	$1, 12(%ap), 1f	# CIF_FLAGS_SHORT
117	movw	%r0, 0(%r2)
118	brb	9f
1191:
120	bbc	$2, 12(%ap), 1f	# CIF_FLAGS_INT
121	movl	%r0, 0(%r2)
122	brb	9f
1231:
124	bbc	$3, 12(%ap), 1f	# CIF_FLAGS_DINT
125	movq	%r0, 0(%r2)
126	brb	9f
1271:
128	movl	%r1, %r0	# might have been a struct
129	#brb	9f
130
1319:
132	ret
133
134/*
135 * ffi_closure_elfbsd(void);
136 * invoked with	%r0: ffi_closure *closure
137 */
138	.globl	ffi_closure_elfbsd
139	.type	ffi_closure_elfbsd, @function
140	.align	2
141ffi_closure_elfbsd:
142	.word	0
143
144	# Allocate room on stack for return value
145	subl2	$8, %sp
146
147	# Invoke the closure function
148	pushal	4(%ap)		# calling stack
149	pushal	4(%sp)		# return value
150	pushl	%r0		# closure
151	calls	$3, ffi_closure_elfbsd_inner
152
153	# Copy return value if necessary
154	bitb	$1, %r0		# CIF_FLAGS_CHAR
155	beql	1f
156	movb	0(%sp), %r0
157	brb	9f
1581:
159	bitb	$2, %r0		# CIF_FLAGS_SHORT
160	beql	1f
161	movw	0(%sp), %r0
162	brb	9f
1631:
164	bitb	$4, %r0		# CIF_FLAGS_INT
165	beql	1f
166	movl	0(%sp), %r0
167	brb	9f
1681:
169	bitb	$8, %r0		# CIF_FLAGS_DINT
170	beql	1f
171	movq	0(%sp), %r0
172	#brb	9f
1731:
174
1759:
176	ret
177
178/*
179 * ffi_closure_struct_elfbsd(void);
180 * invoked with	%r0: ffi_closure *closure
181 *		%r1: struct return address
182 */
183	.globl	ffi_closure_struct_elfbsd
184	.type	ffi_closure_struct_elfbsd, @function
185	.align	2
186ffi_closure_struct_elfbsd:
187	.word	0
188
189	# Invoke the closure function
190	pushal	4(%ap)		# calling stack
191	pushl	%r1		# return value
192	pushl	%r0		# closure
193	calls	$3, ffi_closure_elfbsd_inner
194
195	ret
196