OSDN Git Service

267cff7b8029cf495c031569fa5a0ef3230c360d
[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         .level 1.1
32         .align 4
33
34         /* void ffi_call_LINUX(void (*)(char *, extended_cif *),
35                                extended_cif *ecif,
36                                unsigned bytes,
37                                unsigned flags,
38                                unsigned *rvalue,
39                                void (*fn)());
40          */
41
42         .export ffi_call_LINUX,code
43         .import ffi_prep_args_LINUX,code
44
45         .type ffi_call_LINUX, @function
46 .LFB1:
47 ffi_call_LINUX:
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:
54
55         copy %sp, %r3
56 .LCFI12:
57
58         /* Setup the stack for calling prep_args...
59            We want the stack to look like this:
60
61            [ Previous stack                            ] <- %r3
62
63            [ 64-bytes register save area               ] <- %r4
64
65            [ Stack space for actual call, passed as    ] <- %arg0
66            [     arg0 to ffi_prep_args_LINUX           ]
67
68            [ Stack for calling prep_args               ] <- %sp
69          */
70
71         stwm %r1, 64(%sp)
72         stw %r4, 12(%r3)
73 .LCFI13:
74         copy %sp, %r4
75
76         addl %arg2, %r4, %arg0                  /* arg stack */
77         stw %arg3, -48(%r3)                     /* save flags; we need it later */
78
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_LINUX,%r2
84         ldo 64(%arg0), %sp
85         ldo -64(%sp), %sp
86
87         /* now %sp should point where %arg0 was pointing.  */
88
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
95
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
102
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 */
106
107         /* Store the result according to the return type.  */
108
109 checksmst3:
110         comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, checksmst567
111         /* 3-byte structs are returned in ret0 as ??xxyyzz.  Shift
112            left 8 bits to write to the result structure.  */
113         zdep %ret0, 23, 24, %r22
114         b done
115         stw %r22, 0(%r20)
116
117 checksmst567:
118         /* 5-7 byte values are returned right justified:
119               ret0     ret1
120            5: ??????aa bbccddee
121            6: ????aabb ccddeeff
122            7: ??aabbcc ddeeffgg
123
124            To store this in the result, write the first 4 bytes into a temp
125            register using shrpw (t1 = aabbccdd), followed by a rotation of
126            ret1:
127
128               ret0     ret1        ret1
129            5: ??????aa bbccddee -> eebbccdd (rotate 8)
130            6: ????aabb ccddeeff -> eeffccdd (rotate 16)
131            7: ??aabbcc ddeeffgg -> eeffggdd (rotate 24)
132
133            then we write (t1, ret1) into the result.  */
134
135         addi,<> -FFI_TYPE_SMALL_STRUCT5,%r21,%r0
136         ldi 8, %r22
137         addi,<> -FFI_TYPE_SMALL_STRUCT6,%r21,%r0
138         ldi 16, %r22
139         addi,<> -FFI_TYPE_SMALL_STRUCT7,%r21,%r0
140         ldi 24, %r22
141
142         /* This relies on all the FFI_TYPE_*_STRUCT* defines being <0 */
143         cmpib,<=,n 0, %r21, checkint8
144         mtsar %r22
145
146         shrpw %ret0, %ret1, %sar, %ret0  /* ret0 = aabbccdd */
147         shrpw %ret1, %ret1, %sar, %ret1  /* rotate ret1 */
148         
149         stw %ret0, 0(%r20)
150         b done
151         stw %ret1, 4(%r20)
152
153 checkint8:
154         comib,<>,n FFI_TYPE_UINT8, %r21, checkint16
155         b done
156         stb %ret0, 0(%r20)
157
158 checkint16:
159         comib,<>,n FFI_TYPE_UINT16, %r21, checkint32
160         b done
161         sth %ret0, 0(%r20)
162
163 checkint32:
164         comib,<>,n FFI_TYPE_UINT32, %r21, checkint
165         b done
166         stw %ret0, 0(%r20)
167
168 checkint:
169         comib,<>,n FFI_TYPE_INT, %r21, checkll
170         b done
171         stw %ret0, 0(%r20)
172
173 checkll:
174         comib,<>,n FFI_TYPE_UINT64, %r21, checkdbl
175         stw %ret0, 0(%r20)
176         b done
177         stw %ret1, 4(%r20)
178
179 checkdbl:
180         comib,<>,n FFI_TYPE_DOUBLE, %r21, checkfloat
181         b done
182         fstd %fr4,0(%r20)
183
184 checkfloat:
185         comib,<>,n FFI_TYPE_FLOAT, %r21, done
186         fstw %fr4L,0(%r20)
187
188         /* structure returns are either handled by one of the
189            INT/UINT64 cases above, or, if passed by pointer,
190            is handled by the callee.  */
191
192 done:
193         /* all done, return */
194         copy %r4, %sp                           /* pop arg stack */
195         ldw 12(%r3), %r4
196         ldwm -64(%sp), %r3                      /* .. and pop stack */
197         ldw -20(%sp), %rp
198         bv %r0(%rp)
199         nop
200         .exit
201         .procend
202 .LFE1:
203
204         /* void ffi_closure_LINUX(void);
205            Called with closure argument in %r21 */
206         .export ffi_closure_LINUX,code
207         .import ffi_closure_inner_LINUX,code
208
209         .type ffi_closure_LINUX, @function
210 .LFB2:
211 ffi_closure_LINUX:
212         .proc
213         .callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
214         .entry
215
216         stw %rp, -20(%sp)
217 .LCFI20:
218         copy %r3, %r1
219 .LCFI21:
220         copy %sp, %r3
221 .LCFI22:
222         stwm %r1, 64(%sp)
223
224         /* Put arguments onto the stack and call ffi_closure_inner.  */
225         stw %arg0, -36(%r3)
226         stw %arg1, -40(%r3)
227         stw %arg2, -44(%r3)
228         stw %arg3, -48(%r3)
229
230         copy %r21, %arg0
231         bl ffi_closure_inner_LINUX, %r2
232         copy %r3, %arg1
233
234         ldwm -64(%sp), %r3
235         ldw -20(%sp), %rp
236         ldw -36(%sp), %ret0
237         bv %r0(%r2)
238         ldw -40(%sp), %ret1
239
240         .exit
241         .procend
242 .LFE2:
243
244         .section        ".eh_frame",EH_FRAME_FLAGS,@progbits
245 .Lframe1:
246         .word   .LECIE1-.LSCIE1 ;# Length of Common Information Entry
247 .LSCIE1:
248         .word   0x0     ;# CIE Identifier Tag
249         .byte   0x1     ;# CIE Version
250         .ascii "\0"     ;# CIE Augmentation
251         .uleb128 0x1    ;# CIE Code Alignment Factor
252         .sleb128 4      ;# CIE Data Alignment Factor
253         .byte   0x2     ;# CIE RA Column
254         .byte   0xc     ;# DW_CFA_def_cfa
255         .uleb128 0x1e
256         .uleb128 0x0
257         .align 4
258 .LECIE1:
259 .LSFDE1:
260         .word   .LEFDE1-.LASFDE1        ;# FDE Length
261 .LASFDE1:
262         .word   .LASFDE1-.Lframe1       ;# FDE CIE offset
263         .word   .LFB1   ;# FDE initial location
264         .word   .LFE1-.LFB1     ;# FDE address range
265
266         .byte   0x4     ;# DW_CFA_advance_loc4
267         .word   .LCFI11-.LFB1
268         .byte   0x83    ;# DW_CFA_offset, column 0x3
269         .uleb128 0x0
270         .byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
271         .uleb128 0x2
272         .sleb128 -5
273
274         .byte   0x4     ;# DW_CFA_advance_loc4
275         .word   .LCFI12-.LCFI11
276         .byte   0xd     ;# DW_CFA_def_cfa_register = r3
277         .uleb128 0x3
278
279         .byte   0x4     ;# DW_CFA_advance_loc4
280         .word   .LCFI13-.LCFI12
281         .byte   0x84    ;# DW_CFA_offset, column 0x4
282         .uleb128 0x3
283
284         .align 4
285 .LEFDE1:
286
287 .LSFDE2:
288         .word   .LEFDE2-.LASFDE2        ;# FDE Length
289 .LASFDE2:
290         .word   .LASFDE2-.Lframe1       ;# FDE CIE offset
291         .word   .LFB2   ;# FDE initial location
292         .word   .LFE2-.LFB2     ;# FDE address range
293         .byte   0x4     ;# DW_CFA_advance_loc4
294         .word   .LCFI21-.LFB2
295         .byte   0x83    ;# DW_CFA_offset, column 0x3
296         .uleb128 0x0
297         .byte   0x11    ;# DW_CFA_offset_extended_sf
298         .uleb128 0x2
299         .sleb128 -5
300
301         .byte   0x4     ;# DW_CFA_advance_loc4
302         .word   .LCFI12-.LCFI11
303         .byte   0xd     ;# DW_CFA_def_cfa_register = r3
304         .uleb128 0x3
305
306         .align 4
307 .LEFDE2: