]> git.ipfire.org Git - thirdparty/gcc.git/blob - libffi/src/ia64/unix.S
libffi: Sync with libffi 3.4.2
[thirdparty/gcc.git] / libffi / src / ia64 / unix.S
1 /* -----------------------------------------------------------------------
2 unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
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,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 DEALINGS IN THE SOFTWARE.
30 ----------------------------------------------------------------------- */
31
32 #define LIBFFI_ASM
33 #include <fficonfig.h>
34 #include <ffi.h>
35 #include "ia64_flags.h"
36
37 .pred.safe_across_calls p1-p5,p16-p63
38 .text
39
40 /* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
41 void (*fn)(void), int flags);
42 */
43
44 .align 16
45 .global ffi_call_unix
46 .proc ffi_call_unix
47 ffi_call_unix:
48 .prologue
49 /* Bit o trickiness. We actually share a stack frame with ffi_call.
50 Rely on the fact that ffi_call uses a vframe and don't bother
51 tracking one here at all. */
52 .fframe 0
53 .save ar.pfs, r36 // loc0
54 alloc loc0 = ar.pfs, 4, 3, 8, 0
55 .save rp, loc1
56 mov loc1 = b0
57 .body
58 add r16 = 16, in0
59 mov loc2 = gp
60 mov r8 = in1
61 ;;
62
63 /* Load up all of the argument registers. */
64 ldf.fill f8 = [in0], 32
65 ldf.fill f9 = [r16], 32
66 ;;
67 ldf.fill f10 = [in0], 32
68 ldf.fill f11 = [r16], 32
69 ;;
70 ldf.fill f12 = [in0], 32
71 ldf.fill f13 = [r16], 32
72 ;;
73 ldf.fill f14 = [in0], 32
74 ldf.fill f15 = [r16], 24
75 ;;
76 ld8 out0 = [in0], 16
77 ld8 out1 = [r16], 16
78 ;;
79 ld8 out2 = [in0], 16
80 ld8 out3 = [r16], 16
81 ;;
82 ld8 out4 = [in0], 16
83 ld8 out5 = [r16], 16
84 ;;
85 ld8 out6 = [in0]
86 ld8 out7 = [r16]
87 ;;
88
89 /* Deallocate the register save area from the stack frame. */
90 mov sp = in0
91
92 /* Call the target function. */
93 ld8 r16 = [in2], 8
94 ;;
95 ld8 gp = [in2]
96 mov b6 = r16
97 br.call.sptk.many b0 = b6
98 ;;
99
100 /* Dispatch to handle return value. */
101 mov gp = loc2
102 zxt1 r16 = in3
103 ;;
104 mov ar.pfs = loc0
105 addl r18 = @ltoffx(.Lst_table), gp
106 ;;
107 ld8.mov r18 = [r18], .Lst_table
108 mov b0 = loc1
109 ;;
110 shladd r18 = r16, 3, r18
111 ;;
112 ld8 r17 = [r18]
113 shr in3 = in3, 8
114 ;;
115 add r17 = r17, r18
116 ;;
117 mov b6 = r17
118 br b6
119 ;;
120
121 .Lst_void:
122 br.ret.sptk.many b0
123 ;;
124 .Lst_uint8:
125 zxt1 r8 = r8
126 ;;
127 st8 [in1] = r8
128 br.ret.sptk.many b0
129 ;;
130 .Lst_sint8:
131 sxt1 r8 = r8
132 ;;
133 st8 [in1] = r8
134 br.ret.sptk.many b0
135 ;;
136 .Lst_uint16:
137 zxt2 r8 = r8
138 ;;
139 st8 [in1] = r8
140 br.ret.sptk.many b0
141 ;;
142 .Lst_sint16:
143 sxt2 r8 = r8
144 ;;
145 st8 [in1] = r8
146 br.ret.sptk.many b0
147 ;;
148 .Lst_uint32:
149 zxt4 r8 = r8
150 ;;
151 st8 [in1] = r8
152 br.ret.sptk.many b0
153 ;;
154 .Lst_sint32:
155 sxt4 r8 = r8
156 ;;
157 st8 [in1] = r8
158 br.ret.sptk.many b0
159 ;;
160 .Lst_int64:
161 st8 [in1] = r8
162 br.ret.sptk.many b0
163 ;;
164 .Lst_float:
165 stfs [in1] = f8
166 br.ret.sptk.many b0
167 ;;
168 .Lst_double:
169 stfd [in1] = f8
170 br.ret.sptk.many b0
171 ;;
172 .Lst_ldouble:
173 stfe [in1] = f8
174 br.ret.sptk.many b0
175 ;;
176
177 .Lst_small_struct:
178 cmp.lt p6, p0 = 8, in3
179 cmp.lt p7, p0 = 16, in3
180 cmp.lt p8, p0 = 24, in3
181 ;;
182 add r16 = 8, sp
183 add r17 = 16, sp
184 add r18 = 24, sp
185 ;;
186 st8 [sp] = r8
187 (p6) st8 [r16] = r9
188 mov out0 = in1
189 (p7) st8 [r17] = r10
190 (p8) st8 [r18] = r11
191 mov out1 = sp
192 mov out2 = in3
193 ;;
194 // ia64 software calling convention requires
195 // top 16 bytes of stack to be scratch space
196 // PLT resolver uses that scratch space at
197 // 'memcpy' symbol reolution time
198 add sp = -16, sp
199 br.call.sptk.many b0 = memcpy#
200 ;;
201 mov ar.pfs = loc0
202 mov b0 = loc1
203 mov gp = loc2
204 br.ret.sptk.many b0
205
206 .Lst_hfa_float:
207 add r16 = 4, in1
208 cmp.lt p6, p0 = 4, in3
209 ;;
210 stfs [in1] = f8, 8
211 (p6) stfs [r16] = f9, 8
212 cmp.lt p7, p0 = 8, in3
213 cmp.lt p8, p0 = 12, in3
214 ;;
215 (p7) stfs [in1] = f10, 8
216 (p8) stfs [r16] = f11, 8
217 cmp.lt p9, p0 = 16, in3
218 cmp.lt p10, p0 = 20, in3
219 ;;
220 (p9) stfs [in1] = f12, 8
221 (p10) stfs [r16] = f13, 8
222 cmp.lt p6, p0 = 24, in3
223 cmp.lt p7, p0 = 28, in3
224 ;;
225 (p6) stfs [in1] = f14
226 (p7) stfs [r16] = f15
227 br.ret.sptk.many b0
228 ;;
229
230 .Lst_hfa_double:
231 add r16 = 8, in1
232 cmp.lt p6, p0 = 8, in3
233 ;;
234 stfd [in1] = f8, 16
235 (p6) stfd [r16] = f9, 16
236 cmp.lt p7, p0 = 16, in3
237 cmp.lt p8, p0 = 24, in3
238 ;;
239 (p7) stfd [in1] = f10, 16
240 (p8) stfd [r16] = f11, 16
241 cmp.lt p9, p0 = 32, in3
242 cmp.lt p10, p0 = 40, in3
243 ;;
244 (p9) stfd [in1] = f12, 16
245 (p10) stfd [r16] = f13, 16
246 cmp.lt p6, p0 = 48, in3
247 cmp.lt p7, p0 = 56, in3
248 ;;
249 (p6) stfd [in1] = f14
250 (p7) stfd [r16] = f15
251 br.ret.sptk.many b0
252 ;;
253
254 .Lst_hfa_ldouble:
255 add r16 = 16, in1
256 cmp.lt p6, p0 = 16, in3
257 ;;
258 stfe [in1] = f8, 32
259 (p6) stfe [r16] = f9, 32
260 cmp.lt p7, p0 = 32, in3
261 cmp.lt p8, p0 = 48, in3
262 ;;
263 (p7) stfe [in1] = f10, 32
264 (p8) stfe [r16] = f11, 32
265 cmp.lt p9, p0 = 64, in3
266 cmp.lt p10, p0 = 80, in3
267 ;;
268 (p9) stfe [in1] = f12, 32
269 (p10) stfe [r16] = f13, 32
270 cmp.lt p6, p0 = 96, in3
271 cmp.lt p7, p0 = 112, in3
272 ;;
273 (p6) stfe [in1] = f14
274 (p7) stfe [r16] = f15
275 br.ret.sptk.many b0
276 ;;
277
278 .endp ffi_call_unix
279
280 .align 16
281 .global ffi_closure_unix
282 .proc ffi_closure_unix
283
284 #define FRAME_SIZE (8*16 + 8*8 + 8*16)
285
286 ffi_closure_unix:
287 .prologue
288 .save ar.pfs, r40 // loc0
289 alloc loc0 = ar.pfs, 8, 4, 4, 0
290 .fframe FRAME_SIZE
291 add r12 = -FRAME_SIZE, r12
292 .save rp, loc1
293 mov loc1 = b0
294 .save ar.unat, loc2
295 mov loc2 = ar.unat
296 .body
297
298 /* Retrieve closure pointer and real gp. */
299 #ifdef _ILP32
300 addp4 out0 = 0, gp
301 addp4 gp = 16, gp
302 #else
303 mov out0 = gp
304 add gp = 16, gp
305 #endif
306 ;;
307 ld8 gp = [gp]
308
309 /* Spill all of the possible argument registers. */
310 add r16 = 16 + 8*16, sp
311 add r17 = 16 + 8*16 + 16, sp
312 ;;
313 stf.spill [r16] = f8, 32
314 stf.spill [r17] = f9, 32
315 mov loc3 = gp
316 ;;
317 stf.spill [r16] = f10, 32
318 stf.spill [r17] = f11, 32
319 ;;
320 stf.spill [r16] = f12, 32
321 stf.spill [r17] = f13, 32
322 ;;
323 stf.spill [r16] = f14, 32
324 stf.spill [r17] = f15, 24
325 ;;
326 .mem.offset 0, 0
327 st8.spill [r16] = in0, 16
328 .mem.offset 8, 0
329 st8.spill [r17] = in1, 16
330 add out1 = 16 + 8*16, sp
331 ;;
332 .mem.offset 0, 0
333 st8.spill [r16] = in2, 16
334 .mem.offset 8, 0
335 st8.spill [r17] = in3, 16
336 add out2 = 16, sp
337 ;;
338 .mem.offset 0, 0
339 st8.spill [r16] = in4, 16
340 .mem.offset 8, 0
341 st8.spill [r17] = in5, 16
342 mov out3 = r8
343 ;;
344 .mem.offset 0, 0
345 st8.spill [r16] = in6
346 .mem.offset 8, 0
347 st8.spill [r17] = in7
348
349 /* Invoke ffi_closure_unix_inner for the hard work. */
350 br.call.sptk.many b0 = ffi_closure_unix_inner
351 ;;
352
353 /* Dispatch to handle return value. */
354 mov gp = loc3
355 zxt1 r16 = r8
356 ;;
357 addl r18 = @ltoffx(.Lld_table), gp
358 mov ar.pfs = loc0
359 ;;
360 ld8.mov r18 = [r18], .Lld_table
361 mov b0 = loc1
362 ;;
363 shladd r18 = r16, 3, r18
364 mov ar.unat = loc2
365 ;;
366 ld8 r17 = [r18]
367 shr r8 = r8, 8
368 ;;
369 add r17 = r17, r18
370 add r16 = 16, sp
371 ;;
372 mov b6 = r17
373 br b6
374 ;;
375 .label_state 1
376
377 .Lld_void:
378 .restore sp
379 add sp = FRAME_SIZE, sp
380 br.ret.sptk.many b0
381 ;;
382 .Lld_int:
383 .body
384 .copy_state 1
385 ld8 r8 = [r16]
386 .restore sp
387 add sp = FRAME_SIZE, sp
388 br.ret.sptk.many b0
389 ;;
390 .Lld_float:
391 .body
392 .copy_state 1
393 ldfs f8 = [r16]
394 .restore sp
395 add sp = FRAME_SIZE, sp
396 br.ret.sptk.many b0
397 ;;
398 .Lld_double:
399 .body
400 .copy_state 1
401 ldfd f8 = [r16]
402 .restore sp
403 add sp = FRAME_SIZE, sp
404 br.ret.sptk.many b0
405 ;;
406 .Lld_ldouble:
407 .body
408 .copy_state 1
409 ldfe f8 = [r16]
410 .restore sp
411 add sp = FRAME_SIZE, sp
412 br.ret.sptk.many b0
413 ;;
414
415 .Lld_small_struct:
416 .body
417 .copy_state 1
418 add r17 = 8, r16
419 cmp.lt p6, p0 = 8, r8
420 cmp.lt p7, p0 = 16, r8
421 cmp.lt p8, p0 = 24, r8
422 ;;
423 ld8 r8 = [r16], 16
424 (p6) ld8 r9 = [r17], 16
425 ;;
426 (p7) ld8 r10 = [r16]
427 (p8) ld8 r11 = [r17]
428 .restore sp
429 add sp = FRAME_SIZE, sp
430 br.ret.sptk.many b0
431 ;;
432
433 .Lld_hfa_float:
434 .body
435 .copy_state 1
436 add r17 = 4, r16
437 cmp.lt p6, p0 = 4, r8
438 ;;
439 ldfs f8 = [r16], 8
440 (p6) ldfs f9 = [r17], 8
441 cmp.lt p7, p0 = 8, r8
442 cmp.lt p8, p0 = 12, r8
443 ;;
444 (p7) ldfs f10 = [r16], 8
445 (p8) ldfs f11 = [r17], 8
446 cmp.lt p9, p0 = 16, r8
447 cmp.lt p10, p0 = 20, r8
448 ;;
449 (p9) ldfs f12 = [r16], 8
450 (p10) ldfs f13 = [r17], 8
451 cmp.lt p6, p0 = 24, r8
452 cmp.lt p7, p0 = 28, r8
453 ;;
454 (p6) ldfs f14 = [r16]
455 (p7) ldfs f15 = [r17]
456 .restore sp
457 add sp = FRAME_SIZE, sp
458 br.ret.sptk.many b0
459 ;;
460
461 .Lld_hfa_double:
462 .body
463 .copy_state 1
464 add r17 = 8, r16
465 cmp.lt p6, p0 = 8, r8
466 ;;
467 ldfd f8 = [r16], 16
468 (p6) ldfd f9 = [r17], 16
469 cmp.lt p7, p0 = 16, r8
470 cmp.lt p8, p0 = 24, r8
471 ;;
472 (p7) ldfd f10 = [r16], 16
473 (p8) ldfd f11 = [r17], 16
474 cmp.lt p9, p0 = 32, r8
475 cmp.lt p10, p0 = 40, r8
476 ;;
477 (p9) ldfd f12 = [r16], 16
478 (p10) ldfd f13 = [r17], 16
479 cmp.lt p6, p0 = 48, r8
480 cmp.lt p7, p0 = 56, r8
481 ;;
482 (p6) ldfd f14 = [r16]
483 (p7) ldfd f15 = [r17]
484 .restore sp
485 add sp = FRAME_SIZE, sp
486 br.ret.sptk.many b0
487 ;;
488
489 .Lld_hfa_ldouble:
490 .body
491 .copy_state 1
492 add r17 = 16, r16
493 cmp.lt p6, p0 = 16, r8
494 ;;
495 ldfe f8 = [r16], 32
496 (p6) ldfe f9 = [r17], 32
497 cmp.lt p7, p0 = 32, r8
498 cmp.lt p8, p0 = 48, r8
499 ;;
500 (p7) ldfe f10 = [r16], 32
501 (p8) ldfe f11 = [r17], 32
502 cmp.lt p9, p0 = 64, r8
503 cmp.lt p10, p0 = 80, r8
504 ;;
505 (p9) ldfe f12 = [r16], 32
506 (p10) ldfe f13 = [r17], 32
507 cmp.lt p6, p0 = 96, r8
508 cmp.lt p7, p0 = 112, r8
509 ;;
510 (p6) ldfe f14 = [r16]
511 (p7) ldfe f15 = [r17]
512 .restore sp
513 add sp = FRAME_SIZE, sp
514 br.ret.sptk.many b0
515 ;;
516
517 .endp ffi_closure_unix
518
519 .section .rodata
520 .align 8
521 .Lst_table:
522 data8 @pcrel(.Lst_void) // FFI_TYPE_VOID
523 data8 @pcrel(.Lst_sint32) // FFI_TYPE_INT
524 data8 @pcrel(.Lst_float) // FFI_TYPE_FLOAT
525 data8 @pcrel(.Lst_double) // FFI_TYPE_DOUBLE
526 data8 @pcrel(.Lst_ldouble) // FFI_TYPE_LONGDOUBLE
527 data8 @pcrel(.Lst_uint8) // FFI_TYPE_UINT8
528 data8 @pcrel(.Lst_sint8) // FFI_TYPE_SINT8
529 data8 @pcrel(.Lst_uint16) // FFI_TYPE_UINT16
530 data8 @pcrel(.Lst_sint16) // FFI_TYPE_SINT16
531 data8 @pcrel(.Lst_uint32) // FFI_TYPE_UINT32
532 data8 @pcrel(.Lst_sint32) // FFI_TYPE_SINT32
533 data8 @pcrel(.Lst_int64) // FFI_TYPE_UINT64
534 data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64
535 data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT
536 data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER
537 data8 @pcrel(.Lst_void) // FFI_TYPE_COMPLEX (not implemented)
538 data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
539 data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
540 data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
541 data8 @pcrel(.Lst_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
542
543 .Lld_table:
544 data8 @pcrel(.Lld_void) // FFI_TYPE_VOID
545 data8 @pcrel(.Lld_int) // FFI_TYPE_INT
546 data8 @pcrel(.Lld_float) // FFI_TYPE_FLOAT
547 data8 @pcrel(.Lld_double) // FFI_TYPE_DOUBLE
548 data8 @pcrel(.Lld_ldouble) // FFI_TYPE_LONGDOUBLE
549 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT8
550 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT8
551 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT16
552 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT16
553 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT32
554 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT32
555 data8 @pcrel(.Lld_int) // FFI_TYPE_UINT64
556 data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64
557 data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT
558 data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER
559 data8 @pcrel(.Lld_void) // FFI_TYPE_COMPLEX (not implemented)
560 data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT
561 data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT
562 data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE
563 data8 @pcrel(.Lld_hfa_ldouble) // FFI_IA64_TYPE_HFA_LDOUBLE
564
565 #if defined __ELF__ && defined __linux__
566 .section .note.GNU-stack,"",@progbits
567 #endif