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#ifndef __s390x__
33
34.text
35
36	# r2:	cif->bytes
37	# r3:	&ecif
38	# r4:	ffi_prep_args
39	# r5:	ret_type
40	# r6:	ecif.rvalue
41	# ov:	fn
42
43	# This assumes we are using gas.
44	.globl	ffi_call_SYSV
45	.type	ffi_call_SYSV,%function
46ffi_call_SYSV:
47.LFB1:
48	stm	%r6,%r15,24(%r15)		# Save registers
49.LCFI0:
50	basr	%r13,0				# Set up base register
51.Lbase:
52	lr	%r11,%r15			# Set up frame pointer
53.LCFI1:
54	sr	%r15,%r2
55	ahi	%r15,-96-48			# Allocate stack
56	lr	%r8,%r6				# Save ecif.rvalue
57	sr	%r9,%r9
58	ic	%r9,.Ltable-.Lbase(%r13,%r5)	# Load epilog address
59	l	%r7,96(%r11)			# Load function address
60	st	%r11,0(%r15)			# Set up back chain
61	ahi	%r11,-48			# Register save area
62.LCFI2:
63
64	la	%r2,96(%r15)			# Save area
65						# r3 already holds &ecif
66	basr	%r14,%r4			# Call ffi_prep_args
67
68	lm	%r2,%r6,0(%r11)			# Load arguments
69	ld	%f0,32(%r11)
70	ld	%f2,40(%r11)
71	la	%r14,0(%r13,%r9)		# Set return address
72	br	%r7				# ... and call function
73
74.LretNone:					# Return void
75	l	%r4,48+56(%r11)
76	lm	%r6,%r15,48+24(%r11)
77	br	%r4
78
79.LretFloat:
80	l	%r4,48+56(%r11)
81	ste	%f0,0(%r8)			# Return float
82	lm	%r6,%r15,48+24(%r11)
83	br	%r4
84
85.LretDouble:
86	l	%r4,48+56(%r11)
87	std	%f0,0(%r8)			# Return double
88	lm	%r6,%r15,48+24(%r11)
89	br	%r4
90
91.LretInt32:
92	l	%r4,48+56(%r11)
93	st	%r2,0(%r8)			# Return int
94	lm	%r6,%r15,48+24(%r11)
95	br	%r4
96
97.LretInt64:
98	l	%r4,48+56(%r11)
99	stm	%r2,%r3,0(%r8)			# Return long long
100	lm	%r6,%r15,48+24(%r11)
101	br	%r4
102
103.Ltable:
104	.byte	.LretNone-.Lbase		# FFI390_RET_VOID
105	.byte	.LretNone-.Lbase		# FFI390_RET_STRUCT
106	.byte	.LretFloat-.Lbase		# FFI390_RET_FLOAT
107	.byte	.LretDouble-.Lbase		# FFI390_RET_DOUBLE
108	.byte	.LretInt32-.Lbase		# FFI390_RET_INT32
109	.byte	.LretInt64-.Lbase		# FFI390_RET_INT64
110
111.LFE1:
112.ffi_call_SYSV_end:
113	.size	 ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
114
115
116	.globl	ffi_closure_SYSV
117	.type	ffi_closure_SYSV,%function
118ffi_closure_SYSV:
119.LFB2:
120	stm	%r12,%r15,48(%r15)		# Save registers
121.LCFI10:
122	basr	%r13,0				# Set up base register
123.Lcbase:
124	stm	%r2,%r6,8(%r15)			# Save arguments
125	std	%f0,64(%r15)
126	std	%f2,72(%r15)
127	lr	%r1,%r15			# Set up stack frame
128	ahi	%r15,-96
129.LCFI11:
130	l	%r12,.Lchelper-.Lcbase(%r13)	# Get helper function
131	lr	%r2,%r0				# Closure
132	la	%r3,8(%r1)			# GPRs
133	la	%r4,64(%r1)			# FPRs
134	la	%r5,96(%r1)			# Overflow
135	st	%r1,0(%r15)			# Set up back chain
136
137	bas	%r14,0(%r12,%r13)		# Call helper
138
139	l	%r4,96+56(%r15)
140	ld	%f0,96+64(%r15)			# Load return registers
141	lm	%r2,%r3,96+8(%r15)
142	lm	%r12,%r15,96+48(%r15)
143	br	%r4
144
145	.align 4
146.Lchelper:
147	.long	ffi_closure_helper_SYSV-.Lcbase
148
149.LFE2:
150
151.ffi_closure_SYSV_end:
152	.size	 ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
153
154
155	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
156.Lframe1:
157	.4byte	.LECIE1-.LSCIE1	# Length of Common Information Entry
158.LSCIE1:
159	.4byte	0x0	# CIE Identifier Tag
160	.byte	0x1	# CIE Version
161	.ascii "zR\0"	# CIE Augmentation
162	.uleb128 0x1	# CIE Code Alignment Factor
163	.sleb128 -4	# CIE Data Alignment Factor
164	.byte	0xe	# CIE RA Column
165	.uleb128 0x1	# Augmentation size
166	.byte	0x1b	# FDE Encoding (pcrel sdata4)
167	.byte	0xc	# DW_CFA_def_cfa
168	.uleb128 0xf
169	.uleb128 0x60
170	.align	4
171.LECIE1:
172.LSFDE1:
173	.4byte	.LEFDE1-.LASFDE1	# FDE Length
174.LASFDE1:
175	.4byte	.LASFDE1-.Lframe1	# FDE CIE offset
176	.4byte	.LFB1-.	# FDE initial location
177	.4byte	.LFE1-.LFB1	# FDE address range
178	.uleb128 0x0	# Augmentation size
179	.byte	0x4	# DW_CFA_advance_loc4
180	.4byte	.LCFI0-.LFB1
181	.byte	0x8f	# DW_CFA_offset, column 0xf
182	.uleb128 0x9
183	.byte	0x8e	# DW_CFA_offset, column 0xe
184	.uleb128 0xa
185	.byte	0x8d	# DW_CFA_offset, column 0xd
186	.uleb128 0xb
187	.byte	0x8c	# DW_CFA_offset, column 0xc
188	.uleb128 0xc
189	.byte	0x8b	# DW_CFA_offset, column 0xb
190	.uleb128 0xd
191	.byte	0x8a	# DW_CFA_offset, column 0xa
192	.uleb128 0xe
193	.byte	0x89	# DW_CFA_offset, column 0x9
194	.uleb128 0xf
195	.byte	0x88	# DW_CFA_offset, column 0x8
196	.uleb128 0x10
197	.byte	0x87	# DW_CFA_offset, column 0x7
198	.uleb128 0x11
199	.byte	0x86	# DW_CFA_offset, column 0x6
200	.uleb128 0x12
201	.byte	0x4	# DW_CFA_advance_loc4
202	.4byte	.LCFI1-.LCFI0
203	.byte	0xd	# DW_CFA_def_cfa_register
204	.uleb128 0xb
205	.byte	0x4	# DW_CFA_advance_loc4
206	.4byte	.LCFI2-.LCFI1
207	.byte	0xe	# DW_CFA_def_cfa_offset
208	.uleb128 0x90
209	.align	4
210.LEFDE1:
211.LSFDE2:
212	.4byte	.LEFDE2-.LASFDE2	# FDE Length
213.LASFDE2:
214	.4byte	.LASFDE2-.Lframe1	# FDE CIE offset
215	.4byte	.LFB2-.	# FDE initial location
216	.4byte	.LFE2-.LFB2	# FDE address range
217	.uleb128 0x0	# Augmentation size
218	.byte	0x4	# DW_CFA_advance_loc4
219	.4byte	.LCFI10-.LFB2
220	.byte	0x8f	# DW_CFA_offset, column 0xf
221	.uleb128 0x9
222	.byte	0x8e	# DW_CFA_offset, column 0xe
223	.uleb128 0xa
224	.byte	0x8d	# DW_CFA_offset, column 0xd
225	.uleb128 0xb
226	.byte	0x8c	# DW_CFA_offset, column 0xc
227	.uleb128 0xc
228	.byte	0x4	# DW_CFA_advance_loc4
229	.4byte	.LCFI11-.LCFI10
230	.byte	0xe	# DW_CFA_def_cfa_offset
231	.uleb128 0xc0
232	.align	4
233.LEFDE2:
234
235#else
236
237.text
238
239	# r2:	cif->bytes
240	# r3:	&ecif
241	# r4:	ffi_prep_args
242	# r5:	ret_type
243	# r6:	ecif.rvalue
244	# ov:	fn
245
246	# This assumes we are using gas.
247	.globl	ffi_call_SYSV
248	.type	ffi_call_SYSV,%function
249ffi_call_SYSV:
250.LFB1:
251	stmg	%r6,%r15,48(%r15)		# Save registers
252.LCFI0:
253	larl	%r13,.Lbase			# Set up base register
254	lgr	%r11,%r15			# Set up frame pointer
255.LCFI1:
256	sgr	%r15,%r2
257	aghi	%r15,-160-80			# Allocate stack
258	lgr	%r8,%r6				# Save ecif.rvalue
259	llgc	%r9,.Ltable-.Lbase(%r13,%r5)	# Load epilog address
260	lg	%r7,160(%r11)			# Load function address
261	stg	%r11,0(%r15)			# Set up back chain
262	aghi	%r11,-80			# Register save area
263.LCFI2:
264
265	la	%r2,160(%r15)			# Save area
266						# r3 already holds &ecif
267	basr	%r14,%r4			# Call ffi_prep_args
268
269	lmg	%r2,%r6,0(%r11)			# Load arguments
270	ld	%f0,48(%r11)
271	ld	%f2,56(%r11)
272	ld	%f4,64(%r11)
273	ld	%f6,72(%r11)
274	la	%r14,0(%r13,%r9)		# Set return address
275	br	%r7				# ... and call function
276
277.Lbase:
278.LretNone:					# Return void
279	lg	%r4,80+112(%r11)
280	lmg	%r6,%r15,80+48(%r11)
281	br	%r4
282
283.LretFloat:
284	lg	%r4,80+112(%r11)
285	ste	%f0,0(%r8)			# Return float
286	lmg	%r6,%r15,80+48(%r11)
287	br	%r4
288
289.LretDouble:
290	lg	%r4,80+112(%r11)
291	std	%f0,0(%r8)			# Return double
292	lmg	%r6,%r15,80+48(%r11)
293	br	%r4
294
295.LretInt32:
296	lg	%r4,80+112(%r11)
297	st	%r2,0(%r8)			# Return int
298	lmg	%r6,%r15,80+48(%r11)
299	br	%r4
300
301.LretInt64:
302	lg	%r4,80+112(%r11)
303	stg	%r2,0(%r8)			# Return long
304	lmg	%r6,%r15,80+48(%r11)
305	br	%r4
306
307.Ltable:
308	.byte	.LretNone-.Lbase		# FFI390_RET_VOID
309	.byte	.LretNone-.Lbase		# FFI390_RET_STRUCT
310	.byte	.LretFloat-.Lbase		# FFI390_RET_FLOAT
311	.byte	.LretDouble-.Lbase		# FFI390_RET_DOUBLE
312	.byte	.LretInt32-.Lbase		# FFI390_RET_INT32
313	.byte	.LretInt64-.Lbase		# FFI390_RET_INT64
314
315.LFE1:
316.ffi_call_SYSV_end:
317	.size	 ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
318
319
320	.globl	ffi_closure_SYSV
321	.type	ffi_closure_SYSV,%function
322ffi_closure_SYSV:
323.LFB2:
324	stmg	%r14,%r15,112(%r15)		# Save registers
325.LCFI10:
326	stmg	%r2,%r6,16(%r15)		# Save arguments
327	std	%f0,128(%r15)
328	std	%f2,136(%r15)
329	std	%f4,144(%r15)
330	std	%f6,152(%r15)
331	lgr	%r1,%r15			# Set up stack frame
332	aghi	%r15,-160
333.LCFI11:
334	lgr	%r2,%r0				# Closure
335	la	%r3,16(%r1)			# GPRs
336	la	%r4,128(%r1)			# FPRs
337	la	%r5,160(%r1)			# Overflow
338	stg	%r1,0(%r15)			# Set up back chain
339
340	brasl	%r14,ffi_closure_helper_SYSV	# Call helper
341
342	lg	%r14,160+112(%r15)
343	ld	%f0,160+128(%r15)		# Load return registers
344	lg	%r2,160+16(%r15)
345	la	%r15,160(%r15)
346	br	%r14
347.LFE2:
348
349.ffi_closure_SYSV_end:
350	.size	 ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV
351
352
353
354	.section	.eh_frame,EH_FRAME_FLAGS,@progbits
355.Lframe1:
356	.4byte	.LECIE1-.LSCIE1	# Length of Common Information Entry
357.LSCIE1:
358	.4byte	0x0	# CIE Identifier Tag
359	.byte	0x1	# CIE Version
360	.ascii "zR\0"	# CIE Augmentation
361	.uleb128 0x1	# CIE Code Alignment Factor
362	.sleb128 -8	# CIE Data Alignment Factor
363	.byte	0xe	# CIE RA Column
364	.uleb128 0x1	# Augmentation size
365	.byte	0x1b	# FDE Encoding (pcrel sdata4)
366	.byte	0xc	# DW_CFA_def_cfa
367	.uleb128 0xf
368	.uleb128 0xa0
369	.align	8
370.LECIE1:
371.LSFDE1:
372	.4byte	.LEFDE1-.LASFDE1	# FDE Length
373.LASFDE1:
374	.4byte	.LASFDE1-.Lframe1	# FDE CIE offset
375	.4byte	.LFB1-.	# FDE initial location
376	.4byte	.LFE1-.LFB1	# FDE address range
377	.uleb128 0x0	# Augmentation size
378	.byte	0x4	# DW_CFA_advance_loc4
379	.4byte	.LCFI0-.LFB1
380	.byte	0x8f	# DW_CFA_offset, column 0xf
381	.uleb128 0x5
382	.byte	0x8e	# DW_CFA_offset, column 0xe
383	.uleb128 0x6
384	.byte	0x8d	# DW_CFA_offset, column 0xd
385	.uleb128 0x7
386	.byte	0x8c	# DW_CFA_offset, column 0xc
387	.uleb128 0x8
388	.byte	0x8b	# DW_CFA_offset, column 0xb
389	.uleb128 0x9
390	.byte	0x8a	# DW_CFA_offset, column 0xa
391	.uleb128 0xa
392	.byte	0x89	# DW_CFA_offset, column 0x9
393	.uleb128 0xb
394	.byte	0x88	# DW_CFA_offset, column 0x8
395	.uleb128 0xc
396	.byte	0x87	# DW_CFA_offset, column 0x7
397	.uleb128 0xd
398	.byte	0x86	# DW_CFA_offset, column 0x6
399	.uleb128 0xe
400	.byte	0x4	# DW_CFA_advance_loc4
401	.4byte	.LCFI1-.LCFI0
402	.byte	0xd	# DW_CFA_def_cfa_register
403	.uleb128 0xb
404	.byte	0x4	# DW_CFA_advance_loc4
405	.4byte	.LCFI2-.LCFI1
406	.byte	0xe	# DW_CFA_def_cfa_offset
407	.uleb128 0xf0
408	.align	8
409.LEFDE1:
410.LSFDE2:
411	.4byte	.LEFDE2-.LASFDE2	# FDE Length
412.LASFDE2:
413	.4byte	.LASFDE2-.Lframe1	# FDE CIE offset
414	.4byte	.LFB2-.	# FDE initial location
415	.4byte	.LFE2-.LFB2	# FDE address range
416	.uleb128 0x0	# Augmentation size
417	.byte	0x4	# DW_CFA_advance_loc4
418	.4byte	.LCFI10-.LFB2
419	.byte	0x8f	# DW_CFA_offset, column 0xf
420	.uleb128 0x5
421	.byte	0x8e	# DW_CFA_offset, column 0xe
422	.uleb128 0x6
423	.byte	0x4	# DW_CFA_advance_loc4
424	.4byte	.LCFI11-.LCFI10
425	.byte	0xe	# DW_CFA_def_cfa_offset
426	.uleb128 0x140
427	.align	8
428.LEFDE2:
429
430#endif
431
432#if defined __ELF__ && defined __linux__
433	.section	.note.GNU-stack,"",@progbits
434#endif
435