OSDN Git Service

Restore stack pointer when returning from ffi_closure_UNIX.
[pf3gnuchains/gcc-fork.git] / libffi / src / ia64 / unix.S
1 /* -----------------------------------------------------------------------
2    unix.S - Copyright (c) 1998 Cygnus Solutions
3             Copyright (c) 2000 Hewlett Packard Company
4    
5    IA64/unix Foreign Function Interface 
6
7    Primary author: Hans Boehm, HP Labs
8
9    Loosely modeled on Cygnus code for other platforms.
10
11    Permission is hereby granted, free of charge, to any person obtaining
12    a copy of this software and associated documentation files (the
13    ``Software''), to deal in the Software without restriction, including
14    without limitation the rights to use, copy, modify, merge, publish,
15    distribute, sublicense, and/or sell copies of the Software, and to
16    permit persons to whom the Software is furnished to do so, subject to
17    the following conditions:
18
19    The above copyright notice and this permission notice shall be included
20    in all copies or substantial portions of the Software.
21
22    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
23    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25    IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28    OTHER DEALINGS IN THE SOFTWARE.
29    ----------------------------------------------------------------------- */
30
31 #define LIBFFI_ASM      
32 #include <ffi.h>
33 #include "ia64_flags.h"
34
35 /* parameters:  */
36 #define callback        in0
37 #define ecifp           in1
38 #define bytes           in2
39 #define flags           in3
40 #define raddr           in4
41 #define fn              in5
42
43 #define FLOAT_SZ        8 /* in-memory size of fp operands      */
44
45 .text
46         .align 16
47         .global ffi_call_unix#
48         .proc ffi_call_unix#
49 ffi_call_unix:
50         alloc   loc0=ar.pfs,6,5,8,0
51         mov     loc1=b0;
52         sub     sp=sp,bytes
53         mov     loc4=r1         /* Save gp      */
54         ld8     r8=[callback],8 /* code address of callback     */
55         ;;
56         mov     out0=sp
57         mov     out1=ecifp
58         mov     out2=bytes
59         ld8     r1=[callback]   /* Set up gp for callback.  Unnecessary? */
60         mov     b6=r8
61         ;;
62         br.call.sptk.many b0 = b6       /* call ffi_prep_args           */
63         cmp.eq  p6,p0=0,r8              /* r8 nonzero ==> need fp regs  */
64         ;;
65 (p6)    add     loc2=32+8*FLOAT_SZ,sp
66 (p6)    br.cond.dptk.many       fp_done
67         ;;      /* Quiets warning; needed?      */
68         add     loc2=32,sp
69         add     loc3=32+FLOAT_SZ,sp
70         ;;
71         ldfd    f8=[loc2],2*FLOAT_SZ
72         ldfd    f9=[loc3],2*FLOAT_SZ
73         ;;
74         ldfd    f10=[loc2],2*FLOAT_SZ
75         ldfd    f11=[loc3],2*FLOAT_SZ
76         ;;
77         ldfd    f12=[loc2],2*FLOAT_SZ
78         ldfd    f13=[loc3],2*FLOAT_SZ
79         ;;
80         ldfd    f14=[loc2],2*FLOAT_SZ
81         ldfd    f15=[loc3]
82 fp_done:
83         add     r9=16,sp        /* Pointer to r8_contents       */
84         /* loc2 points at first integer register value.  */
85         add     loc3=8,loc2
86         ;;
87         ld8     r8=[r9]         /* Just in case we return large struct */
88         ld8     out0=[loc2],16
89         ld8     out1=[loc3],16
90         ;;
91         ld8     out2=[loc2],16
92         ld8     out3=[loc3],16
93         ;;
94         ld8     out4=[loc2],16
95         ld8     out5=[loc3],16
96         ;;
97         ld8     out6=[loc2]
98         ld8     out7=[loc3]
99         /* Set sp to 16 bytes below the first stack parameter.  This    */
100         /* is the value currently in loc2.                              */
101         mov     sp=loc2
102         
103         ld8     r8=[fn],8
104         ;;
105         ld8     r1=[fn]         /* Set up gp */
106         mov     b6=r8;;
107         br.call.sptk.many b0 = b6       /* call ffi_prep_args   */
108         
109         /* Handle return value. */
110         cmp.eq  p6,p0=0,raddr
111         cmp.eq  p7,p0=FFI_TYPE_INT,flags
112         cmp.eq  p10,p0=FFI_IS_SMALL_STRUCT2,flags
113         cmp.eq  p11,p0=FFI_IS_SMALL_STRUCT3,flags
114         cmp.eq  p12,p0=FFI_IS_SMALL_STRUCT4,flags
115         ;;
116 (p6)    br.cond.dpnt.few done           /* Dont copy ret values if raddr = 0 */
117 (p7)    br.cond.dptk.few copy1
118 (p10)   br.cond.dpnt.few copy2
119 (p11)   br.cond.dpnt.few copy3
120 (p12)   br.cond.dpnt.few copy4
121         cmp.eq  p8,p0=FFI_TYPE_FLOAT,flags
122         cmp.eq  p9,p0=FFI_TYPE_DOUBLE,flags
123         tbit.nz p6,p0=flags,FLOAT_FP_AGGREGATE_BIT
124         tbit.nz p7,p0=flags,DOUBLE_FP_AGGREGATE_BIT
125         ;;
126 (p8)    stfs    [raddr]=f8
127 (p9)    stfd    [raddr]=f8
128         ;;
129 (p6)    br.cond.dpnt.few handle_float_hfa
130 (p7)    br.cond.dpnt.few handle_double_hfa
131         br done
132
133 copy4:
134         add     loc3=24,raddr
135         ;;
136         st8     [loc3]=r11
137 copy3:
138         add     loc3=16,raddr
139         ;;
140         st8     [loc3]=r10
141 copy2:
142         add     loc3=8,raddr
143         ;;
144         st8     [loc3]=r9
145 copy1:
146         st8     [raddr]=r8
147         /* In the big struct case, raddr was passed as an argument.     */
148         /* In the void case there was nothing to do.                    */
149
150 done:
151         mov     r1=loc4         /* Restore gp   */
152         mov     ar.pfs = loc0
153         mov     b0 = loc1
154         br.ret.sptk.many b0
155
156 handle_double_hfa:
157         /* Homogeneous floating point array of doubles is returned in   */
158         /* registers f8-f15.  Save one at a time to return area.        */
159         and     flags=0xf,flags /* Retrieve size        */
160         ;;
161         cmp.eq  p6,p0=2,flags
162         cmp.eq  p7,p0=3,flags
163         cmp.eq  p8,p0=4,flags
164         cmp.eq  p9,p0=5,flags
165         cmp.eq  p10,p0=6,flags
166         cmp.eq  p11,p0=7,flags
167         cmp.eq  p12,p0=8,flags
168         ;;
169 (p6)    br.cond.dptk.few        dhfa2
170 (p7)    br.cond.dptk.few        dhfa3
171 (p8)    br.cond.dptk.few        dhfa4
172 (p9)    br.cond.dptk.few        dhfa5
173 (p10)   br.cond.dptk.few        dhfa6
174 (p11)   br.cond.dptk.few        dhfa7
175 dhfa8:  add     loc3=7*8,raddr
176         ;;
177         stfd    [loc3]=f15
178 dhfa7:  add     loc3=6*8,raddr
179         ;;
180         stfd    [loc3]=f14
181 dhfa6:  add     loc3=5*8,raddr
182         ;;
183         stfd    [loc3]=f13
184 dhfa5:  add     loc3=4*8,raddr
185         ;;
186         stfd    [loc3]=f12
187 dhfa4:  add     loc3=3*8,raddr
188         ;;
189         stfd    [loc3]=f11
190 dhfa3:  add     loc3=2*8,raddr
191         ;;
192         stfd    [loc3]=f10
193 dhfa2:  add     loc3=1*8,raddr
194         ;;
195         stfd    [loc3]=f9
196         stfd    [raddr]=f8
197         br      done
198
199 handle_float_hfa:
200         /* Homogeneous floating point array of floats is returned in    */
201         /* registers f8-f15.  Save one at a time to return area.        */
202         and     flags=0xf,flags /* Retrieve size        */
203         ;;
204         cmp.eq  p6,p0=2,flags
205         cmp.eq  p7,p0=3,flags
206         cmp.eq  p8,p0=4,flags
207         cmp.eq  p9,p0=5,flags
208         cmp.eq  p10,p0=6,flags
209         cmp.eq  p11,p0=7,flags
210         cmp.eq  p12,p0=8,flags
211         ;;
212 (p6)    br.cond.dptk.few        shfa2
213 (p7)    br.cond.dptk.few        shfa3
214 (p8)    br.cond.dptk.few        shfa4
215 (p9)    br.cond.dptk.few        shfa5
216 (p10)   br.cond.dptk.few        shfa6
217 (p11)   br.cond.dptk.few        shfa7
218 shfa8:  add     loc3=7*4,raddr
219         ;;
220         stfd    [loc3]=f15
221 shfa7:  add     loc3=6*4,raddr
222         ;;
223         stfd    [loc3]=f14
224 shfa6:  add     loc3=5*4,raddr
225         ;;
226         stfd    [loc3]=f13
227 shfa5:  add     loc3=4*4,raddr
228         ;;
229         stfd    [loc3]=f12
230 shfa4:  add     loc3=3*4,raddr
231         ;;
232         stfd    [loc3]=f11
233 shfa3:  add     loc3=2*4,raddr
234         ;;
235         stfd    [loc3]=f10
236 shfa2:  add     loc3=1*4,raddr
237         ;;
238         stfd    [loc3]=f9
239         stfd    [raddr]=f8
240         br      done
241
242         .endp ffi_call_unix
243
244
245 .text
246         .align 16
247         .global ffi_closure_UNIX
248         .proc ffi_closure_UNIX
249 ffi_closure_UNIX:
250         alloc   loc0=ar.pfs,8,2,2,0
251         mov     loc1=b0
252         /* Retrieve closure pointer and real gp.        */
253         mov     out0=gp
254         add     gp=16,gp
255         ;;
256         ld8     gp=[gp]
257         /* Reserve a structia64_args on the stack such that arguments   */
258         /* past the first 8 are automatically placed in the right       */
259         /* slot.  Note that when we start the sp points at 2 8-byte     */
260         /* scratch words, followed by the extra arguments.              */
261 #       define BASIC_ARGS_SZ (8*FLOAT_SZ+8*8+2*8)
262 #       define FIRST_FP_OFFSET (4*8)
263         add     r14=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET),sp
264         add     r15=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET-FLOAT_SZ),sp
265         add     sp=-BASIC_ARGS_SZ,sp
266         /* r14 points to fp_regs[0], r15 points to fp_regs[1]   */
267         ;;
268         stfd    [r14]=f8,2*FLOAT_SZ
269         stfd    [r15]=f9,2*FLOAT_SZ
270         ;;
271         stfd    [r14]=f10,2*FLOAT_SZ
272         stfd    [r15]=f11,2*FLOAT_SZ
273         ;;
274         stfd    [r14]=f12,2*FLOAT_SZ
275         stfd    [r15]=f13,2*FLOAT_SZ
276         ;;
277         stfd    [r14]=f14,FLOAT_SZ+8
278         stfd    [r15]=f15,2*8
279         ;;
280         /* r14 points to first parameter register area, r15 to second. */
281         st8     [r14]=in0,2*8
282         st8     [r15]=in1,2*8
283         ;;
284         st8     [r14]=in2,2*8
285         st8     [r15]=in3,2*8
286         ;;
287         st8     [r14]=in4,2*8
288         st8     [r15]=in5,2*8
289         ;;
290         st8     [r14]=in6,2*8
291         st8     [r15]=in7,2*8
292         /* Call ffi_closure_UNIX_inner */
293         mov     out1=sp
294         br.call.sptk.many b0=ffi_closure_UNIX_inner
295         ;;
296         mov     b0=loc1
297         mov     ar.pfs=loc0
298         add     sp=BASIC_ARGS_SZ,sp
299         br.ret.sptk.many b0
300         .endp ffi_closure_UNIX
301         
302