diff options
Diffstat (limited to 'sysdeps')
-rw-r--r-- | sysdeps/i386/bits/string.h | 8 | ||||
-rw-r--r-- | sysdeps/i386/i686/strtok.S | 240 | ||||
-rw-r--r-- | sysdeps/i386/i686/strtok_r.S | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/getcwd.c | 59 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/chown.c | 12 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/i686/sysdep.h | 71 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/sysdep.h | 4 |
7 files changed, 386 insertions, 12 deletions
diff --git a/sysdeps/i386/bits/string.h b/sysdeps/i386/bits/string.h index b95ec8a4c2..6885cbb019 100644 --- a/sysdeps/i386/bits/string.h +++ b/sysdeps/i386/bits/string.h @@ -72,7 +72,7 @@ __memcpy_c (void *__dest, __const void *__src, size_t __n) *(2 + (const unsigned short int *) __src); return __dest; case 8: - *(unsigned long int *) __dest = *(const unsigned long int *) __to; + *(unsigned long int *) __dest = *(const unsigned long int *) __src; *(1 + (unsigned long int *) __dest) = *(1 + (const unsigned long int *) __src); return __dest; @@ -177,13 +177,13 @@ __memset_cc (void *__s, unsigned long int __pattern, size_t __n) switch (__n) { case 0: - return s; + return __s; case 1: *(unsigned char *) __s = __pattern; return __s; case 2: *(unsigned short int *) __s = __pattern; - return s; + return __s; case 3: *(unsigned short int *) __s = __pattern; *(2 + (unsigned char *) __s) = __pattern; @@ -210,7 +210,7 @@ __memset_cc (void *__s, unsigned long int __pattern, size_t __n) __COMMON_CODE ("\n\tstosb"); return __s; case 2: - __COMMON__CODE ("\n\tstosw"); + __COMMON_CODE ("\n\tstosw"); return s; case 3: __COMMON_CODE ("\n\tstosw\n\tstosb"); diff --git a/sysdeps/i386/i686/strtok.S b/sysdeps/i386/i686/strtok.S new file mode 100644 index 0000000000..62d54c4e1a --- /dev/null +++ b/sysdeps/i386/i686/strtok.S @@ -0,0 +1,240 @@ +/* strtok (str, delim) -- Return next DELIM separated token from STR. + For Intel 80686. + Copyright (C) 1998 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 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 <sysdep.h> +#include "asm-syntax.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. */ + +#ifndef USE_AS_STRTOK_R + .bss + .local save_ptr + ASM_TYPE_DIRECTIVE (save_ptr, @object) + .size save_ptr, 4 +save_ptr: + .space 4 + +#define FUNCTION strtok +#endif + + .text + +#if !defined USE_AS_STRTOK_R && defined PIC +0: movl (%esp), %ebx + ret +#endif + +ENTRY (FUNCTION) + +#if !defined USE_AS_STRTOK_R && defined PIC + pushl %ebx /* Save PIC register. */ + 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 + movl $64, %ecx + movl %esp, %edi + xorl %eax, %eax + rep + stosl + + /* Note: %ecx = 0 !!! */ + movl %edx, %edi + +#if !defined USE_AS_STRTOK_R && defined PIC + movl 264(%esp), %edx /* Get start of string. */ +#else + movl 260(%esp), %edx /* Get start of string. */ +#endif + +#ifdef USE_AS_STRTOK_R + /* The value is stored in the third argument. */ + movl 268(%esp), %eax + movl (%eax), %eax +#else + /* The value is in the local variable defined above. But + we have to take care for PIC code. */ +# ifndef PIC + movl save_ptr, %eax +# else + movl save_ptr@GOTOFF(%ebx), %eax +# endif +#endif + + /* If the pointer is NULL we have to use the stored value of + the last run. */ + cmpl $0, %edx + cmove %eax, %edx + +#if !defined USE_AS_STRTOK_R && defined PIC + movl 268(%esp), %eax /* Get start of delimiter set. */ +#else + movl 264(%esp), %eax /* Get start of delimiter set. */ +#endif + +/* 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) /* 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) /* 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) /* 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 */ + +L(1): 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): /* Remove the stopset table. */ + addl $256, %esp + + 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 12(%esp), %ecx + movl %edx, (%ecx) +#else +# ifndef PIC + movl %edx, save_ptr +# else + movl %edx, save_ptr@GOTOFF(%ebx) + popl %ebx +# endif +#endif + ret + +L(returnNULL): + xorl %eax, %eax + + /* Store current pointer for next round. */ +#ifdef USE_AS_STRTOK_R + movl 12(%esp), %ecx + movl %edx, (%ecx) +#else +# ifndef PIC + movl %edx, save_ptr +# else + movl %edx, save_ptr@GOTOFF(%ebx) + popl %ebx +# endif +#endif + ret +END (FUNCTION) diff --git a/sysdeps/i386/i686/strtok_r.S b/sysdeps/i386/i686/strtok_r.S new file mode 100644 index 0000000000..70048db2c4 --- /dev/null +++ b/sysdeps/i386/i686/strtok_r.S @@ -0,0 +1,4 @@ +#define FUNCTION __strtok_r +#define USE_AS_STRTOK_R 1 +#include <sysdeps/i386/i686/strtok.S> +weak_alias (__strtok_r, strtok_r) diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c index ed649f8fef..0bf9a9fb0e 100644 --- a/sysdeps/unix/sysv/linux/getcwd.c +++ b/sysdeps/unix/sysv/linux/getcwd.c @@ -1,5 +1,5 @@ /* Determine current working directory. Linux version. - Copyright (C) 1997 Free Software Foundation, Inc. + 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. @@ -22,6 +22,7 @@ #include <limits.h> #include <stdlib.h> #include <unistd.h> +#include <sys/syscall.h> /* The "proc" filesystem provides an easy method to retrieve the value. @@ -31,10 +32,20 @@ the proc filesystem mounted. Use the POSIX implementation in this case. */ static char *generic_getcwd (char *buf, size_t size) internal_function; +#ifdef __NR_getcwd +/* Kernel 2.1.92 introduced a third way to get the current working + directory: a syscall. We've got to be careful that even when + compiling under 2.1.92+ the libc still runs under older kernels. */ +extern int __syscall_getcwd (char *buf, unsigned long size); +static no_syscall_getcwd; +static int no_new_dcache = 1; +#else +static int no_new_dcache; +#endif + char * __getcwd (char *buf, size_t size) { - static int no_new_dcache = 0; int save_errno; char *path; int n; @@ -66,6 +77,41 @@ __getcwd (char *buf, size_t size) save_errno = errno; +#ifdef __NR_getcwd + if (!no_syscall_getcwd) + { + int retval; + + do + retval = __syscall_getcwd (path, alloc_size); + if (retval >= 0) + { + if (buf == NULL) + { + buf = realloc (path, strlen (path) + 1); + if (buf == NULL) + /* `relloc' failed but we still have the original string. */ + buf = path; + } + return buf; + } + + if (errno == ENOSYS) + { + no_syscall_getcwd = 1; + no_new_dcache = 0; /* Now we will try the /proc method. */ + } + else if (errno != ERANGE || buf != NULL) + { + if (buf == NULL) + free (path); + return NULL; + } + + __set_errno (save_errno); + } +#endif + n = __readlink ("/proc/self/cwd", path, alloc_size - 1); if (n != -1) { @@ -79,7 +125,14 @@ __getcwd (char *buf, size_t size) } path[n] = '\0'; - return buf ?: (char *) realloc (path, (size_t) n + 1); + if (buf == NULL) + { + buf = realloc (path, (size_t) n + 1); + if (buf == NULL) + /* `relloc' failed but we still have the original string. */ + buf = path; + } + return buf; } else no_new_dcache = 1; diff --git a/sysdeps/unix/sysv/linux/i386/chown.c b/sysdeps/unix/sysv/linux/i386/chown.c index e985ce0dae..7536b26923 100644 --- a/sysdeps/unix/sysv/linux/i386/chown.c +++ b/sysdeps/unix/sysv/linux/i386/chown.c @@ -59,9 +59,15 @@ __real_chown (const char *file, uid_t owner, gid_t group) #endif -#if !defined __NR_lchown || \ - (defined HAVE_ELF && defined PIC && defined DO_VERSIONING) -/* compiling under older kernels or for compatibiity */ +#ifndef __NR_lchown +/* Compiling under older kernels. */ +int +__chown_is_lchown (const char *file, uid_t owner, gid_t group) +{ + return __syscall_chown (file, owner, group); +} +#elif defined HAVE_ELF && defined PIC && defined DO_VERSIONING +/* Compiling for compatibiity. */ int __chown_is_lchown (const char *file, uid_t owner, gid_t group) { diff --git a/sysdeps/unix/sysv/linux/i386/i686/sysdep.h b/sysdeps/unix/sysv/linux/i386/i686/sysdep.h new file mode 100644 index 0000000000..001f3fc4d7 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/i686/sysdep.h @@ -0,0 +1,71 @@ +/* Copyright (C) 1998 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 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. */ + +#ifndef _LINUX_I386_I686_SYSDEP_H +#define _LINUX_I386_I686_SYSDEP_H 1 + +/* There is some commonality. */ +#include <sysdeps/unix/sysv/linux/i386/sysdep.h> + +/* We define special versions of the error handler code to match the i686's + deep branch prediction mechanism. */ +#ifdef PIC +# undef SYSCALL_ERROR_HANDLER + +/* Store (- %eax) into errno through the GOT. */ +# ifdef _LIBC_REENTRANT +# define SYSCALL_ERROR_HANDLER \ + .type syscall_error,@function; \ +0:movl (%esp),%ebx; \ + ret; \ +syscall_error: \ + pushl %ebx; \ + call 0b; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + pushl %edx; \ + call __errno_location@PLT; \ + popl %ecx; \ + popl %ebx; \ + movl %ecx, (%eax); \ + movl $-1, %eax; \ + jmp L(pseudo_end); \ + .size syscall_error,.-syscall_error; +/* A quick note: it is assumed that the call to `__errno_location' does + not modify the stack! */ +# else +# define SYSCALL_ERROR_HANDLER \ + .type syscall_error,@function; \ +0:movl (%esp),%ecx; \ + ret; \ +syscall_error: \ + call 0b; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + movl errno@GOT(%ecx), %ecx; \ + movl %edx, (%ecx); \ + movl $-1, %eax; \ + jmp L(pseudo_end); \ + .size syscall_error,.-syscall_error; +# endif /* _LIBC_REENTRANT */ +#endif /* PIC */ + +#endif /* linux/i386/i686/sysdep.h */ diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h index 713bd44524..2bb82a2009 100644 --- a/sysdeps/unix/sysv/linux/i386/sysdep.h +++ b/sysdeps/unix/sysv/linux/i386/sysdep.h @@ -140,10 +140,10 @@ syscall_error: \ %ecx and %edx when we have more than 1 and 2 registers resp. The code below might look a bit long but we have to take care for - the pipelined processors (i586 and up). Here the `pushl' and `popl' + the pipelined processors (i586). Here the `pushl' and `popl' instructions are marked as NP (not pairable) but the exception is two consecutive of these instruction. This gives no penalty on - i386 and i486 processors though. */ + other processors though. */ #undef DO_CALL #define DO_CALL(args, syscall_name) \ |