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