Fix build on sparc64-linux-gnu.
[official-gcc.git] / libffi / src / pa / linux.S
blob602690432c046214fa003a40bbc034a20952d8d6
1 /* -----------------------------------------------------------------------
2    linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
3              (c) 2008 Red Hat, Inc.
4              (c) 2016 John David Anglin
6    HPPA Foreign Function Interface
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:
16    The above copyright notice and this permission notice shall be included
17    in all copies or substantial portions of the Software.
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 RENESAS TECHNOLOGY 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    ----------------------------------------------------------------------- */
28 #define LIBFFI_ASM
29 #include <fficonfig.h>
30 #include <ffi.h>
32         .text
33         .level 1.1
34         .align 4
36         /* void ffi_call_pa32(void (*)(char *, extended_cif *),
37                                extended_cif *ecif,
38                                unsigned bytes,
39                                unsigned flags,
40                                unsigned *rvalue,
41                                void (*fn)(void),
42                                ffi_go_closure *closure);
43          */
45         .export ffi_call_pa32,code
46         .import ffi_prep_args_pa32,code
48         .type ffi_call_pa32, @function
49         .cfi_startproc
50 ffi_call_pa32:
51         .proc
52         .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
53         .entry
54         stw %rp, -20(%sp)
55         copy %r3, %r1
56         .cfi_offset 2, -20
57         .cfi_register 3, 1
59         copy %sp, %r3
60         .cfi_def_cfa_register 3
62         /* Setup the stack for calling prep_args...
63            We want the stack to look like this:
65            [ Previous stack                            ] <- %r3
67            [ 64-bytes register save area               ] <- %r4
69            [ Stack space for actual call, passed as    ] <- %arg0
70            [     arg0 to ffi_prep_args_pa32           ]
72            [ Stack for calling prep_args               ] <- %sp
73          */
75         stwm %r1, 64(%sp)
76         .cfi_offset 3, 0
77         stw %r4, 12(%r3)
78         copy %sp, %r4
80         addl %arg2, %r4, %arg0      /* arg stack */
81         stw %arg3, -48(%r3)         /* save flags; we need it later */
83         /* Call prep_args:
84            %arg0(stack) -- set up above
85            %arg1(ecif) -- same as incoming param
86            %arg2(bytes) -- same as incoming param */
87         bl ffi_prep_args_pa32,%r2
88         ldo 64(%arg0), %sp
89         ldo -64(%sp), %sp
91         /* now %sp should point where %arg0 was pointing.  */
93         /* Load the arguments that should be passed in registers
94            The fp args were loaded by the prep_args function.  */
95         ldw -36(%sp), %arg0
96         ldw -40(%sp), %arg1
97         ldw -44(%sp), %arg2
98         ldw -48(%sp), %arg3
100         /* in case the function is going to return a structure
101            we need to give it a place to put the result.  */
102         ldw -52(%r3), %ret0                     /* %ret0 <- rvalue */
103         ldw -56(%r3), %r22                      /* %r22 <- function to call */
104         ldw -60(%r3), %ret1                     /* %ret1 <- closure */
105         bl $$dyncall, %r31                      /* Call the user function */
106         copy %r31, %rp
108         /* Prepare to store the result; we need to recover flags and rvalue.  */
109         ldw -48(%r3), %r21                      /* r21 <- flags */
110         ldw -52(%r3), %r20                      /* r20 <- rvalue */
112         /* Store the result according to the return type.  */
114 .Lcheckint:
115         comib,<>,n FFI_TYPE_INT, %r21, .Lcheckint8
116         b       .Ldone
117         stw     %ret0, 0(%r20)
119 .Lcheckint8:
120         comib,<>,n FFI_TYPE_UINT8, %r21, .Lcheckint16
121         b       .Ldone
122         stb     %ret0, 0(%r20)
124 .Lcheckint16:
125         comib,<>,n FFI_TYPE_UINT16, %r21, .Lcheckdbl
126         b       .Ldone
127         sth     %ret0, 0(%r20)
129 .Lcheckdbl:
130         comib,<>,n FFI_TYPE_DOUBLE, %r21, .Lcheckfloat
131         b       .Ldone
132         fstd    %fr4,0(%r20)
134 .Lcheckfloat:
135         comib,<>,n FFI_TYPE_FLOAT, %r21, .Lcheckll
136         b       .Ldone
137         fstw    %fr4L,0(%r20)
139 .Lcheckll:
140         comib,<>,n FFI_TYPE_UINT64, %r21, .Lchecksmst2
141         stw     %ret0, 0(%r20)
142         b       .Ldone
143         stw     %ret1, 4(%r20)
145 .Lchecksmst2:
146         comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, .Lchecksmst3
147         /* 2-byte structs are returned in ret0 as ????xxyy.  */
148         extru   %ret0, 23, 8, %r22
149         stbs,ma %r22, 1(%r20)
150         b       .Ldone
151         stb     %ret0, 0(%r20)
153 .Lchecksmst3:
154         comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, .Lchecksmst4
155         /* 3-byte structs are returned in ret0 as ??xxyyzz.  */
156         extru   %ret0, 15, 8, %r22
157         stbs,ma %r22, 1(%r20)
158         extru   %ret0, 23, 8, %r22
159         stbs,ma %r22, 1(%r20)
160         b       .Ldone
161         stb     %ret0, 0(%r20)
163 .Lchecksmst4:
164         comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, .Lchecksmst5
165         /* 4-byte structs are returned in ret0 as wwxxyyzz.  */
166         extru   %ret0, 7, 8, %r22
167         stbs,ma %r22, 1(%r20)
168         extru   %ret0, 15, 8, %r22
169         stbs,ma %r22, 1(%r20)
170         extru   %ret0, 23, 8, %r22
171         stbs,ma %r22, 1(%r20)
172         b       .Ldone
173         stb     %ret0, 0(%r20)
175 .Lchecksmst5:
176         comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, .Lchecksmst6
177         /* 5 byte values are returned right justified:
178               ret0     ret1
179            5: ??????aa bbccddee */
180         stbs,ma %ret0, 1(%r20)
181         extru   %ret1, 7, 8, %r22
182         stbs,ma %r22, 1(%r20)
183         extru   %ret1, 15, 8, %r22
184         stbs,ma %r22, 1(%r20)
185         extru   %ret1, 23, 8, %r22
186         stbs,ma %r22, 1(%r20)
187         b       .Ldone
188         stb     %ret1, 0(%r20)
190 .Lchecksmst6:
191         comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, .Lchecksmst7
192         /* 6 byte values are returned right justified:
193               ret0     ret1
194            6: ????aabb ccddeeff */
195         extru   %ret0, 23, 8, %r22
196         stbs,ma %r22, 1(%r20)
197         stbs,ma %ret0, 1(%r20)
198         extru   %ret1, 7, 8, %r22
199         stbs,ma %r22, 1(%r20)
200         extru   %ret1, 15, 8, %r22
201         stbs,ma %r22, 1(%r20)
202         extru   %ret1, 23, 8, %r22
203         stbs,ma %r22, 1(%r20)
204         b       .Ldone
205         stb     %ret1, 0(%r20)
207 .Lchecksmst7:
208         comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, .Lchecksmst8
209         /* 7 byte values are returned right justified:
210               ret0     ret1
211            7: ??aabbcc ddeeffgg */
212         extru   %ret0, 15, 8, %r22
213         stbs,ma %r22, 1(%r20)
214         extru   %ret0, 23, 8, %r22
215         stbs,ma %r22, 1(%r20)
216         stbs,ma %ret0, 1(%r20)
217         extru   %ret1, 7, 8, %r22
218         stbs,ma %r22, 1(%r20)
219         extru   %ret1, 15, 8, %r22
220         stbs,ma %r22, 1(%r20)
221         extru   %ret1, 23, 8, %r22
222         stbs,ma %r22, 1(%r20)
223         b       .Ldone
224         stb     %ret1, 0(%r20)
226 .Lchecksmst8:
227         comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, .Ldone
228         /* 8 byte values are returned right justified:
229               ret0     ret1
230            8: aabbccdd eeffgghh */
231         extru   %ret0, 7, 8, %r22
232         stbs,ma %r22, 1(%r20)
233         extru   %ret0, 15, 8, %r22
234         stbs,ma %r22, 1(%r20)
235         extru   %ret0, 23, 8, %r22
236         stbs,ma %r22, 1(%r20)
237         stbs,ma %ret0, 1(%r20)
238         extru   %ret1, 7, 8, %r22
239         stbs,ma %r22, 1(%r20)
240         extru   %ret1, 15, 8, %r22
241         stbs,ma %r22, 1(%r20)
242         extru   %ret1, 23, 8, %r22
243         stbs,ma %r22, 1(%r20)
244         stb     %ret1, 0(%r20)
246 .Ldone:
247         /* all done, return */
248         copy %r4, %sp                           /* pop arg stack */
249         ldw 12(%r3), %r4
250         ldwm -64(%sp), %r3                      /* .. and pop stack */
251         ldw -20(%sp), %rp
252         bv %r0(%rp)
253         nop
254         .exit
255         .procend
256         .cfi_endproc
258         /* void ffi_closure_pa32(void);
259            Called with ffi_closure argument in %r21.  */
260         .export ffi_closure_pa32,code
261         .import ffi_closure_inner_pa32,code
262         .type ffi_closure_pa32, @function
263         .cfi_startproc
264 ffi_closure_pa32:
265         .proc
266         .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
267         .entry
269         stw %rp, -20(%sp)
270         copy %r3, %r1
271         .cfi_offset 2, -20
272         .cfi_register 3, 1
273         copy %sp, %r3
274         .cfi_def_cfa_register 3
275         stwm %r1, 64(%sp)
276         .cfi_offset 3, 0
278         /* Put arguments onto the stack and call ffi_closure_inner.  */
279         stw %arg0, -36(%r3)
280         stw %arg1, -40(%r3)
281         stw %arg2, -44(%r3)
282         stw %arg3, -48(%r3)
284         /* Closure type 0.  */
285         copy %r21, %arg0
286         copy %r0, %arg2
287         bl ffi_closure_inner_pa32, %r2
288         copy %r3, %arg1
290         ldwm -64(%sp), %r3
291         ldw -20(%sp), %rp
292         ldw -36(%sp), %ret0
293         bv %r0(%r2)
294         ldw -40(%sp), %ret1
296         .exit
297         .procend
298         .cfi_endproc
300         /* void ffi_go_closure_pa32(void);
301            Called with ffi_go_closure argument in %ret1.  */
302         .export ffi_go_closure_pa32,code
303         .import ffi_closure_inner_pa32,code
304         .type ffi_go_closure_pa32, @function
305         .cfi_startproc
306 ffi_go_closure_pa32:
307         .proc
308         .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
309         .entry
311         stw %rp, -20(%sp)
312         copy %r3, %r1
313         .cfi_offset 2, -20
314         .cfi_register 3, 1
315         copy %sp, %r3
316         .cfi_def_cfa_register 3
317         stwm %r1, 64(%sp)
318         .cfi_offset 3, 0
320         /* Put arguments onto the stack and call ffi_closure_inner.  */
321         stw %arg0, -36(%r3)
322         stw %arg1, -40(%r3)
323         stw %arg2, -44(%r3)
324         stw %arg3, -48(%r3)
326         /* Closure type 1.  */
327         copy %ret1, %arg0
328         ldi 1, %arg2
329         bl ffi_closure_inner_pa32, %r2
330         copy %r3, %arg1
332         ldwm -64(%sp), %r3
333         ldw -20(%sp), %rp
334         ldw -36(%sp), %ret0
335         bv %r0(%r2)
336         ldw -40(%sp), %ret1
338         .exit
339         .procend
340         .cfi_endproc