diff options
Diffstat (limited to 'REORG.TODO/sysdeps/tile/tilegx')
19 files changed, 1366 insertions, 0 deletions
diff --git a/REORG.TODO/sysdeps/tile/tilegx/Implies b/REORG.TODO/sysdeps/tile/tilegx/Implies new file mode 100644 index 0000000000..ade71c1957 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/Implies @@ -0,0 +1 @@ +ieee754/dbl-64/wordsize-64 diff --git a/REORG.TODO/sysdeps/tile/tilegx/Makefile b/REORG.TODO/sysdeps/tile/tilegx/Makefile new file mode 100644 index 0000000000..4281dd98fc --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/Makefile @@ -0,0 +1,35 @@ +include $(common-objpfx)cflags-mcmodel-large.mk + +# Check for gcc to support the command-line switch, and for +# binutils to support the hwN_plt() assembly operators and relocations. +$(common-objpfx)cflags-mcmodel-large.mk: $(common-objpfx)config.make + mcmodel=no; \ + (echo 'int main() { return getuid(); }' | \ + $(CC) -o /dev/null -xc - -mcmodel=large -fpic) && mcmodel=yes; \ + echo "cflags-mcmodel-large = $$mcmodel" > $@ + +ifeq (yes,$(cflags-mcmodel-large)) + +ifeq ($(subdir),csu) +# elf-init.c is in libc_nonshared.o (the end of the shared object) but +# must reach the _init symbol at the very start of the shared object. +CFLAGS-elf-init.c += -mcmodel=large + +# __gmon_start__ is at the very start of the shared object when linked +# with profiling, but calls to libc.so via the PLT at the very end. +CFLAGS-gmon-start.c += -mcmodel=large +endif + +else + +# Don't try to compile assembly code with hwN_plt() directives if the +# toolchain doesn't support -mcmodel=large. +ifeq ($(subdir),csu) +CPPFLAGS-start.S += -DNO_PLT_PCREL +CPPFLAGS-crti.S += -DNO_PLT_PCREL +endif +ifeq ($(subdir),nptl) +CPPFLAGS-pt-crti.S += -DNO_PLT_PCREL +endif + +endif diff --git a/REORG.TODO/sysdeps/tile/tilegx/atomic-machine.h b/REORG.TODO/sysdeps/tile/tilegx/atomic-machine.h new file mode 100644 index 0000000000..e77f6707b0 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/atomic-machine.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _ATOMIC_MACHINE_H +#define _ATOMIC_MACHINE_H 1 + +#include <arch/spr_def.h> + +#ifdef _LP64 +# define __HAVE_64B_ATOMICS 1 +#else +/* tilegx32 does have 64-bit atomics, but assumptions in the semaphore + code mean that unaligned 64-bit atomics will be used if this symbol + is true, and unaligned atomics are not supported on tile. */ +# define __HAVE_64B_ATOMICS 0 +#endif + +#define USE_ATOMIC_COMPILER_BUILTINS 0 +#define ATOMIC_EXCHANGE_USES_CAS 0 + +/* Pick appropriate 8- or 4-byte instruction. */ +#define __atomic_update(mem, v, op) \ + ((__typeof (*(mem))) (__typeof (*(mem) - *(mem))) \ + ((sizeof (*(mem)) == 8) ? \ + __insn_##op ((void *) (mem), (int64_t) (__typeof((v) - (v))) (v)) : \ + (sizeof (*(mem)) == 4) ? \ + __insn_##op##4 ((void *) (mem), (int32_t) (__typeof ((v) - (v))) (v)) : \ + __atomic_error_bad_argument_size())) + +#define atomic_compare_and_exchange_val_acq(mem, n, o) \ + ({ __insn_mtspr (SPR_CMPEXCH_VALUE, (int64_t) (__typeof ((o) - (o))) (o)); \ + __atomic_update (mem, n, cmpexch); }) +#define atomic_exchange_acq(mem, newvalue) \ + __atomic_update (mem, newvalue, exch) +#define atomic_exchange_and_add(mem, value) \ + __atomic_update (mem, value, fetchadd) +#define atomic_and_val(mem, mask) \ + __atomic_update (mem, mask, fetchand) +#define atomic_or_val(mem, mask) \ + __atomic_update (mem, mask, fetchor) +#define atomic_decrement_if_positive(mem) \ + __atomic_update (mem, -1, fetchaddgez) + +#include <sysdeps/tile/atomic-machine.h> + +#endif /* atomic-machine.h */ diff --git a/REORG.TODO/sysdeps/tile/tilegx/bits/wordsize.h b/REORG.TODO/sysdeps/tile/tilegx/bits/wordsize.h new file mode 100644 index 0000000000..9dc4da5de9 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/bits/wordsize.h @@ -0,0 +1,11 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#ifdef __LP64__ +# define __WORDSIZE 64 +# define __WORDSIZE_TIME64_COMPAT32 1 +#else +# define __WORDSIZE 32 +# define __WORDSIZE_TIME64_COMPAT32 0 +# define __WORDSIZE32_SIZE_ULONG 0 +# define __WORDSIZE32_PTRDIFF_LONG 0 +#endif diff --git a/REORG.TODO/sysdeps/tile/tilegx/memchr.c b/REORG.TODO/sysdeps/tile/tilegx/memchr.c new file mode 100644 index 0000000000..7da0f79da2 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/memchr.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +void * +__memchr (const void *s, int c, size_t n) +{ + const uint64_t *last_word_ptr; + const uint64_t *p; + const char *last_byte_ptr; + uintptr_t s_int; + uint64_t goal, before_mask, v, bits; + char *ret; + + if (__builtin_expect (n == 0, 0)) + { + /* Don't dereference any memory if the array is empty. */ + return NULL; + } + + /* Get an aligned pointer. */ + s_int = (uintptr_t) s; + p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + goal = copy_byte(c); + + /* Read the first word, but munge it so that bytes before the array + will not match goal. */ + before_mask = MASK (s_int); + v = (*p | before_mask) ^ (goal & before_mask); + + /* Compute the address of the last byte. */ + last_byte_ptr = (const char *) s + n - 1; + + /* Handle possible addition overflow. */ + if (__glibc_unlikely ((uintptr_t) last_byte_ptr < (uintptr_t) s)) + last_byte_ptr = (const char *) UINTPTR_MAX; + + /* Compute the address of the word containing the last byte. */ + last_word_ptr = (const uint64_t *) ((uintptr_t) last_byte_ptr & -8); + + while ((bits = __insn_v1cmpeq (v, goal)) == 0) + { + if (__builtin_expect (p == last_word_ptr, 0)) + { + /* We already read the last word in the array, so give up. */ + return NULL; + } + v = *++p; + } + + /* We found a match, but it might be in a byte past the end + of the array. */ + ret = ((char *) p) + (CFZ (bits) >> 3); + return (ret <= last_byte_ptr) ? ret : NULL; +} +weak_alias (__memchr, memchr) +libc_hidden_builtin_def (memchr) diff --git a/REORG.TODO/sysdeps/tile/tilegx/memcpy.c b/REORG.TODO/sysdeps/tile/tilegx/memcpy.c new file mode 100644 index 0000000000..c1a2a29860 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/memcpy.c @@ -0,0 +1,272 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <memcopy.h> +#include <arch/chip.h> + +/* How many cache lines ahead should we prefetch? */ +#define PREFETCH_LINES_AHEAD 3 + +void * inhibit_loop_to_libcall +__memcpy (void *__restrict dstv, const void *__restrict srcv, size_t n) +{ + char *__restrict dst1 = (char *) dstv; + const char *__restrict src1 = (const char *) srcv; + const char *__restrict src1_end; + const char *__restrict prefetch; + op_t *__restrict dst8; /* 8-byte pointer to destination memory. */ + op_t final; /* Final bytes to write to trailing word, if any */ + long i; + + if (n < 16) + { + for (; n; n--) + *dst1++ = *src1++; + return dstv; + } + + /* Locate the end of source memory we will copy. Don't prefetch + past this. */ + src1_end = src1 + n - 1; + + /* Prefetch ahead a few cache lines, but not past the end. */ + prefetch = src1; + for (i = 0; i < PREFETCH_LINES_AHEAD; i++) + { + __insn_prefetch (prefetch); + prefetch += CHIP_L2_LINE_SIZE (); + prefetch = (prefetch < src1_end) ? prefetch : src1; + } + + /* Copy bytes until dst is word-aligned. */ + for (; (uintptr_t) dst1 & (sizeof (op_t) - 1); n--) + *dst1++ = *src1++; + + /* 8-byte pointer to destination memory. */ + dst8 = (op_t *) dst1; + + if (__builtin_expect ((uintptr_t) src1 & (sizeof (op_t) - 1), 0)) + { + /* Misaligned copy. Use glibc's _wordcopy_fwd_dest_aligned, but + inline it to avoid prologue/epilogue. TODO: Consider + prefetching and using wh64 as well. */ + void * srci; + op_t a0, a1, a2, a3; + long int dstp = (long int) dst1; + long int srcp = (long int) src1; + long int len = n / OPSIZ; + + /* Save the initial source pointer so we know the number of + bytes to shift for merging two unaligned results. */ + srci = (void *) srcp; + + /* Make SRCP aligned by rounding it down to the beginning of the + `op_t' it points in the middle of. */ + srcp &= -OPSIZ; + + switch (len % 4) + { + case 2: + a1 = ((op_t *) srcp)[0]; + a2 = ((op_t *) srcp)[1]; + len += 2; + srcp += 2 * OPSIZ; + goto do1; + case 3: + a0 = ((op_t *) srcp)[0]; + a1 = ((op_t *) srcp)[1]; + len += 1; + srcp += 2 * OPSIZ; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return dstv; + a3 = ((op_t *) srcp)[0]; + a0 = ((op_t *) srcp)[1]; + len += 0; + srcp += 2 * OPSIZ; + goto do3; + case 1: + a2 = ((op_t *) srcp)[0]; + a3 = ((op_t *) srcp)[1]; + srcp += 2 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do + { + do4: + a0 = ((op_t *) srcp)[0]; + a2 = __insn_dblalign (a2, a3, srci); + ((op_t *) dstp)[0] = a2; + srcp += OPSIZ; + dstp += OPSIZ; + do3: + a1 = ((op_t *) srcp)[0]; + a3 = __insn_dblalign (a3, a0, srci); + ((op_t *) dstp)[0] = a3; + srcp += OPSIZ; + dstp += OPSIZ; + do2: + a2 = ((op_t *) srcp)[0]; + a0 = __insn_dblalign (a0, a1, srci); + ((op_t *) dstp)[0] = a0; + srcp += OPSIZ; + dstp += OPSIZ; + do1: + a3 = ((op_t *) srcp)[0]; + a1 = __insn_dblalign (a1, a2, srci); + ((op_t *) dstp)[0] = a1; + srcp += OPSIZ; + dstp += OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[0] = __insn_dblalign (a2, a3, srci); + + n = n % OPSIZ; + if (n == 0) + return dstv; + + a0 = ((const char *) srcp <= src1_end) ? ((op_t *) srcp)[0] : 0; + + final = __insn_dblalign (a3, a0, srci); + dst8 = (op_t *)(dstp + OPSIZ); + } + else + { + /* Aligned copy. */ + + const op_t *__restrict src8 = (const op_t *) src1; + + /* src8 and dst8 are both word-aligned. */ + if (n >= CHIP_L2_LINE_SIZE ()) + { + /* Copy until 'dst' is cache-line-aligned. */ + for (; (uintptr_t) dst8 & (CHIP_L2_LINE_SIZE () - 1); + n -= sizeof (op_t)) + *dst8++ = *src8++; + + for (; n >= CHIP_L2_LINE_SIZE ();) + { + op_t tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + + /* Prefetch and advance to next line to prefetch, but + don't go past the end. */ + __insn_prefetch (prefetch); + prefetch += CHIP_L2_LINE_SIZE (); + prefetch = (prefetch < src1_end) ? prefetch : + (const char *) src8; + + /* Do all the loads before wh64. This is necessary if + [src8, src8+7] and [dst8, dst8+7] share the same + cache line and dst8 <= src8, as can be the case when + called from memmove, or with code tested on x86 whose + memcpy always works with forward copies. */ + tmp0 = *src8++; + tmp1 = *src8++; + tmp2 = *src8++; + tmp3 = *src8++; + tmp4 = *src8++; + tmp5 = *src8++; + tmp6 = *src8++; + tmp7 = *src8++; + + __insn_wh64 (dst8); + + *dst8++ = tmp0; + *dst8++ = tmp1; + *dst8++ = tmp2; + *dst8++ = tmp3; + *dst8++ = tmp4; + *dst8++ = tmp5; + *dst8++ = tmp6; + *dst8++ = tmp7; + + n -= 64; + } +#if CHIP_L2_LINE_SIZE() != 64 +# error "Fix code that assumes particular L2 cache line size." +#endif + } + + for (; n >= sizeof (op_t); n -= sizeof (op_t)) + *dst8++ = *src8++; + + if (__builtin_expect (n == 0, 1)) + return dstv; + + final = *src8; + } + + /* n != 0 if we get here. Write out any trailing bytes. */ + dst1 = (char *) dst8; +#ifndef __BIG_ENDIAN__ + if (n & 4) + { + *(uint32_t *) dst1 = final; + dst1 += 4; + final >>= 32; + n &= 3; + } + if (n & 2) + { + *(uint16_t *) dst1 = final; + dst1 += 2; + final >>= 16; + n &= 1; + } + if (n) + *(uint8_t *) dst1 = final; +#else + if (n & 4) + { + *(uint32_t *) dst1 = final >> 32; + dst1 += 4; + } + else + { + final >>= 32; + } + if (n & 2) + { + *(uint16_t *) dst1 = final >> 16; + dst1 += 2; + } + else + { + final >>= 16; + } + if (n & 1) + *(uint8_t *) dst1 = final >> 8; +#endif + + return dstv; +} +weak_alias (__memcpy, memcpy) +libc_hidden_builtin_def (memcpy) diff --git a/REORG.TODO/sysdeps/tile/tilegx/memset.c b/REORG.TODO/sysdeps/tile/tilegx/memset.c new file mode 100644 index 0000000000..c6804a9dc6 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/memset.c @@ -0,0 +1,151 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <arch/chip.h> +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +void * inhibit_loop_to_libcall +__memset (void *s, int c, size_t n) +{ + uint64_t *out64; + int n64, to_align64; + uint64_t v64; + uint8_t *out8 = s; + + /* Experimentation shows that a trivial tight loop is a win up until + around a size of 20, where writing a word at a time starts to win. */ +#define BYTE_CUTOFF 20 + +#if BYTE_CUTOFF < 7 + /* This must be at least at least this big, or some code later + on doesn't work. */ +# error "BYTE_CUTOFF is too small." +#endif + + if (n < BYTE_CUTOFF) + { + /* Strangely, this turns out to be the tightest way to write + this loop. */ + if (n != 0) + { + do + { + /* Strangely, combining these into one line performs worse. */ + *out8 = c; + out8++; + } + while (--n != 0); + } + + return s; + } + + /* Align 'out8'. We know n >= 7 so this won't write past the end. */ + while (((uintptr_t) out8 & 7) != 0) + { + *out8++ = c; + --n; + } + + /* Align 'n'. */ + while (n & 7) + out8[--n] = c; + + out64 = (uint64_t *) out8; + n64 = n >> 3; + + /* Tile input byte out to 64 bits. */ + v64 = copy_byte(c); + + /* This must be at least 8 or the following loop doesn't work. */ +#define CACHE_LINE_SIZE_IN_DOUBLEWORDS (CHIP_L2_LINE_SIZE() / 8) + + /* Determine how many words we need to emit before the 'out32' + pointer becomes aligned modulo the cache line size. */ + to_align64 = (-((uintptr_t) out64 >> 3)) & + (CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1); + + /* Only bother aligning and using wh64 if there is at least + one full cache line to process. This check also prevents + overrunning the end of the buffer with alignment words. */ + if (to_align64 <= n64 - CACHE_LINE_SIZE_IN_DOUBLEWORDS) + { + int lines_left; + + /* Align out64 mod the cache line size so we can use wh64. */ + n64 -= to_align64; + for (; to_align64 != 0; to_align64--) + { + *out64 = v64; + out64++; + } + + /* Use unsigned divide to turn this into a right shift. */ + lines_left = (unsigned) n64 / CACHE_LINE_SIZE_IN_DOUBLEWORDS; + + do + { + /* Only wh64 a few lines at a time, so we don't exceed the + maximum number of victim lines. */ + int x = ((lines_left < CHIP_MAX_OUTSTANDING_VICTIMS ()) ? lines_left + : CHIP_MAX_OUTSTANDING_VICTIMS ()); + uint64_t *wh = out64; + int i = x; + int j; + + lines_left -= x; + + do + { + __insn_wh64 (wh); + wh += CACHE_LINE_SIZE_IN_DOUBLEWORDS; + } + while (--i); + + for (j = x * (CACHE_LINE_SIZE_IN_DOUBLEWORDS / 4); j != 0; j--) + { + *out64++ = v64; + *out64++ = v64; + *out64++ = v64; + *out64++ = v64; + } + } + while (lines_left != 0); + + /* We processed all full lines above, so only this many + words remain to be processed. */ + n64 &= CACHE_LINE_SIZE_IN_DOUBLEWORDS - 1; + } + + /* Now handle any leftover values. */ + if (n64 != 0) + { + do + { + *out64 = v64; + out64++; + } + while (--n64 != 0); + } + + return s; +} +weak_alias (__memset, memset) +libc_hidden_builtin_def (memset) diff --git a/REORG.TODO/sysdeps/tile/tilegx/memusage.h b/REORG.TODO/sysdeps/tile/tilegx/memusage.h new file mode 100644 index 0000000000..c91371adcd --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/memusage.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <stdint.h> +#include <arch/spr_def.h> + +#define GETSP() ({ register uintptr_t stack_ptr asm ("sp"); stack_ptr; }) + +#define GETTIME(low,high) \ + { \ + uint64_t cycles = __insn_mfspr (SPR_CYCLE); \ + low = cycles & 0xffffffff; \ + high = cycles >> 32; \ + } + +#include <sysdeps/generic/memusage.h> diff --git a/REORG.TODO/sysdeps/tile/tilegx/rawmemchr.c b/REORG.TODO/sysdeps/tile/tilegx/rawmemchr.c new file mode 100644 index 0000000000..54b4a5c1b8 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/rawmemchr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +void * +__rawmemchr (const void *s, int c) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = copy_byte(c); + + /* Read the first word, but munge it so that bytes before the array + will not match goal. */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & before_mask); + + uint64_t bits; + while ((bits = __insn_v1cmpeq (v, goal)) == 0) + v = *++p; + + return ((char *) p) + (CFZ (bits) >> 3); +} +libc_hidden_def (__rawmemchr) +weak_alias (__rawmemchr, rawmemchr) diff --git a/REORG.TODO/sysdeps/tile/tilegx/strcasestr.c b/REORG.TODO/sysdeps/tile/tilegx/strcasestr.c new file mode 100644 index 0000000000..ecb3e623ca --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/strcasestr.c @@ -0,0 +1,53 @@ +/* Return the offset of one string within another. + Copyright (C) 1994-2017 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, see + <http://www.gnu.org/licenses/>. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +/* Specification. */ +#include <string.h> + +#include <ctype.h> +#include <stdbool.h> +#include <strings.h> + +#define USE_AS_STRCASESTR +#define STRSTR __strcasestr +#define STRSTR2 strcasestr2 +#define STRCHR strcasechr +#define STRSTR_SCAN strcasestr_scan + +#undef strcasestr +#undef __strcasestr + +#ifndef STRCASESTR +#define STRCASESTR __strcasestr +#endif + +#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) + +#define CANON_ELEMENT(c) TOLOWER (c) +#define CMP_FUNC(p1, p2, l) \ + __strncasecmp ((const char *) (p1), (const char *) (p2), l) + +#include "strstr.c" + +#ifndef NO_ALIAS +weak_alias (__strcasestr, strcasestr) +#endif diff --git a/REORG.TODO/sysdeps/tile/tilegx/strchr.c b/REORG.TODO/sysdeps/tile/tilegx/strchr.c new file mode 100644 index 0000000000..36dfd31391 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/strchr.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +#undef strchr + +char * +strchr (const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = copy_byte(c); + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1)); + + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq (v, goal); + + if (__builtin_expect ((zero_matches | goal_matches) != 0, 0)) + break; + + v = *++p; + } + + z = CFZ (zero_matches); + g = CFZ (goal_matches); + + /* If we found c before '\0' we got a match. Note that if c == '\0' + then g == z, and we correctly return the address of the '\0' + rather than NULL. */ + return (g <= z) ? ((char *) p) + (g >> 3) : NULL; +} +weak_alias (strchr, index) +libc_hidden_builtin_def (strchr) diff --git a/REORG.TODO/sysdeps/tile/tilegx/strchrnul.c b/REORG.TODO/sysdeps/tile/tilegx/strchrnul.c new file mode 100644 index 0000000000..e0f13b684e --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/strchrnul.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +char * +__strchrnul (const char *s, int c) +{ + int z, g; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = copy_byte(c); + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1)); + + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq (v, goal); + + if (__builtin_expect ((zero_matches | goal_matches) != 0, 0)) + break; + + v = *++p; + } + + z = CFZ (zero_matches); + g = CFZ (goal_matches); + + /* Return a pointer to the NUL or goal, whichever is first. */ + if (z < g) + g = z; + return ((char *) p) + (g >> 3); +} +weak_alias (__strchrnul, strchrnul) diff --git a/REORG.TODO/sysdeps/tile/tilegx/string-endian.h b/REORG.TODO/sysdeps/tile/tilegx/string-endian.h new file mode 100644 index 0000000000..fe9b073efb --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/string-endian.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <endian.h> +#include <stdint.h> + +/* Provide a set of macros to help keep endianness #ifdefs out of + the string functions. + + MASK: Provide a mask based on the pointer alignment that + sets up non-zero bytes before the beginning of the string. + The MASK expression works because shift counts are taken mod 64. + + NULMASK: Clear bytes beyond a given point in the string. + + CFZ: Find the first zero bit in the 8 string bytes in a long. + + REVCZ: Find the last zero bit in the 8 string bytes in a long. + + STRSHIFT: Shift N bits towards the start of the string. */ + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define MASK(x) (__insn_shl(1ULL, (x << 3)) - 1) +#define NULMASK(x) ((2ULL << x) - 1) +#define CFZ(x) __insn_ctz(x) +#define REVCZ(x) __insn_clz(x) +#define STRSHIFT(x,n) ((x) >> n) +#else +#define MASK(x) (__insn_shl(-2LL, ((-x << 3) - 1))) +#define NULMASK(x) (-2LL << (63 - x)) +#define CFZ(x) __insn_clz(x) +#define REVCZ(x) __insn_ctz(x) +#define STRSHIFT(x,n) ((x) << n) +#endif + +/* Create eight copies of the byte in a uint64_t. Byte Shuffle uses + the bytes of srcB as the index into the dest vector to select a + byte. With all indices of zero, the first byte is copied into all + the other bytes. */ +static inline uint64_t copy_byte(uint8_t byte) +{ + return __insn_shufflebytes(byte, 0, 0); +} diff --git a/REORG.TODO/sysdeps/tile/tilegx/strlen.c b/REORG.TODO/sysdeps/tile/tilegx/strlen.c new file mode 100644 index 0000000000..5cd04acc59 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/strlen.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +size_t +strlen (const char *s) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Read and MASK the first word. */ + uint64_t v = *p | MASK (s_int); + + uint64_t bits; + while ((bits = __insn_v1cmpeqi (v, 0)) == 0) + v = *++p; + + return ((const char *) p) + (CFZ (bits) >> 3) - s; +} +libc_hidden_builtin_def (strlen) diff --git a/REORG.TODO/sysdeps/tile/tilegx/strnlen.c b/REORG.TODO/sysdeps/tile/tilegx/strnlen.c new file mode 100644 index 0000000000..5d73a14926 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/strnlen.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2013-2017 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +/* Find the length of S, but scan at most MAXLEN characters. If no + '\0' terminator is found in that many characters, return MAXLEN. */ +size_t +__strnlen (const char *s, size_t maxlen) +{ + /* When maxlen is 0, can't read any bytes or it might cause a page fault. */ + if (maxlen == 0) + return 0; + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + size_t bytes_read = sizeof (*p) - (s_int & (sizeof (*p) - 1)); + + /* Read and MASK the first word. */ + uint64_t v = *p | MASK (s_int); + + uint64_t bits; + while ((bits = __insn_v1cmpeqi (v, 0)) == 0) + { + if (bytes_read >= maxlen) + { + /* Read maxlen bytes and didn't find the terminator. */ + return maxlen; + } + v = *++p; + bytes_read += sizeof (v); + } + + /* Found '\0', check it is not larger than maxlen */ + size_t len = ((const char *) p) + (CFZ (bits) >> 3) - s; + return (len < maxlen ? len : maxlen); +} +libc_hidden_def (__strnlen) +weak_alias (__strnlen, strnlen) +libc_hidden_def (strnlen) diff --git a/REORG.TODO/sysdeps/tile/tilegx/strrchr.c b/REORG.TODO/sysdeps/tile/tilegx/strrchr.c new file mode 100644 index 0000000000..5a9049e1b9 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/strrchr.c @@ -0,0 +1,68 @@ +/* Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011. + + 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, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdint.h> +#include "string-endian.h" + +char * +strrchr (const char *s, int c) +{ + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = copy_byte(c); + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1)); + const char *found = NULL; + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq (v, goal); + + /* If we found the goal, record the last offset. */ + if (__builtin_expect (goal_matches != 0, 0)) + { + if (__builtin_expect (zero_matches != 0, 0)) + { + /* Clear any goal after the first zero. */ + int first_nul = CFZ (zero_matches); + goal_matches &= NULMASK (first_nul); + } + if (__builtin_expect (goal_matches != 0, 1)) + found = ((char *) p) + 7 - (REVCZ (goal_matches) >> 3); + } + + if (__builtin_expect (zero_matches != 0, 0)) + return (char *) found; + + v = *++p; + } +} +weak_alias (strrchr, rindex) +libc_hidden_builtin_def (strrchr) diff --git a/REORG.TODO/sysdeps/tile/tilegx/strstr.c b/REORG.TODO/sysdeps/tile/tilegx/strstr.c new file mode 100644 index 0000000000..548a92045d --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/strstr.c @@ -0,0 +1,270 @@ +/* Copyright (C) 2013-2017 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. */ + +/* Specification of strstr. */ +#include <string.h> + +#include <stdbool.h> +#include "string-endian.h" + +#define RETURN_TYPE char * +#define AVAILABLE(h, h_l, j, n_l) \ + (!memchr ((h) + (h_l), '\0', (j) + (n_l) - (h_l)) \ + && ((h_l) = (j) + (n_l))) +#include "str-two-way.h" +typeof(two_way_short_needle) two_way_short_needle __attribute__((unused)); + +#undef strstr + +#ifndef STRSTR +#define STRSTR strstr +#endif + +#ifndef STRSTR2 +#define STRSTR2 strstr2 +#endif + +#ifndef STRCHR +#define STRCHR strchr +#endif + +#ifndef STRSTR_SCAN +#define STRSTR_SCAN strstr_scan +#endif + +#ifndef TOLOWER +# define TOLOWER(Ch) (Ch) +#endif + +#ifdef USE_AS_STRCASESTR + +static uint64_t +vec_tolower (uint64_t cc) +{ + /* For Uppercases letters, add 32 to convert to lower case. */ + uint64_t less_than_eq_Z = __insn_v1cmpltui (cc, 'Z' + 1); + uint64_t less_than_A = __insn_v1cmpltui (cc, 'A'); + uint64_t is_upper = __insn_v1cmpne (less_than_eq_Z, less_than_A); + return __insn_v1add (cc,__insn_v1shli (is_upper, 5)); +} + +/* There is no strcasechr() defined, but needed for 1 byte case + of strcasestr(), so create it here. */ + +static char * +strcasechr (const char *s, int c) +{ + int z, g; + + c = tolower (c); + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) s; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the byte for which we are looking. */ + const uint64_t goal = copy_byte(c); + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = + (vec_tolower (*p) | before_mask) ^ (goal & __insn_v1shrui (before_mask, 1)); + + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + + /* Look for the goal byte. */ + goal_matches = __insn_v1cmpeq (v, goal); + + if (__builtin_expect ((zero_matches | goal_matches) != 0, 0)) + break; + + v = vec_tolower (*++p); + } + + z = CFZ (zero_matches); + g = CFZ (goal_matches); + + /* If we found c before '\0' we got a match. Note that if c == '\0' + then g == z, and we correctly return the address of the '\0' + rather than NULL. */ + return (g <= z) ? ((char *) p) + (g >> 3) : NULL; +} + +# define vec_load(p) vec_tolower (*(p)) +# define STRCHR strcasechr +# define CMP_FUNC __strncasecmp + +#else + +# define vec_load(p) (*(p)) +# define STRCHR strchr +# define CMP_FUNC memcmp + +#endif + + +/* Compare 2-character needle using SIMD. */ +static char * +STRSTR2 (const char *haystack_start, const char *needle) +{ + int z, g; + + __insn_prefetch (haystack_start + 64); + + /* Get an aligned pointer. */ + const uintptr_t s_int = (uintptr_t) haystack_start; + const uint64_t *p = (const uint64_t *) (s_int & -8); + + /* Create eight copies of the first byte for which we are looking. */ + const uint64_t byte1 = copy_byte (TOLOWER (*needle)); + /* Create eight copies of the second byte for which we are looking. */ + const uint64_t byte2 = copy_byte (TOLOWER (*(needle + 1))); + + /* Read the first aligned word, but force bytes before the string to + match neither zero nor goal (we make sure the high bit of each byte + is 1, and the low 7 bits are all the opposite of the goal byte). */ + const uint64_t before_mask = MASK (s_int); + uint64_t v = + (vec_load (p) | before_mask) ^ (byte1 & __insn_v1shrui (before_mask, 1)); + + uint64_t zero_matches, goal_matches; + while (1) + { + /* Look for a terminating '\0'. */ + zero_matches = __insn_v1cmpeqi (v, 0); + uint64_t byte1_matches = __insn_v1cmpeq (v, byte1); + if (__builtin_expect (zero_matches != 0, 0)) + { + /* This is the last vector. Don't worry about matches + crossing into the next vector. Shift the second byte + back 1 byte to align it with the first byte, then and to + check for both matching. Each vector has a 1 in the LSB + of the byte if there was match. */ + uint64_t byte2_matches = __insn_v1cmpeq (v, byte2); + goal_matches = byte1_matches & STRSHIFT (byte2_matches, 8); + break; + } + else + { + /* This is not the last vector, so load the next vector now. + And compare byte2 to the 8-bytes starting 1 byte shifted from v, + which goes 1-byte into the next vector. */ + uint64_t v2 = vec_load (p + 1); + if (byte1_matches) + { + /* 8-bytes starting 1 byte into v. */ + v = __insn_dblalign (v, v2, (void*)1); + uint64_t byte2_matches_shifted = __insn_v1cmpeq (v, byte2); + goal_matches = byte1_matches & byte2_matches_shifted; + if (__builtin_expect (goal_matches != 0, 0)) + break; + } + __insn_prefetch (p + 4); + /* Move to next vector. */ + v = v2; + p++; + } + } + + z = CFZ (zero_matches); + g = CFZ (goal_matches); + + /* If we found the match before '\0' we got a true match. Note that + if c == '\0' then g == z, and we correctly return the address of + the '\0' rather than NULL. */ + return (g <= z) ? ((char *) p) + (g >> 3) : NULL; +} + +/* Scan for NEEDLE, using the first two characters as a filter. */ +static char * +STRSTR_SCAN (const char *haystack, const char *needle, + unsigned int needle_len) +{ + char *match; + while (1) + { + match = STRSTR2 (haystack, needle); + if (match == NULL) + return NULL; + /* Found first two characters of needle, check for remainder. */ + if (CMP_FUNC (match + 2, needle + 2, needle_len - 2) == 0) + return match; + /* Move past the previous match. Could be +2 instead of +1 if + first two characters are different, but that tested slower. */ + haystack = match + 1; + } +} + +/* Return the first occurrence of NEEDLE in HAYSTACK. Return HAYSTACK + if NEEDLE is empty, otherwise NULL if NEEDLE is not found in + HAYSTACK. */ +char * +STRSTR (const char *haystack_start, const char *needle_start) +{ + const char *haystack = haystack_start; + const char *needle = needle_start; + __insn_prefetch (haystack); + size_t needle_len = strlen (needle_start); /* Length of NEEDLE. */ + size_t haystack_len; /* Known minimum length of HAYSTACK. */ + + if (needle_len <= 2) + { + if (needle_len == 1) + return STRCHR (haystack_start, *needle_start); + if (needle_len == 0) + return (char *) haystack_start; + else + return STRSTR2 (haystack_start, needle_start); + } + + /* Fail if NEEDLE is longer than HAYSTACK. */ + if (__strnlen (haystack, needle_len) < needle_len) + return NULL; + + /* Perform the search. Abstract memory is considered to be an array + of 'unsigned char' values, not an array of 'char' values. See + ISO C 99 section 6.2.6.1. */ + if (needle_len < 40) + return STRSTR_SCAN (haystack_start, needle_start, needle_len); + else + { + /* Reduce the size of haystack using STRSTR2, since it has a smaller + linear coefficient than the Two-Way algorithm. */ + haystack = STRSTR2 (haystack_start, needle_start); + if (haystack == NULL) + return NULL; + needle = needle_start; + haystack_len = (haystack > haystack_start + needle_len ? 1 + : needle_len + haystack_start - haystack); + + return two_way_long_needle ((const unsigned char *) haystack, + haystack_len, + (const unsigned char *) needle, needle_len); + } +} +#ifndef USE_AS_STRCASESTR +libc_hidden_builtin_def (STRSTR) +#endif + +#undef LONG_NEEDLE_THRESHOLD diff --git a/REORG.TODO/sysdeps/tile/tilegx/tilegx32/Implies b/REORG.TODO/sysdeps/tile/tilegx/tilegx32/Implies new file mode 100644 index 0000000000..993b7f4cd1 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/tilegx32/Implies @@ -0,0 +1,3 @@ +tile/tilegx +tile +wordsize-32 diff --git a/REORG.TODO/sysdeps/tile/tilegx/tilegx64/Implies b/REORG.TODO/sysdeps/tile/tilegx/tilegx64/Implies new file mode 100644 index 0000000000..eb0686e0e6 --- /dev/null +++ b/REORG.TODO/sysdeps/tile/tilegx/tilegx64/Implies @@ -0,0 +1,3 @@ +tile/tilegx +tile +wordsize-64 |