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