From 95a89bf364c80593fcf146aeb5e0569b26c7f6b3 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 19 Mar 1996 19:52:47 +0000 Subject: [PATCH] Wed Feb 14 00:21:17 1996 David Mosberger-Tang * 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 | 112 +++++++++++++++++++++++ sysdeps/alpha/divrem.S | 169 +++++++++++++++++++++++++++++++++++ sysdeps/alpha/htonl.S | 42 +++++++++ sysdeps/alpha/htons.S | 36 ++++++++ sysdeps/alpha/machine-gmon.h | 25 ++++++ sysdeps/alpha/ntohl.s | 2 + sysdeps/alpha/ntohs.s | 2 + sysdeps/alpha/strlen.S | 75 ++++++++++++++++ 8 files changed, 463 insertions(+) create mode 100644 sysdeps/alpha/_mcount.S create mode 100644 sysdeps/alpha/divrem.S create mode 100644 sysdeps/alpha/htonl.S create mode 100644 sysdeps/alpha/htons.S create mode 100644 sysdeps/alpha/machine-gmon.h create mode 100644 sysdeps/alpha/ntohl.s create mode 100644 sysdeps/alpha/ntohs.s create mode 100644 sysdeps/alpha/strlen.S diff --git a/sysdeps/alpha/_mcount.S b/sysdeps/alpha/_mcount.S new file mode 100644 index 0000000000..2d6e2ed532 --- /dev/null +++ b/sysdeps/alpha/_mcount.S @@ -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 +#ifdef __linux__ +# include +#else +# include +#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 index 0000000000..e6293bf355 --- /dev/null +++ b/sysdeps/alpha/divrem.S @@ -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 +# include +# include +#else +# include +# include +#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 index 0000000000..d0bf7e1718 --- /dev/null +++ b/sysdeps/alpha/htonl.S @@ -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 +#ifdef __linux__ +# include +#else +#include +#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 index 0000000000..6e18c7c441 --- /dev/null +++ b/sysdeps/alpha/htons.S @@ -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 +#ifdef __linux__ +# include +#else +#include +#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 index 0000000000..a551e9f8b1 --- /dev/null +++ b/sysdeps/alpha/machine-gmon.h @@ -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 index 0000000000..6a99a01dc4 --- /dev/null +++ b/sysdeps/alpha/ntohl.s @@ -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 index 0000000000..69992a894c --- /dev/null +++ b/sysdeps/alpha/ntohs.s @@ -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 index 0000000000..7e6a61be8c --- /dev/null +++ b/sysdeps/alpha/strlen.S @@ -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 +#ifdef __linux__ +# include +#else +#include +#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