diff options
author | gcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2006-08-17 01:18:26 +0000 |
---|---|---|
committer | gcc <gcc@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2006-08-17 01:18:26 +0000 |
commit | 15f34685e7a9b5caf761af2ebf6afa20438d440b (patch) | |
tree | dc04ce3cdf040f198743c15b64557824de174680 /libc/sysdeps/i386/i686 | |
parent | 1e848e0e775a36f6359161f5deb890942ef42ff3 (diff) | |
download | eglibc2-15f34685e7a9b5caf761af2ebf6afa20438d440b.tar.gz |
Import glibc-mainline for 2006-08-16
git-svn-id: svn://svn.eglibc.org/fsf/trunk@4 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/sysdeps/i386/i686')
31 files changed, 2169 insertions, 0 deletions
diff --git a/libc/sysdeps/i386/i686/Implies b/libc/sysdeps/i386/i686/Implies new file mode 100644 index 000000000..e1fcccd5f --- /dev/null +++ b/libc/sysdeps/i386/i686/Implies @@ -0,0 +1,4 @@ +# Due to the reordering and the other nifty extensions in the i686 it is +# not really good to use heavily i586 optimized code on a i686. It's +# better to use i486/i386 code. +i386/i486 diff --git a/libc/sysdeps/i386/i686/Makefile b/libc/sysdeps/i386/i686/Makefile new file mode 100644 index 000000000..c7378ab21 --- /dev/null +++ b/libc/sysdeps/i386/i686/Makefile @@ -0,0 +1,7 @@ +ifeq ($(subdir),csu) +sysdep_routines += hp-timing +elide-routines.os += hp-timing +endif + +# So that we can test __m128's alignment +stack-align-test-flags += -msse diff --git a/libc/sysdeps/i386/i686/add_n.S b/libc/sysdeps/i386/i686/add_n.S new file mode 100644 index 000000000..3cce33acf --- /dev/null +++ b/libc/sysdeps/i386/i686/add_n.S @@ -0,0 +1,122 @@ +/* Add two limb vectors of the same length > 0 and store sum in a third + limb vector. + Copyright (C) 1992,94,95,97,98,2000,2005 Free Software Foundation, Inc. + This file is part of the GNU MP Library. + + The GNU MP Library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your + option) any later version. + + The GNU MP 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 Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the GNU MP Library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + MA 02111-1307, USA. */ + +#include "sysdep.h" +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE+8 /* space for 2 saved regs */ +#define RES PARMS +#define S1 RES+PTR_SIZE +#define S2 S1+PTR_SIZE +#define SIZE S2+PTR_SIZE + + .text +#ifdef PIC +L(1): addl (%esp), %eax + ret +#endif +ENTRY (BP_SYM (__mpn_add_n)) + ENTER + + pushl %edi + cfi_adjust_cfa_offset (4) + pushl %esi + cfi_adjust_cfa_offset (4) + + movl RES(%esp),%edi + cfi_rel_offset (edi, 4) + movl S1(%esp),%esi + cfi_rel_offset (esi, 0) + movl S2(%esp),%edx + movl SIZE(%esp),%ecx +#if __BOUNDED_POINTERS__ + shll $2, %ecx /* convert limbs to bytes */ + CHECK_BOUNDS_BOTH_WIDE (%edi, RES(%esp), %ecx) + CHECK_BOUNDS_BOTH_WIDE (%esi, S1(%esp), %ecx) + CHECK_BOUNDS_BOTH_WIDE (%edx, S2(%esp), %ecx) + shrl $2, %ecx +#endif + movl %ecx,%eax + shrl $3,%ecx /* compute count for unrolled loop */ + negl %eax + andl $7,%eax /* get index where to start loop */ + jz L(oop) /* necessary special case for 0 */ + incl %ecx /* adjust loop count */ + shll $2,%eax /* adjustment for pointers... */ + subl %eax,%edi /* ... since they are offset ... */ + subl %eax,%esi /* ... by a constant when we ... */ + subl %eax,%edx /* ... enter the loop */ + shrl $2,%eax /* restore previous value */ +#ifdef PIC +/* Calculate start address in loop for PIC. */ + leal (L(oop)-L(0)-3)(%eax,%eax,8),%eax + call L(1) +L(0): +#else +/* Calculate start address in loop for non-PIC. */ + leal (L(oop) - 3)(%eax,%eax,8),%eax +#endif + jmp *%eax /* jump into loop */ + ALIGN (3) +L(oop): movl (%esi),%eax + adcl (%edx),%eax + movl %eax,(%edi) + movl 4(%esi),%eax + adcl 4(%edx),%eax + movl %eax,4(%edi) + movl 8(%esi),%eax + adcl 8(%edx),%eax + movl %eax,8(%edi) + movl 12(%esi),%eax + adcl 12(%edx),%eax + movl %eax,12(%edi) + movl 16(%esi),%eax + adcl 16(%edx),%eax + movl %eax,16(%edi) + movl 20(%esi),%eax + adcl 20(%edx),%eax + movl %eax,20(%edi) + movl 24(%esi),%eax + adcl 24(%edx),%eax + movl %eax,24(%edi) + movl 28(%esi),%eax + adcl 28(%edx),%eax + movl %eax,28(%edi) + leal 32(%edi),%edi + leal 32(%esi),%esi + leal 32(%edx),%edx + decl %ecx + jnz L(oop) + + sbbl %eax,%eax + negl %eax + + popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (esi) + popl %edi + cfi_adjust_cfa_offset (-4) + cfi_restore (edi) + + LEAVE + ret +END (BP_SYM (__mpn_add_n)) diff --git a/libc/sysdeps/i386/i686/bzero.S b/libc/sysdeps/i386/i686/bzero.S new file mode 100644 index 000000000..c1e4a6d50 --- /dev/null +++ b/libc/sysdeps/i386/i686/bzero.S @@ -0,0 +1,3 @@ +#define memset __bzero +#include <sysdeps/i386/i686/memset.S> +weak_alias (BP_SYM (__bzero), BP_SYM (bzero)) diff --git a/libc/sysdeps/i386/i686/dl-hash.h b/libc/sysdeps/i386/i686/dl-hash.h new file mode 100644 index 000000000..4bdd998aa --- /dev/null +++ b/libc/sysdeps/i386/i686/dl-hash.h @@ -0,0 +1,79 @@ +/* Compute hash alue for given string according to ELF standard. + Copyright (C) 1998, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_HASH_H +#define _DL_HASH_H 1 + + +/* This is the hashing function specified by the ELF ABI. It is highly + optimized for the PII processors. Though it will run on i586 it + would be much slower than the generic C implementation. So don't + use it. */ +static unsigned int +_dl_elf_hash (const char *name) +{ + unsigned int result; + unsigned int temp0; + unsigned int temp1; + + __asm__ __volatile__ + ("movzbl (%1),%2\n\t" + "testl %2, %2\n\t" + "jz 1f\n\t" + "movl %2, %0\n\t" + "movzbl 1(%1), %2\n\t" + "jecxz 1f\n\t" + "shll $4, %0\n\t" + "addl %2, %0\n\t" + "movzbl 2(%1), %2\n\t" + "jecxz 1f\n\t" + "shll $4, %0\n\t" + "addl %2, %0\n\t" + "movzbl 3(%1), %2\n\t" + "jecxz 1f\n\t" + "shll $4, %0\n\t" + "addl %2, %0\n\t" + "movzbl 4(%1), %2\n\t" + "jecxz 1f\n\t" + "shll $4, %0\n\t" + "addl $5, %1\n\t" + "addl %2, %0\n\t" + "movzbl (%1), %2\n\t" + "jecxz 1f\n" + "2:\t" + "shll $4, %0\n\t" + "movl $0xf0000000, %3\n\t" + "incl %1\n\t" + "addl %2, %0\n\t" + "andl %0, %3\n\t" + "andl $0x0fffffff, %0\n\t" + "shrl $24, %3\n\t" + "movzbl (%1), %2\n\t" + "xorl %3, %0\n\t" + "testl %2, %2\n\t" + "jnz 2b\n" + "1:\t" + : "=&r" (result), "=r" (name), "=&c" (temp0), "=&r" (temp1) + : "0" (0), "1" ((const unsigned char *) name)); + + return result; +} + +#endif /* dl-hash.h */ diff --git a/libc/sysdeps/i386/i686/ffs.c b/libc/sysdeps/i386/i686/ffs.c new file mode 100644 index 000000000..684ae2182 --- /dev/null +++ b/libc/sysdeps/i386/i686/ffs.c @@ -0,0 +1,49 @@ +/* ffs -- find first set bit in a word, counted from least significant end. + For Intel 80x86, x>=6. + This file is part of the GNU C Library. + Copyright (C) 1991, 92, 93, 94, 97, 98, 2004, 2005 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define ffsl __something_else +#include <string.h> + +#undef ffs + +#ifdef __GNUC__ + +int +__ffs (x) + int x; +{ + int cnt; + int tmp; + + asm ("bsfl %2,%0\n" /* Count low bits in X and store in %1. */ + "cmovel %1,%0\n" /* If number was zero, use -1 as result. */ + : "=&r" (cnt), "=r" (tmp) : "rm" (x), "1" (-1)); + + return cnt + 1; +} +weak_alias (__ffs, ffs) +libc_hidden_builtin_def (ffs) +#undef ffsl +weak_alias (__ffs, ffsl) + +#else +#include <string/ffs.c> +#endif diff --git a/libc/sysdeps/i386/i686/fpu/s_fdim.S b/libc/sysdeps/i386/i686/fpu/s_fdim.S new file mode 100644 index 000000000..30ecff4e7 --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fdim.S @@ -0,0 +1,44 @@ +/* Compute positive difference. + Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fdim) + fldl 4(%esp) // x + fldl 12(%esp) // x : y + + fucomi %st(1), %st + jp 1f + + jc 3f + fstp %st(1) + fldz + jmp 2f + +3: fsubrp %st, %st(1) + ret + +1: fucomi %st(0), %st + fcmovnu %st(1), %st +2: fstp %st(1) + ret +END(__fdim) +weak_alias (__fdim, fdim) diff --git a/libc/sysdeps/i386/i686/fpu/s_fdimf.S b/libc/sysdeps/i386/i686/fpu/s_fdimf.S new file mode 100644 index 000000000..888df14b6 --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fdimf.S @@ -0,0 +1,44 @@ +/* Compute positive difference. + Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fdimf) + flds 4(%esp) // x + flds 8(%esp) // x : y + + fucomi %st(1), %st + jp 1f + + jc 3f + fstp %st(1) + fldz + jmp 2f + +3: fsubrp %st, %st(1) + ret + +1: fucomi %st(0), %st + fcmovnu %st(1), %st +2: fstp %st(1) + ret +END(__fdimf) +weak_alias (__fdimf, fdimf) diff --git a/libc/sysdeps/i386/i686/fpu/s_fdiml.S b/libc/sysdeps/i386/i686/fpu/s_fdiml.S new file mode 100644 index 000000000..cb0e26e36 --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fdiml.S @@ -0,0 +1,44 @@ +/* Compute positive difference. + Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fdiml) + fldt 4(%esp) // x + fldt 16(%esp) // x : y + + fucomi %st(1), %st + jp 1f + + jc 3f + fstp %st(1) + fldz + jmp 2f + +3: fsubrp %st, %st(1) + ret + +1: fucomi %st(0), %st + fcmovnu %st(1), %st +2: fstp %st(1) + ret +END(__fdiml) +weak_alias (__fdiml, fdiml) diff --git a/libc/sysdeps/i386/i686/fpu/s_fmax.S b/libc/sysdeps/i386/i686/fpu/s_fmax.S new file mode 100644 index 000000000..b28226987 --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fmax.S @@ -0,0 +1,40 @@ +/* Compute maximum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fmax) + fldl 4(%esp) // x + fldl 12(%esp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fxch + + fucomi %st(1), %st + fcmovb %st(1), %st + + fstp %st(1) + + ret +END(__fmax) +weak_alias (__fmax, fmax) diff --git a/libc/sysdeps/i386/i686/fpu/s_fmaxf.S b/libc/sysdeps/i386/i686/fpu/s_fmaxf.S new file mode 100644 index 000000000..fbf3e5bff --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fmaxf.S @@ -0,0 +1,40 @@ +/* Compute maximum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fmaxf) + flds 4(%esp) // x + flds 8(%esp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fxch + + fucomi %st(1), %st + fcmovb %st(1), %st + + fstp %st(1) + + ret +END(__fmaxf) +weak_alias (__fmaxf, fmaxf) diff --git a/libc/sysdeps/i386/i686/fpu/s_fmaxl.S b/libc/sysdeps/i386/i686/fpu/s_fmaxl.S new file mode 100644 index 000000000..229febf52 --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fmaxl.S @@ -0,0 +1,40 @@ +/* Compute maximum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fmaxl) + fldt 4(%esp) // x + fldt 16(%esp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fxch + + fucomi %st(1), %st + fcmovb %st(1), %st + + fstp %st(1) + + ret +END(__fmaxl) +weak_alias (__fmaxl, fmaxl) diff --git a/libc/sysdeps/i386/i686/fpu/s_fmin.S b/libc/sysdeps/i386/i686/fpu/s_fmin.S new file mode 100644 index 000000000..d821cda2f --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fmin.S @@ -0,0 +1,38 @@ +/* Compute minimum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fmin) + fldl 4(%esp) // x + fldl 12(%esp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fucomi %st(1), %st + fcmovnb %st(1), %st + + fstp %st(1) + + ret +END(__fmin) +weak_alias (__fmin, fmin) diff --git a/libc/sysdeps/i386/i686/fpu/s_fminf.S b/libc/sysdeps/i386/i686/fpu/s_fminf.S new file mode 100644 index 000000000..8ef12035e --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fminf.S @@ -0,0 +1,38 @@ +/* Compute minimum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fminf) + flds 4(%esp) // x + flds 8(%esp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fucomi %st(1), %st + fcmovnb %st(1), %st + + fstp %st(1) + + ret +END(__fminf) +weak_alias (__fminf, fminf) diff --git a/libc/sysdeps/i386/i686/fpu/s_fminl.S b/libc/sysdeps/i386/i686/fpu/s_fminl.S new file mode 100644 index 000000000..e158ff895 --- /dev/null +++ b/libc/sysdeps/i386/i686/fpu/s_fminl.S @@ -0,0 +1,38 @@ +/* Compute minimum of two numbers, regarding NaN as missing argument. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> + + .text +ENTRY(__fminl) + fldt 4(%esp) // x + fldt 16(%esp) // x : y + + fucomi %st(0), %st + fcmovu %st(1), %st // now %st contains y if not NaN, x otherwise + + fucomi %st(1), %st + fcmovnb %st(1), %st + + fstp %st(1) + + ret +END(__fminl) +weak_alias (__fminl, fminl) diff --git a/libc/sysdeps/i386/i686/hp-timing.c b/libc/sysdeps/i386/i686/hp-timing.c new file mode 100644 index 000000000..c8c88650c --- /dev/null +++ b/libc/sysdeps/i386/i686/hp-timing.c @@ -0,0 +1,24 @@ +/* Support for high precision, low overhead timing functions. i686 version. + Copyright (C) 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <hp-timing.h> + +/* We have to define the variable for the overhead. */ +hp_timing_t _dl_hp_timing_overhead; diff --git a/libc/sysdeps/i386/i686/hp-timing.h b/libc/sysdeps/i386/i686/hp-timing.h new file mode 100644 index 000000000..b92486964 --- /dev/null +++ b/libc/sysdeps/i386/i686/hp-timing.h @@ -0,0 +1,157 @@ +/* High precision, low overhead timing functions. i686 version. + Copyright (C) 1998, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _HP_TIMING_H +#define _HP_TIMING_H 1 + +#include <string.h> +#include <sys/param.h> +#include <stdio-common/_itoa.h> + +/* The macros defined here use the timestamp counter in i586 and up versions + of the x86 processors. They provide a very accurate way to measure the + time with very little overhead. The time values themself have no real + meaning, only differences are interesting. + + This version is for the i686 processors. The difference to the i586 + version is that the timerstamp register is unconditionally used. This is + not the case for the i586 version where we have to perform runtime test + whether the processor really has this capability. We have to make this + distinction since the sysdeps/i386/i586 code is supposed to work on all + platforms while the i686 already contains i686-specific code. + + The list of macros we need includes the following: + + - HP_TIMING_AVAIL: test for availability. + + - HP_TIMING_INLINE: this macro is non-zero if the functionality is not + implemented using function calls but instead uses some inlined code + which might simply consist of a few assembler instructions. We have to + know this since we might want to use the macros here in places where we + cannot make function calls. + + - hp_timing_t: This is the type for variables used to store the time + values. + + - HP_TIMING_ZERO: clear `hp_timing_t' object. + + - HP_TIMING_NOW: place timestamp for current time in variable given as + parameter. + + - HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the + HP_TIMING_DIFF macro. + + - HP_TIMING_DIFF: compute difference between two times and store it + in a third. Source and destination might overlap. + + - HP_TIMING_ACCUM: add time difference to another variable. This might + be a bit more complicated to implement for some platforms as the + operation should be thread-safe and 64bit arithmetic on 32bit platforms + is not. + + - HP_TIMING_ACCUM_NT: this is the variant for situations where we know + there are no threads involved. + + - HP_TIMING_PRINT: write decimal representation of the timing value into + the given string. This operation need not be inline even though + HP_TIMING_INLINE is specified. + +*/ + +/* We always assume having the timestamp register. */ +#define HP_TIMING_AVAIL (1) + +/* We indeed have inlined functions. */ +#define HP_TIMING_INLINE (1) + +/* We use 64bit values for the times. */ +typedef unsigned long long int hp_timing_t; + +/* Set timestamp value to zero. */ +#define HP_TIMING_ZERO(Var) (Var) = (0) + +/* That's quite simple. Use the `rdtsc' instruction. Note that the value + might not be 100% accurate since there might be some more instructions + running in this moment. This could be changed by using a barrier like + 'cpuid' right before the `rdtsc' instruciton. But we are not interested + in accurate clock cycles here so we don't do this. */ +#define HP_TIMING_NOW(Var) __asm__ __volatile__ ("rdtsc" : "=A" (Var)) + +/* Use two 'rdtsc' instructions in a row to find out how long it takes. */ +#define HP_TIMING_DIFF_INIT() \ + do { \ + if (GLRO(dl_hp_timing_overhead) == 0) \ + { \ + int __cnt = 5; \ + GLRO(dl_hp_timing_overhead) = ~0ull; \ + do \ + { \ + hp_timing_t __t1, __t2; \ + HP_TIMING_NOW (__t1); \ + HP_TIMING_NOW (__t2); \ + if (__t2 - __t1 < GLRO(dl_hp_timing_overhead)) \ + GLRO(dl_hp_timing_overhead) = __t2 - __t1; \ + } \ + while (--__cnt > 0); \ + } \ + } while (0) + +/* It's simple arithmetic for us. */ +#define HP_TIMING_DIFF(Diff, Start, End) (Diff) = ((End) - (Start)) + +/* We have to jump through hoops to get this correctly implemented. */ +#define HP_TIMING_ACCUM(Sum, Diff) \ + do { \ + int __not_done; \ + hp_timing_t __oldval = (Sum); \ + hp_timing_t __diff = (Diff) - GLRO(dl_hp_timing_overhead); \ + do \ + { \ + hp_timing_t __newval = __oldval + __diff; \ + int __temp0, __temp1; \ + __asm__ __volatile__ ("xchgl %0, %%ebx\n\t" \ + "lock; cmpxchg8b %1\n\t" \ + "sete %%bl\n\t" \ + "xchgl %0, %%ebx" \ + : "=SD" (__not_done), "=m" (Sum), \ + "=A" (__oldval), "=c" (__temp0) \ + : "m" (Sum), "2" (__oldval), \ + "3" ((unsigned int) (__newval >> 32)), \ + "0" ((unsigned int) __newval)); \ + } \ + while ((unsigned char) __not_done); \ + } while (0) + +/* No threads, no extra work. */ +#define HP_TIMING_ACCUM_NT(Sum, Diff) (Sum) += (Diff) + +/* Print the time value. */ +#define HP_TIMING_PRINT(Buf, Len, Val) \ + do { \ + char __buf[20]; \ + char *__cp = _itoa (Val, __buf + sizeof (__buf), 10, 0); \ + size_t __len = (Len); \ + char *__dest = (Buf); \ + while (__len-- > 0 && __cp < __buf + sizeof (__buf)) \ + *__dest++ = *__cp++; \ + memcpy (__dest, " clock cycles", MIN (__len, sizeof (" clock cycles"))); \ + } while (0) + +#endif /* hp-timing.h */ diff --git a/libc/sysdeps/i386/i686/memcmp.S b/libc/sysdeps/i386/i686/memcmp.S new file mode 100644 index 000000000..4bd5394be --- /dev/null +++ b/libc/sysdeps/i386/i686/memcmp.S @@ -0,0 +1,423 @@ +/* Compare two memory blocks for differences in the first COUNT bytes. + Copyright (C) 2004, 2005 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE+4 /* Preserve EBX. */ +#define BLK1 PARMS +#define BLK2 BLK1+PTR_SIZE +#define LEN BLK2+PTR_SIZE +#define ENTRANCE pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); ENTER +#define RETURN popl %ebx; cfi_adjust_cfa_offset (-4); \ + cfi_restore (ebx); LEAVE; ret; \ + cfi_adjust_cfa_offset (4); cfi_rel_offset (ebx, 0); + +/* Load an entry in a jump table into EBX. TABLE is a jump table + with relative offsets. INDEX is a register contains the index + into the jump table. */ +#define LOAD_JUMP_TABLE_ENTRY(TABLE, INDEX) \ + /* We first load PC into EBX. */ \ + call __i686.get_pc_thunk.bx; \ + /* Get the address of the jump table. */ \ + addl $(TABLE - .), %ebx; \ + /* Get the entry and convert the relative offset to the \ + absolute address. */ \ + addl (%ebx,INDEX,4), %ebx + +#ifdef HAVE_HIDDEN + .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits + .globl __i686.get_pc_thunk.bx + .hidden __i686.get_pc_thunk.bx +#else + .text +#endif + ALIGN (4) + .type __i686.get_pc_thunk.bx,@function +__i686.get_pc_thunk.bx: + movl (%esp), %ebx + ret + + .text + ALIGN (4) +ENTRY (BP_SYM (memcmp)) + ENTRANCE + + movl BLK1(%esp), %eax + movl BLK2(%esp), %edx + movl LEN(%esp), %ecx + + cmpl $1, %ecx + jne L(not_1) + movzbl (%eax), %ecx /* LEN == 1 */ + cmpb (%edx), %cl + jne L(neq) +L(bye): + xorl %eax, %eax + RETURN + +L(neq): + sbbl %eax, %eax + sbbl $-1, %eax + RETURN + + cfi_adjust_cfa_offset (4) + cfi_rel_offset (ebx, 0) +L(not_1): + jl L(bye) /* LEN == 0 */ + + pushl %esi + cfi_adjust_cfa_offset (4) + movl %eax, %esi + cfi_rel_offset (esi, 0) + cmpl $32, %ecx; + jge L(32bytesormore) /* LEN => 32 */ + + LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx) + addl %ecx, %edx + addl %ecx, %esi + jmp *%ebx + + ALIGN (4) +L(28bytes): + movl -28(%esi), %eax + movl -28(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(24bytes): + movl -24(%esi), %eax + movl -24(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(20bytes): + movl -20(%esi), %eax + movl -20(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(16bytes): + movl -16(%esi), %eax + movl -16(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(12bytes): + movl -12(%esi), %eax + movl -12(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(8bytes): + movl -8(%esi), %eax + movl -8(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(4bytes): + movl -4(%esi), %eax + movl -4(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(0bytes): + popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (esi) + xorl %eax, %eax + RETURN + + cfi_adjust_cfa_offset (8) + cfi_rel_offset (esi, 0) + cfi_rel_offset (ebx, 4) +L(29bytes): + movl -29(%esi), %eax + movl -29(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(25bytes): + movl -25(%esi), %eax + movl -25(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(21bytes): + movl -21(%esi), %eax + movl -21(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(17bytes): + movl -17(%esi), %eax + movl -17(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(13bytes): + movl -13(%esi), %eax + movl -13(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(9bytes): + movl -9(%esi), %eax + movl -9(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(5bytes): + movl -5(%esi), %eax + movl -5(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(1bytes): + movzbl -1(%esi), %eax + cmpb -1(%edx), %al + jne L(set) + popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (esi) + xorl %eax, %eax + RETURN + + cfi_adjust_cfa_offset (8) + cfi_rel_offset (esi, 0) + cfi_rel_offset (ebx, 4) +L(30bytes): + movl -30(%esi), %eax + movl -30(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(26bytes): + movl -26(%esi), %eax + movl -26(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(22bytes): + movl -22(%esi), %eax + movl -22(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(18bytes): + movl -18(%esi), %eax + movl -18(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(14bytes): + movl -14(%esi), %eax + movl -14(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(10bytes): + movl -10(%esi), %eax + movl -10(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(6bytes): + movl -6(%esi), %eax + movl -6(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(2bytes): + movzwl -2(%esi), %eax + movzwl -2(%edx), %ecx + cmpb %cl, %al + jne L(set) + cmpl %ecx, %eax + jne L(set) + popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (esi) + xorl %eax, %eax + RETURN + + cfi_adjust_cfa_offset (8) + cfi_rel_offset (esi, 0) + cfi_rel_offset (ebx, 4) +L(31bytes): + movl -31(%esi), %eax + movl -31(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(27bytes): + movl -27(%esi), %eax + movl -27(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(23bytes): + movl -23(%esi), %eax + movl -23(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(19bytes): + movl -19(%esi), %eax + movl -19(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(15bytes): + movl -15(%esi), %eax + movl -15(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(11bytes): + movl -11(%esi), %eax + movl -11(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(7bytes): + movl -7(%esi), %eax + movl -7(%edx), %ecx + cmpl %ecx, %eax + jne L(find_diff) +L(3bytes): + movzwl -3(%esi), %eax + movzwl -3(%edx), %ecx + cmpb %cl, %al + jne L(set) + cmpl %ecx, %eax + jne L(set) + movzbl -1(%esi), %eax + cmpb -1(%edx), %al + jne L(set) + popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (esi) + xorl %eax, %eax + RETURN + + cfi_adjust_cfa_offset (8) + cfi_rel_offset (esi, 0) + cfi_rel_offset (ebx, 4) + ALIGN (4) +/* ECX >= 32. */ +L(32bytesormore): + subl $32, %ecx + + movl (%esi), %eax + cmpl (%edx), %eax + jne L(load_ecx) + + movl 4(%esi), %eax + cmpl 4(%edx), %eax + jne L(load_ecx_4) + + movl 8(%esi), %eax + cmpl 8(%edx), %eax + jne L(load_ecx_8) + + movl 12(%esi), %eax + cmpl 12(%edx), %eax + jne L(load_ecx_12) + + movl 16(%esi), %eax + cmpl 16(%edx), %eax + jne L(load_ecx_16) + + movl 20(%esi), %eax + cmpl 20(%edx), %eax + jne L(load_ecx_20) + + movl 24(%esi), %eax + cmpl 24(%edx), %eax + jne L(load_ecx_24) + + movl 28(%esi), %eax + cmpl 28(%edx), %eax + jne L(load_ecx_28) + + addl $32, %esi + addl $32, %edx + cmpl $32, %ecx + jge L(32bytesormore) + + LOAD_JUMP_TABLE_ENTRY (L(table_32bytes), %ecx) + addl %ecx, %edx + addl %ecx, %esi + jmp *%ebx + +L(load_ecx_28): + addl $0x4, %edx +L(load_ecx_24): + addl $0x4, %edx +L(load_ecx_20): + addl $0x4, %edx +L(load_ecx_16): + addl $0x4, %edx +L(load_ecx_12): + addl $0x4, %edx +L(load_ecx_8): + addl $0x4, %edx +L(load_ecx_4): + addl $0x4, %edx +L(load_ecx): + movl (%edx), %ecx + +L(find_diff): + cmpb %cl, %al + jne L(set) + cmpb %ch, %ah + jne L(set) + shrl $16,%eax + shrl $16,%ecx + cmpb %cl, %al + jne L(set) + /* We get there only if we already know there is a + difference. */ + cmpl %ecx, %eax +L(set): + sbbl %eax, %eax + sbbl $-1, %eax + popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (esi) + RETURN +END (BP_SYM (memcmp)) + + .section .rodata + ALIGN (2) +L(table_32bytes) : + .long L(0bytes) - . + 0x0 + .long L(1bytes) - . + 0x4 + .long L(2bytes) - . + 0x8 + .long L(3bytes) - . + 0xc + .long L(4bytes) - . + 0x10 + .long L(5bytes) - . + 0x14 + .long L(6bytes) - . + 0x18 + .long L(7bytes) - . + 0x1c + .long L(8bytes) - . + 0x20 + .long L(9bytes) - . + 0x24 + .long L(10bytes) - . + 0x28 + .long L(11bytes) - . + 0x2c + .long L(12bytes) - . + 0x30 + .long L(13bytes) - . + 0x34 + .long L(14bytes) - . + 0x38 + .long L(15bytes) - . + 0x3c + .long L(16bytes) - . + 0x40 + .long L(17bytes) - . + 0x44 + .long L(18bytes) - . + 0x48 + .long L(19bytes) - . + 0x4c + .long L(20bytes) - . + 0x50 + .long L(21bytes) - . + 0x54 + .long L(22bytes) - . + 0x58 + .long L(23bytes) - . + 0x5c + .long L(24bytes) - . + 0x60 + .long L(25bytes) - . + 0x64 + .long L(26bytes) - . + 0x68 + .long L(27bytes) - . + 0x6c + .long L(28bytes) - . + 0x70 + .long L(29bytes) - . + 0x74 + .long L(30bytes) - . + 0x78 + .long L(31bytes) - . + 0x7c + + +#undef bcmp +weak_alias (BP_SYM (memcmp), BP_SYM (bcmp)) +libc_hidden_builtin_def (BP_SYM (memcmp)) diff --git a/libc/sysdeps/i386/i686/memcpy.S b/libc/sysdeps/i386/i686/memcpy.S new file mode 100644 index 000000000..00e84ec2e --- /dev/null +++ b/libc/sysdeps/i386/i686/memcpy.S @@ -0,0 +1,69 @@ +/* Copy memory block and return pointer to beginning of destination block + For Intel 80x86, x>=6. + This file is part of the GNU C Library. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE /* no space for saved regs */ +#define RTN PARMS +#define DEST RTN+RTN_SIZE +#define SRC DEST+PTR_SIZE +#define LEN SRC+PTR_SIZE + + .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__memcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memcpy_chk) +#endif +ENTRY (BP_SYM (memcpy)) + ENTER + + movl LEN(%esp), %ecx + movl %edi, %eax + movl DEST(%esp), %edi + movl %esi, %edx + movl SRC(%esp), %esi + CHECK_BOUNDS_BOTH_WIDE (%edi, DEST(%esp), %ecx) + CHECK_BOUNDS_BOTH_WIDE (%esi, SRC(%esp), %ecx) + + cld + shrl $1, %ecx + jnc 1f + movsb +1: shrl $1, %ecx + jnc 2f + movsw +2: rep + movsl + movl %eax, %edi + movl %edx, %esi + movl DEST(%esp), %eax + RETURN_BOUNDED_POINTER (DEST(%esp)) + + LEAVE + RET_PTR +END (BP_SYM (memcpy)) +libc_hidden_builtin_def (memcpy) diff --git a/libc/sysdeps/i386/i686/memcpy_chk.S b/libc/sysdeps/i386/i686/memcpy_chk.S new file mode 100644 index 000000000..2893911cd --- /dev/null +++ b/libc/sysdeps/i386/i686/memcpy_chk.S @@ -0,0 +1,35 @@ +/* Checking memcpy for i686. + Copyright (C) 2004 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memcpy.S. + For libc.a, this is a separate source to avoid + memcpy bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp memcpy +END (__memcpy_chk) +#endif diff --git a/libc/sysdeps/i386/i686/memmove.S b/libc/sysdeps/i386/i686/memmove.S new file mode 100644 index 000000000..b93b5c729 --- /dev/null +++ b/libc/sysdeps/i386/i686/memmove.S @@ -0,0 +1,115 @@ +/* Copy memory block and return pointer to beginning of destination block + For Intel 80x86, x>=6. + This file is part of the GNU C Library. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE+4 /* one spilled register */ +#define RTN PARMS +#define DEST RTN+RTN_SIZE +#define SRC DEST+PTR_SIZE +#define LEN SRC+PTR_SIZE + + .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__memmove_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memmove_chk) +#endif +ENTRY (BP_SYM (memmove)) + ENTER + + pushl %edi + cfi_adjust_cfa_offset (4) + + movl LEN(%esp), %ecx + movl DEST(%esp), %edi + cfi_rel_offset (edi, 0) + movl %esi, %edx + movl SRC(%esp), %esi + cfi_register (esi, edx) + CHECK_BOUNDS_BOTH_WIDE (%edi, DEST(%esp), %ecx) + CHECK_BOUNDS_BOTH_WIDE (%esi, SRC(%esp), %ecx) + + movl %edi, %eax + subl %esi, %eax + cmpl %eax, %edi + jae 3f + + cld + shrl $1, %ecx + jnc 1f + movsb +1: shrl $1, %ecx + jnc 2f + movsw +2: rep + movsl + movl %edx, %esi + cfi_restore (esi) + movl DEST(%esp), %eax + RETURN_BOUNDED_POINTER (DEST(%esp)) + + popl %edi + cfi_adjust_cfa_offset (-4) + cfi_restore (edi) + + LEAVE + RET_PTR + + cfi_adjust_cfa_offset (4) + cfi_rel_offset (edi, 0) + cfi_register (esi, edx) + + /* Backward copying. */ +3: std + leal -1(%edi, %ecx), %edi + leal -1(%esi, %ecx), %esi + shrl $1, %ecx + jnc 1f + movsb +1: subl $1, %edi + subl $1, %esi + shrl $1, %ecx + jnc 2f + movsw +2: subl $2, %edi + subl $2, %esi + rep + movsl + movl %edx, %esi + cfi_restore (esi) + movl DEST(%esp), %eax + RETURN_BOUNDED_POINTER (DEST(%esp)) + + cld + popl %edi + cfi_adjust_cfa_offset (-4) + cfi_restore (edi) + + LEAVE + RET_PTR +END (BP_SYM (memmove)) +libc_hidden_builtin_def (memmove) diff --git a/libc/sysdeps/i386/i686/memmove_chk.S b/libc/sysdeps/i386/i686/memmove_chk.S new file mode 100644 index 000000000..23382ea8b --- /dev/null +++ b/libc/sysdeps/i386/i686/memmove_chk.S @@ -0,0 +1,35 @@ +/* Checking memmove for x86-64. + Copyright (C) 2004 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memmove.S. + For libc.a, this is a separate source to avoid + memmove bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memmove_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp memmove +END (__memmove_chk) +#endif diff --git a/libc/sysdeps/i386/i686/mempcpy.S b/libc/sysdeps/i386/i686/mempcpy.S new file mode 100644 index 000000000..6437e4a5d --- /dev/null +++ b/libc/sysdeps/i386/i686/mempcpy.S @@ -0,0 +1,73 @@ +/* Copy memory block and return pointer to following byte. + For Intel 80x86, x>=6. + This file is part of the GNU C Library. + Copyright (C) 1998,1999,2000,2002,2004,2005 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE /* no space for saved regs */ +#define RTN PARMS +#define DEST RTN+RTN_SIZE +#define SRC DEST+PTR_SIZE +#define LEN SRC+PTR_SIZE + + .text +#if defined PIC && !defined NOT_IN_libc +ENTRY (__mempcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__mempcpy_chk) +#endif +ENTRY (BP_SYM (__mempcpy)) + ENTER + + movl LEN(%esp), %ecx + movl %edi, %eax + cfi_register (edi, eax) + movl DEST(%esp), %edi + CHECK_BOUNDS_BOTH_WIDE (%edi, DEST(%esp), %ecx) + movl %esi, %edx + cfi_register (esi, edx) + movl SRC(%esp), %esi + CHECK_BOUNDS_BOTH_WIDE (%esi, SRC(%esp), %ecx) + cld + shrl $1, %ecx + jnc 1f + movsb +1: shrl $1, %ecx + jnc 2f + movsw +2: rep + movsl + xchgl %edi, %eax + cfi_restore (edi) + movl %edx, %esi + cfi_restore (esi) + RETURN_BOUNDED_POINTER (DEST(%esp)) + + LEAVE + RET_PTR +END (BP_SYM (__mempcpy)) +libc_hidden_def (BP_SYM (__mempcpy)) +weak_alias (BP_SYM (__mempcpy), BP_SYM (mempcpy)) +libc_hidden_builtin_def (mempcpy) diff --git a/libc/sysdeps/i386/i686/mempcpy_chk.S b/libc/sysdeps/i386/i686/mempcpy_chk.S new file mode 100644 index 000000000..dc9c6095f --- /dev/null +++ b/libc/sysdeps/i386/i686/mempcpy_chk.S @@ -0,0 +1,35 @@ +/* Checking mempcpy for x86-64. + Copyright (C) 2004 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in mempcpy.S. + For libc.a, this is a separate source to avoid + mempcpy bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__mempcpy_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp mempcpy +END (__mempcpy_chk) +#endif diff --git a/libc/sysdeps/i386/i686/memset.S b/libc/sysdeps/i386/i686/memset.S new file mode 100644 index 000000000..dfa1aa701 --- /dev/null +++ b/libc/sysdeps/i386/i686/memset.S @@ -0,0 +1,113 @@ +/* memset/bzero -- set memory area to CH/0 + Highly optimized version for ix86, x>=6. + Copyright (C) 1999,2000,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +/* BEWARE: `#ifdef memset' means that memset is redefined as `bzero' */ +#define BZERO_P (defined memset) + +#define PARMS LINKAGE+4 /* space for 1 saved reg */ +#if BZERO_P +# define DEST PARMS +# define LEN DEST+PTR_SIZE +#else +# define RTN PARMS +# define DEST RTN+RTN_SIZE +# define CHR DEST+PTR_SIZE +# define LEN CHR+4 +#endif + + .text +#if defined PIC && !defined NOT_IN_libc && !BZERO_P +ENTRY (__memset_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb HIDDEN_JUMPTARGET (__chk_fail) +END (__memset_chk) +#endif +ENTRY (BP_SYM (memset)) + ENTER + + cld + pushl %edi + cfi_adjust_cfa_offset (4) + movl DEST(%esp), %edx + movl LEN(%esp), %ecx + CHECK_BOUNDS_BOTH_WIDE (%edx, DEST(%esp), %ecx) +#if BZERO_P + xorl %eax, %eax /* fill with 0 */ +#else + movzbl CHR(%esp), %eax +#endif + jecxz 1f + movl %edx, %edi + cfi_rel_offset (edi, 0) + andl $3, %edx + jz 2f /* aligned */ + jp 3f /* misaligned at 3, store just one byte below */ + stosb /* misaligned at 1 or 2, store two bytes */ + decl %ecx + jz 1f +3: stosb + decl %ecx + jz 1f + xorl $1, %edx + jnz 2f /* was misaligned at 2 or 3, now aligned */ + stosb /* was misaligned at 1, store third byte */ + decl %ecx +2: movl %ecx, %edx + shrl $2, %ecx + andl $3, %edx +#if !BZERO_P + imul $0x01010101, %eax +#endif + rep + stosl + movl %edx, %ecx + rep + stosb + +1: +#if !BZERO_P + movl DEST(%esp), %eax /* start address of destination is result */ + RETURN_BOUNDED_POINTER (DEST(%esp)) +#endif + popl %edi + cfi_adjust_cfa_offset (-4) + cfi_restore (edi) + + LEAVE +#if BZERO_P + ret +#else + RET_PTR +#endif +END (BP_SYM (memset)) +libc_hidden_builtin_def (memset) + +#if defined PIC && !defined NOT_IN_libc && !BZERO_P +strong_alias (__memset_chk, __memset_zero_constant_len_parameter) + .section .gnu.warning.__memset_zero_constant_len_parameter + .string "memset used with constant zero length parameter; this could be due to transposed parameters" +#endif diff --git a/libc/sysdeps/i386/i686/memset_chk.S b/libc/sysdeps/i386/i686/memset_chk.S new file mode 100644 index 000000000..cd93d5ee1 --- /dev/null +++ b/libc/sysdeps/i386/i686/memset_chk.S @@ -0,0 +1,35 @@ +/* Checking memset for i686. + Copyright (C) 2004, 2005 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" + +#ifndef PIC + /* For libc.so this is defined in memset.S. + For libc.a, this is a separate source to avoid + memset bringing in __chk_fail and all routines + it calls. */ + .text +ENTRY (__memset_chk) + movl 12(%esp), %eax + cmpl %eax, 16(%esp) + jb __chk_fail + jmp memset +END (__memset_chk) +#endif diff --git a/libc/sysdeps/i386/i686/memusage.h b/libc/sysdeps/i386/i686/memusage.h new file mode 100644 index 000000000..235c3fc72 --- /dev/null +++ b/libc/sysdeps/i386/i686/memusage.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2000, 2005 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define GETSP() ({ register uintptr_t stack_ptr asm ("esp"); stack_ptr; }) +#define GETTIME(low,high) asm ("rdtsc" : "=a" (low), "=d" (high)) + +#include <sysdeps/generic/memusage.h> diff --git a/libc/sysdeps/i386/i686/strcmp.S b/libc/sysdeps/i386/i686/strcmp.S new file mode 100644 index 000000000..8601c1ca0 --- /dev/null +++ b/libc/sysdeps/i386/i686/strcmp.S @@ -0,0 +1,72 @@ +/* Highly optimized version for ix86, x>=6. + Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +#define PARMS LINKAGE /* no space for saved regs */ +#define STR1 PARMS +#define STR2 STR1+PTR_SIZE + + .text +ENTRY (BP_SYM (strcmp)) + ENTER + + movl STR1(%esp), %ecx + movl STR2(%esp), %edx + CHECK_BOUNDS_LOW (%ecx, STR1(%esp)) + CHECK_BOUNDS_LOW (%edx, STR2(%esp)) + +L(oop): movb (%ecx), %al + cmpb (%edx), %al + jne L(neq) + incl %ecx + incl %edx + testb %al, %al + jnz L(oop) + + xorl %eax, %eax + /* when strings are equal, pointers rest one beyond + the end of the NUL terminators. */ + CHECK_BOUNDS_HIGH (%ecx, STR1(%esp), jbe) + CHECK_BOUNDS_HIGH (%edx, STR2(%esp), jbe) + LEAVE + ret + +#ifndef __BOUNDED_POINTERS__ +L(neq): movl $1, %eax + movl $-1, %ecx + cmovbl %ecx, %eax +#else +L(neq): movl $1, %eax + ja L(chk) + negl %eax + /* When strings differ, pointers rest on + the unequal characters. */ +L(chk): CHECK_BOUNDS_HIGH (%ecx, STR1(%esp), jb) + CHECK_BOUNDS_HIGH (%edx, STR2(%esp), jb) +#endif + + LEAVE + ret +END (BP_SYM (strcmp)) +libc_hidden_builtin_def (strcmp) diff --git a/libc/sysdeps/i386/i686/strtok.S b/libc/sysdeps/i386/i686/strtok.S new file mode 100644 index 000000000..fe225e548 --- /dev/null +++ b/libc/sysdeps/i386/i686/strtok.S @@ -0,0 +1,281 @@ +/* strtok (str, delim) -- Return next DELIM separated token from STR. + For Intel 80686. + Copyright (C) 1998, 2000, 2001, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include "asm-syntax.h" +#include "bp-sym.h" +#include "bp-asm.h" + +/* This file can be used for three variants of the strtok function: + + strtok: + INPUT PARAMETER: + str (sp + 4) + delim (sp + 8) + + strtok_r: + INPUT PARAMETER: + str (sp + 4) + delim (sp + 8) + save_ptr (sp + 12) + + We do a common implementation here. */ + +#ifdef USE_AS_STRTOK_R +# define SAVE_PTR 0(%ecx) +#else + .bss + .local save_ptr + ASM_TYPE_DIRECTIVE (save_ptr, @object) + .size save_ptr, 4 +save_ptr: +# if __BOUNDED_POINTERS__ + .space 12 +# else + .space 4 +# endif + +# ifdef PIC +# define SAVE_PTR save_ptr@GOTOFF(%ebx) +# else +# define SAVE_PTR save_ptr +# endif + +# define FUNCTION strtok +#endif + +#if !defined USE_AS_STRTOK_R && defined PIC +# define PARMS LINKAGE+256+4 /* space for table and saved PIC register */ +#else +# define PARMS LINKAGE+256 /* space for table */ +#endif +#define RTN PARMS +#define STR RTN+RTN_SIZE +#define DELIM STR+PTR_SIZE +#ifdef USE_AS_STRTOK_R +# define SAVE DELIM+PTR_SIZE +#endif + + .text + +#if !defined USE_AS_STRTOK_R && defined PIC +0: movl (%esp), %ebx + ret +#endif + +ENTRY (BP_SYM (FUNCTION)) + ENTER + +#if !defined USE_AS_STRTOK_R && defined PIC + pushl %ebx /* Save PIC register. */ + cfi_adjust_cfa_offset (4) + cfi_rel_offset (ebx, 0) + call 0b + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#endif + + /* First we create a table with flags for all possible characters. + For the ASCII (7bit/8bit) or ISO-8859-X character sets which are + supported by the C string functions we have 256 characters. + Before inserting marks for the stop characters we clear the whole + table. */ + movl %edi, %edx + subl $256, %esp + cfi_adjust_cfa_offset (256) + movl $64, %ecx + movl %esp, %edi + xorl %eax, %eax + cld + rep + stosl + + /* Note: %ecx = 0 !!! */ + movl %edx, %edi + + movl STR(%esp), %edx /* Get start of string. */ + +#ifdef USE_AS_STRTOK_R + /* The value is stored in the third argument. */ + movl SAVE(%esp), %eax + movl (%eax), %eax +#else + /* The value is in the local variable defined above. But + we have to take care for PIC code. */ + movl SAVE_PTR, %eax +#endif + + /* If the pointer is NULL we have to use the stored value of + the last run. */ + cmpl $0, %edx + cmove %eax, %edx + testl %edx, %edx + jz L(returnNULL) +#if __BOUNDED_POINTERS__ +# ifdef USE_AS_STRTOK_R + movl SAVE(%esp), %ecx /* borrow %ecx for a moment */ +# endif + je L(0) + /* Save bounds of incoming non-NULL STR into save area. */ + movl 4+STR(%esp), %eax + movl %eax, 4+SAVE_PTR + movl 8+STR(%esp), %eax + movl %eax, 8+SAVE_PTR +L(0): CHECK_BOUNDS_LOW (%edx, SAVE_PTR) +# ifdef USE_AS_STRTOK_R + xorl %ecx, %ecx /* restore %ecx to zero */ +# endif +#endif + movl DELIM(%esp), %eax /* Get start of delimiter set. */ + CHECK_BOUNDS_LOW (%eax, DELIM(%esp)) + +/* For understanding the following code remember that %ecx == 0 now. + Although all the following instruction only modify %cl we always + have a correct zero-extended 32-bit value in %ecx. */ + +L(2): movb (%eax), %cl /* get byte from stopset */ + testb %cl, %cl /* is NUL char? */ + jz L(1_1) /* yes => start compare loop */ + movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ + + movb 1(%eax), %cl /* get byte from stopset */ + testb $0xff, %cl /* is NUL char? */ + jz L(1_2) /* yes => start compare loop */ + movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ + + movb 2(%eax), %cl /* get byte from stopset */ + testb $0xff, %cl /* is NUL char? */ + jz L(1_3) /* yes => start compare loop */ + movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ + + movb 3(%eax), %cl /* get byte from stopset */ + addl $4, %eax /* increment stopset pointer */ + movb %cl, (%esp,%ecx) /* set corresponding byte in stopset table */ + testb $0xff, %cl /* is NUL char? */ + jnz L(2) /* no => process next dword from stopset */ + +#if __BOUNDED_POINTERS__ + jmp L(1_0) /* pointer is correct for bounds check */ +L(1_3): incl %eax /* adjust pointer for bounds check */ +L(1_2): incl %eax /* ditto */ +L(1_1): incl %eax /* ditto */ +L(1_0): CHECK_BOUNDS_HIGH (%eax, DELIM(%esp), jbe) +#else +L(1_3):; L(1_2):; L(1_1): /* fall through */ +#endif + leal -4(%edx), %eax /* prepare loop */ + + /* We use a neat trick for the following loop. Normally we would + have to test for two termination conditions + 1. a character in the stopset was found + and + 2. the end of the string was found + As a sign that the character is in the stopset we store its + value in the table. The value of NUL is NUL so the loop + terminates for NUL in every case. */ + +L(3): addl $4, %eax /* adjust pointer for full loop round */ + + movb (%eax), %cl /* get byte from string */ + testb %cl, (%esp,%ecx) /* is it contained in stopset? */ + jz L(4) /* no => start of token */ + + movb 1(%eax), %cl /* get byte from string */ + testb %cl, (%esp,%ecx) /* is it contained in stopset? */ + jz L(5) /* no => start of token */ + + movb 2(%eax), %cl /* get byte from string */ + testb %cl, (%esp,%ecx) /* is it contained in stopset? */ + jz L(6) /* no => start of token */ + + movb 3(%eax), %cl /* get byte from string */ + testb %cl, (%esp,%ecx) /* is it contained in stopset? */ + jnz L(3) /* yes => start of loop */ + + incl %eax /* adjust pointer */ +L(6): incl %eax +L(5): incl %eax + + /* Now we have to terminate the string. */ + +L(4): leal -4(%eax), %edx /* We use %EDX for the next run. */ + +L(7): addl $4, %edx /* adjust pointer for full loop round */ + + movb (%edx), %cl /* get byte from string */ + cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ + je L(8) /* yes => return */ + + movb 1(%edx), %cl /* get byte from string */ + cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ + je L(9) /* yes => return */ + + movb 2(%edx), %cl /* get byte from string */ + cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ + je L(10) /* yes => return */ + + movb 3(%edx), %cl /* get byte from string */ + cmpb %cl, (%esp,%ecx) /* is it contained in skipset? */ + jne L(7) /* no => start loop again */ + + incl %edx /* adjust pointer */ +L(10): incl %edx +L(9): incl %edx + +L(8): cmpl %eax, %edx + je L(returnNULL) /* There was no token anymore. */ + + movb $0, (%edx) /* Terminate string. */ + + /* Are we at end of string? */ + cmpb $0, %cl + leal 1(%edx), %ecx + cmovne %ecx, %edx + + /* Store the pointer to the next character. */ +#ifdef USE_AS_STRTOK_R + movl SAVE(%esp), %ecx +#endif + movl %edx, SAVE_PTR + CHECK_BOUNDS_HIGH (%edx, SAVE_PTR, jb) + RETURN_BOUNDED_POINTER (SAVE_PTR) + +L(epilogue): + /* Remove the stopset table. */ + addl $256, %esp + cfi_adjust_cfa_offset (-256) +#if !defined USE_AS_STRTOK_R && defined PIC + popl %ebx + cfi_adjust_cfa_offset (-4) + cfi_restore (ebx) +#endif + LEAVE + RET_PTR + +L(returnNULL): + xorl %eax, %eax +#ifdef USE_AS_STRTOK_R + movl SAVE(%esp), %ecx +#endif + movl %edx, SAVE_PTR + RETURN_NULL_BOUNDED_POINTER + jmp L(epilogue) + +END (BP_SYM (FUNCTION)) diff --git a/libc/sysdeps/i386/i686/strtok_r.S b/libc/sysdeps/i386/i686/strtok_r.S new file mode 100644 index 000000000..1c24ca85f --- /dev/null +++ b/libc/sysdeps/i386/i686/strtok_r.S @@ -0,0 +1,5 @@ +#define FUNCTION __strtok_r +#define USE_AS_STRTOK_R 1 +#include <sysdeps/i386/i686/strtok.S> +weak_alias (BP_SYM (__strtok_r), BP_SYM (strtok_r)) +strong_alias (BP_SYM (__strtok_r), BP_SYM (__GI___strtok_r)) diff --git a/libc/sysdeps/i386/i686/tst-stack-align.h b/libc/sysdeps/i386/i686/tst-stack-align.h new file mode 100644 index 000000000..e1894c65e --- /dev/null +++ b/libc/sysdeps/i386/i686/tst-stack-align.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2003 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 Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <stdio.h> +#include <stdint.h> +#ifndef __SSE__ +#include_next <tst-stack-align.h> +#else +#include <xmmintrin.h> + +#define TEST_STACK_ALIGN() \ + ({ \ + __m128 _m; \ + double _d = 12.0; \ + long double _ld = 15.0; \ + int _ret = 0; \ + printf ("__m128: %p %zu\n", &_m, __alignof (__m128)); \ + if ((((uintptr_t) &_m) & (__alignof (__m128) - 1)) != 0) \ + _ret = 1; \ + \ + printf ("double: %g %p %zu\n", _d, &_d, __alignof (double)); \ + if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0) \ + _ret = 1; \ + \ + printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double)); \ + if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0) \ + _ret = 1; \ + _ret; \ + }) +#endif |