OSDN Git Service

2004-03-19 Matthias Klose <doko@debian.org>
[pf3gnuchains/gcc-fork.git] / libffi / src / pa / linux.S
1 /* -----------------------------------------------------------------------
2    linux.S - (c) 2003-2004 Randolph Chung <tausq@debian.org>
3
4    HPPA Foreign Function Interface
5
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:
13
14    The above copyright notice and this permission notice shall be included
15    in all copies or substantial portions of the Software.
16
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    ----------------------------------------------------------------------- */
25
26 #define LIBFFI_ASM
27 #include <fficonfig.h>
28 #include <ffi.h>
29
30         .text
31         .align 4
32
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          */
40
41         .export ffi_call_LINUX,code
42         .import ffi_prep_args_LINUX,code
43
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:
53
54         copy %sp, %r3
55 .LCFI12:
56
57         /* Setup the stack for calling prep_args...
58            We want the stack to look like this:
59
60            [ Previous stack                            ] <- %r3
61
62            [ 64-bytes register save area               ] <- %r4
63
64            [ Stack space for actual call, passed as    ] <- %arg0
65            [     arg0 to ffi_prep_args_LINUX           ]
66
67            [ Stack for calling prep_args               ] <- %sp
68          */
69
70         stwm %r1, 64(%sp)
71         stw %r4, 12(%r3)
72 .LCFI13:
73         copy %sp, %r4
74
75         addl %arg2, %r4, %arg0                  /* arg stack */
76         stw %arg3, -48(%r3)                     /* save flags; we need it later */
77
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
85
86         /* now %sp should point where %arg0 was pointing.  */
87
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
94
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
101
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 */
105
106         /* Store the result according to the return type.  */
107
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)
117
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)
126
127 checkint8:
128         comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
129         b done
130         stb %ret0, 0(%r20)
131
132 checkint16:
133         comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
134         b done
135         sth %ret0, 0(%r20)
136
137 checkint32:
138         comib,<>,n FFI_TYPE_UINT32, %r21, checkint
139         b done
140         stw %ret0, 0(%r20)
141
142 checkint:
143         comib,<>,n FFI_TYPE_INT, %r21, checkll
144         b done
145         stw %ret0, 0(%r20)
146
147 checkll:
148         comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
149         stw %ret0, 0(%r20)
150         b done
151         stw %ret1, 4(%r20)
152
153 checkdbl:
154         comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
155         b done
156         fstd %fr4,0(%r20)
157
158 checkfloat:
159         comib,<>,n FFI_TYPE_FLOAT, %r21, done
160         fstw %fr4L,0(%r20)
161
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.  */
165
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:
177
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
182
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
189
190         stw %rp, -20(%sp)
191 .LCFI20:
192         copy %r3, %r1
193 .LCFI21:
194         copy %sp, %r3
195 .LCFI22:
196         stwm %r1, 64(%sp)
197
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)
203
204         copy %r21, %arg0
205         bl ffi_closure_inner_LINUX, %r2
206         copy %r3, %arg1
207
208         ldwm -64(%sp), %r3
209         ldw -20(%sp), %rp
210         ldw -36(%sp), %ret0
211         bv %r0(%r2)
212         ldw -40(%sp), %ret1
213
214         .exit
215         .procend
216 .LFE2:
217
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
239
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
247
248         .byte   0x4     ;# DW_CFA_advance_loc4
249         .word   .LCFI12-.LCFI11
250         .byte   0xd     ;# DW_CFA_def_cfa_register = r3
251         .uleb128 0x3
252
253         .byte   0x4     ;# DW_CFA_advance_loc4
254         .word   .LCFI13-.LCFI12
255         .byte   0x84    ;# DW_CFA_offset, column 0x4
256         .uleb128 0x3
257
258         .align 4
259 .LEFDE1:
260
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
274
275         .byte   0x4     ;# DW_CFA_advance_loc4
276         .word   .LCFI12-.LCFI11
277         .byte   0xd     ;# DW_CFA_def_cfa_register = r3
278         .uleb128 0x3
279
280         .align 4
281 .LEFDE2: