source: trunk/gcc/libffi/src/ia64/unix.S

Last change on this file was 2, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 7.8 KB
Line 
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
54ffi_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]
93fp_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
145copy4:
146 add loc3=24,raddr
147 ;;
148 st8 [loc3]=r11
149copy3:
150 add loc3=16,raddr
151 ;;
152 st8 [loc3]=r10
153copy2:
154 add loc3=8,raddr
155 ;;
156 st8 [loc3]=r9
157copy1:
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
162done:
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
170handle_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
191dhfa8: add loc3=7*8,raddr
192 ;;
193 stfd [loc3]=f15
194dhfa7: add loc3=6*8,raddr
195 ;;
196 stfd [loc3]=f14
197dhfa6: add loc3=5*8,raddr
198 ;;
199 stfd [loc3]=f13
200dhfa5: add loc3=4*8,raddr
201 ;;
202 stfd [loc3]=f12
203dhfa4: add loc3=3*8,raddr
204 ;;
205 stfd [loc3]=f11
206dhfa3: add loc3=2*8,raddr
207 ;;
208 stfd [loc3]=f10
209dhfa2: add loc3=1*8,raddr
210 ;;
211 stfd [loc3]=f9
212 stfd [raddr]=f8
213 br done
214
215handle_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
234shfa8: add loc3=7*4,raddr
235 ;;
236 stfd [loc3]=f15
237shfa7: add loc3=6*4,raddr
238 ;;
239 stfd [loc3]=f14
240shfa6: add loc3=5*4,raddr
241 ;;
242 stfd [loc3]=f13
243shfa5: add loc3=4*4,raddr
244 ;;
245 stfd [loc3]=f12
246shfa4: add loc3=3*4,raddr
247 ;;
248 stfd [loc3]=f11
249shfa3: add loc3=2*4,raddr
250 ;;
251 stfd [loc3]=f10
252shfa2: 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
266ffi_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
Note: See TracBrowser for help on using the repository browser.