* configure.ac: (target_alias): Default to $host_alias, not
[official-gcc.git] / libffi / src / pa / linux.S
blob1a2ecdbb54cdc212f5ef7df1fe20b3df82eac8ca
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         .align 4
33         /* void ffi_call_LINUX(void (*)(char *, extended_cif *),
34                                extended_cif *ecif,
35                                unsigned bytes,
36                                unsigned flags,
37                                unsigned *rvalue,
38                                void (*fn)());
39          */
41         .export ffi_call_LINUX,code
42         .import ffi_prep_args_LINUX,code
44         .type ffi_call_LINUX, @function
45 .LFB1:
46 ffi_call_LINUX:
47         .proc
48         .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
49         .entry
50         stw %rp, -20(%sp)
51         copy %r3, %r1
52 .LCFI11:
54         copy %sp, %r3
55 .LCFI12:
57         /* Setup the stack for calling prep_args...
58            We want the stack to look like this:
60            [ Previous stack                            ] <- %r3
62            [ 64-bytes register save area               ] <- %r4
64            [ Stack space for actual call, passed as    ] <- %arg0
65            [     arg0 to ffi_prep_args_LINUX           ]
67            [ Stack for calling prep_args               ] <- %sp
68          */
70         stwm %r1, 64(%sp)
71         stw %r4, 12(%r3)
72 .LCFI13:
73         copy %sp, %r4
75         addl %arg2, %r4, %arg0                  /* arg stack */
76         stw %arg3, -48(%r3)                     /* save flags; we need it later */
78         /* Call prep_args:
79            %arg0(stack) -- set up above
80            %arg1(ecif) -- same as incoming param
81            %arg2(bytes) -- same as incoming param */
82         bl ffi_prep_args_LINUX,%r2
83         ldo 64(%arg0), %sp
84         ldo -64(%sp), %sp
86         /* now %sp should point where %arg0 was pointing.  */
88         /* Load the arguments that should be passed in registers
89            The fp args were loaded by the prep_args function.  */
90         ldw -36(%sp), %arg0
91         ldw -40(%sp), %arg1
92         ldw -44(%sp), %arg2
93         ldw -48(%sp), %arg3
95         /* in case the function is going to return a structure
96            we need to give it a place to put the result.  */
97         ldw -52(%r3), %ret0                     /* %ret0 <- rvalue */
98         ldw -56(%r3), %r22                      /* %r22 <- function to call */
99         bl $$dyncall, %r31                      /* Call the user function */
100         copy %r31, %rp
102         /* Prepare to store the result; we need to recover flags and rvalue.  */
103         ldw -48(%r3), %r21                      /* r21 <- flags */
104         ldw -52(%r3), %r20                      /* r20 <- rvalue */
106         /* Store the result according to the return type.  */
108 checksmst1:
109         comib,<>,n FFI_TYPE_SMALL_STRUCT1, %r21, checksmst2
110         /* There is maybe a better way to handle 3 byte structs.  */
111         sh2add %ret0,0,%ret0
112         sh2add %ret0,0,%ret0
113         sh2add %ret0,0,%ret0
114         sh2add %ret0,0,%ret0
115         b done
116         stw %ret0, 0(%r20)
118 checksmst2:
119         comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, checkint8
120         /* Up to now I don't have a way to handle 6/7 byte structs.
121            The values are left bounded in the registers. In the struct
122            itself they are left bounded.  */
123         stw %ret0, 0(%r20)
124         b done
125         stw %ret1, 4(%r20)
127 checkint8:
128         comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
129         b done
130         stb %ret0, 0(%r20)
132 checkint16:
133         comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
134         b done
135         sth %ret0, 0(%r20)
137 checkint32:
138         comib,<>,n FFI_TYPE_UINT32, %r21, checkint
139         b done
140         stw %ret0, 0(%r20)
142 checkint:
143         comib,<>,n FFI_TYPE_INT, %r21, checkll
144         b done
145         stw %ret0, 0(%r20)
147 checkll:
148         comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
149         stw %ret0, 0(%r20)
150         b done
151         stw %ret1, 4(%r20)
153 checkdbl:
154         comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
155         b done
156         fstd %fr4,0(%r20)
158 checkfloat:
159         comib,<>,n FFI_TYPE_FLOAT, %r21, done
160         fstw %fr4L,0(%r20)
162         /* structure returns are either handled by one of the
163            INT/UINT64 cases above, or, if passed by pointer,
164            is handled by the callee.  */
166 done:
167         /* all done, return */
168         copy %r4, %sp                           /* pop arg stack */
169         ldw 12(%r3), %r4
170         ldwm -64(%sp), %r3                      /* .. and pop stack */
171         ldw -20(%sp), %rp
172         bv %r0(%rp)
173         nop
174         .exit
175         .procend
176 .LFE1:
178         /* void ffi_closure_LINUX(void);
179            Called with closure argument in %r21 */
180         .export ffi_closure_LINUX,code
181         .import ffi_closure_inner_LINUX,code
183         .type ffi_closure_LINUX, @function
184 .LFB2:
185 ffi_closure_LINUX:
186         .proc
187         .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
188         .entry
190         stw %rp, -20(%sp)
191 .LCFI20:
192         copy %r3, %r1
193 .LCFI21:
194         copy %sp, %r3
195 .LCFI22:
196         stwm %r1, 64(%sp)
198         /* Put arguments onto the stack and call ffi_closure_inner.  */
199         stw %arg0, -36(%r3)
200         stw %arg1, -40(%r3)
201         stw %arg2, -44(%r3)
202         stw %arg3, -48(%r3)
204         copy %r21, %arg0
205         bl ffi_closure_inner_LINUX, %r2
206         copy %r3, %arg1
208         ldwm -64(%sp), %r3
209         ldw -20(%sp), %rp
210         ldw -36(%sp), %ret0
211         bv %r0(%r2)
212         ldw -40(%sp), %ret1
214         .exit
215         .procend
216 .LFE2:
218         .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
219 .Lframe1:
220         .word   .LECIE1-.LSCIE1 ;# Length of Common Information Entry
221 .LSCIE1:
222         .word   0x0     ;# CIE Identifier Tag
223         .byte   0x1     ;# CIE Version
224         .ascii "\0"     ;# CIE Augmentation
225         .uleb128 0x1    ;# CIE Code Alignment Factor
226         .sleb128 4      ;# CIE Data Alignment Factor
227         .byte   0x2     ;# CIE RA Column
228         .byte   0xc     ;# DW_CFA_def_cfa
229         .uleb128 0x1e
230         .uleb128 0x0
231         .align 4
232 .LECIE1:
233 .LSFDE1:
234         .word   .LEFDE1-.LASFDE1        ;# FDE Length
235 .LASFDE1:
236         .word   .LASFDE1-.Lframe1       ;# FDE CIE offset
237         .word   .LFB1   ;# FDE initial location
238         .word   .LFE1-.LFB1     ;# FDE address range
240         .byte   0x4     ;# DW_CFA_advance_loc4
241         .word   .LCFI11-.LFB1
242         .byte   0x83    ;# DW_CFA_offset, column 0x3
243         .uleb128 0x0
244         .byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
245         .uleb128 0x2
246         .sleb128 -5
248         .byte   0x4     ;# DW_CFA_advance_loc4
249         .word   .LCFI12-.LCFI11
250         .byte   0xd     ;# DW_CFA_def_cfa_register = r3
251         .uleb128 0x3
253         .byte   0x4     ;# DW_CFA_advance_loc4
254         .word   .LCFI13-.LCFI12
255         .byte   0x84    ;# DW_CFA_offset, column 0x4
256         .uleb128 0x3
258         .align 4
259 .LEFDE1:
261 .LSFDE2:
262         .word   .LEFDE2-.LASFDE2        ;# FDE Length
263 .LASFDE2:
264         .word   .LASFDE2-.Lframe1       ;# FDE CIE offset
265         .word   .LFB2   ;# FDE initial location
266         .word   .LFE2-.LFB2     ;# FDE address range
267         .byte   0x4     ;# DW_CFA_advance_loc4
268         .word   .LCFI21-.LFB2
269         .byte   0x83    ;# DW_CFA_offset, column 0x3
270         .uleb128 0x0
271         .byte   0x11    ;# DW_CFA_offset_extended_sf
272         .uleb128 0x2
273         .sleb128 -5
275         .byte   0x4     ;# DW_CFA_advance_loc4
276         .word   .LCFI12-.LCFI11
277         .byte   0xd     ;# DW_CFA_def_cfa_register = r3
278         .uleb128 0x3
280         .align 4
281 .LEFDE2: