1/* -----------------------------------------------------------------------
2   hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
3	                (c) 2008 Red Hat, Inc.
4   based on src/pa/linux.S
5
6   HP-UX PA Foreign Function Interface
7
8   Permission is hereby granted, free of charge, to any person obtaining
9   a copy of this software and associated documentation files (the
10   ``Software''), to deal in the Software without restriction, including
11   without limitation the rights to use, copy, modify, merge, publish,
12   distribute, sublicense, and/or sell copies of the Software, and to
13   permit persons to whom the Software is furnished to do so, subject to
14   the following conditions:
15
16   The above copyright notice and this permission notice shall be included
17   in all copies or substantial portions of the Software.
18
19   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
20   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22   IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
23   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25   OTHER DEALINGS IN THE SOFTWARE.
26   ----------------------------------------------------------------------- */
27
28#define LIBFFI_ASM
29#include <fficonfig.h>
30#include <ffi.h>
31
32	.LEVEL 1.1
33	.SPACE	$PRIVATE$
34	.IMPORT	$global$,DATA
35	.IMPORT	$$dyncall,MILLICODE
36	.SUBSPA	$DATA$
37	.align	4
38
39	/* void ffi_call_pa32(void (*)(char *, extended_cif *),
40			       extended_cif *ecif,
41			       unsigned bytes,
42			       unsigned flags,
43			       unsigned *rvalue,
44			       void (*fn)(void));
45	 */
46
47	.export	ffi_call_pa32,ENTRY,PRIV_LEV=3
48	.import	ffi_prep_args_pa32,CODE
49
50	.SPACE	$TEXT$
51	.SUBSPA $CODE$
52	.align	4
53
54L$FB1
55ffi_call_pa32
56	.proc
57	.callinfo	FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
58	.entry
59	stw	%rp, -20(%sp)
60	copy	%r3, %r1
61L$CFI11
62	copy	%sp, %r3
63L$CFI12
64
65	/* Setup the stack for calling prep_args...
66	   We want the stack to look like this:
67
68	   [ Previous stack                            ] <- %r3
69
70	   [ 64-bytes register save area               ] <- %r4
71
72	   [ Stack space for actual call, passed as    ] <- %arg0
73	   [     arg0 to ffi_prep_args_pa32           ]
74
75	   [ Stack for calling prep_args               ] <- %sp
76	 */
77
78	stwm	%r1, 64(%sp)
79	stw	%r4, 12(%r3)
80L$CFI13
81	copy	%sp, %r4
82
83	addl	%arg2, %r4, %arg0	; arg stack
84	stw	%arg3, -48(%r3)		; save flags we need it later
85
86	/* Call prep_args:
87	   %arg0(stack) -- set up above
88	   %arg1(ecif)  -- same as incoming param
89	   %arg2(bytes) -- same as incoming param */
90	bl	ffi_prep_args_pa32,%r2
91	ldo	64(%arg0), %sp
92	ldo	-64(%sp), %sp
93
94	/* now %sp should point where %arg0 was pointing.  */
95
96	/* Load the arguments that should be passed in registers
97	   The fp args are loaded by the prep_args function.  */
98	ldw	-36(%sp), %arg0
99	ldw	-40(%sp), %arg1
100	ldw	-44(%sp), %arg2
101	ldw	-48(%sp), %arg3
102
103	/* in case the function is going to return a structure
104	   we need to give it a place to put the result.  */
105	ldw	-52(%r3), %ret0		; %ret0 <- rvalue
106	ldw	-56(%r3), %r22		; %r22 <- function to call
107	bl	$$dyncall, %r31		; Call the user function
108	copy	%r31, %rp
109
110	/* Prepare to store the result; we need to recover flags and rvalue.  */
111	ldw	-48(%r3), %r21		; r21 <- flags
112	ldw	-52(%r3), %r20		; r20 <- rvalue
113
114	/* Store the result according to the return type.  The most
115	   likely types should come first.  */
116
117L$checkint
118	comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
119	b	L$done
120	stw	%ret0, 0(%r20)
121
122L$checkint8
123	comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
124	b	L$done
125	stb	%ret0, 0(%r20)
126
127L$checkint16
128	comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
129	b	L$done
130	sth	%ret0, 0(%r20)
131
132L$checkdbl
133	comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
134	b	L$done
135	fstd	%fr4,0(%r20)
136
137L$checkfloat
138	comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
139	b	L$done
140	fstw	%fr4L,0(%r20)
141
142L$checkll
143	comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
144	stw	%ret0, 0(%r20)
145	b	L$done
146	stw	%ret1, 4(%r20)
147
148L$checksmst2
149	comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
150	/* 2-byte structs are returned in ret0 as ????xxyy.  */
151	extru	%ret0, 23, 8, %r22
152	stbs,ma	%r22, 1(%r20)
153	b	L$done
154	stb	%ret0, 0(%r20)
155
156L$checksmst3
157	comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
158	/* 3-byte structs are returned in ret0 as ??xxyyzz.  */
159	extru	%ret0, 15, 8, %r22
160	stbs,ma	%r22, 1(%r20)
161	extru	%ret0, 23, 8, %r22
162	stbs,ma	%r22, 1(%r20)
163	b	L$done
164	stb	%ret0, 0(%r20)
165
166L$checksmst4
167	comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
168	/* 4-byte structs are returned in ret0 as wwxxyyzz.  */
169	extru	%ret0, 7, 8, %r22
170	stbs,ma	%r22, 1(%r20)
171	extru	%ret0, 15, 8, %r22
172	stbs,ma	%r22, 1(%r20)
173	extru	%ret0, 23, 8, %r22
174	stbs,ma	%r22, 1(%r20)
175	b	L$done
176	stb	%ret0, 0(%r20)
177
178L$checksmst5
179	comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
180	/* 5 byte values are returned right justified:
181	      ret0     ret1
182	   5: ??????aa bbccddee */
183	stbs,ma	%ret0, 1(%r20)
184	extru	%ret1, 7, 8, %r22
185	stbs,ma	%r22, 1(%r20)
186	extru	%ret1, 15, 8, %r22
187	stbs,ma	%r22, 1(%r20)
188	extru	%ret1, 23, 8, %r22
189	stbs,ma	%r22, 1(%r20)
190	b	L$done
191	stb	%ret1, 0(%r20)
192
193L$checksmst6
194	comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
195	/* 6 byte values are returned right justified:
196	      ret0     ret1
197	   6: ????aabb ccddeeff */
198	extru	%ret0, 23, 8, %r22
199	stbs,ma	%r22, 1(%r20)
200	stbs,ma	%ret0, 1(%r20)
201	extru	%ret1, 7, 8, %r22
202	stbs,ma	%r22, 1(%r20)
203	extru	%ret1, 15, 8, %r22
204	stbs,ma	%r22, 1(%r20)
205	extru	%ret1, 23, 8, %r22
206	stbs,ma	%r22, 1(%r20)
207	b	L$done
208	stb	%ret1, 0(%r20)
209
210L$checksmst7
211	comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
212	/* 7 byte values are returned right justified:
213	      ret0     ret1
214	   7: ??aabbcc ddeeffgg */
215	extru	%ret0, 15, 8, %r22
216	stbs,ma	%r22, 1(%r20)
217	extru	%ret0, 23, 8, %r22
218	stbs,ma	%r22, 1(%r20)
219	stbs,ma	%ret0, 1(%r20)
220	extru	%ret1, 7, 8, %r22
221	stbs,ma	%r22, 1(%r20)
222	extru	%ret1, 15, 8, %r22
223	stbs,ma	%r22, 1(%r20)
224	extru	%ret1, 23, 8, %r22
225	stbs,ma	%r22, 1(%r20)
226	b	L$done
227	stb	%ret1, 0(%r20)
228
229L$checksmst8
230	comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
231	/* 8 byte values are returned right justified:
232	      ret0     ret1
233	   8: aabbccdd eeffgghh */
234	extru	%ret0, 7, 8, %r22
235	stbs,ma	%r22, 1(%r20)
236	extru	%ret0, 15, 8, %r22
237	stbs,ma	%r22, 1(%r20)
238	extru	%ret0, 23, 8, %r22
239	stbs,ma	%r22, 1(%r20)
240	stbs,ma	%ret0, 1(%r20)
241	extru	%ret1, 7, 8, %r22
242	stbs,ma	%r22, 1(%r20)
243	extru	%ret1, 15, 8, %r22
244	stbs,ma	%r22, 1(%r20)
245	extru	%ret1, 23, 8, %r22
246	stbs,ma	%r22, 1(%r20)
247	stb	%ret1, 0(%r20)
248
249L$done
250	/* all done, return */
251	copy	%r4, %sp	; pop arg stack
252	ldw	12(%r3), %r4
253	ldwm	-64(%sp), %r3	; .. and pop stack
254	ldw	-20(%sp), %rp
255	bv	%r0(%rp)
256	nop
257	.exit
258	.procend
259L$FE1
260
261	/* void ffi_closure_pa32(void);
262	   Called with closure argument in %r21 */
263
264	.SPACE $TEXT$
265	.SUBSPA $CODE$
266	.export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
267	.import ffi_closure_inner_pa32,CODE
268	.align 4
269L$FB2
270ffi_closure_pa32
271	.proc
272	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
273	.entry
274
275	stw	%rp, -20(%sp)
276	copy	%r3, %r1
277L$CFI21
278	copy	%sp, %r3
279L$CFI22
280	stwm	%r1, 64(%sp)
281
282	/* Put arguments onto the stack and call ffi_closure_inner.  */
283	stw	%arg0, -36(%r3)
284	stw	%arg1, -40(%r3)
285	stw	%arg2, -44(%r3)
286	stw	%arg3, -48(%r3)
287
288	copy	%r21, %arg0
289	bl	ffi_closure_inner_pa32, %r2
290	copy    %r3, %arg1
291	ldwm	-64(%sp), %r3
292	ldw	-20(%sp), %rp
293	ldw	-36(%sp), %ret0
294	bv	%r0(%rp)
295	ldw	-40(%sp), %ret1
296	.exit
297	.procend
298L$FE2:
299
300	.SPACE $PRIVATE$
301	.SUBSPA $DATA$
302
303	.align 4
304	.EXPORT _GLOBAL__F_ffi_call_pa32,DATA
305_GLOBAL__F_ffi_call_pa32
306L$frame1:
307	.word   L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
308L$SCIE1:
309	.word   0x0     ;# CIE Identifier Tag
310	.byte   0x1     ;# CIE Version
311	.ascii "\0"     ;# CIE Augmentation
312	.uleb128 0x1    ;# CIE Code Alignment Factor
313	.sleb128 4      ;# CIE Data Alignment Factor
314	.byte   0x2     ;# CIE RA Column
315	.byte   0xc     ;# DW_CFA_def_cfa
316	.uleb128 0x1e
317	.uleb128 0x0
318	.align 4
319L$ECIE1:
320L$SFDE1:
321	.word   L$EFDE1-L$ASFDE1        ;# FDE Length
322L$ASFDE1:
323	.word   L$ASFDE1-L$frame1       ;# FDE CIE offset
324	.word   L$FB1   ;# FDE initial location
325	.word   L$FE1-L$FB1     ;# FDE address range
326
327	.byte   0x4     ;# DW_CFA_advance_loc4
328	.word   L$CFI11-L$FB1
329	.byte	0x83	;# DW_CFA_offset, column 0x3
330	.uleb128 0x0
331	.byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
332	.uleb128 0x2
333	.sleb128 -5
334
335	.byte   0x4     ;# DW_CFA_advance_loc4
336	.word   L$CFI12-L$CFI11
337	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
338	.uleb128 0x3
339
340	.byte   0x4     ;# DW_CFA_advance_loc4
341	.word   L$CFI13-L$CFI12
342	.byte	0x84	;# DW_CFA_offset, column 0x4
343	.uleb128 0x3
344
345	.align 4
346L$EFDE1:
347
348L$SFDE2:
349	.word   L$EFDE2-L$ASFDE2        ;# FDE Length
350L$ASFDE2:
351	.word   L$ASFDE2-L$frame1       ;# FDE CIE offset
352	.word   L$FB2   ;# FDE initial location
353	.word   L$FE2-L$FB2     ;# FDE address range
354	.byte   0x4     ;# DW_CFA_advance_loc4
355	.word   L$CFI21-L$FB2
356	.byte   0x83    ;# DW_CFA_offset, column 0x3
357	.uleb128 0x0
358	.byte   0x11    ;# DW_CFA_offset_extended_sf
359	.uleb128 0x2
360	.sleb128 -5
361
362	.byte   0x4     ;# DW_CFA_advance_loc4
363	.word   L$CFI22-L$CFI21
364	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
365	.uleb128 0x3
366
367	.align 4
368L$EFDE2:
369