1/* -----------------------------------------------------------------------
2   linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
3	     (c) 2008 Red Hat, Inc.
4
5   HPPA 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, EXPRESS
19   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21   IN NO EVENT SHALL RENESAS TECHNOLOGY BE LIABLE FOR ANY CLAIM, DAMAGES OR
22   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24   OTHER DEALINGS IN THE SOFTWARE.
25   ----------------------------------------------------------------------- */
26
27#define LIBFFI_ASM
28#include <fficonfig.h>
29#include <ffi.h>
30
31	.text
32	.level 1.1
33	.align 4
34
35	/* void ffi_call_pa32(void (*)(char *, extended_cif *),
36			       extended_cif *ecif,
37			       unsigned bytes,
38			       unsigned flags,
39			       unsigned *rvalue,
40			       void (*fn)(void));
41	 */
42
43	.export ffi_call_pa32,code
44	.import ffi_prep_args_pa32,code
45
46	.type ffi_call_pa32, @function
47.LFB1:
48ffi_call_pa32:
49	.proc
50	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
51	.entry
52	stw %rp, -20(%sp)
53	copy %r3, %r1
54.LCFI11:
55
56	copy %sp, %r3
57.LCFI12:
58
59	/* Setup the stack for calling prep_args...
60	   We want the stack to look like this:
61
62	   [ Previous stack                            ] <- %r3
63
64	   [ 64-bytes register save area               ] <- %r4
65
66	   [ Stack space for actual call, passed as    ] <- %arg0
67	   [     arg0 to ffi_prep_args_pa32           ]
68
69	   [ Stack for calling prep_args               ] <- %sp
70	 */
71
72	stwm %r1, 64(%sp)
73	stw %r4, 12(%r3)
74.LCFI13:
75	copy %sp, %r4
76
77	addl %arg2, %r4, %arg0      /* arg stack */
78	stw %arg3, -48(%r3)         /* save flags; we need it later */
79
80	/* Call prep_args:
81	   %arg0(stack) -- set up above
82	   %arg1(ecif) -- same as incoming param
83	   %arg2(bytes) -- same as incoming param */
84	bl ffi_prep_args_pa32,%r2
85	ldo 64(%arg0), %sp
86	ldo -64(%sp), %sp
87
88	/* now %sp should point where %arg0 was pointing.  */
89
90	/* Load the arguments that should be passed in registers
91	   The fp args were loaded by the prep_args function.  */
92	ldw -36(%sp), %arg0
93	ldw -40(%sp), %arg1
94	ldw -44(%sp), %arg2
95	ldw -48(%sp), %arg3
96
97	/* in case the function is going to return a structure
98	   we need to give it a place to put the result.  */
99	ldw -52(%r3), %ret0                     /* %ret0 <- rvalue */
100	ldw -56(%r3), %r22                      /* %r22 <- function to call */
101	bl $$dyncall, %r31                      /* Call the user function */
102	copy %r31, %rp
103
104	/* Prepare to store the result; we need to recover flags and rvalue.  */
105	ldw -48(%r3), %r21                      /* r21 <- flags */
106	ldw -52(%r3), %r20                      /* r20 <- rvalue */
107
108	/* Store the result according to the return type.  */
109
110.Lcheckint:
111	comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
112	b	.Ldone
113	stw	%ret0, 0(%r20)
114
115.Lcheckint8:
116	comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
117	b	.Ldone
118	stb	%ret0, 0(%r20)
119
120.Lcheckint16:
121	comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
122	b	.Ldone
123	sth	%ret0, 0(%r20)
124
125.Lcheckdbl:
126	comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
127	b	.Ldone
128	fstd	%fr4,0(%r20)
129
130.Lcheckfloat:
131	comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
132	b	.Ldone
133	fstw	%fr4L,0(%r20)
134
135.Lcheckll:
136	comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
137	stw	%ret0, 0(%r20)
138	b	.Ldone
139	stw	%ret1, 4(%r20)
140
141.Lchecksmst2:
142	comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
143	/* 2-byte structs are returned in ret0 as ????xxyy.  */
144	extru	%ret0, 23, 8, %r22
145	stbs,ma	%r22, 1(%r20)
146	b	.Ldone
147	stb	%ret0, 0(%r20)
148
149.Lchecksmst3:
150	comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
151	/* 3-byte structs are returned in ret0 as ??xxyyzz.  */
152	extru	%ret0, 15, 8, %r22
153	stbs,ma	%r22, 1(%r20)
154	extru	%ret0, 23, 8, %r22
155	stbs,ma	%r22, 1(%r20)
156	b	.Ldone
157	stb	%ret0, 0(%r20)
158
159.Lchecksmst4:
160	comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
161	/* 4-byte structs are returned in ret0 as wwxxyyzz.  */
162	extru	%ret0, 7, 8, %r22
163	stbs,ma	%r22, 1(%r20)
164	extru	%ret0, 15, 8, %r22
165	stbs,ma	%r22, 1(%r20)
166	extru	%ret0, 23, 8, %r22
167	stbs,ma	%r22, 1(%r20)
168	b	.Ldone
169	stb	%ret0, 0(%r20)
170
171.Lchecksmst5:
172	comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
173	/* 5 byte values are returned right justified:
174	      ret0     ret1
175	   5: ??????aa bbccddee */
176	stbs,ma	%ret0, 1(%r20)
177	extru	%ret1, 7, 8, %r22
178	stbs,ma	%r22, 1(%r20)
179	extru	%ret1, 15, 8, %r22
180	stbs,ma	%r22, 1(%r20)
181	extru	%ret1, 23, 8, %r22
182	stbs,ma	%r22, 1(%r20)
183	b	.Ldone
184	stb	%ret1, 0(%r20)
185
186.Lchecksmst6:
187	comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
188	/* 6 byte values are returned right justified:
189	      ret0     ret1
190	   6: ????aabb ccddeeff */
191	extru	%ret0, 23, 8, %r22
192	stbs,ma	%r22, 1(%r20)
193	stbs,ma	%ret0, 1(%r20)
194	extru	%ret1, 7, 8, %r22
195	stbs,ma	%r22, 1(%r20)
196	extru	%ret1, 15, 8, %r22
197	stbs,ma	%r22, 1(%r20)
198	extru	%ret1, 23, 8, %r22
199	stbs,ma	%r22, 1(%r20)
200	b	.Ldone
201	stb	%ret1, 0(%r20)
202
203.Lchecksmst7:
204	comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
205	/* 7 byte values are returned right justified:
206	      ret0     ret1
207	   7: ??aabbcc ddeeffgg */
208	extru	%ret0, 15, 8, %r22
209	stbs,ma	%r22, 1(%r20)
210	extru	%ret0, 23, 8, %r22
211	stbs,ma	%r22, 1(%r20)
212	stbs,ma	%ret0, 1(%r20)
213	extru	%ret1, 7, 8, %r22
214	stbs,ma	%r22, 1(%r20)
215	extru	%ret1, 15, 8, %r22
216	stbs,ma	%r22, 1(%r20)
217	extru	%ret1, 23, 8, %r22
218	stbs,ma	%r22, 1(%r20)
219	b	.Ldone
220	stb	%ret1, 0(%r20)
221
222.Lchecksmst8:
223	comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
224	/* 8 byte values are returned right justified:
225	      ret0     ret1
226	   8: aabbccdd eeffgghh */
227	extru	%ret0, 7, 8, %r22
228	stbs,ma	%r22, 1(%r20)
229	extru	%ret0, 15, 8, %r22
230	stbs,ma	%r22, 1(%r20)
231	extru	%ret0, 23, 8, %r22
232	stbs,ma	%r22, 1(%r20)
233	stbs,ma	%ret0, 1(%r20)
234	extru	%ret1, 7, 8, %r22
235	stbs,ma	%r22, 1(%r20)
236	extru	%ret1, 15, 8, %r22
237	stbs,ma	%r22, 1(%r20)
238	extru	%ret1, 23, 8, %r22
239	stbs,ma	%r22, 1(%r20)
240	stb	%ret1, 0(%r20)
241
242.Ldone:
243	/* all done, return */
244	copy %r4, %sp                           /* pop arg stack */
245	ldw 12(%r3), %r4
246	ldwm -64(%sp), %r3                      /* .. and pop stack */
247	ldw -20(%sp), %rp
248	bv %r0(%rp)
249	nop
250	.exit
251	.procend
252.LFE1:
253
254	/* void ffi_closure_pa32(void);
255	   Called with closure argument in %r21 */
256	.export ffi_closure_pa32,code
257	.import ffi_closure_inner_pa32,code
258
259	.type ffi_closure_pa32, @function
260.LFB2:
261ffi_closure_pa32:
262	.proc
263	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
264	.entry
265
266	stw %rp, -20(%sp)
267.LCFI20:
268	copy %r3, %r1
269.LCFI21:
270	copy %sp, %r3
271.LCFI22:
272	stwm %r1, 64(%sp)
273
274	/* Put arguments onto the stack and call ffi_closure_inner.  */
275	stw %arg0, -36(%r3)
276	stw %arg1, -40(%r3)
277	stw %arg2, -44(%r3)
278	stw %arg3, -48(%r3)
279
280	copy %r21, %arg0
281	bl ffi_closure_inner_pa32, %r2
282	copy %r3, %arg1
283
284	ldwm -64(%sp), %r3
285	ldw -20(%sp), %rp
286	ldw -36(%sp), %ret0
287	bv %r0(%r2)
288	ldw -40(%sp), %ret1
289
290	.exit
291	.procend
292.LFE2:
293
294	.section        ".eh_frame",EH_FRAME_FLAGS,@progbits
295.Lframe1:
296	.word   .LECIE1-.LSCIE1 ;# Length of Common Information Entry
297.LSCIE1:
298	.word   0x0     ;# CIE Identifier Tag
299	.byte   0x1     ;# CIE Version
300	.ascii "\0"     ;# CIE Augmentation
301	.uleb128 0x1    ;# CIE Code Alignment Factor
302	.sleb128 4      ;# CIE Data Alignment Factor
303	.byte   0x2     ;# CIE RA Column
304	.byte   0xc     ;# DW_CFA_def_cfa
305	.uleb128 0x1e
306	.uleb128 0x0
307	.align 4
308.LECIE1:
309.LSFDE1:
310	.word   .LEFDE1-.LASFDE1        ;# FDE Length
311.LASFDE1:
312	.word   .LASFDE1-.Lframe1       ;# FDE CIE offset
313	.word   .LFB1   ;# FDE initial location
314	.word   .LFE1-.LFB1     ;# FDE address range
315
316	.byte   0x4     ;# DW_CFA_advance_loc4
317	.word   .LCFI11-.LFB1
318	.byte	0x83	;# DW_CFA_offset, column 0x3
319	.uleb128 0x0
320	.byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
321	.uleb128 0x2
322	.sleb128 -5
323
324	.byte   0x4     ;# DW_CFA_advance_loc4
325	.word   .LCFI12-.LCFI11
326	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
327	.uleb128 0x3
328
329	.byte   0x4     ;# DW_CFA_advance_loc4
330	.word   .LCFI13-.LCFI12
331	.byte	0x84	;# DW_CFA_offset, column 0x4
332	.uleb128 0x3
333
334	.align 4
335.LEFDE1:
336
337.LSFDE2:
338	.word   .LEFDE2-.LASFDE2        ;# FDE Length
339.LASFDE2:
340	.word   .LASFDE2-.Lframe1       ;# FDE CIE offset
341	.word   .LFB2   ;# FDE initial location
342	.word   .LFE2-.LFB2     ;# FDE address range
343	.byte   0x4     ;# DW_CFA_advance_loc4
344	.word   .LCFI21-.LFB2
345	.byte   0x83    ;# DW_CFA_offset, column 0x3
346	.uleb128 0x0
347	.byte   0x11    ;# DW_CFA_offset_extended_sf
348	.uleb128 0x2
349	.sleb128 -5
350
351	.byte   0x4     ;# DW_CFA_advance_loc4
352	.word   .LCFI22-.LCFI21
353	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
354	.uleb128 0x3
355
356	.align 4
357.LEFDE2:
358