OSDN Git Service

e599268c72114e7e193419802fd5999cc1bd331d
[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 /* Allocate an ia64_args structure on the stack; call ffi_prep_args     */
46 /* to fill it in with argument values; copy those to the real           */
47 /* registers, leaving overflow arguments on the stack.  Then call fn    */
48 /* and move the result from registers into *raddr.                      */
49         .pred.safe_across_calls p1-p5,p16-p63
50 .text
51         .align 16
52         .global ffi_call_unix
53         .proc ffi_call_unix
54 ffi_call_unix:
55         .prologue
56         .save   ar.pfs,r38 /* loc0 */
57         alloc   loc0=ar.pfs,6,6,8,0
58         .save   rp,loc1
59         mov     loc1=b0;
60         .vframe loc5
61         mov     loc5=sp;
62         .body
63         sub     sp=sp,bytes
64         mov     loc4=r1         /* Save gp      */
65         ld8     r8=[callback],8 /* code address of callback     */
66         ;;
67         mov     out0=sp
68         mov     out1=ecifp
69         mov     out2=bytes
70         ld8     r1=[callback]   /* Set up gp for callback.  Unnecessary? */
71         mov     b6=r8
72         ;;
73         br.call.sptk.many b0 = b6       /* call ffi_prep_args           */
74         cmp.eq  p6,p0=0,r8              /* r8 nonzero ==> need fp regs  */
75         ;;
76 (p6)    add     loc2=32+8*FLOAT_SZ,sp
77 (p6)    br.cond.dptk.many       fp_done
78         ;;      /* Quiets warning; needed?      */
79         add     loc2=32,sp
80         add     loc3=32+FLOAT_SZ,sp
81         ;;
82         ldfd    f8=[loc2],2*FLOAT_SZ
83         ldfd    f9=[loc3],2*FLOAT_SZ
84         ;;
85         ldfd    f10=[loc2],2*FLOAT_SZ
86         ldfd    f11=[loc3],2*FLOAT_SZ
87         ;;
88         ldfd    f12=[loc2],2*FLOAT_SZ
89         ldfd    f13=[loc3],2*FLOAT_SZ
90         ;;
91         ldfd    f14=[loc2],2*FLOAT_SZ
92         ldfd    f15=[loc3]
93 fp_done:
94         add     r9=16,sp        /* Pointer to r8_contents       */
95         /* loc2 points at first integer register value.  */
96         add     loc3=8,loc2
97         ;;
98         ld8     r8=[r9]         /* Just in case we return large struct */
99         ld8     out0=[loc2],16
100         ld8     out1=[loc3],16
101         ;;
102         ld8     out2=[loc2],16
103         ld8     out3=[loc3],16
104         ;;
105         ld8     out4=[loc2],16
106         ld8     out5=[loc3],16
107         ;;
108         ld8     out6=[loc2]
109         ld8     out7=[loc3]
110         /* Set sp to 16 bytes below the first stack parameter.  This    */
111         /* is the value currently in loc2.                              */
112         mov     sp=loc2
113         
114         ld8     r8=[fn],8
115         ;;
116         ld8     r1=[fn]         /* Set up gp */
117         mov     b6=r8;;
118         br.call.sptk.many b0 = b6       /* call fn      */
119         
120         /* Handle return value. */
121         cmp.eq  p6,p0=0,raddr
122         cmp.eq  p7,p0=FFI_TYPE_INT,flags
123         cmp.eq  p10,p0=FFI_IS_SMALL_STRUCT2,flags
124         cmp.eq  p11,p0=FFI_IS_SMALL_STRUCT3,flags
125         cmp.eq  p12,p0=FFI_IS_SMALL_STRUCT4,flags
126         ;;
127 (p6)    br.cond.dpnt.few done           /* Dont copy ret values if raddr = 0 */
128 (p7)    br.cond.dptk.few copy1
129 (p10)   br.cond.dpnt.few copy2
130 (p11)   br.cond.dpnt.few copy3
131 (p12)   br.cond.dpnt.few copy4
132         cmp.eq  p8,p0=FFI_TYPE_FLOAT,flags
133         cmp.eq  p9,p0=FFI_TYPE_DOUBLE,flags
134         tbit.nz p6,p0=flags,FLOAT_FP_AGGREGATE_BIT
135         tbit.nz p7,p0=flags,DOUBLE_FP_AGGREGATE_BIT
136         ;;
137 (p8)    stfs    [raddr]=f8
138 (p9)    stfd    [raddr]=f8
139         ;;
140         .label_state 1
141 (p6)    br.cond.dpnt.few handle_float_hfa
142 (p7)    br.cond.dpnt.few handle_double_hfa
143         br done
144
145 copy4:
146         add     loc3=24,raddr
147         ;;
148         st8     [loc3]=r11
149 copy3:
150         add     loc3=16,raddr
151         ;;
152         st8     [loc3]=r10
153 copy2:
154         add     loc3=8,raddr
155         ;;
156         st8     [loc3]=r9
157 copy1:
158         st8     [raddr]=r8
159         /* In the big struct case, raddr was passed as an argument.     */
160         /* In the void case there was nothing to do.                    */
161
162 done:
163         mov     r1=loc4         /* Restore gp   */
164         mov     ar.pfs = loc0
165         mov     b0 = loc1
166         .restore sp
167         mov     sp = loc5
168         br.ret.sptk.many b0
169
170 handle_double_hfa:
171         .body
172         .copy_state 1
173         /* Homogeneous floating point array of doubles is returned in   */
174         /* registers f8-f15.  Save one at a time to return area.        */
175         and     flags=0xf,flags /* Retrieve size        */
176         ;;
177         cmp.eq  p6,p0=2,flags
178         cmp.eq  p7,p0=3,flags
179         cmp.eq  p8,p0=4,flags
180         cmp.eq  p9,p0=5,flags
181         cmp.eq  p10,p0=6,flags
182         cmp.eq  p11,p0=7,flags
183         cmp.eq  p12,p0=8,flags
184         ;;
185 (p6)    br.cond.dptk.few        dhfa2
186 (p7)    br.cond.dptk.few        dhfa3
187 (p8)    br.cond.dptk.few        dhfa4
188 (p9)    br.cond.dptk.few        dhfa5
189 (p10)   br.cond.dptk.few        dhfa6
190 (p11)   br.cond.dptk.few        dhfa7
191 dhfa8:  add     loc3=7*8,raddr
192         ;;
193         stfd    [loc3]=f15
194 dhfa7:  add     loc3=6*8,raddr
195         ;;
196         stfd    [loc3]=f14
197 dhfa6:  add     loc3=5*8,raddr
198         ;;
199         stfd    [loc3]=f13
200 dhfa5:  add     loc3=4*8,raddr
201         ;;
202         stfd    [loc3]=f12
203 dhfa4:  add     loc3=3*8,raddr
204         ;;
205         stfd    [loc3]=f11
206 dhfa3:  add     loc3=2*8,raddr
207         ;;
208         stfd    [loc3]=f10
209 dhfa2:  add     loc3=1*8,raddr
210         ;;
211         stfd    [loc3]=f9
212         stfd    [raddr]=f8
213         br      done
214
215 handle_float_hfa:
216         /* Homogeneous floating point array of floats is returned in    */
217         /* registers f8-f15.  Save one at a time to return area.        */
218         and     flags=0xf,flags /* Retrieve size        */
219         ;;
220         cmp.eq  p6,p0=2,flags
221         cmp.eq  p7,p0=3,flags
222         cmp.eq  p8,p0=4,flags
223         cmp.eq  p9,p0=5,flags
224         cmp.eq  p10,p0=6,flags
225         cmp.eq  p11,p0=7,flags
226         cmp.eq  p12,p0=8,flags
227         ;;
228 (p6)    br.cond.dptk.few        shfa2
229 (p7)    br.cond.dptk.few        shfa3
230 (p8)    br.cond.dptk.few        shfa4
231 (p9)    br.cond.dptk.few        shfa5
232 (p10)   br.cond.dptk.few        shfa6
233 (p11)   br.cond.dptk.few        shfa7
234 shfa8:  add     loc3=7*4,raddr
235         ;;
236         stfd    [loc3]=f15
237 shfa7:  add     loc3=6*4,raddr
238         ;;
239         stfd    [loc3]=f14
240 shfa6:  add     loc3=5*4,raddr
241         ;;
242         stfd    [loc3]=f13
243 shfa5:  add     loc3=4*4,raddr
244         ;;
245         stfd    [loc3]=f12
246 shfa4:  add     loc3=3*4,raddr
247         ;;
248         stfd    [loc3]=f11
249 shfa3:  add     loc3=2*4,raddr
250         ;;
251         stfd    [loc3]=f10
252 shfa2:  add     loc3=1*4,raddr
253         ;;
254         stfd    [loc3]=f9
255         stfd    [raddr]=f8
256         br      done
257
258         .endp ffi_call_unix
259
260
261         .pred.safe_across_calls p1-p5,p16-p63
262 .text
263         .align 16
264         .global ffi_closure_UNIX
265         .proc ffi_closure_UNIX
266 ffi_closure_UNIX:
267         .prologue
268         .save   ar.pfs,r40 /* loc0 */
269         alloc   loc0=ar.pfs,8,3,2,0
270         .save   rp,loc1
271         mov     loc1=b0
272         .vframe loc2
273         mov     loc2=sp
274         /* Retrieve closure pointer and real gp.        */
275         mov     out0=gp
276         add     gp=16,gp
277         ;;
278         ld8     gp=[gp]
279         /* Reserve a structia64_args on the stack such that arguments   */
280         /* past the first 8 are automatically placed in the right       */
281         /* slot.  Note that when we start the sp points at 2 8-byte     */
282         /* scratch words, followed by the extra arguments.              */
283 #       define BASIC_ARGS_SZ (8*FLOAT_SZ+8*8+2*8)
284 #       define FIRST_FP_OFFSET (4*8)
285         add     r14=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET),sp
286         add     r15=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET-FLOAT_SZ),sp
287         add     sp=-BASIC_ARGS_SZ,sp
288         /* r14 points to fp_regs[0], r15 points to fp_regs[1]   */
289         ;;
290         stfd    [r14]=f8,2*FLOAT_SZ
291         stfd    [r15]=f9,2*FLOAT_SZ
292         ;;
293         stfd    [r14]=f10,2*FLOAT_SZ
294         stfd    [r15]=f11,2*FLOAT_SZ
295         ;;
296         stfd    [r14]=f12,2*FLOAT_SZ
297         stfd    [r15]=f13,2*FLOAT_SZ
298         ;;
299         stfd    [r14]=f14,FLOAT_SZ+8
300         stfd    [r15]=f15,2*8
301         ;;
302         /* r14 points to first parameter register area, r15 to second. */
303         st8     [r14]=in0,2*8
304         st8     [r15]=in1,2*8
305         ;;
306         st8     [r14]=in2,2*8
307         st8     [r15]=in3,2*8
308         ;;
309         st8     [r14]=in4,2*8
310         st8     [r15]=in5,2*8
311         ;;
312         st8     [r14]=in6,2*8
313         st8     [r15]=in7,2*8
314         /* Call ffi_closure_UNIX_inner */
315         mov     out1=sp
316         br.call.sptk.many b0=ffi_closure_UNIX_inner
317         ;;
318         mov     b0=loc1
319         mov     ar.pfs=loc0
320         .restore sp
321         mov     sp=loc2
322         br.ret.sptk.many b0
323         .endp ffi_closure_UNIX
324         
325