Wed Feb 14 00:21:17 1996 David Mosberger-Tang <davidm@azstarnet.com>
authorRoland McGrath <roland@gnu.org>
Tue, 19 Mar 1996 19:52:47 +0000 (19:52 +0000)
committerRoland McGrath <roland@gnu.org>
Tue, 19 Mar 1996 19:52:47 +0000 (19:52 +0000)
* sysdeps/alpha/divrem.S, sysdeps/alpha/htonl.S,
sysdeps/alpha/htons.S, sysdeps/alpha/machine-gmon.h,
sysdeps/alpha/_mcount.S, sysdeps/alpha/ntohl.s, sysdeps/alpha/ntohs.s,
sysdeps/alpha/strlen.S: New files.

sysdeps/alpha/_mcount.S [new file with mode: 0644]
sysdeps/alpha/divrem.S [new file with mode: 0644]
sysdeps/alpha/htonl.S [new file with mode: 0644]
sysdeps/alpha/htons.S [new file with mode: 0644]
sysdeps/alpha/machine-gmon.h [new file with mode: 0644]
sysdeps/alpha/ntohl.s [new file with mode: 0644]
sysdeps/alpha/ntohs.s [new file with mode: 0644]
sysdeps/alpha/strlen.S [new file with mode: 0644]

diff --git a/sysdeps/alpha/_mcount.S b/sysdeps/alpha/_mcount.S
new file mode 100644 (file)
index 0000000..2d6e2ed
--- /dev/null
@@ -0,0 +1,112 @@
+/* Machine-specific calling sequence for `mcount' profiling function.  alpha
+Copyright (C) 1995 Free Software Foundation, Inc.
+Contributed by David Mosberger (davidm@cs.arizona.edu).
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* Assembly stub to invoke _mcount().  Compiler generated code calls
+this stub after executing a function's prologue and without saving any
+registers.  It is therefore necessary to preserve a0..a5 as they may
+contain function arguments.  To work correctly with frame- less
+functions, it is also necessary to preserve ra.  Finally, division
+routines are invoked with a special calling convention and the
+compiler treats those calls as if they were instructions.  In
+particular, it doesn't save any of the temporary registers (caller
+saved registers).  It is therefore necessary to preserve all
+caller-saved registers as well
+Upon entering _mcount, register $at holds the return address and ra
+holds the return address of the function's caller (selfpc and frompc,
+respectively in gmon.c language...). */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+# include <regdef.h>
+#endif
+
+#undef ret     /* discard `ret' as defined in sysdep.h */
+
+       .set    noat
+       .set    noreorder
+
+ENTRY(_mcount)
+       subq     sp, 0xb0, sp
+       stq      a0, 0x00(sp)
+       mov      ra, a0         # a0 = caller-pc
+       stq      a1, 0x08(sp)
+       mov     $at, a1         # a1 = self-pc
+       stq     $at, 0x10(sp)
+
+       stq      a2, 0x18(sp)
+       stq      a3, 0x20(sp)
+       stq      a4, 0x28(sp)
+       stq      a5, 0x30(sp)
+       stq      ra, 0x38(sp)
+       stq      gp, 0x40(sp)
+
+       br      gp, 1f
+1:     ldgp    gp, 0(gp)
+
+       stq      t0, 0x48(sp)
+       stq      t1, 0x50(sp)
+       stq      t2, 0x58(sp)
+       stq      t3, 0x60(sp)
+       stq      t4, 0x68(sp)
+       stq      t5, 0x70(sp)
+       stq      t6, 0x78(sp)
+
+       lda      pv, __mcount
+
+       stq      t7, 0x80(sp)
+       stq      t8, 0x88(sp)
+       stq      t9, 0x90(sp)
+       stq     t10, 0x98(sp)
+       stq     t11, 0xa0(sp)
+       stq      v0, 0xa8(sp)
+
+       jsr     ra, (pv), __mcount
+
+       ldq      a0, 0x00(sp)
+       ldq      a1, 0x08(sp)
+       ldq     $at, 0x10(sp)   # restore self-pc
+       ldq      a2, 0x18(sp)
+       ldq      a3, 0x20(sp)
+       ldq      a4, 0x28(sp)
+       ldq      a5, 0x30(sp)
+       ldq      ra, 0x38(sp)
+       ldq      gp, 0x40(sp)
+       mov     $at, pv         # make pv point to return address
+       ldq      t0, 0x48(sp)   # this is important under OSF/1 to
+       ldq      t1, 0x50(sp)   # ensure that the code that we return
+       ldq      t2, 0x58(sp)   # can correctly compute its gp
+       ldq      t3, 0x60(sp)
+       ldq      t4, 0x68(sp)
+       ldq      t5, 0x70(sp)
+       ldq      t6, 0x78(sp)
+       ldq      t7, 0x80(sp)
+       ldq      t8, 0x88(sp)
+       ldq      t9, 0x90(sp)
+       ldq     t10, 0x98(sp)
+       ldq     t11, 0xa0(sp)
+       ldq      v0, 0xa8(sp)
+
+       addq    sp, 0xb0, sp
+       ret     zero,($at),1
+
+       .end _mcount
diff --git a/sysdeps/alpha/divrem.S b/sysdeps/alpha/divrem.S
new file mode 100644 (file)
index 0000000..e6293bf
--- /dev/null
@@ -0,0 +1,169 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* The current Alpha chips don't provide hardware for integer
+division.  The C compiler expects the functions
+
+       __divqu: 64-bit unsigned long divide
+       __remqu: 64-bit unsigned long remainder
+       __divqs/__remqs: signed 64-bit
+       __divlu/__remlu: unsigned 32-bit
+       __divls/__remls: signed 32-bit
+
+These are not normal C functions: instead of the normal calling
+sequence, these expect their arguments in registers t10 and t11, and
+return the result in t12 (aka pv). Registers AT and v0 may be
+clobbered (assembly temporary), anything else must be saved.  */
+
+#ifdef __linux__
+# include <alpha/regdef.h>
+# include <asm/gentrap.h>
+# include <asm/pal.h>
+#else
+# include <regdef.h>
+# include <machine/pal.h>
+#endif
+
+#ifdef DEBUG
+# define arg1          a0
+# define arg2          a1
+# define result                v0
+# define mask          t0
+# define tmp0          t1
+# define tmp1          t2
+# define sign          t3
+# define retaddr       ra
+#else
+# define arg1          t10
+# define arg2          t11
+# define result                t12
+# define mask          v0
+# define tmp0          t0
+# define tmp1          t1
+# define sign          t2
+# define retaddr       t9
+#endif
+
+# define divisor       arg2
+#if IS_REM
+# define dividend      result
+# define quotient      arg1
+# define GETDIVIDEND   bis arg1,zero,dividend
+#else
+# define dividend      arg1
+# define quotient      result
+# define GETDIVIDEND
+#endif
+
+#if SIZE == 8
+# define LONGIFYarg1   GETDIVIDEND
+# define LONGIFYarg2
+#else
+# if SIGNED
+#  define LONGIFYarg1  addl    arg1,zero,dividend
+#  define LONGIFYarg2  addl    arg2,zero,divisor
+# else
+#  define LONGIFYarg1  zapnot  arg1,0x0f,dividend
+#  define LONGIFYarg2  zapnot  arg2,0x0f,divisor
+# endif
+#endif
+
+#if SIGNED
+# define SETSIGN(sign,reg,tmp) subq zero,reg,tmp; cmovlt sign,tmp,reg
+# if IS_REM
+#  define GETSIGN(x,y,s)       bis     x,zero,s
+# else
+#  define GETSIGN(x,y,s)       xor     x,y,s
+# endif
+#else
+# define SETSIGN(sign,reg,tmp)
+# define GETSIGN(x,y,s)
+#endif
+
+       .set noreorder
+       .set noat
+
+       .ent FUNC_NAME
+       .globl FUNC_NAME
+
+       .align 5
+FUNC_NAME:
+#      define FRAME_SIZE       0x30
+       .frame  sp,FRAME_SIZE,ra,0
+       lda     sp,-FRAME_SIZE(sp)
+       .prologue 1
+       stq     arg1,0x00(sp)
+       LONGIFYarg1
+       stq     arg2,0x08(sp)
+       LONGIFYarg2
+       stq     mask,0x10(sp)
+       bis     zero,1,mask
+       stq     tmp0,0x18(sp)
+       bis     zero,zero,quotient
+       stq     tmp1,0x20(sp)
+       beq     divisor,divbyzero
+       stq     sign,0x28(sp)
+       GETSIGN(dividend,divisor,sign)
+#if SIGNED
+       subq    zero,dividend,tmp0
+       subq    zero,divisor,tmp1
+       cmovlt  dividend,tmp0,dividend
+       cmovlt  divisor,tmp1,divisor
+#endif
+       /*
+        * Shift divisor left until either bit 63 is set or until it
+        * is at least as big as the dividend:
+        */
+       .align  3
+1:     cmpule  dividend,divisor,AT
+       blt     divisor,2f
+       blbs    AT,2f
+       addq    mask,mask,mask
+       addq    divisor,divisor,divisor
+       br      1b
+
+       .align  3
+2:     addq    mask,quotient,tmp0
+       cmpule  divisor,dividend,AT
+       subq    dividend,divisor,tmp1
+       srl     divisor,1,divisor
+       srl     mask,1,mask
+       cmovlbs AT,tmp0,quotient
+       cmovlbs AT,tmp1,dividend
+       bne     mask,2b
+
+       ldq     arg1,0x00(sp)
+       SETSIGN(sign,result,tmp0)
+done:  ldq     arg2,0x08(sp)
+       ldq     mask,0x10(sp)
+       ldq     tmp0,0x18(sp)
+       ldq     tmp1,0x20(sp)
+       ldq     sign,0x28(sp)
+       lda     sp,FRAME_SIZE(sp)
+       ret     zero,(retaddr),0
+
+divbyzero:
+       lda     a0,GEN_INTDIV(zero)
+       call_pal PAL_gentrap
+       bis     zero,zero,result        /* if trap returns, return 0 */
+       ldq     arg1,0x00(sp)
+       br      done
+
+       .end FUNC_NAME
diff --git a/sysdeps/alpha/htonl.S b/sysdeps/alpha/htonl.S
new file mode 100644 (file)
index 0000000..d0bf7e1
--- /dev/null
@@ -0,0 +1,42 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+#include <regdef.h>
+#endif
+
+ENTRY(__htonl)
+       extlh   a0,5,t1         # t1 = dd000000
+       zap     a0,0xfd,t2      # t2 = 0000cc00
+       sll     t2,5,t2         # t2 = 00198000
+       s8addl  t2,t1,t1        # t1 = ddcc0000
+       zap     a0,0xfb,t2      # t2 = 00bb0000
+       srl     t2,8,t2         # t2 = 0000bb00
+       extbl   a0,3,v0         # v0 = 000000aa
+       or      t1,v0,v0        # v0 = ddcc00aa
+       or      t2,v0,v0        # v0 = ddccbbaa
+       ret
+
+       .end    __htonl
+
+strong_alias_asm(__htonl, __ntohl)
+weak_alias(__htonl, htonl)
+weak_alias(__htonl, ntohl)
diff --git a/sysdeps/alpha/htons.S b/sysdeps/alpha/htons.S
new file mode 100644 (file)
index 0000000..6e18c7c
--- /dev/null
@@ -0,0 +1,36 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+#include <regdef.h>
+#endif
+
+ENTRY(__htons)
+       extwh   a0,7,t1         # t1 = bb00
+       extbl   a0,1,v0         # v0 = 00aa
+       bis     v0,t1,v0        # v0 = bbaa
+       ret
+
+       .end    __htons
+
+strong_alias_asm(__htons, __ntohs)
+weak_alias(__htons, htons)
+weak_alias(__htons, ntohs)
diff --git a/sysdeps/alpha/machine-gmon.h b/sysdeps/alpha/machine-gmon.h
new file mode 100644 (file)
index 0000000..a551e9f
--- /dev/null
@@ -0,0 +1,25 @@
+/* Machine-specific calling sequence for `mcount' profiling function.  alpha
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#define _MCOUNT_DECL void __mcount
+
+/* Call __mcount with our the return PC for our caller, and the return
+   PC our caller will return to.  Empty since we use an assembly stub
+   instead. */
+#define MCOUNT
diff --git a/sysdeps/alpha/ntohl.s b/sysdeps/alpha/ntohl.s
new file mode 100644 (file)
index 0000000..6a99a01
--- /dev/null
@@ -0,0 +1,2 @@
+/* This is a dummy to avoid including the generic version.  htonl and
+ntohl are identical and htonl.S defines appropriate aliases.  */
diff --git a/sysdeps/alpha/ntohs.s b/sysdeps/alpha/ntohs.s
new file mode 100644 (file)
index 0000000..69992a8
--- /dev/null
@@ -0,0 +1,2 @@
+/* This is a dummy to avoid including the generic version.  htons and
+ntohs are identical and htons.S defines appropriate aliases.  */
diff --git a/sysdeps/alpha/strlen.S b/sysdeps/alpha/strlen.S
new file mode 100644 (file)
index 0000000..7e6a61b
--- /dev/null
@@ -0,0 +1,75 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   Contributed by David Mosberger (davidm@cs.arizona.edu).
+
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* Finds length of a 0-terminated string.  Optimized for the Alpha
+architecture:
+
+      - memory accessed as aligned quadwords only
+      - uses bcmpge to compare 8 bytes in parallel
+      - does binary search to find 0 byte in last
+        quadword (HAKMEM needed 12 instructions to
+        do this instead of the 9 instructions that
+        binary search needs).  */
+
+#include <sysdep.h>
+#ifdef __linux__
+# include <alpha/regdef.h>
+#else
+#include <regdef.h>
+#endif
+
+        .set noreorder
+        .set noat
+
+ENTRY(strlen)
+        ldq_u   t0, 0(a0)       # load first quadword (a0 may be misaligned)
+        lda     t1, -1(zero)
+        insqh   t1, a0, t1
+        andnot  a0, 7, v0
+        or      t1, t0, t0
+        cmpbge  zero, t0, t1    # t1 <- bitmask: bit i == 1 <==> i-th byte == 0
+        bne     t1, found
+
+loop:   ldq     t0, 8(v0)
+        addq    v0, 8, v0       # addr += 8
+        nop                     # helps dual issue last two insns
+        cmpbge  zero, t0, t1
+        beq     t1, loop
+
+found:  blbs    t1, done        # make aligned case fast
+        negq    t1, t2
+        and     t1, t2, t1
+
+        and     t1, 0x0f, t0
+        addq    v0, 4, t2
+        cmoveq  t0, t2, v0
+
+        and     t1, 0x33, t0
+        addq    v0, 2, t2
+        cmoveq  t0, t2, v0
+
+        and     t1, 0x55, t0
+        addq    v0, 1, t2
+        cmoveq  t0, t2, v0
+
+done:   subq    v0, a0, v0
+        ret
+
+        .end    strlen