From 8f5ca04bc7fd53741d80117df992995ace8f6d2d Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 16 Oct 1995 01:37:51 +0000 Subject: Sat Oct 14 02:52:36 1995 Ulrich Drepper * malloc/malloc.c (_malloc_internal): Performance fix. Move if statement out of loop. * stdio/_itoa.c, stdio/_itoa.h: Complete rewrite. Much faster implementation using GMP functions. Contributed by Torbjorn Granlund and Ulrich Drepper. * stdio/test_rdwr.c: Include . * sysdeps/i386/i586/Implies: New file. New highly optimized string functions for i[345]86. * sysdeps/i386/memchr.S, sysdeps/i386/memcmp.S: New files. * sysdeps/i386/stpcpy.S, sysdeps/i386/stpncpy.S: New files. * sysdeps/i386/strchr.S, sysdeps/i386/strcspn.S: New files. * sysdeps/i386/strpbrk.S, sysdeps/i386/strrchr.S: New files. * sysdeps/i386/strspn.S, sysdeps/i386/i486/strcat.S: New files. * sysdeps/i386/i486/strlen.S, sysdeps/i386/i586/strchr.S: New files. * sysdeps/i386/i586/strlen.S: New file. * sysdeps/i386/memchr.c: Removed. There is now an assembler version. * sysdeps/i386/i586/memcopy.h (WORD_COPY_BWD): Parameters did not correspond to used values. * sysdeps/unix/sysv/linux/nfs/nfs.h: New file. Simply a wrapper around a kernel header file. * sysdeps/unix/sysv/linux/Dist: Add it. * sysdeps/unix/sysv/linux/Makefile [$(subdir)=sunrpc] (headers): Likewise. * sysdeps/unix/sysv/linux/local_lim.h: Rewrite. Instead of defining ourself we use a kernel header file. * sysdeps/unix/sysv/linux/i386/sysdep.h (DO_CALL): Optimize system call handler for i586. * sysdeps/unix/sysv/linux/sys/param.h: Add copyright and clean up. Sat Oct 14 02:52:36 1995 Ulrich Drepper * malloc/malloc.c (_malloc_internal): Performance fix. Move if statement out of loop. * stdio/_itoa.c, stdio/_itoa.h: Complete rewrite. Much faster implementation using GMP functions. Contributed by Torbjorn Granlund and Ulrich Drepper. * stdio/test_rdwr.c: Include . * sysdeps/i386/i586/Implies: New file. New highly optimized string functions for i[345]86. * sysdeps/i386/memchr.S, sysdeps/i386/memcmp.S: New files. * sysdeps/i386/stpcpy.S, sysdeps/i386/stpncpy.S: New files. * sysdeps/i386/strchr.S, sysdeps/i386/strcspn.S: New files. * sysdeps/i386/strpbrk.S, sysdeps/i386/strrchr.S: New files. * sysdeps/i386/strspn.S, sysdeps/i386/i486/strcat.S: New files. * sysdeps/i386/i486/strlen.S, sysdeps/i386/i586/strchr.S: New files. * sysdeps/i386/i586/strlen.S: New file. * sysdeps/i386/memchr.c: Removed. There is now an assembler version. * sysdeps/i386/i586/memcopy.h (WORD_COPY_BWD): Parameters did not correspond to used values. * sysdeps/unix/sysv/linux/nfs/nfs.h: New file. Simply a wrapper around a kernel header file. * sysdeps/unix/sysv/linux/Dist: Add it. * sysdeps/unix/sysv/linux/Makefile [$(subdir)=sunrpc] (headers): Likewise. * sysdeps/unix/sysv/linux/local_lim.h: Rewrite. Instead of defining ourself we use a kernel header file. * sysdeps/unix/sysv/linux/i386/sysdep.h (DO_CALL): Optimize system call handler for i586. * sysdeps/unix/sysv/linux/sys/param.h: Add copyright and clean up. --- sysdeps/i386/stpncpy.S | 143 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 sysdeps/i386/stpncpy.S (limited to 'sysdeps/i386/stpncpy.S') diff --git a/sysdeps/i386/stpncpy.S b/sysdeps/i386/stpncpy.S new file mode 100644 index 0000000000..59192e66c9 --- /dev/null +++ b/sysdeps/i386/stpncpy.S @@ -0,0 +1,143 @@ +/* stpncpy -- copy no more then N bytes from SRC to DEST, returning the + address of the terminating '\0' in DEST. +For Intel 80x86, x>=3. +Copyright (C) 1994, 1995 Free Software Foundation, Inc. +Contributed by Ulrich Drepper +Some bug fixes by Alan Modra + - original wrote n+1 chars in some cases. + - stpncpy() ought to behave like strncpy() ie. not null-terminate + if limited by n. glibc-1.09 stpncpy() does this. +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., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include +#include "asm-syntax.h" + +/* + INPUT PARAMETERS: + dest (sp + 4) + src (sp + 8) + maxlen (sp + 12) +*/ + + .text +ENTRY (__stpncpy) + + pushl %esi + + movl 8(%esp), %eax /* load destination pointer */ + movl 12(%esp), %esi /* load source pointer */ + movl 16(%esp), %ecx /* load maximal length */ + + subl %eax, %esi /* magic: reduce number of loop variants + to one using addressing mode */ + jmp L1 /* jump to loop "head" */ + + ALIGN(4) + + /* Four times unfolded loop with two loop counters. We get the + the third value (the source address) by using the index+base + adressing mode. */ +L2: movb (%eax,%esi), %dl /* load current char */ + movb %dl, (%eax) /* and store it */ + testb %dl, %dl /* was it NUL? */ + jz L7 /* yes, then exit */ + + movb 1(%eax,%esi), %dl /* load current char */ + movb %dl, 1(%eax) /* and store it */ + testb %dl, %dl /* was it NUL? */ + jz L6 /* yes, then exit */ + + movb 2(%eax,%esi), %dl /* load current char */ + movb %dl, 2(%eax) /* and store it */ + testb %dl, %dl /* was it NUL? */ + jz L5 /* yes, then exit */ + + movb 3(%eax,%esi), %dl /* load current char */ + movb %dl, 3(%eax) /* and store it */ + testb %dl, %dl /* was it NUL? */ + jz L4 /* yes, then exit */ + + addl $4, %eax /* increment loop counter for full round */ + +L1: subl $4, %ecx /* still more than 4 bytes allowed? */ + jae L2 /* yes, then go to start of loop */ + + /* The maximal remaining 15 bytes are not processed in a loop. */ + + addl $4, %ecx /* correct above subtraction */ + jz L9 /* maximal allowed char reached => go to end */ + + movb (%eax,%esi), %dl /* load current char */ + movb %dl, (%eax) /* and store it */ + testb %dl, %dl /* was it NUL? */ + jz L3 /* yes, then exit */ + + incl %eax /* increment pointer */ + decl %ecx /* decrement length counter */ + jz L9 /* no more allowed => exit */ + + movb (%eax,%esi), %dl /* load current char */ + movb %dl, (%eax) /* and store it */ + testb %dl, %dl /* was it NUL? */ + jz L3 /* yes, then exit */ + + incl %eax /* increment pointer */ + decl %ecx /* decrement length counter */ + jz L9 /* no more allowed => exit */ + + movb (%eax,%esi), %dl /* load current char */ + movb %dl, (%eax) /* and store it */ + testb %dl, %dl /* was it NUL? */ + jz L3 /* yes, then exit */ + + incl %eax /* increment pointer */ + jmp L9 /* we don't have to test for counter underflow + because we know we had a most 3 bytes + remaining => exit */ + + /* When coming from the main loop we have to adjust the pointer. */ +L4: decl %ecx /* decrement counter */ + incl %eax /* increment pointer */ + +L5: decl %ecx /* increment pointer */ + incl %eax /* increment pointer */ + +L6: decl %ecx /* increment pointer */ + incl %eax /* increment pointer */ +L7: + + addl $3, %ecx /* correct pre-decrementation of counter + at the beginning of the loop; but why 3 + and not 4? Very simple, we have to count + the NUL char we already wrote. */ + jz L9 /* counter is also 0 => exit */ + + /* We now have to fill the rest of the buffer with NUL. This + is done in a tricky way. Please note that the adressing mode + used below is not the same we used above. Here we use the + %ecx register. */ +L8: + movb $0, (%ecx,%eax) /* store NUL char */ +L3: decl %ecx /* all bytes written? */ + jnz L8 /* no, then again */ + +L9: popl %esi /* restore saved register content */ + + ret + +weak_alias (__stpncpy, stpncpy) -- cgit v1.2.3