summaryrefslogtreecommitdiff
path: root/libffi.old/src/ia64/unix.S
diff options
context:
space:
mode:
Diffstat (limited to 'libffi.old/src/ia64/unix.S')
-rw-r--r--libffi.old/src/ia64/unix.S326
1 files changed, 326 insertions, 0 deletions
diff --git a/libffi.old/src/ia64/unix.S b/libffi.old/src/ia64/unix.S
new file mode 100644
index 0000000..c0c5058
--- /dev/null
+++ b/libffi.old/src/ia64/unix.S
@@ -0,0 +1,326 @@
+/* -----------------------------------------------------------------------
+ unix.S - Copyright (c) 1998 Red Hat, Inc.
+ Copyright (c) 2000 Hewlett Packard Company
+
+ IA64/unix Foreign Function Interface
+
+ Primary author: Hans Boehm, HP Labs
+
+ Loosely modeled on Cygnus code for other platforms.
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ ``Software''), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+ ----------------------------------------------------------------------- */
+
+#define LIBFFI_ASM
+#include <fficonfig.h>
+#include <ffi.h>
+#include "ia64_flags.h"
+
+/* parameters: */
+#define callback in0
+#define ecifp in1
+#define bytes in2
+#define flags in3
+#define raddr in4
+#define fn in5
+
+#define FLOAT_SZ 8 /* in-memory size of fp operands */
+
+/* Allocate an ia64_args structure on the stack; call ffi_prep_args */
+/* to fill it in with argument values; copy those to the real */
+/* registers, leaving overflow arguments on the stack. Then call fn */
+/* and move the result from registers into *raddr. */
+ .pred.safe_across_calls p1-p5,p16-p63
+.text
+ .align 16
+ .global ffi_call_unix
+ .proc ffi_call_unix
+ffi_call_unix:
+ .prologue
+ .save ar.pfs,r38 /* loc0 */
+ alloc loc0=ar.pfs,6,6,8,0
+ .save rp,loc1
+ mov loc1=b0;
+ .vframe loc5
+ mov loc5=sp;
+ .body
+ sub sp=sp,bytes
+ mov loc4=r1 /* Save gp */
+ ld8 r8=[callback],8 /* code address of callback */
+ ;;
+ mov out0=sp
+ mov out1=ecifp
+ mov out2=bytes
+ ld8 r1=[callback] /* Set up gp for callback. Unnecessary? */
+ mov b6=r8
+ ;;
+ br.call.sptk.many b0 = b6 /* call ffi_prep_args */
+ cmp.eq p6,p0=0,r8 /* r8 nonzero ==> need fp regs */
+ ;;
+(p6) add loc2=32+8*FLOAT_SZ,sp
+(p6) br.cond.dptk.many fp_done
+ ;; /* Quiets warning; needed? */
+ add loc2=32,sp
+ add loc3=32+FLOAT_SZ,sp
+ ;;
+ ldfd f8=[loc2],2*FLOAT_SZ
+ ldfd f9=[loc3],2*FLOAT_SZ
+ ;;
+ ldfd f10=[loc2],2*FLOAT_SZ
+ ldfd f11=[loc3],2*FLOAT_SZ
+ ;;
+ ldfd f12=[loc2],2*FLOAT_SZ
+ ldfd f13=[loc3],2*FLOAT_SZ
+ ;;
+ ldfd f14=[loc2],2*FLOAT_SZ
+ ldfd f15=[loc3]
+fp_done:
+ add r9=16,sp /* Pointer to r8_contents */
+ /* loc2 points at first integer register value. */
+ add loc3=8,loc2
+ ;;
+ ld8 r8=[r9] /* Just in case we return large struct */
+ ld8 out0=[loc2],16
+ ld8 out1=[loc3],16
+ ;;
+ ld8 out2=[loc2],16
+ ld8 out3=[loc3],16
+ ;;
+ ld8 out4=[loc2],16
+ ld8 out5=[loc3],16
+ ;;
+ ld8 out6=[loc2]
+ ld8 out7=[loc3]
+ /* Set sp to 16 bytes below the first stack parameter. This */
+ /* is the value currently in loc2. */
+ mov sp=loc2
+
+ ld8 r8=[fn],8
+ ;;
+ ld8 r1=[fn] /* Set up gp */
+ mov b6=r8;;
+ br.call.sptk.many b0 = b6 /* call fn */
+
+ /* Handle return value. */
+ cmp.eq p6,p0=0,raddr
+ cmp.eq p7,p0=FFI_TYPE_INT,flags
+ cmp.eq p10,p0=FFI_IS_SMALL_STRUCT2,flags
+ cmp.eq p11,p0=FFI_IS_SMALL_STRUCT3,flags
+ cmp.eq p12,p0=FFI_IS_SMALL_STRUCT4,flags
+ ;;
+(p6) br.cond.dpnt.few done /* Dont copy ret values if raddr = 0 */
+(p7) br.cond.dptk.few copy1
+(p10) br.cond.dpnt.few copy2
+(p11) br.cond.dpnt.few copy3
+(p12) br.cond.dpnt.few copy4
+ cmp.eq p8,p0=FFI_TYPE_FLOAT,flags
+ cmp.eq p9,p0=FFI_TYPE_DOUBLE,flags
+ tbit.nz p6,p0=flags,FLOAT_FP_AGGREGATE_BIT
+ tbit.nz p7,p0=flags,DOUBLE_FP_AGGREGATE_BIT
+ ;;
+(p8) stfs [raddr]=f8
+(p9) stfd [raddr]=f8
+ ;;
+ .label_state 1
+(p6) br.cond.dpnt.few handle_float_hfa
+(p7) br.cond.dpnt.few handle_double_hfa
+ br done
+
+copy4:
+ add loc3=24,raddr
+ ;;
+ st8 [loc3]=r11
+copy3:
+ add loc3=16,raddr
+ ;;
+ st8 [loc3]=r10
+copy2:
+ add loc3=8,raddr
+ ;;
+ st8 [loc3]=r9
+copy1:
+ st8 [raddr]=r8
+ /* In the big struct case, raddr was passed as an argument. */
+ /* In the void case there was nothing to do. */
+
+done:
+ mov r1=loc4 /* Restore gp */
+ mov ar.pfs = loc0
+ mov b0 = loc1
+ .restore sp
+ mov sp = loc5
+ br.ret.sptk.many b0
+
+handle_double_hfa:
+ .body
+ .copy_state 1
+ /* Homogeneous floating point array of doubles is returned in */
+ /* registers f8-f15. Save one at a time to return area. */
+ and flags=0xf,flags /* Retrieve size */
+ ;;
+ cmp.eq p6,p0=2,flags
+ cmp.eq p7,p0=3,flags
+ cmp.eq p8,p0=4,flags
+ cmp.eq p9,p0=5,flags
+ cmp.eq p10,p0=6,flags
+ cmp.eq p11,p0=7,flags
+ cmp.eq p12,p0=8,flags
+ ;;
+(p6) br.cond.dptk.few dhfa2
+(p7) br.cond.dptk.few dhfa3
+(p8) br.cond.dptk.few dhfa4
+(p9) br.cond.dptk.few dhfa5
+(p10) br.cond.dptk.few dhfa6
+(p11) br.cond.dptk.few dhfa7
+dhfa8: add loc3=7*8,raddr
+ ;;
+ stfd [loc3]=f15
+dhfa7: add loc3=6*8,raddr
+ ;;
+ stfd [loc3]=f14
+dhfa6: add loc3=5*8,raddr
+ ;;
+ stfd [loc3]=f13
+dhfa5: add loc3=4*8,raddr
+ ;;
+ stfd [loc3]=f12
+dhfa4: add loc3=3*8,raddr
+ ;;
+ stfd [loc3]=f11
+dhfa3: add loc3=2*8,raddr
+ ;;
+ stfd [loc3]=f10
+dhfa2: add loc3=1*8,raddr
+ ;;
+ stfd [loc3]=f9
+ stfd [raddr]=f8
+ br done
+
+handle_float_hfa:
+ /* Homogeneous floating point array of floats is returned in */
+ /* registers f8-f15. Save one at a time to return area. */
+ and flags=0xf,flags /* Retrieve size */
+ ;;
+ cmp.eq p6,p0=2,flags
+ cmp.eq p7,p0=3,flags
+ cmp.eq p8,p0=4,flags
+ cmp.eq p9,p0=5,flags
+ cmp.eq p10,p0=6,flags
+ cmp.eq p11,p0=7,flags
+ cmp.eq p12,p0=8,flags
+ ;;
+(p6) br.cond.dptk.few shfa2
+(p7) br.cond.dptk.few shfa3
+(p8) br.cond.dptk.few shfa4
+(p9) br.cond.dptk.few shfa5
+(p10) br.cond.dptk.few shfa6
+(p11) br.cond.dptk.few shfa7
+shfa8: add loc3=7*4,raddr
+ ;;
+ stfd [loc3]=f15
+shfa7: add loc3=6*4,raddr
+ ;;
+ stfd [loc3]=f14
+shfa6: add loc3=5*4,raddr
+ ;;
+ stfd [loc3]=f13
+shfa5: add loc3=4*4,raddr
+ ;;
+ stfd [loc3]=f12
+shfa4: add loc3=3*4,raddr
+ ;;
+ stfd [loc3]=f11
+shfa3: add loc3=2*4,raddr
+ ;;
+ stfd [loc3]=f10
+shfa2: add loc3=1*4,raddr
+ ;;
+ stfd [loc3]=f9
+ stfd [raddr]=f8
+ br done
+
+ .endp ffi_call_unix
+
+
+ .pred.safe_across_calls p1-p5,p16-p63
+.text
+ .align 16
+ .global ffi_closure_UNIX
+ .proc ffi_closure_UNIX
+ffi_closure_UNIX:
+ .prologue
+ .save ar.pfs,r40 /* loc0 */
+ alloc loc0=ar.pfs,8,3,2,0
+ .save rp,loc1
+ mov loc1=b0
+ .vframe loc2
+ mov loc2=sp
+ /* Retrieve closure pointer and real gp. */
+ mov out0=gp
+ add gp=16,gp
+ ;;
+ ld8 gp=[gp]
+ /* Reserve a structia64_args on the stack such that arguments */
+ /* past the first 8 are automatically placed in the right */
+ /* slot. Note that when we start the sp points at 2 8-byte */
+ /* scratch words, followed by the extra arguments. */
+# define BASIC_ARGS_SZ (8*FLOAT_SZ+8*8+2*8)
+# define FIRST_FP_OFFSET (4*8)
+ add r14=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET),sp
+ add r15=-(BASIC_ARGS_SZ-FIRST_FP_OFFSET-FLOAT_SZ),sp
+ add sp=-BASIC_ARGS_SZ,sp
+ /* r14 points to fp_regs[0], r15 points to fp_regs[1] */
+ ;;
+ stfd [r14]=f8,2*FLOAT_SZ
+ stfd [r15]=f9,2*FLOAT_SZ
+ ;;
+ stfd [r14]=f10,2*FLOAT_SZ
+ stfd [r15]=f11,2*FLOAT_SZ
+ ;;
+ stfd [r14]=f12,2*FLOAT_SZ
+ stfd [r15]=f13,2*FLOAT_SZ
+ ;;
+ stfd [r14]=f14,FLOAT_SZ+8
+ stfd [r15]=f15,2*8
+ ;;
+ /* r14 points to first parameter register area, r15 to second. */
+ st8 [r14]=in0,2*8
+ st8 [r15]=in1,2*8
+ ;;
+ st8 [r14]=in2,2*8
+ st8 [r15]=in3,2*8
+ ;;
+ st8 [r14]=in4,2*8
+ st8 [r15]=in5,2*8
+ ;;
+ st8 [r14]=in6,2*8
+ st8 [r15]=in7,2*8
+ /* Call ffi_closure_UNIX_inner */
+ mov out1=sp
+ br.call.sptk.many b0=ffi_closure_UNIX_inner
+ ;;
+ mov b0=loc1
+ mov ar.pfs=loc0
+ .restore sp
+ mov sp=loc2
+ br.ret.sptk.many b0
+ .endp ffi_closure_UNIX
+
+