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 |
|
---|