Optimized implementation for x86-64.
authoraj <aj>
Sat, 31 Aug 2002 17:33:34 +0000 (17:33 +0000)
committeraj <aj>
Sat, 31 Aug 2002 17:33:34 +0000 (17:33 +0000)
sysdeps/x86_64/memcpy.S [new file with mode: 0644]
sysdeps/x86_64/mempcpy.S [new file with mode: 0644]
sysdeps/x86_64/strtok.S [new file with mode: 0644]
sysdeps/x86_64/strtok_r.S [new file with mode: 0644]

diff --git a/sysdeps/x86_64/memcpy.S b/sysdeps/x86_64/memcpy.S
new file mode 100644 (file)
index 0000000..1339036
--- /dev/null
@@ -0,0 +1,92 @@
+/* Highly optimized version for x86-64.
+   Copyright (C) 1997, 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on i586 version 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>
+#include "asm-syntax.h"
+#include "bp-sym.h"
+#include "bp-asm.h"
+
+/* BEWARE: `#ifdef memcpy' means that memcpy is redefined as `mempcpy',
+   and the return value is the byte after the last one copied in
+   the destination. */
+#define MEMPCPY_P (defined memcpy)
+
+        .text
+ENTRY (BP_SYM (memcpy))
+       /* Cutoff for the big loop is a size of 32 bytes since otherwise
+          the loop will never be entered.  */
+       cmpq    $32, %rdx
+       movq    %rdx, %rcx
+#if !MEMPCPY_P
+       movq    %rdi, %r10      /* Save value. */
+#endif
+
+       /* We need this in any case.  */
+       cld
+
+       jbe     1f
+
+       /* Align destination.  */
+       movq    %rdi, %rax
+       negq    %rax
+       andq    $3, %rax
+       subq    %rax, %rcx
+       xchgq   %rax, %rcx
+
+       rep; movsb
+
+       movq    %rax, %rcx
+       subq    $32, %rcx
+       js      2f
+
+       .p2align 4
+3:
+
+       /* Now correct the loop counter.  Please note that in the following
+          code the flags are not changed anymore.  */
+       subq    $32, %rcx
+
+       movq    (%rsi), %rax
+       movq    8(%rsi), %rdx
+       movq    16(%rsi), %r8
+       movq    24(%rsi), %r9
+       movq    %rax, (%rdi)
+       movq    %rdx, 8(%rdi)
+       movq    %r8, 16(%rdi)
+       movq    %r9, 24(%rdi)
+
+       leaq    32(%rsi), %rsi
+       leaq    32(%rdi), %rdi
+
+       jns     3b
+
+       /* Correct extra loop counter modification.  */
+2:     addq    $32, %rcx
+1:     rep; movsb
+
+#if MEMPCPY_P
+       movq    %rdi, %rax              /* Set return value.  */
+#else
+       movq    %r10, %rax              /* Set return value.  */
+       
+#endif
+       ret
+
+END (BP_SYM (memcpy))
diff --git a/sysdeps/x86_64/mempcpy.S b/sysdeps/x86_64/mempcpy.S
new file mode 100644 (file)
index 0000000..38fdd05
--- /dev/null
@@ -0,0 +1,5 @@
+#define memcpy __mempcpy
+#include <sysdeps/x86_64/memcpy.S>
+
+libc_hidden_def (BP_SYM (__mempcpy))
+weak_alias (BP_SYM (__mempcpy), BP_SYM (mempcpy))
diff --git a/sysdeps/x86_64/strtok.S b/sysdeps/x86_64/strtok.S
new file mode 100644 (file)
index 0000000..771bd2d
--- /dev/null
@@ -0,0 +1,208 @@
+/* strtok (str, delim) -- Return next DELIM separated token from STR.
+   For AMD x86-64.
+   Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Based on i686 version 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 the strtok and strtok_r functions:
+
+   strtok:
+       INPUT PARAMETER:
+       str             %rdi
+       delim           %rsi
+
+   strtok_r:
+       INPUT PARAMETER:
+       str             %rdi
+       delim           %rsi
+       save_ptr        %rdx
+
+   We do a common implementation here.  */
+
+#ifdef USE_AS_STRTOK_R
+# define SAVE_PTR (%r9)
+#else
+       .bss
+       .local save_ptr
+       ASM_TYPE_DIRECTIVE (save_ptr, @object)
+       .size save_ptr, 8
+save_ptr:
+       .space 8
+
+# ifdef PIC
+#  define SAVE_PTR save_ptr(%rip)
+# else
+#  define SAVE_PTR save_ptr
+# endif
+
+# define FUNCTION strtok
+#endif
+
+       .text
+ENTRY (BP_SYM (FUNCTION))
+       /* 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.  */
+       movq %rdi, %r8                  /* Save value.  */
+       subq $256, %rsp                 /* Make space for 256 bytes.  */
+       movq $32,  %rcx                 /* 32*8 bytes = 256 bytes.  */
+       movq %rsp, %rdi
+       xorq %rax, %rax                 /* We store 0s.  */
+       cld
+       rep
+       stosq
+
+       /* Note: %rcx = 0 !!! */
+
+#ifdef USE_AS_STRTOK_R
+       /* The value is stored in the third argument.  */
+       movq %rdx, %rax
+       movq %rdx, %r9          /* Save value - see def. of SAVE_PTR.  */
+       movq (%rax), %rax
+#else
+       /* The value is in the local variable defined above.  But
+          we have to take care for PIC code.  */
+       movq SAVE_PTR, %rax
+#endif
+       movq %r8, %rdx          /* Get start of string.  */
+
+       /* If the pointer is NULL we have to use the stored value of
+          the last run.  */
+       cmpq $0, %rdx
+       cmove %rax, %rdx
+       testq %rdx, %rdx
+       jz L(returnNULL)
+       movq %rsi, %rax         /* Get start of delimiter set.  */
+
+/* For understanding the following code remember that %rcx == 0 now.
+   Although all the following instruction only modify %cl we always
+   have a correct zero-extended 64-bit value in %rcx.  */
+
+L(2):  movb (%rax), %cl        /* get byte from stopset */
+       testb %cl, %cl          /* is NUL char? */
+       jz L(1)                 /* yes => start compare loop */
+       movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
+
+       movb 1(%rax), %cl       /* get byte from stopset */
+       testb $0xff, %cl        /* is NUL char? */
+       jz L(1)                 /* yes => start compare loop */
+       movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
+
+       movb 2(%rax), %cl       /* get byte from stopset */
+       testb $0xff, %cl        /* is NUL char? */
+       jz L(1)                 /* yes => start compare loop */
+       movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
+
+       movb 3(%rax), %cl       /* get byte from stopset */
+       addq $4, %rax           /* increment stopset pointer */
+       movb %cl, (%rsp,%rcx)   /* set corresponding byte in stopset table */
+       testb $0xff, %cl        /* is NUL char? */
+       jnz L(2)                /* no => process next dword from stopset */
+
+L(1):
+
+       leaq -4(%rdx), %rax     /* 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):  addq $4, %rax           /* adjust pointer for full loop round */
+
+       movb (%rax), %cl        /* get byte from string */
+       testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
+       jz L(4)                 /* no => start of token */
+
+       movb 1(%rax), %cl       /* get byte from string */
+       testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
+       jz L(5)                 /* no => start of token */
+
+       movb 2(%rax), %cl       /* get byte from string */
+       testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
+       jz L(6)                 /* no => start of token */
+
+       movb 3(%rax), %cl       /* get byte from string */
+       testb %cl, (%rsp,%rcx)  /* is it contained in stopset? */
+       jnz L(3)                /* yes => start of loop */
+
+       incq %rax               /* adjust pointer */
+L(6):  incq %rax
+L(5):  incq %rax
+
+       /* Now we have to terminate the string.  */
+
+L(4):  leaq -4(%rax), %rdx     /* We use %rDX for the next run.  */
+
+L(7):  addq $4, %rdx           /* adjust pointer for full loop round */
+
+       movb (%rdx), %cl        /* get byte from string */
+       cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
+       je L(8)                 /* yes => return */
+
+       movb 1(%rdx), %cl       /* get byte from string */
+       cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
+       je L(9)                 /* yes => return */
+
+       movb 2(%rdx), %cl       /* get byte from string */
+       cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
+       je L(10)                /* yes => return */
+
+       movb 3(%rdx), %cl       /* get byte from string */
+       cmpb %cl, (%rsp,%rcx)   /* is it contained in skipset? */
+       jne L(7)                /* no => start loop again */
+
+       incq %rdx               /* adjust pointer */
+L(10): incq %rdx
+L(9):  incq %rdx
+
+L(8):  cmpq %rax, %rdx
+       je L(returnNULL)        /* There was no token anymore.  */
+
+       movb $0, (%rdx)         /* Terminate string.  */
+
+       /* Are we at end of string?  */
+       cmpb $0, %cl
+       leaq 1(%rdx), %rcx
+       cmovne %rcx, %rdx
+
+       /* Store the pointer to the next character.  */
+       movq %rdx, SAVE_PTR
+
+L(epilogue):
+       /* Remove the stopset table.  */
+       addq $256, %rsp
+       retq
+
+L(returnNULL):
+       xorq %rax, %rax
+       jmp L(epilogue)
+
+END (BP_SYM (FUNCTION))
diff --git a/sysdeps/x86_64/strtok_r.S b/sysdeps/x86_64/strtok_r.S
new file mode 100644 (file)
index 0000000..0248f27
--- /dev/null
@@ -0,0 +1,4 @@
+#define FUNCTION __strtok_r
+#define USE_AS_STRTOK_R        1
+#include <sysdeps/x86_64/strtok.S>
+weak_alias (BP_SYM (__strtok_r), BP_SYM (strtok_r))