1/* -----------------------------------------------------------------------
2   osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat
3
4   Alpha/OSF Foreign Function Interface
5
6   Permission is hereby granted, free of charge, to any person obtaining
7   a copy of this software and associated documentation files (the
8   ``Software''), to deal in the Software without restriction, including
9   without limitation the rights to use, copy, modify, merge, publish,
10   distribute, sublicense, and/or sell copies of the Software, and to
11   permit persons to whom the Software is furnished to do so, subject to
12   the following conditions:
13
14   The above copyright notice and this permission notice shall be included
15   in all copies or substantial portions of the Software.
16
17   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24   DEALINGS IN THE SOFTWARE.
25   ----------------------------------------------------------------------- */
26
27#define LIBFFI_ASM
28#include <fficonfig.h>
29#include <ffi.h>
30#include <ffi_cfi.h>
31#include "internal.h"
32
33	.arch ev6
34	.text
35
36/* Aid in building a direct addressed jump table, 4 insns per entry.  */
37.macro E index
38	.align	4
39	.org	99b + \index * 16
40.endm
41
42/* ffi_call_osf (void *stack, void *frame, unsigned flags,
43		 void *raddr, void (*fnaddr)(void), void *closure)
44
45   Bit o trickiness here -- FRAME is the base of the stack frame
46   for this function.  This has been allocated by ffi_call.  We also
47   deallocate some of the stack that has been alloca'd.  */
48
49	.align	4
50	.globl	ffi_call_osf
51	.ent	ffi_call_osf
52	FFI_HIDDEN(ffi_call_osf)
53
54ffi_call_osf:
55	cfi_startproc
56	cfi_def_cfa($17, 32)
57	mov	$16, $30
58	stq	$26, 0($17)
59	stq	$15, 8($17)
60	mov	$17, $15
61	.prologue 0
62	cfi_def_cfa_register($15)
63	cfi_rel_offset($26, 0)
64	cfi_rel_offset($15, 8)
65
66	stq	$18, 16($17)		# save flags into frame
67	stq	$19, 24($17)		# save rvalue into frame
68	mov	$20, $27		# fn into place for call
69	mov	$21, $1			# closure into static chain
70
71	# Load up all of the (potential) argument registers.
72	ldq	$16, 0($30)
73	ldt	$f16, 0($30)
74	ldt	$f17, 8($30)
75	ldq	$17, 8($30)
76	ldt	$f18, 16($30)
77	ldq	$18, 16($30)
78	ldt	$f19, 24($30)
79	ldq	$19, 24($30)
80	ldt	$f20, 32($30)
81	ldq	$20, 32($30)
82	ldt	$f21, 40($30)
83	ldq	$21, 40($30)
84
85	# Deallocate the register argument area.
86	lda	$30, 48($30)
87
88	jsr	$26, ($27), 0
890:
90	ldah	$29, 0($26)		!gpdisp!1
91	ldq	$2, 24($15)		# reload rvalue
92	lda	$29, 0($29)		!gpdisp!1
93	ldq	$3, 16($15)		# reload flags
94	lda	$1, 99f-0b($26)
95	ldq	$26, 0($15)
96	ldq	$15, 8($15)
97	cfi_restore($26)
98	cfi_restore($15)
99	cfi_def_cfa($sp, 0)
100	cmoveq	$2, ALPHA_ST_VOID, $3	# mash null rvalue to void
101	addq	$3, $3, $3
102	s8addq	$3, $1, $1		# 99f + stcode * 16
103	jmp	$31, ($1), $st_int
104
105	.align	4
10699:
107E ALPHA_ST_VOID
108	ret
109E ALPHA_ST_INT
110$st_int:
111	stq	$0, 0($2)
112	ret
113E ALPHA_ST_FLOAT
114	sts	$f0, 0($2)
115	ret
116E ALPHA_ST_DOUBLE
117	stt	$f0, 0($2)
118	ret
119E ALPHA_ST_CPLXF
120	sts	$f0, 0($2)
121	sts	$f1, 4($2)
122	ret
123E ALPHA_ST_CPLXD
124	stt	$f0, 0($2)
125	stt	$f1, 8($2)
126	ret
127
128	cfi_endproc
129	.end	ffi_call_osf
130
131/* ffi_closure_osf(...)
132
133   Receives the closure argument in $1.   */
134
135#define CLOSURE_FS	(16*8)
136
137	.align	4
138	.globl	ffi_go_closure_osf
139	.ent	ffi_go_closure_osf
140	FFI_HIDDEN(ffi_go_closure_osf)
141
142ffi_go_closure_osf:
143	cfi_startproc
144	ldgp	$29, 0($27)
145	subq	$30, CLOSURE_FS, $30
146	cfi_adjust_cfa_offset(CLOSURE_FS)
147	stq	$26, 0($30)
148	.prologue 1
149	cfi_rel_offset($26, 0)
150
151	stq	$16, 10*8($30)
152	stq	$17, 11*8($30)
153	stq	$18, 12*8($30)
154
155	ldq	$16, 8($1)			# load cif
156	ldq	$17, 16($1)			# load fun
157	mov	$1, $18				# closure is user_data
158	br	$do_closure
159
160	cfi_endproc
161	.end	ffi_go_closure_osf
162
163	.align	4
164	.globl	ffi_closure_osf
165	.ent	ffi_closure_osf
166	FFI_HIDDEN(ffi_closure_osf)
167
168ffi_closure_osf:
169	cfi_startproc
170	ldgp	$29, 0($27)
171	subq	$30, CLOSURE_FS, $30
172	cfi_adjust_cfa_offset(CLOSURE_FS)
173	stq	$26, 0($30)
174	.prologue 1
175	cfi_rel_offset($26, 0)
176
177	# Store all of the potential argument registers in va_list format.
178	stq	$16, 10*8($30)
179	stq	$17, 11*8($30)
180	stq	$18, 12*8($30)
181
182	ldq	$16, 24($1)			# load cif
183	ldq	$17, 32($1)			# load fun
184	ldq	$18, 40($1)			# load user_data
185
186$do_closure:
187	stq	$19, 13*8($30)
188	stq	$20, 14*8($30)
189	stq	$21, 15*8($30)
190	stt	$f16, 4*8($30)
191	stt	$f17, 5*8($30)
192	stt	$f18, 6*8($30)
193	stt	$f19, 7*8($30)
194	stt	$f20, 8*8($30)
195	stt	$f21, 9*8($30)
196
197	# Call ffi_closure_osf_inner to do the bulk of the work.
198	lda	$19, 2*8($30)
199	lda	$20, 10*8($30)
200	jsr	$26, ffi_closure_osf_inner
2010:
202	ldah	$29, 0($26)			!gpdisp!2
203	lda	$2, 99f-0b($26)
204	s4addq	$0, 0, $1			# ldcode * 4
205	ldq	$0, 16($30)			# preload return value
206	s4addq	$1, $2, $1			# 99f + ldcode * 16
207	lda	$29, 0($29)			!gpdisp!2
208	ldq	$26, 0($30)
209	cfi_restore($26)
210	jmp	$31, ($1), $load_32
211
212.macro epilogue
213	addq	$30, CLOSURE_FS, $30
214	cfi_adjust_cfa_offset(-CLOSURE_FS)
215	ret
216	.align	4
217	cfi_adjust_cfa_offset(CLOSURE_FS)
218.endm
219
220	.align 4
22199:
222E ALPHA_LD_VOID
223	epilogue
224
225E ALPHA_LD_INT64
226	epilogue
227
228E ALPHA_LD_INT32
229$load_32:
230	sextl	$0, $0
231	epilogue
232
233E ALPHA_LD_UINT16
234	zapnot	$0, 3, $0
235	epilogue
236
237E ALPHA_LD_SINT16
238#ifdef __alpha_bwx__
239	sextw	$0, $0
240#else
241	sll	$0, 48, $0
242	sra	$0, 48, $0
243#endif
244	epilogue
245
246E ALPHA_LD_UINT8
247	and	$0, 0xff, $0
248	epilogue
249
250E ALPHA_LD_SINT8
251#ifdef __alpha_bwx__
252	sextb	$0, $0
253#else
254	sll	$0, 56, $0
255	sra	$0, 56, $0
256#endif
257	epilogue
258
259E ALPHA_LD_FLOAT
260	lds	$f0, 16($sp)
261	epilogue
262
263E ALPHA_LD_DOUBLE
264	ldt	$f0, 16($sp)
265	epilogue
266
267E ALPHA_LD_CPLXF
268	lds	$f0, 16($sp)
269	lds	$f1, 20($sp)
270	epilogue
271
272E ALPHA_LD_CPLXD
273	ldt	$f0, 16($sp)
274	ldt	$f1, 24($sp)
275	epilogue
276
277	cfi_endproc
278	.end	ffi_closure_osf
279
280#if defined __ELF__ && defined __linux__
281	.section	.note.GNU-stack,"",@progbits
282#endif
283