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 * m88k Foreign Function Interface
26 */
27
28#define LIBFFI_ASM
29#include <fficonfig.h>
30#include <ffi.h>
31
32	.text
33
34/*
35 * ffi_cacheflush_OBSD(unsigned int addr,	%r2
36 *		       unsigned int size);	%r3
37 */
38	.align	4
39	.globl	ffi_cacheflush_OBSD
40	.type	ffi_cacheflush_OBSD,@function
41ffi_cacheflush_OBSD:
42	tb0	0,   %r0, 451
43	or	%r0, %r0, %r0
44	jmp	%r1
45	.size	ffi_cacheflush_OBSD, . - ffi_cacheflush_OBSD
46
47/*
48 * ffi_call_OBSD(unsigned bytes,		%r2
49 *		 extended_cif *ecif,		%r3
50 *		 unsigned flags,		%r4
51 *		 void *rvalue,			%r5
52 *		 void (*fn)());			%r6
53 */
54	.align	4
55	.globl	ffi_call_OBSD
56	.type	ffi_call_OBSD,@function
57ffi_call_OBSD:
58	subu	%r31, %r31, 32
59	st	%r30, %r31, 4
60	st	%r1,  %r31, 0
61	addu	%r30, %r31, 32
62
63	| Save the few arguments we'll need after ffi_prep_args()
64	st.d	%r4, %r31, 8
65	st	%r6, %r31, 16
66
67	| Allocate room for the image of r2-r9, and the stack space for
68	| the args (rounded to a 16-byte boundary)
69	addu	%r2,  %r2,  (8 * 4) + 15
70	clr	%r2,  %r2,  4<0>
71	subu	%r31, %r31, %r2
72
73	| Fill register and stack image
74	or	%r2, %r31, %r0
75#ifdef PIC
76	bsr	ffi_prep_args#plt
77#else
78	bsr	ffi_prep_args
79#endif
80
81	| Save pointer to return struct address, if any
82	or	%r12, %r2, %r0
83
84	| Get function pointer
85	subu	%r4,  %r30, 32
86	ld	%r1,  %r4,  16
87
88	| Fetch the register arguments
89	ld.d	%r2, %r31, (0 * 4)
90	ld.d	%r4, %r31, (2 * 4)
91	ld.d	%r6, %r31, (4 * 4)
92	ld.d	%r8, %r31, (6 * 4)
93	addu	%r31, %r31, (8 * 4)
94
95	| Invoke the function
96	jsr	%r1
97
98	| Restore stack now that we don't need the args anymore
99	subu	%r31, %r30, 32
100
101	| Figure out what to return as the function's return value
102	ld	%r5, %r31, 12		| rvalue
103	ld	%r4, %r31, 8		| flags
104
105	bcnd	eq0, %r5, 9f
106
107	bb0	0, %r4, 1f		| CIF_FLAGS_INT
108	st	%r2, %r5, 0
109	br	9f
110
1111:
112	bb0	1, %r4, 1f		| CIF_FLAGS_DINT
113	st.d	%r2, %r5, 0
114	br	9f
115
1161:
1179:
118	ld	%r1,  %r31, 0
119	ld	%r30, %r31, 4
120	jmp.n	%r1
121	 addu	%r31, %r31, 32
122	.size	ffi_call_OBSD, . - ffi_call_OBSD
123
124/*
125 * ffi_closure_OBSD(ffi_closure *closure);	%r13
126 */
127	.align	4
128	.globl	ffi_closure_OBSD
129	.type	ffi_closure_OBSD, @function
130ffi_closure_OBSD:
131	subu	%r31, %r31, 16
132	st	%r30, %r31, 4
133	st	%r1,  %r31, 0
134	addu	%r30, %r31, 16
135
136	| Make room on the stack for saved register arguments and return
137	| value
138	subu	%r31, %r31, (8 * 4) + (2 * 4)
139	st.d	%r2,  %r31, (0 * 4)
140	st.d	%r4,  %r31, (2 * 4)
141	st.d	%r6,  %r31, (4 * 4)
142	st.d	%r8,  %r31, (6 * 4)
143
144	| Invoke the closure function
145	or	%r5,  %r30, 0			| calling stack
146	addu	%r4,  %r31, 0			| saved registers
147	addu	%r3,  %r31, (8 * 4)		| return value
148	or	%r2,  %r13, %r0			| closure
149#ifdef PIC
150	bsr	ffi_closure_OBSD_inner#plt
151#else
152	bsr	ffi_closure_OBSD_inner
153#endif
154
155	| Figure out what to return as the function's return value
156	bb0	0, %r2, 1f		| CIF_FLAGS_INT
157	ld	%r2, %r31, (8 * 4)
158	br	9f
159
1601:
161	bb0	1, %r2, 1f		| CIF_FLAGS_DINT
162	ld.d	%r2, %r31, (8 * 4)
163	br	9f
164
1651:
1669:
167	subu	%r31, %r30, 16
168	ld	%r1,  %r31, 0
169	ld	%r30, %r31, 4
170	jmp.n	%r1
171	 addu	%r31, %r31, 16
172	.size	ffi_closure_OBSD,.-ffi_closure_OBSD
173
174/*
175 * ffi_closure_struct_OBSD(ffi_closure *closure);	%r13
176 */
177	.align	4
178	.globl	ffi_closure_struct_OBSD
179	.type	ffi_closure_struct_OBSD, @function
180ffi_closure_struct_OBSD:
181	subu	%r31, %r31, 16
182	st	%r30, %r31, 4
183	st	%r1,  %r31, 0
184	addu	%r30, %r31, 16
185
186	| Make room on the stack for saved register arguments
187	subu	%r31, %r31, (8 * 4)
188	st.d	%r2,  %r31, (0 * 4)
189	st.d	%r4,  %r31, (2 * 4)
190	st.d	%r6,  %r31, (4 * 4)
191	st.d	%r8,  %r31, (6 * 4)
192
193	| Invoke the closure function
194	or	%r5,  %r30, 0			| calling stack
195	addu	%r4,  %r31, 0			| saved registers
196	or	%r3,  %r12, 0			| return value
197	or	%r2,  %r13, %r0			| closure
198#ifdef PIC
199	bsr	ffi_closure_OBSD_inner#plt
200#else
201	bsr	ffi_closure_OBSD_inner
202#endif
203
204	subu	%r31, %r30, 16
205	ld	%r1,  %r31, 0
206	ld	%r30, %r31, 4
207	jmp.n	%r1
208	 addu	%r31, %r31, 16
209	.size	ffi_closure_struct_OBSD,.-ffi_closure_struct_OBSD
210