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 */
47 .global ffi_call_unix#
50 alloc loc0=ar.pfs,6,5,8,0
53 mov loc4=r1 /* Save gp */
54 ld8 r8=[callback],8 /* code address of callback */
59 ld8 r1=[callback] /* Set up gp for callback. Unnecessary? */
62 br.call.sptk.many b0 = b6 /* call ffi_prep_args */
63 cmp.eq p6,p0=0,r8 /* r8 nonzero ==> need fp regs */
65 (p6) add loc2=32+8*FLOAT_SZ,sp
66 (p6) br.cond.dptk.many fp_done
67 ;; /* Quiets warning; needed? */
69 add loc3=32+FLOAT_SZ,sp
71 ldfd f8=[loc2],2*FLOAT_SZ
72 ldfd f9=[loc3],2*FLOAT_SZ
74 ldfd f10=[loc2],2*FLOAT_SZ
75 ldfd f11=[loc3],2*FLOAT_SZ
77 ldfd f12=[loc2],2*FLOAT_SZ
78 ldfd f13=[loc3],2*FLOAT_SZ
80 ldfd f14=[loc2],2*FLOAT_SZ
83 add r9=16,sp /* Pointer to r8_contents */
84 /* loc2 points at first integer register value. */
87 ld8 r8=[r9] /* Just in case we return large struct */
99 /* Set sp to 16 bytes below the first stack parameter. This */
100 /* is the value currently in loc2. */
105 ld8 r1=[fn] /* Set up gp */
107 br.call.sptk.many b0 = b6 /* call ffi_prep_args */
109 /* Handle return value. */
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
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
129 (p6) br.cond.dpnt.few handle_float_hfa
130 (p7) br.cond.dpnt.few handle_double_hfa
147 /* In the big struct case, raddr was passed as an argument. */
148 /* In the void case there was nothing to do. */
151 mov r1=loc4 /* Restore gp */
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 */
165 cmp.eq p10,p0=6,flags
166 cmp.eq p11,p0=7,flags
167 cmp.eq p12,p0=8,flags
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
178 dhfa7: add loc3=6*8,raddr
181 dhfa6: add loc3=5*8,raddr
184 dhfa5: add loc3=4*8,raddr
187 dhfa4: add loc3=3*8,raddr
190 dhfa3: add loc3=2*8,raddr
193 dhfa2: add loc3=1*8,raddr
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 */
208 cmp.eq p10,p0=6,flags
209 cmp.eq p11,p0=7,flags
210 cmp.eq p12,p0=8,flags
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
221 shfa7: add loc3=6*4,raddr
224 shfa6: add loc3=5*4,raddr
227 shfa5: add loc3=4*4,raddr
230 shfa4: add loc3=3*4,raddr
233 shfa3: add loc3=2*4,raddr
236 shfa2: add loc3=1*4,raddr
247 .global ffi_closure_UNIX
248 .proc ffi_closure_UNIX
250 alloc loc0=ar.pfs,8,2,2,0
252 /* Retrieve closure pointer and real 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] */
268 stfd [r14]=f8,2*FLOAT_SZ
269 stfd [r15]=f9,2*FLOAT_SZ
271 stfd [r14]=f10,2*FLOAT_SZ
272 stfd [r15]=f11,2*FLOAT_SZ
274 stfd [r14]=f12,2*FLOAT_SZ
275 stfd [r15]=f13,2*FLOAT_SZ
277 stfd [r14]=f14,FLOAT_SZ+8
280 /* r14 points to first parameter register area, r15 to second. */
292 /* Call ffi_closure_UNIX_inner */
294 br.call.sptk.many b0=ffi_closure_UNIX_inner
298 add sp=BASIC_ARGS_SZ,sp
300 .endp ffi_closure_UNIX