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