diff options
Diffstat (limited to 'sysdeps/alpha')
-rw-r--r-- | sysdeps/alpha/Makefile | 75 | ||||
-rw-r--r-- | sysdeps/alpha/__longjmp.c | 20 | ||||
-rw-r--r-- | sysdeps/alpha/__math.h | 20 | ||||
-rw-r--r-- | sysdeps/alpha/_mcount.S | 112 | ||||
-rw-r--r-- | sysdeps/alpha/bb_init_func.S | 85 | ||||
-rw-r--r-- | sysdeps/alpha/divl.S | 61 | ||||
-rw-r--r-- | sysdeps/alpha/divlu.S | 61 | ||||
-rw-r--r-- | sysdeps/alpha/divq.S | 58 | ||||
-rw-r--r-- | sysdeps/alpha/divqu.S | 64 | ||||
-rw-r--r-- | sysdeps/alpha/divrem.S | 169 | ||||
-rw-r--r-- | sysdeps/alpha/divrem.m4 | 51 | ||||
-rw-r--r-- | sysdeps/alpha/ffs.S | 71 | ||||
-rw-r--r-- | sysdeps/alpha/htonl.S | 42 | ||||
-rw-r--r-- | sysdeps/alpha/htons.S | 36 | ||||
-rw-r--r-- | sysdeps/alpha/machine-gmon.h (renamed from sysdeps/alpha/fabs.c) | 17 | ||||
-rw-r--r-- | sysdeps/alpha/macros.m4 | 34 | ||||
-rw-r--r-- | sysdeps/alpha/ntohl.s | 2 | ||||
-rw-r--r-- | sysdeps/alpha/ntohs.s | 2 | ||||
-rw-r--r-- | sysdeps/alpha/reml.S | 64 | ||||
-rw-r--r-- | sysdeps/alpha/remlu.S | 64 | ||||
-rw-r--r-- | sysdeps/alpha/remq.S | 61 | ||||
-rw-r--r-- | sysdeps/alpha/remqu.S | 67 | ||||
-rw-r--r-- | sysdeps/alpha/setjmp.S | 4 | ||||
-rw-r--r-- | sysdeps/alpha/setjmp_aux.c | 2 | ||||
-rw-r--r-- | sysdeps/alpha/strlen.S | 75 | ||||
-rw-r--r-- | sysdeps/alpha/strlen.c | 55 |
26 files changed, 681 insertions, 691 deletions
diff --git a/sysdeps/alpha/Makefile b/sysdeps/alpha/Makefile index 8573ca811c..4bb1f299e1 100644 --- a/sysdeps/alpha/Makefile +++ b/sysdeps/alpha/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. +# Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc. # Contributed by Brendan Kehoe (brendan@zen.org). # The GNU C Library is free software; you can redistribute it and/or @@ -16,79 +16,16 @@ # not, write to the Free Software Foundation, Inc., 675 Mass Ave, # Cambridge, MA 02139, USA. +ifeq ($(subdir),gmon) +sysdep_routines := bb_init_func _mcount +endif + ifeq ($(subdir),setjmp) sysdep_routines := $(sysdep_routines) setjmp_aux endif ifeq ($(subdir),gnulib) -routines = $(divrem) +routines = $(divrem) endif # gnulib -# We distribute these files, even though they are generated, -# so as to avoid the need for a functioning m4 to build the library. divrem := divl divlu divq divqu reml remlu remq remqu - -+divrem-NAME-divl := divl -+divrem-NAME-divlu := divlu -+divrem-NAME-divq := divq -+divrem-NAME-divqu := divqu -+divrem-NAME-reml := reml -+divrem-NAME-remlu := remlu -+divrem-NAME-remq := remq -+divrem-NAME-remqu := remqu -+divrem-NAME = $(+divrem-NAME-$(basename $(notdir $@))) - -+divrem-OP-divl := divl -+divrem-OP-divlu := divlu -+divrem-OP-divq := divq -+divrem-OP-divqu := divqu -+divrem-OP-reml := reml -+divrem-OP-remlu := remlu -+divrem-OP-remq := remq -+divrem-OP-remqu := remqu -+divrem-BASEOP-divl := div -+divrem-BASEOP-divlu := div -+divrem-BASEOP-divq := div -+divrem-BASEOP-divqu := div -+divrem-BASEOP-reml := rem -+divrem-BASEOP-remlu := rem -+divrem-BASEOP-remq := rem -+divrem-BASEOP-remqu := rem -+divrem-S-divl := true -+divrem-S-divlu := false -+divrem-S-divq := true -+divrem-S-divqu := false -+divrem-S-reml := true -+divrem-S-remlu := false -+divrem-S-remq := true -+divrem-S-remqu := false -+divrem-SIZE-divl := l -+divrem-SIZE-divlu := l -+divrem-SIZE-divq := q -+divrem-SIZE-divqu := q -+divrem-SIZE-reml := l -+divrem-SIZE-remlu := l -+divrem-SIZE-remq := q -+divrem-SIZE-remqu := q -+divrem-MODE-divl := l -+divrem-MODE-divlu := lu -+divrem-MODE-divq := q -+divrem-MODE-divqu := qu -+divrem-MODE-reml := l -+divrem-MODE-remlu := lu -+divrem-MODE-remq := q -+divrem-MODE-remqu := qu - -$(divrem:%=$(sysdep_dir)/alpha/%.S): $(sysdep_dir)/alpha/divrem.m4 $(sysdep_dir)/alpha/DEFS.h $(sysdep_dir)/alpha/macros.m4 - (echo "define(OP,\`$(+divrem-NAME)')\ - define(BASEOP,\`$(+divrem-BASEOP-$(+divrem-NAME))')\ - define(MODE,\`$(+divrem-MODE-$(+divrem-NAME))')\ - define(SIZE,\`$(+divrem-SIZE-$(+divrem-NAME))')\ - define(SIGNED,\`$(+divrem-S-$(+divrem-NAME))')\ - define(SYSDEP_DIR, \`$(sysdep_dir)/alpha')\ - /* This file is generated from divrem.m4; DO NOT EDIT! */"; \ - cat $<) | $(M4) > $@-tmp -# Make it unwritable so noone will edit it by mistake. - -chmod a-w $@-tmp - mv -f $@-tmp $@ - test ! -d CVS || cvs commit -m'Regenerated from $<' $@ diff --git a/sysdeps/alpha/__longjmp.c b/sysdeps/alpha/__longjmp.c index f3f35eec9c..65b6804bd3 100644 --- a/sysdeps/alpha/__longjmp.c +++ b/sysdeps/alpha/__longjmp.c @@ -38,6 +38,8 @@ register double void __longjmp (__jmp_buf env, int val) { + register long int retval asm ("$0"); + /* Restore the integer registers. */ r9 = env[0].__9; r10 = env[0].__10; @@ -73,18 +75,18 @@ __longjmp (__jmp_buf env, int val) precisely the FP and SP the desired environment needs, we must avoid the compiler doing anything with the stack. */ + + asm volatile + ("cmoveq %1, 1, %0\n\t" /* $0 = val ?: 1; */ + "ret $31, (%2), 1" /* return $0 */ + : "=r" (retval) + /* The "0" constraint should force VAL into $0. */ + : "0" (val), "r" (retpc)); + while (1) { /* The loop is just to avoid `volatile function does return' warnings. The instruction will only be executed once. */ - - register long int retval asm ("$0"); - - asm volatile - ("cmoveq %1, 1, %0\n\t" /* $0 = val ?: 1; */ - "ret $31, (%2), 1" /* return $0 */ - : "=r" (retval) - /* The "0" constraint should force VAL into $0. */ - : "0" (val), "r" (retpc)); + asm volatile (""); } } diff --git a/sysdeps/alpha/__math.h b/sysdeps/alpha/__math.h index 5461fca2ac..9aea9d7097 100644 --- a/sysdeps/alpha/__math.h +++ b/sysdeps/alpha/__math.h @@ -1,5 +1,7 @@ -/* Copyright (C) 1992 Free Software Foundation, Inc. +/* Inline math functions for Alpha. +Copyright (C) 1996 Free Software Foundation, Inc. This file is part of the GNU C Library. +Contributed by David Mosberger-Tang. 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 @@ -32,4 +34,20 @@ fabs (double __x) return __x; } +extern __inline double +atan (double __x) +{ + extern double __atan2 (double, double); + return __atan2 (__x, 1.0); +} + +#ifdef __USE_MISC +extern __inline double +cabs (struct __cabs_complex __z) +{ + extern double __hypot (double, double); + return __hypot(__z.__x, __z.__y); +} +#endif + #endif 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 <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/bb_init_func.S b/sysdeps/alpha/bb_init_func.S new file mode 100644 index 0000000000..9bf985ccc0 --- /dev/null +++ b/sysdeps/alpha/bb_init_func.S @@ -0,0 +1,85 @@ +/* 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. */ + +/* __bb_init_func is invoked at the beginning of each function, before +any registers have been saved. It is therefore safe to use any +caller-saved (call-used) registers (except for argument registers +a1-a5). */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +# include <regdef.h> +#endif + +/* + * These offsets should match with "struct bb" declared in gcc/libgcc2.c. + */ +#define ZERO_WORD 0x00 +#define NEXT 0x20 + + .set noat + .set noreorder + +ENTRY(__bb_init_func) + ldq t0, ZERO_WORD(a0) /* t0 <- blocks->zero_word */ + beq t0, init /* not initialized yet -> */ + ret + + +init: subq sp, 0x38, sp + stq pv, 0x30(sp) + br pv, 1f +1: ldgp gp, 0(pv) + + lda t1, __bb_head + lda t3, _gmonparam + ldq t2, 0(t1) + ldl t3, 0(t3) /* t3 = _gmonparam.state */ + ldi t0, 1 + stq t0, ZERO_WORD(a0) /* blocks->zero_word = 1 */ + stq t2, NEXT(a0) /* blocks->next = __bb_head */ + stq a0, 0(t1) + bne t2, leave + beq t3, leave /* t3 == GMON_PROF_ON? yes -> */ + + /* also need to initialize destructor: */ + stq ra, 0x00(sp) + lda a0, __bb_exit_func + stq a1, 0x08(sp) + lda pv, atexit + stq a2, 0x10(sp) + stq a3, 0x18(sp) + stq a4, 0x20(sp) + stq a5, 0x28(sp) + jsr ra, (pv), atexit + ldq ra, 0x00(sp) + ldq a1, 0x08(sp) + ldq a2, 0x10(sp) + ldq a3, 0x18(sp) + ldq a4, 0x20(sp) + ldq a5, 0x28(sp) + +leave: ldq pv, 0x30(sp) + addq sp, 0x38, sp + ret + + .end __bb_init_func diff --git a/sysdeps/alpha/divl.S b/sysdeps/alpha/divl.S index 5c94362cf5..7dbb5048c7 100644 --- a/sysdeps/alpha/divl.S +++ b/sysdeps/alpha/divl.S @@ -1,57 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 4 +#define SIGNED 1 +#define FUNC_NAME __divl - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divl) - /* First set up the dividend. */ - sextl t10, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - sextl t11, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divl) +#include "divrem.S" diff --git a/sysdeps/alpha/divlu.S b/sysdeps/alpha/divlu.S index 3a7589d355..9cc71da308 100644 --- a/sysdeps/alpha/divlu.S +++ b/sysdeps/alpha/divlu.S @@ -1,57 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 4 +#define SIGNED 0 +#define FUNC_NAME __divlu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divlu) - /* First set up the dividend. */ - zapnot t10, 0xf, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - zapnot t11, 0xf, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divlu) +#include "divrem.S" diff --git a/sysdeps/alpha/divq.S b/sysdeps/alpha/divq.S index 730a338f63..f7af8d62a3 100644 --- a/sysdeps/alpha/divq.S +++ b/sysdeps/alpha/divq.S @@ -1,54 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 8 +#define SIGNED 1 +#define FUNC_NAME __divq - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divq) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divq) +#include "divrem.S" diff --git a/sysdeps/alpha/divqu.S b/sysdeps/alpha/divqu.S index 7614742440..faf2932cb5 100644 --- a/sysdeps/alpha/divqu.S +++ b/sysdeps/alpha/divqu.S @@ -1,60 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 0 +#define SIZE 8 +#define SIGNED 0 +#define FUNC_NAME __divqu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(divqu) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - ldit $f26, 18446744073709551616.0 - addt $f26, $f10, $f26 - fcmovlt $f10, $f26, $f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - ldit $f26, 18446744073709551616.0 - addt $f26, $f1, $f26 - fcmovlt $f1, $f26, $f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(divqu) +#include "divrem.S" 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 <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/divrem.m4 b/sysdeps/alpha/divrem.m4 deleted file mode 100644 index d2f36383cb..0000000000 --- a/sysdeps/alpha/divrem.m4 +++ /dev/null @@ -1,51 +0,0 @@ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) - - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - -define(path, `SYSDEP_DIR/macros.m4')dnl -include(path) - -FUNC__(OP) - /* First set up the dividend. */ - EXTEND(t10) - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - ADJQU($f10) - - /* Then set up the divisor. */ - EXTEND(t11) - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - ADJQU($f1) - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - FULLEXTEND(t12) - - DOREM - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(OP) diff --git a/sysdeps/alpha/ffs.S b/sysdeps/alpha/ffs.S new file mode 100644 index 0000000000..7676b85aaa --- /dev/null +++ b/sysdeps/alpha/ffs.S @@ -0,0 +1,71 @@ +/* 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 the first bit set in an integer. Optimized for the Alpha +architecture. */ + +#include <sysdep.h> +#ifdef __linux__ +# include <alpha/regdef.h> +#else +#include <regdef.h> +#endif + + .set noreorder + .set noat + +ENTRY(ffs) + .prologue 0 + + ldq_u zero, 0(sp) # on the 21064, this helps dual-issuing + addl a0, zero, a0 # the last insn and reduces the stall + negq a0, t0 # due to the srl instruction + and a0, t0, t0 + clr v0 + beq a0, done + + # now do binary search for first non-zero bit + + zapnot t0, 0x03, t2 + addq v0, 16, t3 + cmoveq t2, t3, v0 + + zapnot t0, 0x05, t2 + addq v0, 8, t3 + cmoveq t2, t3, v0 + + srl t0, v0, t0 + addq v0, 1, v0 + + and t0, 0x0f, t2 + addq v0, 4, t3 + cmoveq t2, t3, v0 + + and t0, 0x33, t2 + addq v0, 2, t3 + cmoveq t2, t3, v0 + + and t0, 0x55, t2 + addq v0, 1, t3 + cmoveq t2, t3, v0 + +done: ret + + .end ffs 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 <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 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 <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/fabs.c b/sysdeps/alpha/machine-gmon.h index 321df0d1e1..a551e9f8b1 100644 --- a/sysdeps/alpha/fabs.c +++ b/sysdeps/alpha/machine-gmon.h @@ -1,4 +1,5 @@ -/* Copyright (C) 1992 Free Software Foundation, Inc. +/* 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 @@ -16,13 +17,9 @@ 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 __NO_MATH_INLINES +#define _MCOUNT_DECL void __mcount -#include <math.h> - -__inline double -fabs (double __x) -{ - __asm ("cpys $f31, %1, %0" : "=f" (__x) : "f" (__x)); - return __x; -} +/* 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/macros.m4 b/sysdeps/alpha/macros.m4 deleted file mode 100644 index f8c1fe9662..0000000000 --- a/sysdeps/alpha/macros.m4 +++ /dev/null @@ -1,34 +0,0 @@ -dnl NOTE: The $1 below is the argument to EXTEND, not register $1. -define(EXTEND, -`ifelse(SIZE, `l', -`ifelse(SIGNED, `true', -` sextl $1, $1 -',dnl -` zapnot $1, 0xf, $1 -')')')dnl - -dnl FULLEXTEND -- extend the register named in the first argument -define(FULLEXTEND, -`ifelse(SIZE, `l', -` sextl $1, $1 -')')dnl - -dnl This is used by divqu. -define(ADJQU, -`ifelse(MODE, `qu', -` ldit $f26, 18446744073709551616.0 - addt $f26, $1, $f26 - fcmovlt $1, $f26, $1 -')')dnl - -define(DOREM, -`ifelse(BASEOP, `rem', -` /* Compute the remainder. */ -ifelse(SIZE, `l', -` mull t11, t12, t11 - subl t10, t11, t12 -',dnl Note mulq/subq were only really used in remq, but we will find out -dnl if assuming they apply to remqu as well is wrong or not. -` mulq t11, t12, t11 - subq t10, t11, t12 -')')')dnl 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/reml.S b/sysdeps/alpha/reml.S index 95896fb831..cede136acd 100644 --- a/sysdeps/alpha/reml.S +++ b/sysdeps/alpha/reml.S @@ -1,60 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 4 +#define SIGNED 1 +#define FUNC_NAME __reml - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(reml) - /* First set up the dividend. */ - sextl t10, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - sextl t11, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - /* Compute the remainder. */ - mull t11, t12, t11 - subl t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(reml) +#include "divrem.S" diff --git a/sysdeps/alpha/remlu.S b/sysdeps/alpha/remlu.S index 24e07cf327..3658d92bc1 100644 --- a/sysdeps/alpha/remlu.S +++ b/sysdeps/alpha/remlu.S @@ -1,60 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 4 +#define SIGNED 0 +#define FUNC_NAME __remlu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(remlu) - /* First set up the dividend. */ - zapnot t10, 0xf, t10 - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - zapnot t11, 0xf, t11 - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - sextl t12, t12 - - - /* Compute the remainder. */ - mull t11, t12, t11 - subl t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(remlu) +#include "divrem.S" diff --git a/sysdeps/alpha/remq.S b/sysdeps/alpha/remq.S index ce38c2460a..61f2067383 100644 --- a/sysdeps/alpha/remq.S +++ b/sysdeps/alpha/remq.S @@ -1,57 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 8 +#define SIGNED 1 +#define FUNC_NAME __remq - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(remq) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - /* Compute the remainder. */ - mulq t11, t12, t11 - subq t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(remq) +#include "divrem.S" diff --git a/sysdeps/alpha/remqu.S b/sysdeps/alpha/remqu.S index 26bdd3b037..e22d5ac1c8 100644 --- a/sysdeps/alpha/remqu.S +++ b/sysdeps/alpha/remqu.S @@ -1,63 +1,6 @@ - /* This file is generated from divrem.m4; DO NOT EDIT! */ -/* For each N divided by D, we do: - result = (double) N / (double) D - Then, for each N mod D, we do: - result = N - (D * divMODE (N, D)) +#define IS_REM 1 +#define SIZE 8 +#define SIGNED 0 +#define FUNC_NAME __remqu - FIXME: - The q and qu versions won't deal with operands > 50 bits. We also - don't check for divide by zero. */ - -#include "DEFS.h" -#if 0 -/* We do not handle div by zero yet. */ -#include <machine/pal.h> -#endif -#include <sysdep.h> - -/* Avoid the definition of ret that we set in the alpha sysdep.h. */ -#undef ret - - - - - - -FUNC__(remqu) - /* First set up the dividend. */ - - stq t10,0(sp) - ldt $f10,0(sp) - cvtqt $f10,$f10 - ldit $f26, 18446744073709551616.0 - addt $f26, $f10, $f26 - fcmovlt $f10, $f26, $f10 - - - /* Then set up the divisor. */ - - stq t11,0(sp) - ldt $f1,0(sp) - cvtqt $f1,$f1 - ldit $f26, 18446744073709551616.0 - addt $f26, $f1, $f26 - fcmovlt $f1, $f26, $f1 - - - /* Do the division. */ - divt $f10,$f1,$f10 - cvttqc $f10,$f10 - - /* Put the result in t12. */ - stt $f10,0(sp) - ldq t12,0(sp) - - - /* Compute the remainder. */ - mulq t11, t12, t11 - subq t10, t11, t12 - - - lda sp,16(sp) - ret zero,(t9),1 - .end NAME__(remqu) +#include "divrem.S" diff --git a/sysdeps/alpha/setjmp.S b/sysdeps/alpha/setjmp.S index 08932ccd1a..8ea2b50f87 100644 --- a/sysdeps/alpha/setjmp.S +++ b/sysdeps/alpha/setjmp.S @@ -23,7 +23,7 @@ Cambridge, MA 02139, USA. */ extra arguments. */ ENTRY (__sigsetjmp) lda $27, __sigsetjmp_aux/* Load address to jump to. */ - bis $15, $15, $18 /* Pass FP as 3rd arg. */ - bis $30, $30, $19 /* Pass SP as 4th arg. */ + bis $30, $30, $18 /* Pass SP as 3rd arg. */ + bis $15, $15, $19 /* Pass FP as 4th arg. */ jmp $31, ($27), __sigsetjmp_aux /* Call __sigsetjmp_aux. */ .end __sigsetjmp diff --git a/sysdeps/alpha/setjmp_aux.c b/sysdeps/alpha/setjmp_aux.c index f92517be92..0f05f8b043 100644 --- a/sysdeps/alpha/setjmp_aux.c +++ b/sysdeps/alpha/setjmp_aux.c @@ -69,6 +69,8 @@ __sigsetjmp_aux (sigjmp_buf env, int savemask, long int *sp, long int *fp) /* Save the signal mask if requested. */ __sigjmp_save (env, savemask); + retpc = env[0].__jmpbuf[0].__pc; /* restore ra, ugly... */ + /* Return to the original caller of __sigsetjmp. */ return 0; } 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 <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 diff --git a/sysdeps/alpha/strlen.c b/sysdeps/alpha/strlen.c deleted file mode 100644 index 36f106c9c3..0000000000 --- a/sysdeps/alpha/strlen.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 1992 Free Software Foundation, Inc. - -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 <string.h> - -/* Return the length of the null-terminated string STR. Scan for - the null terminator quickly by testing eight bytes at a time. */ - -size_t -strlen (const char *str) -{ - const char *char_ptr; - const unsigned long int *longword_ptr; - - /* Handle the first few characters by reading one character at a time. - Do this until STR is aligned on a 8-byte border. */ - for (char_ptr = str; ((unsigned long int) char_ptr & 7) != 0; ++char_ptr) - if (*char_ptr == '\0') - return char_ptr - str; - - longword_ptr = (unsigned long int *) char_ptr; - - for (;;) - { - const unsigned long int longword = *longword_ptr++; - int mask; - - /* Set bits in MASK if bytes in LONGWORD are zero. */ - asm ("cmpbge $31, %1, %0" : "=r" (mask) : "r" (longword)); - if (mask) - { - /* Which of the bytes was the zero? */ - const char *cp = (const char *) (longword_ptr - 1); - int i; - - for (i = 0; i < 8; i++) - if (cp[i] == 0) - return cp - str + i; - } - } -} |