1 /* -----------------------------------------------------------------------
2 unix.S - Copyright (c) 1998 Cygnus Solutions
3 Copyright (c) 2000 Hewlett Packard Company
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 ----------------------------------------------------------------------- */
33 #include "ia64_flags.h"
43 #define FLOAT_SZ 8 /* in-memory size of fp operands */
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
56 .save ar.pfs,r38 /* loc0 */
57 alloc loc0=ar.pfs,6,6,8,0
64 mov loc4=r1 /* Save gp */
65 ld8 r8=[callback],8 /* code address of callback */
70 ld8 r1=[callback] /* Set up gp for callback. Unnecessary? */
73 br.call.sptk.many b0 = b6 /* call ffi_prep_args */
74 cmp.eq p6,p0=0,r8 /* r8 nonzero ==> need fp regs */
76 (p6) add loc2=32+8*FLOAT_SZ,sp
77 (p6) br.cond.dptk.many fp_done
78 ;; /* Quiets warning; needed? */
80 add loc3=32+FLOAT_SZ,sp
82 ldfd f8=[loc2],2*FLOAT_SZ
83 ldfd f9=[loc3],2*FLOAT_SZ
85 ldfd f10=[loc2],2*FLOAT_SZ
86 ldfd f11=[loc3],2*FLOAT_SZ
88 ldfd f12=[loc2],2*FLOAT_SZ
89 ldfd f13=[loc3],2*FLOAT_SZ
91 ldfd f14=[loc2],2*FLOAT_SZ
94 add r9=16,sp /* Pointer to r8_contents */
95 /* loc2 points at first integer register value. */
98 ld8 r8=[r9] /* Just in case we return large struct */
110 /* Set sp to 16 bytes below the first stack parameter. This */
111 /* is the value currently in loc2. */
116 ld8 r1=[fn] /* Set up gp */
118 br.call.sptk.many b0 = b6 /* call fn */
120 /* Handle return value. */
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
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
141 (p6) br.cond.dpnt.few handle_float_hfa
142 (p7) br.cond.dpnt.few handle_double_hfa
159 /* In the big struct case, raddr was passed as an argument. */
160 /* In the void case there was nothing to do. */
163 mov r1=loc4 /* Restore gp */
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 */
181 cmp.eq p10,p0=6,flags
182 cmp.eq p11,p0=7,flags
183 cmp.eq p12,p0=8,flags
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
194 dhfa7: add loc3=6*8,raddr
197 dhfa6: add loc3=5*8,raddr
200 dhfa5: add loc3=4*8,raddr
203 dhfa4: add loc3=3*8,raddr
206 dhfa3: add loc3=2*8,raddr
209 dhfa2: add loc3=1*8,raddr
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 */
224 cmp.eq p10,p0=6,flags
225 cmp.eq p11,p0=7,flags
226 cmp.eq p12,p0=8,flags
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
237 shfa7: add loc3=6*4,raddr
240 shfa6: add loc3=5*4,raddr
243 shfa5: add loc3=4*4,raddr
246 shfa4: add loc3=3*4,raddr
249 shfa3: add loc3=2*4,raddr
252 shfa2: add loc3=1*4,raddr
261 .pred.safe_across_calls p1-p5,p16-p63
264 .global ffi_closure_UNIX
265 .proc ffi_closure_UNIX
268 .save ar.pfs,r40 /* loc0 */
269 alloc loc0=ar.pfs,8,3,2,0
274 /* Retrieve closure pointer and real 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] */
290 stfd [r14]=f8,2*FLOAT_SZ
291 stfd [r15]=f9,2*FLOAT_SZ
293 stfd [r14]=f10,2*FLOAT_SZ
294 stfd [r15]=f11,2*FLOAT_SZ
296 stfd [r14]=f12,2*FLOAT_SZ
297 stfd [r15]=f13,2*FLOAT_SZ
299 stfd [r14]=f14,FLOAT_SZ+8
302 /* r14 points to first parameter register area, r15 to second. */
314 /* Call ffi_closure_UNIX_inner */
316 br.call.sptk.many b0=ffi_closure_UNIX_inner
323 .endp ffi_closure_UNIX