1/* -----------------------------------------------------------------------
2   sysv.S - Copyright (c) 2000 Software AG
3            Copyright (c) 2008 Red Hat, Inc.
4
5   S390 Foreign Function Interface
6
7   Permission is hereby granted, free of charge, to any person obtaining
8   a copy of this software and associated documentation files (the
9   ``Software''), to deal in the Software without restriction, including
10   without limitation the rights to use, copy, modify, merge, publish,
11   distribute, sublicense, and/or sell copies of the Software, and to
12   permit persons to whom the Software is furnished to do so, subject to
13   the following conditions:
14
15   The above copyright notice and this permission notice shall be included
16   in all copies or substantial portions of the Software.
17
18   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25   DEALINGS IN THE SOFTWARE.
26   ----------------------------------------------------------------------- */
27
28#define LIBFFI_ASM
29#include <fficonfig.h>
30#include <ffi.h>
31
32	.text
33
34#ifndef __s390x__
35
36	# r2:	frame
37	# r3:	ret_type
38	# r4:	ret_addr
39	# r5:	fun
40	# r6:	closure
41
42	# This assumes we are using gas.
43	.balign	8
44	.globl	ffi_call_SYSV
45	FFI_HIDDEN(ffi_call_SYSV)
46	.type	ffi_call_SYSV,%function
47ffi_call_SYSV:
48	.cfi_startproc
49	st	%r6,44(%r2)			# Save registers
50	stm	%r12,%r14,48(%r2)
51	lr	%r13,%r2			# Install frame pointer
52	.cfi_rel_offset r6, 44
53	.cfi_rel_offset r12, 48
54	.cfi_rel_offset r13, 52
55	.cfi_rel_offset r14, 56
56	.cfi_def_cfa_register r13
57	st	%r2,0(%r15)			# Set up back chain
58	sla	%r3,3				# ret_type *= 8
59	lr	%r12,%r4			# Save ret_addr
60	lr	%r1,%r5				# Save fun
61	lr	%r0,%r6				# Install static chain
62
63	# Set return address, so that there is only one indirect jump.
64#ifdef HAVE_AS_S390_ZARCH
65	larl	%r14,.Ltable
66	ar	%r14,%r3
67#else
68	basr	%r14,0
690:	la	%r14,.Ltable-0b(%r14,%r3)
70#endif
71
72	lm	%r2,%r6,8(%r13)			# Load arguments
73	ld	%f0,64(%r13)
74	ld	%f2,72(%r13)
75	br	%r1				# ... and call function
76
77	.balign	8
78.Ltable:
79# FFI390_RET_DOUBLE
80	std	%f0,0(%r12)
81	j	.Ldone
82
83	.balign	8
84# FFI390_RET_FLOAT
85	ste	%f0,0(%r12)
86	j	.Ldone
87
88	.balign	8
89# FFI390_RET_INT64
90	st	%r3,4(%r12)
91	nop
92	# fallthru
93
94	.balign	8
95# FFI390_RET_INT32
96	st	%r2,0(%r12)
97	nop
98	# fallthru
99
100	.balign	8
101# FFI390_RET_VOID
102.Ldone:
103	l	%r14,56(%r13)
104	l	%r12,48(%r13)
105	l	%r6,44(%r13)
106	l	%r13,52(%r13)
107	.cfi_restore 14
108	.cfi_restore 13
109	.cfi_restore 12
110	.cfi_restore 6
111	.cfi_def_cfa r15, 96
112	br	%r14
113	.cfi_endproc
114	.size	 ffi_call_SYSV,.-ffi_call_SYSV
115
116
117	.balign	8
118	.globl	ffi_go_closure_SYSV
119	FFI_HIDDEN(ffi_go_closure_SYSV)
120	.type	ffi_go_closure_SYSV,%function
121ffi_go_closure_SYSV:
122	.cfi_startproc
123	stm	%r2,%r6,8(%r15)			# Save arguments
124	lr	%r4,%r0				# Load closure -> user_data
125	l	%r2,4(%r4)			#   ->cif
126	l	%r3,8(%r4)			#   ->fun
127	j	.Ldoclosure
128	.cfi_endproc
129
130	.balign	8
131	.globl	ffi_closure_SYSV
132	FFI_HIDDEN(ffi_closure_SYSV)
133	.type	ffi_closure_SYSV,%function
134ffi_closure_SYSV:
135	.cfi_startproc
136	stm	%r2,%r6,8(%r15)			# Save arguments
137	lr	%r4,%r0				# Closure
138	l	%r2,16(%r4)			#   ->cif
139	l	%r3,20(%r4)			#   ->fun
140	l	%r4,24(%r4)			#   ->user_data
141.Ldoclosure:
142	stm	%r12,%r15,48(%r15)		# Save registers
143	lr	%r12,%r15
144	.cfi_def_cfa_register r12
145	.cfi_rel_offset r6, 24
146	.cfi_rel_offset r12, 48
147	.cfi_rel_offset r13, 52
148	.cfi_rel_offset r14, 56
149	.cfi_rel_offset r15, 60
150#ifndef HAVE_AS_S390_ZARCH
151	basr	%r13,0				# Set up base register
152.Lcbase:
153	l	%r1,.Lchelper-.Lcbase(%r13)	# Get helper function
154#endif
155	ahi	%r15,-96-8			# Set up stack frame
156	st	%r12,0(%r15)			# Set up back chain
157
158	std	%f0,64(%r12)			# Save fp arguments
159	std	%f2,72(%r12)
160
161	la	%r5,96(%r12)			# Overflow
162	st	%r5,96(%r15)
163	la	%r6,64(%r12)			# FPRs
164	la	%r5,8(%r12)			# GPRs
165#ifdef HAVE_AS_S390_ZARCH
166	brasl	%r14,ffi_closure_helper_SYSV
167#else
168	bas	%r14,0(%r1,%r13)		# Call helper
169#endif
170
171	lr	%r15,%r12
172	.cfi_def_cfa_register r15
173	lm	%r12,%r14,48(%r12)		# Restore saved registers
174	l	%r6,24(%r15)
175	ld	%f0,64(%r15)			# Load return registers
176	lm	%r2,%r3,8(%r15)
177	br	%r14
178	.cfi_endproc
179
180#ifndef HAVE_AS_S390_ZARCH
181	.align 4
182.Lchelper:
183	.long	ffi_closure_helper_SYSV-.Lcbase
184#endif
185
186	.size	 ffi_closure_SYSV,.-ffi_closure_SYSV
187
188#else
189
190	# r2:	frame
191	# r3:	ret_type
192	# r4:	ret_addr
193	# r5:	fun
194	# r6:	closure
195
196	# This assumes we are using gas.
197	.balign	8
198	.globl	ffi_call_SYSV
199	FFI_HIDDEN(ffi_call_SYSV)
200	.type	ffi_call_SYSV,%function
201ffi_call_SYSV:
202	.cfi_startproc
203	stg	%r6,88(%r2)			# Save registers
204	stmg	%r12,%r14,96(%r2)
205	lgr	%r13,%r2			# Install frame pointer
206	.cfi_rel_offset r6, 88
207	.cfi_rel_offset r12, 96
208	.cfi_rel_offset r13, 104
209	.cfi_rel_offset r14, 112
210	.cfi_def_cfa_register r13
211	stg	%r2,0(%r15)			# Set up back chain
212	larl	%r14,.Ltable			# Set up return address
213	slag	%r3,%r3,3			# ret_type *= 8
214	lgr	%r12,%r4			# Save ret_addr
215	lgr	%r1,%r5				# Save fun
216	lgr	%r0,%r6				# Install static chain
217	agr	%r14,%r3
218	lmg	%r2,%r6,16(%r13)		# Load arguments
219	ld	%f0,128(%r13)
220	ld	%f2,136(%r13)
221	ld	%f4,144(%r13)
222	ld	%f6,152(%r13)
223	br	%r1				# ... and call function
224
225	.balign	8
226.Ltable:
227# FFI390_RET_DOUBLE
228	std	%f0,0(%r12)
229	j	.Ldone
230
231	.balign	8
232# FFI390_RET_DOUBLE
233	ste	%f0,0(%r12)
234	j	.Ldone
235
236	.balign	8
237# FFI390_RET_INT64
238	stg	%r2,0(%r12)
239
240	.balign	8
241# FFI390_RET_INT32
242	# Never used, as we always store type ffi_arg.
243	# But the stg above is 6 bytes and we cannot
244	# jump around this case, so fall through.
245	nop
246	nop
247
248	.balign	8
249# FFI390_RET_VOID
250.Ldone:
251	lg	%r14,112(%r13)
252	lg	%r12,96(%r13)
253	lg	%r6,88(%r13)
254	lg	%r13,104(%r13)
255	.cfi_restore r14
256	.cfi_restore r13
257	.cfi_restore r12
258	.cfi_restore r6
259	.cfi_def_cfa r15, 160
260	br	%r14
261	.cfi_endproc
262	.size	 ffi_call_SYSV,.-ffi_call_SYSV
263
264
265	.balign	8
266	.globl	ffi_go_closure_SYSV
267	FFI_HIDDEN(ffi_go_closure_SYSV)
268	.type	ffi_go_closure_SYSV,%function
269ffi_go_closure_SYSV:
270	.cfi_startproc
271	stmg	%r2,%r6,16(%r15)		# Save arguments
272	lgr	%r4,%r0				# Load closure -> user_data
273	lg	%r2,8(%r4)			#   ->cif
274	lg	%r3,16(%r4)			#   ->fun
275	j	.Ldoclosure
276	.cfi_endproc
277	.size	 ffi_go_closure_SYSV,.-ffi_go_closure_SYSV
278
279
280	.balign	8
281	.globl	ffi_closure_SYSV
282	FFI_HIDDEN(ffi_closure_SYSV)
283	.type	ffi_closure_SYSV,%function
284ffi_closure_SYSV:
285	.cfi_startproc
286	stmg	%r2,%r6,16(%r15)		# Save arguments
287	lgr	%r4,%r0				# Load closure
288	lg	%r2,32(%r4)			#   ->cif
289	lg	%r3,40(%r4)			#   ->fun
290	lg	%r4,48(%r4)			#   ->user_data
291.Ldoclosure:
292	stmg	%r13,%r15,104(%r15)		# Save registers
293	lgr	%r13,%r15
294	.cfi_def_cfa_register r13
295	.cfi_rel_offset r6, 48
296	.cfi_rel_offset r13, 104
297	.cfi_rel_offset r14, 112
298	.cfi_rel_offset r15, 120
299	aghi	%r15,-160-16			# Set up stack frame
300	stg	%r13,0(%r15)			# Set up back chain
301
302	std	%f0,128(%r13)			# Save fp arguments
303	std	%f2,136(%r13)
304	std	%f4,144(%r13)
305	std	%f6,152(%r13)
306	la	%r5,160(%r13)			# Overflow
307	stg	%r5,160(%r15)
308	la	%r6,128(%r13)			# FPRs
309	la	%r5,16(%r13)			# GPRs
310	brasl	%r14,ffi_closure_helper_SYSV	# Call helper
311
312	lgr	%r15,%r13
313	.cfi_def_cfa_register r15
314	lmg	%r13,%r14,104(%r13)		# Restore saved registers
315	lg	%r6,48(%r15)
316	ld	%f0,128(%r15)			# Load return registers
317	lg	%r2,16(%r15)
318	br	%r14
319	.cfi_endproc
320	.size	 ffi_closure_SYSV,.-ffi_closure_SYSV
321#endif /* !s390x */
322
323#if defined __ELF__ && defined __linux__
324	.section	.note.GNU-stack,"",@progbits
325#endif
326