diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 3673c71b1..fee2ed253 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,27 @@ +2006-10-27 Joel Schopp + + * libc/machine/spu/memcpy.c: Override generic function with vectorized + version optimized for the cell spu. + * libc/machine/spu/memmove.c: Ditto. + * libc/machine/spu/memset.c: Ditto. + * libc/machine/spu/strcat.c: Ditto. + * libc/machine/spu/strchr.c: Ditto. + * libc/machine/spu/strcmp.c: Ditto. + * libc/machine/spu/strcpy.c: Ditto. + * libc/machine/spu/strcspn.c: Ditto. + * libc/machine/spu/strlen.c: Ditto. + * libc/machine/spu/strncat.c: Ditto. + * libc/machine/spu/strncmp.c: Ditto. + * libc/machine/spu/strncpy.c: Ditto. + * libc/machine/spu/strpbrk.c: Ditto. + * libc/machine/spu/strrchr.c: Ditto. + * libc/machine/spu/strspn.c: Ditto. + * libc/machine/spu/strxfrm.c: Ditto. + * libc/machine/spu/vec_literal.h: Add abstraction of vector literals, + removing altivec style initializers. + * libc/machine/spu/Makefile.am: Add new files to list so they build + * libc/machine/spu/Makefile.in: Regenerate from new Makefile.am + 2006-10-27 Jeff Johnston * README: Add a brief section on how to regenerate diff --git a/newlib/libc/machine/spu/Makefile.am b/newlib/libc/machine/spu/Makefile.am index 36014d372..e825b4203 100644 --- a/newlib/libc/machine/spu/Makefile.am +++ b/newlib/libc/machine/spu/Makefile.am @@ -8,7 +8,7 @@ noinst_LIBRARIES = lib.a AM_CCASFLAGS = $(INCLUDES) -lib_a_SOURCES = setjmp.S memcpy.c +lib_a_SOURCES = setjmp.S memcpy.c memmove.c memset.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strspn.c strxfrm.c lib_a_CCASFLAGS = $(AM_CCASFLAGS) lib_a_CFLAGS = $(AM_CFLAGS) diff --git a/newlib/libc/machine/spu/Makefile.in b/newlib/libc/machine/spu/Makefile.in index 3f6c4e098..04df1e139 100644 --- a/newlib/libc/machine/spu/Makefile.in +++ b/newlib/libc/machine/spu/Makefile.in @@ -42,7 +42,14 @@ DIST_COMMON = $(srcdir)/../../../../config.guess \ $(srcdir)/../../../../config.sub $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(srcdir)/../../../../mkinstalldirs \ - $(srcdir)/../../../../compile + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \ + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \ + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \ + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \ + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \ + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \ + $(srcdir)/../../../../compile $(srcdir)/../../../../compile \ + $(srcdir)/../../../../compile $(srcdir)/../../../../compile subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../../../acinclude.m4 \ @@ -57,7 +64,15 @@ LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru lib_a_AR = $(AR) $(ARFLAGS) lib_a_LIBADD = -am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-memcpy.$(OBJEXT) +am_lib_a_OBJECTS = lib_a-setjmp.$(OBJEXT) lib_a-memcpy.$(OBJEXT) \ + lib_a-memmove.$(OBJEXT) lib_a-memset.$(OBJEXT) \ + lib_a-strcat.$(OBJEXT) lib_a-strchr.$(OBJEXT) \ + lib_a-strcmp.$(OBJEXT) lib_a-strcpy.$(OBJEXT) \ + lib_a-strcspn.$(OBJEXT) lib_a-strlen.$(OBJEXT) \ + lib_a-strncat.$(OBJEXT) lib_a-strncmp.$(OBJEXT) \ + lib_a-strncpy.$(OBJEXT) lib_a-strpbrk.$(OBJEXT) \ + lib_a-strrchr.$(OBJEXT) lib_a-strspn.$(OBJEXT) \ + lib_a-strxfrm.$(OBJEXT) lib_a_OBJECTS = $(am_lib_a_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) depcomp = @@ -182,7 +197,7 @@ AUTOMAKE_OPTIONS = cygnus INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) noinst_LIBRARIES = lib.a AM_CCASFLAGS = $(INCLUDES) -lib_a_SOURCES = setjmp.S memcpy.c +lib_a_SOURCES = setjmp.S memcpy.c memmove.c memset.c strcat.c strchr.c strcmp.c strcpy.c strcspn.c strlen.c strncat.c strncmp.c strncpy.c strpbrk.c strrchr.c strspn.c strxfrm.c lib_a_CCASFLAGS = $(AM_CCASFLAGS) lib_a_CFLAGS = $(AM_CFLAGS) ACLOCAL_AMFLAGS = -I ../../.. @@ -262,6 +277,96 @@ lib_a-memcpy.o: memcpy.c lib_a-memcpy.obj: memcpy.c $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memcpy.obj `if test -f 'memcpy.c'; then $(CYGPATH_W) 'memcpy.c'; else $(CYGPATH_W) '$(srcdir)/memcpy.c'; fi` + +lib_a-memmove.o: memmove.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memmove.o `test -f 'memmove.c' || echo '$(srcdir)/'`memmove.c + +lib_a-memmove.obj: memmove.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memmove.obj `if test -f 'memmove.c'; then $(CYGPATH_W) 'memmove.c'; else $(CYGPATH_W) '$(srcdir)/memmove.c'; fi` + +lib_a-memset.o: memset.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memset.o `test -f 'memset.c' || echo '$(srcdir)/'`memset.c + +lib_a-memset.obj: memset.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-memset.obj `if test -f 'memset.c'; then $(CYGPATH_W) 'memset.c'; else $(CYGPATH_W) '$(srcdir)/memset.c'; fi` + +lib_a-strcat.o: strcat.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcat.o `test -f 'strcat.c' || echo '$(srcdir)/'`strcat.c + +lib_a-strcat.obj: strcat.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcat.obj `if test -f 'strcat.c'; then $(CYGPATH_W) 'strcat.c'; else $(CYGPATH_W) '$(srcdir)/strcat.c'; fi` + +lib_a-strchr.o: strchr.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strchr.o `test -f 'strchr.c' || echo '$(srcdir)/'`strchr.c + +lib_a-strchr.obj: strchr.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strchr.obj `if test -f 'strchr.c'; then $(CYGPATH_W) 'strchr.c'; else $(CYGPATH_W) '$(srcdir)/strchr.c'; fi` + +lib_a-strcmp.o: strcmp.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcmp.o `test -f 'strcmp.c' || echo '$(srcdir)/'`strcmp.c + +lib_a-strcmp.obj: strcmp.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcmp.obj `if test -f 'strcmp.c'; then $(CYGPATH_W) 'strcmp.c'; else $(CYGPATH_W) '$(srcdir)/strcmp.c'; fi` + +lib_a-strcpy.o: strcpy.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcpy.o `test -f 'strcpy.c' || echo '$(srcdir)/'`strcpy.c + +lib_a-strcpy.obj: strcpy.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcpy.obj `if test -f 'strcpy.c'; then $(CYGPATH_W) 'strcpy.c'; else $(CYGPATH_W) '$(srcdir)/strcpy.c'; fi` + +lib_a-strcspn.o: strcspn.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcspn.o `test -f 'strcspn.c' || echo '$(srcdir)/'`strcspn.c + +lib_a-strcspn.obj: strcspn.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strcspn.obj `if test -f 'strcspn.c'; then $(CYGPATH_W) 'strcspn.c'; else $(CYGPATH_W) '$(srcdir)/strcspn.c'; fi` + +lib_a-strlen.o: strlen.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strlen.o `test -f 'strlen.c' || echo '$(srcdir)/'`strlen.c + +lib_a-strlen.obj: strlen.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strlen.obj `if test -f 'strlen.c'; then $(CYGPATH_W) 'strlen.c'; else $(CYGPATH_W) '$(srcdir)/strlen.c'; fi` + +lib_a-strncat.o: strncat.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncat.o `test -f 'strncat.c' || echo '$(srcdir)/'`strncat.c + +lib_a-strncat.obj: strncat.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncat.obj `if test -f 'strncat.c'; then $(CYGPATH_W) 'strncat.c'; else $(CYGPATH_W) '$(srcdir)/strncat.c'; fi` + +lib_a-strncmp.o: strncmp.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncmp.o `test -f 'strncmp.c' || echo '$(srcdir)/'`strncmp.c + +lib_a-strncmp.obj: strncmp.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncmp.obj `if test -f 'strncmp.c'; then $(CYGPATH_W) 'strncmp.c'; else $(CYGPATH_W) '$(srcdir)/strncmp.c'; fi` + +lib_a-strncpy.o: strncpy.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncpy.o `test -f 'strncpy.c' || echo '$(srcdir)/'`strncpy.c + +lib_a-strncpy.obj: strncpy.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strncpy.obj `if test -f 'strncpy.c'; then $(CYGPATH_W) 'strncpy.c'; else $(CYGPATH_W) '$(srcdir)/strncpy.c'; fi` + +lib_a-strpbrk.o: strpbrk.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strpbrk.o `test -f 'strpbrk.c' || echo '$(srcdir)/'`strpbrk.c + +lib_a-strpbrk.obj: strpbrk.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strpbrk.obj `if test -f 'strpbrk.c'; then $(CYGPATH_W) 'strpbrk.c'; else $(CYGPATH_W) '$(srcdir)/strpbrk.c'; fi` + +lib_a-strrchr.o: strrchr.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strrchr.o `test -f 'strrchr.c' || echo '$(srcdir)/'`strrchr.c + +lib_a-strrchr.obj: strrchr.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strrchr.obj `if test -f 'strrchr.c'; then $(CYGPATH_W) 'strrchr.c'; else $(CYGPATH_W) '$(srcdir)/strrchr.c'; fi` + +lib_a-strspn.o: strspn.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strspn.o `test -f 'strspn.c' || echo '$(srcdir)/'`strspn.c + +lib_a-strspn.obj: strspn.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strspn.obj `if test -f 'strspn.c'; then $(CYGPATH_W) 'strspn.c'; else $(CYGPATH_W) '$(srcdir)/strspn.c'; fi` + +lib_a-strxfrm.o: strxfrm.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strxfrm.o `test -f 'strxfrm.c' || echo '$(srcdir)/'`strxfrm.c + +lib_a-strxfrm.obj: strxfrm.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-strxfrm.obj `if test -f 'strxfrm.c'; then $(CYGPATH_W) 'strxfrm.c'; else $(CYGPATH_W) '$(srcdir)/strxfrm.c'; fi` uninstall-info-am: ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) diff --git a/newlib/libc/machine/spu/memcpy.c b/newlib/libc/machine/spu/memcpy.c index 2ef1711dd..08f835e47 100644 --- a/newlib/libc/machine/spu/memcpy.c +++ b/newlib/libc/machine/spu/memcpy.c @@ -1,48 +1,115 @@ /* -(C) Copyright IBM Corp. 2005, 2006 + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, -All rights reserved. + All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - * Neither the name of IBM nor the names of its contributors may be -used to endorse or promote products derived from this software without -specific prior written permission. + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include -Author: Andreas Neukoetter (ti95neuk@de.ibm.com) -*/ - -#include - -void * memcpy (void *dst, const void *src, size_t len) +/* Copy n bytes from memory area src to memory area dest. + * The memory areas may not overlap. The memcpy subroutine + * returns a pointer to dest. + * + * Faster implemenation of this function can be implemented + * either with prior knowledge of the alignment or special + * casing specific optimal alignments. + */ +void * memcpy(void * __restrict__ dest, const void * __restrict__ src, size_t n) { - /* TODO: copying byte by byte is far to inefficient */ - int i = 0; - char *d = ( char* )dst; - char *s = ( char* )src; + int adjust, delta; + unsigned int soffset1, doffset1, doffset2; + vec_uchar16 *vSrc, *vDst; + vec_uchar16 sdata1, sdata2, sdata, ddata, shuffle; + vec_uchar16 mask, mask1, mask2, mask3; - while( i< len ){ - *( d++ )= *( s++ ); - i++; - } + vSrc = (vec_uchar16 *)(src); + vDst = (vec_uchar16 *)(dest); - return( dst ); + /* Handle any leading destination partial quadwords as + * well a very short copy (ie, such that the n characters + * all reside in a single (destination) quadword. + */ + soffset1 = (unsigned int)(src) & 15; + doffset1 = (unsigned int)(dest) & 15; + doffset2 = ((unsigned int)(dest) + n) & 15; + + /* Compute a shuffle pattern used to align the source string + * with the alignment of the destination string. + */ + + adjust = (int)spu_extract(spu_cmpgt(spu_promote(doffset1, 0), spu_promote(soffset1, 0)), 0); + delta = (int)soffset1 - (int)doffset1; + delta += adjust & 16; + + shuffle = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char)delta), + VEC_LITERAL(vec_uint4, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + + vSrc += adjust; + + sdata1 = *vSrc++; + sdata2 = *vSrc++; + + ddata = *vDst; + sdata = spu_shuffle(sdata1, sdata2, shuffle); + + /* Construct a series of masks used to data insert. The masks + * contain 0 when the destination word is unchanged, 1 when it + * must be replaced by source bytes. + * + * mask1 = mask for leading unchanged bytes + * mask2 = mask for trailing unchange bytes + * mask3 = mask indicating the more than one qword is being changed. + */ + mask = VEC_SPLAT_U8(-1); + mask1 = spu_rlmaskqwbyte(mask, -doffset1); + mask2 = spu_slqwbyte(mask, 16-doffset2); + mask3 = (vec_uchar16)spu_cmpgt(spu_splats(doffset1 + n), 15); + + *vDst++ = spu_sel(ddata, sdata, spu_and(mask1, spu_or(mask2, mask3))); + + n += doffset1; + + /* Handle complete destination quadwords + */ + while (n > 31) { + sdata1 = sdata2; + sdata2 = *vSrc++; + *vDst++ = spu_shuffle(sdata1, sdata2, shuffle); + n -= 16; + } + + /* Handle any trailing partial (destination) quadwords + */ + mask = spu_and((vec_uchar16)spu_cmpgt(spu_splats(n), 16), mask2); + *vDst = spu_sel(*vDst, spu_shuffle(sdata2, *vSrc, shuffle), mask); + + return (dest); } diff --git a/newlib/libc/machine/spu/memmove.c b/newlib/libc/machine/spu/memmove.c new file mode 100644 index 000000000..d870a9d7f --- /dev/null +++ b/newlib/libc/machine/spu/memmove.c @@ -0,0 +1,216 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include "vec_literal.h" + +/* Copy n bytes from memory area src to memory area dest. + * Copying is performed as if the n characters pointed to + * by src are first copied into a temporary array that does + * not overlap the src and dest arrays. Then the n characters + * of the temporary array are copied into the destination + * array. The memmove subroutine returns a pointer to dest. + */ + +void * memmove(void * __restrict__ dest, const void * __restrict__ src, size_t n) +{ + int adjust, delta; + unsigned int soffset1, soffset2, doffset1, doffset2; + vec_uchar16 *vSrc, *vDst; + vec_uchar16 sdata1, sdata2, sdata, ddata, shuffle; + vec_uchar16 mask, mask1, mask2, mask3; + + soffset1 = (unsigned int)(src) & 15; + doffset1 = (unsigned int)(dest) & 15; + doffset2 = ((unsigned int)(dest) + n) & 15; + + /* Construct a series of masks used to data insert. The masks + * contains 0 bit when the destination word is unchanged, 1 when it + * must be replaced by source bits. + * + * mask1 = mask for leading unchanged bytes + * mask2 = mask for trailing unchange bytes + * mask3 = mask indicating the more than one qword is being changed. + */ + mask = VEC_SPLAT_U8(-1); + mask1 = spu_rlmaskqwbyte(mask, -doffset1); + mask2 = spu_slqwbyte(mask, 16-doffset2); + mask3 = (vec_uchar16)spu_cmpgt(spu_splats(doffset1 + n), 15); + + vDst = (vec_uchar16 *)(dest); + + delta = (int)soffset1 - (int)doffset1; + + /* The follow check only works if the SPU addresses are not + * wrapped. No provisions have been made to correct for this + * limitation. + */ + if (((unsigned int)dest - (unsigned int)src) >= (unsigned int)n) { + /* Forward copy. Perform a memcpy. + * + * Handle any leading destination partial quadwords as + * well a very short copy (ie, such that the n characters + * all reside in a single (destination) quadword. + */ + vSrc = (vec_uchar16 *)(src); + vDst = (vec_uchar16 *)(dest); + + /* Handle any leading destination partial quadwords as + * well a very short copy (ie, such that the n characters + * all reside in a single (destination) quadword. + */ + soffset1 = (unsigned int)(src) & 15; + doffset1 = (unsigned int)(dest) & 15; + doffset2 = ((unsigned int)(dest) + n) & 15; + + /* Compute a shuffle pattern used to align the source string + * with the alignment of the destination string. + */ + + adjust = (int)spu_extract(spu_cmpgt(spu_promote(doffset1, 0), spu_promote(soffset1, 0)), 0); + delta = (int)soffset1 - (int)doffset1; + delta += adjust & 16; + + shuffle = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char)delta), + VEC_LITERAL(vec_uint4, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + + vSrc += adjust; + + sdata1 = *vSrc++; + sdata2 = *vSrc++; + + ddata = *vDst; + sdata = spu_shuffle(sdata1, sdata2, shuffle); + + /* Construct a series of masks used to data insert. The masks + * contain 0 when the destination word is unchanged, 1 when it + * must be replaced by source bytes. + * + * mask1 = mask for leading unchanged bytes + * mask2 = mask for trailing unchange bytes + * mask3 = mask indicating the more than one qword is being changed. + */ + mask = VEC_SPLAT_U8(-1); + mask1 = spu_rlmaskqwbyte(mask, -doffset1); + mask2 = spu_slqwbyte(mask, 16-doffset2); + mask3 = (vec_uchar16)spu_cmpgt(spu_splats(doffset1 + n), 15); + + *vDst++ = spu_sel(ddata, sdata, spu_and(mask1, spu_or(mask2, mask3))); + + n += doffset1; + + /* Handle complete destination quadwords + */ + while (n > 31) { + sdata1 = sdata2; + sdata2 = *vSrc++; + *vDst++ = spu_shuffle(sdata1, sdata2, shuffle); + n -= 16; + } + + /* Handle any trailing partial (destination) quadwords + */ + mask = spu_and((vec_uchar16)spu_cmpgt(spu_splats(n), 16), mask2); + *vDst = spu_sel(*vDst, spu_shuffle(sdata2, *vSrc, shuffle), mask); + + } else { + /* Backward copy. + * + * Handle any leading destination partial quadwords as + * well a very short copy (ie, such that the n characters + * all reside in a single (destination) quadword. + */ + vSrc = (vec_uchar16 *)((unsigned int)src + n-1); + vDst = (vec_uchar16 *)((unsigned int)dest + n-1); + + /* Handle any leading destination partial quadwords as + * well a very short copy (ie, such that the n characters + * all reside in a single (destination) quadword. + */ + soffset1 = (unsigned int)(src) & 15; + soffset2 = (unsigned int)(vSrc) & 15; + doffset1 = (unsigned int)(dest) & 15; + doffset2 = (unsigned int)(vDst) & 15; + + /* Compute a shuffle pattern used to align the source string + * with the alignment of the destination string. + */ + adjust = (int)spu_extract(spu_cmpgt(spu_promote(soffset2, 0), spu_promote(doffset2, 0)), 0); + delta = (int)doffset2 - (int)soffset2; + delta += adjust & 16; + + shuffle = (vec_uchar16)spu_sub(VEC_LITERAL(vec_uint4, 0x10111213, 0x14151617, 0x18191A1B, 0x1C1D1E1F), + (vec_uint4)spu_splats((unsigned char)delta)); + + vSrc -= adjust; + + sdata2 = *vSrc--; + sdata1 = *vSrc--; + + ddata = *vDst; + sdata = spu_shuffle(sdata1, sdata2, shuffle); + + /* Construct a series of masks used to data insert. The masks + * contain 0 when the destination word is unchanged, 1 when it + * must be replaced by source bytes. + * + * mask1 = mask for leading unchanged bytes + * mask2 = mask for trailing unchange bytes + * mask3 = mask indicating the more than one qword is being changed. + */ + mask = VEC_SPLAT_U8(-1); + mask1 = spu_rlmaskqwbyte(mask, -doffset1); + mask2 = spu_slqwbyte(mask, 15-doffset2); + mask3 = (vec_uchar16)spu_cmpgt(spu_splats((int)(doffset2 - n)), -2); + + *vDst-- = spu_sel(ddata, sdata, spu_and(mask2, spu_orc(mask1, mask3))); + + n -= doffset2 + 1; + + /* Handle complete destination quadwords + */ + while ((int)n > 15) { + sdata2 = sdata1; + sdata1 = *vSrc--; + *vDst-- = spu_shuffle(sdata1, sdata2, shuffle); + n -= 16; + } + + /* Handle any trailing partial (destination) quadwords + */ + mask = spu_and((vec_uchar16)spu_cmpgt(spu_splats((int)n), 0), mask1); + *vDst = spu_sel(*vDst, spu_shuffle(*vSrc, sdata1, shuffle), mask); + } + return (dest); +} + diff --git a/newlib/libc/machine/spu/memset.c b/newlib/libc/machine/spu/memset.c new file mode 100644 index 000000000..9ca2a6992 --- /dev/null +++ b/newlib/libc/machine/spu/memset.c @@ -0,0 +1,90 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include + +/* Fills the first n bytes of the memory area pointed to by s + * with the constant byte c. Returns a pointer to the memory area s. + */ +void * memset(void *s, int c, size_t n) +{ + int skip, cnt, i; + vec_uchar16 *vs; + vec_uchar16 vc, mask; + + vs = (vec_uchar16 *)(s); + vc = spu_splats((unsigned char)c); + cnt = (int)(n); + + /* Handle any leading partial quadwords as well a + * very short settings (ie, such that the n characters + * all reside in a single quadword. + */ + skip = (int)(s) & 15; + if (skip) { + mask = spu_rlmaskqwbyte((vec_uchar16)(-1), 0-skip); + cnt -= 16 - skip; + if (cnt < 0) { + mask = spu_and(mask, spu_slqwbyte((vec_uchar16)(-1), (unsigned int)(-cnt))); + } + *vs = spu_sel(*vs, vc, mask); + vs++; + } + + /* Handle 8 quadwords at a time + */ + for (i=127; i 0) { + mask = spu_slqwbyte((vec_uchar16)(-1), (unsigned int)(16-cnt)); + *vs = spu_sel(*vs, vc, mask); + } + + return (s); +} diff --git a/newlib/libc/machine/spu/strcat.c b/newlib/libc/machine/spu/strcat.c new file mode 100644 index 000000000..902049e6c --- /dev/null +++ b/newlib/libc/machine/spu/strcat.c @@ -0,0 +1,55 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include + +/* Appends the string pointed to by src (up to and including the /0 + * character) to the array pointed to by dest (overwriting the + * /0 character at the end of dest. The strings may not overlap and + * the dest string must have enough space for the result. + */ + +char *strcat(char * __restrict__ dest, const char * __restrict__ src) +{ + size_t d_len, s_len; + + /* Determine the length of the src and dest input arrays. + */ + d_len = strlen(dest); + s_len = strlen(src); + + (void)memcpy((void *)(dest+d_len), (const void *)src, s_len + 1); + + return ((char *)dest); +} diff --git a/newlib/libc/machine/spu/strchr.c b/newlib/libc/machine/spu/strchr.c new file mode 100644 index 000000000..2b1eeac80 --- /dev/null +++ b/newlib/libc/machine/spu/strchr.c @@ -0,0 +1,82 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include + +/* Scans the string pointed to by s for the character c and + * returns a pointer to the first occurance of c. If + * c is not found, then NULL is returned. + */ +char *strchr(const char *s, int c) +{ + unsigned int cmp, skip; + vec_uchar16 *ptr, data, vc; + vec_uint4 cmp_c, cmp_0; + vec_uint4 result; + vec_uint4 mask; + + /* Scan memory array a quadword at a time. Skip leading + * mis-aligned bytes. + */ + ptr = (vec_uchar16 *)s; + + skip = (unsigned int)(ptr) & 15; + mask = spu_rlmask((vec_uint4)(0xFFFF), -skip); + + vc = spu_splats((unsigned char)(c)); + + data = *ptr++; + + cmp_c = spu_and(spu_gather(spu_cmpeq(data, vc)), mask); + cmp_0 = spu_and(spu_gather(spu_cmpeq(data, 0)), mask); + + cmp = spu_extract(spu_or(cmp_c, cmp_0), 0); + + while (cmp == 0) { + data = *ptr++; + cmp_c = spu_gather(spu_cmpeq(data, vc)); + cmp_0 = spu_gather(spu_cmpeq(data, 0)); + + cmp = spu_extract(spu_or(cmp_c, cmp_0), 0); + } + + /* Compute the location of the first character. If it is beyond + * the end of the string, then return NULL. + */ + result = spu_add(spu_promote((unsigned int)ptr - (skip+32), 0), + spu_cntlz(spu_promote(cmp, 0))); + + result = spu_andc(result, spu_cmpgt(cmp_0, cmp_c)); + + return ((char *)spu_extract(result, 0)); +} diff --git a/newlib/libc/machine/spu/strcmp.c b/newlib/libc/machine/spu/strcmp.c new file mode 100644 index 000000000..2db1a130f --- /dev/null +++ b/newlib/libc/machine/spu/strcmp.c @@ -0,0 +1,94 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include "vec_literal.h" + +/* Compare the two strings s1 and s2. Return an integer less than, equal + * to, or greater than zero if s1 is found, respectively, to be less than, + * to match, or be greater than s2. + */ + +int strcmp(const char *s1, const char *s2) +{ + unsigned int offset1, offset2; + vec_uint4 gt_v, lt_v, mask_v; + vec_uint4 cnt1_v, cnt2_v; + vec_uint4 end1_v, end2_v, end_v, neq_v; + vec_uchar16 shuffle1, shuffle2; + vec_uchar16 data1A, data1B, data1, data2A, data2B, data2; + vec_uchar16 *ptr1, *ptr2; + + ptr1 = (vec_uchar16 *)s1; + ptr2 = (vec_uchar16 *)s2; + + offset1 = (unsigned int)(ptr1) & 15; + offset2 = (unsigned int)(ptr2) & 15; + + shuffle1 = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char)offset1), + VEC_LITERAL(vec_uint4, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + shuffle2 = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char)offset2), + VEC_LITERAL(vec_uint4, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + + data1A = *ptr1++; + data2A = *ptr2++; + + do { + data1B = *ptr1++; + data2B = *ptr2++; + + data1 = spu_shuffle(data1A, data1B, shuffle1); + data2 = spu_shuffle(data2A, data2B, shuffle2); + + data1A = data1B; + data2A = data2B; + + neq_v = spu_gather(spu_xor(spu_cmpeq(data1, data2), -1)); + + end1_v = spu_gather(spu_cmpeq(data1, 0)); + end2_v = spu_gather(spu_cmpeq(data2, 0)); + end_v = spu_or(end1_v, end2_v), 0; + } while (spu_extract(spu_or(end_v, neq_v), 0) == 0); + + cnt1_v = spu_cntlz(end1_v); + cnt2_v = spu_cntlz(end2_v); + + gt_v = spu_gather(spu_cmpgt(data1, data2)); + lt_v = spu_gather(spu_cmpgt(data2, data1)); + + mask_v = spu_and(spu_cmpeq(cnt1_v, cnt2_v), + spu_cmpeq(spu_rlmask(neq_v, (vec_int4)spu_add((vec_uint4)cnt1_v, -32)), 0)); + + gt_v = spu_sub(-1, spu_sl(spu_cmpgt(gt_v, lt_v), 1)); + + return (spu_extract(spu_andc(gt_v, mask_v), 0)); +} diff --git a/newlib/libc/machine/spu/strcpy.c b/newlib/libc/machine/spu/strcpy.c new file mode 100644 index 000000000..4d71cf483 --- /dev/null +++ b/newlib/libc/machine/spu/strcpy.c @@ -0,0 +1,48 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include + +/* Copy the string pointed to by src (up to and including the /0 + * character) into the array pointed to by dest. If copy between + * two arrays that overlap, then behavior is undefined. + */ + +char * strcpy(char * __restrict__ dest, const char * __restrict__ src) +{ + /* Due to the need to support all alignment variances, this + * function can not easily be optimized. As a result, it is + * serviced using strlen and memcpy. + */ + return ((char *)memcpy((void *)dest, (const void *)src, strlen(src)+1)); +} diff --git a/newlib/libc/machine/spu/strcspn.c b/newlib/libc/machine/spu/strcspn.c new file mode 100644 index 000000000..5f75a290a --- /dev/null +++ b/newlib/libc/machine/spu/strcspn.c @@ -0,0 +1,96 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include "vec_literal.h" + +/* Computes the length of the maximum initial segement + * of the string pointed to by s1 which consists entirely + * of characters not contained in the string pointed to by s2. + */ +size_t strcspn(const char *s1, const char *s2) +{ + size_t len, cnt; + unsigned int offset; + vec_uchar16 shuffle, match, initial_splat, splat; + vec_uchar16 data1, data2, dataA, dataB, *ptr1, *ptr2; + + ptr1 = (vec_uchar16 *)s1; + + offset = (unsigned int)(s1) & 15; + shuffle = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char) offset), + VEC_LITERAL(vec_uint4, 0x0010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + + len = 0; + + dataA = *ptr1++; + dataB = *ptr1++; + + initial_splat = spu_splats((unsigned char)((unsigned int)(s2) & 0xF)); + + /* For each quadword of the string s1. + */ + do { + data1 = spu_shuffle(dataA, dataB, shuffle); + + + ptr2 = (vec_uchar16 *)s2; + data2 = *ptr2; + data2 = spu_shuffle(data2, data2, initial_splat); + ptr2 = (vec_uchar16 *)((unsigned int)(ptr2) + 1); + splat = initial_splat; + + match = spu_cmpeq(data1, 0); + + /* For each character of s2, compare agains a quadword of s1, + * accumulating match success in the variable match. + */ + while (spu_extract((vec_uint4)data2, 0)) { + match = spu_or(match, spu_cmpeq(data1, data2)); + + splat = spu_and((vec_uchar16)(spu_add((vec_uint4)splat, VEC_SPLAT_U32(0x01010101))), 0xF); + + data2 = *ptr2; + data2 = spu_shuffle(data2, data2, splat); + ptr2 = (vec_uchar16 *)((unsigned int)(ptr2) + 1); + } + + cnt = spu_extract(spu_cntlz(spu_gather(match)), 0); + len = (len - 16) + cnt; + + dataA = dataB; + dataB = *ptr1++; + } while (cnt == 32); + + return (len); +} diff --git a/newlib/libc/machine/spu/strlen.c b/newlib/libc/machine/spu/strlen.c new file mode 100644 index 000000000..8a7ae07ab --- /dev/null +++ b/newlib/libc/machine/spu/strlen.c @@ -0,0 +1,66 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include + +/* Calculates the length of the string s, not including the terminating + * \0 character. + */ +size_t strlen(const char *s) +{ + size_t len; + unsigned int cnt, cmp, skip, mask; + vec_uchar16 *ptr, data; + + /* Compensate for initial mis-aligned string. + */ + ptr = (vec_uchar16 *)s; + skip = (unsigned int)(ptr) & 15; + mask = 0xFFFF >> skip; + + data = *ptr++; + cmp = spu_extract(spu_gather(spu_cmpeq(data, 0)), 0); + cmp &= mask; + + cnt = spu_extract(spu_cntlz(spu_promote(cmp, 0)), 0); + len = cnt - (skip + 16); + + while (cnt == 32) { + data = *ptr++; + len -= 16; + cnt = spu_extract(spu_cntlz(spu_gather(spu_cmpeq(data, 0))), 0); + len += cnt; + } + + return (len); +} diff --git a/newlib/libc/machine/spu/strncat.c b/newlib/libc/machine/spu/strncat.c new file mode 100644 index 000000000..e1c3088a4 --- /dev/null +++ b/newlib/libc/machine/spu/strncat.c @@ -0,0 +1,98 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include + +/* Appends the string pointed to by src (up to and including the /0 + * character) to the array pointed to by dest (overwriting the + * /0 character at the end of dest. The strings may not overlap and + * the dest string must have enough space for the result. + */ + +char * strncat(char * __restrict__ dest, const char * __restrict__ src, size_t n) +{ + size_t len; + unsigned int cmp, skip, mask; + vec_uchar16 *ptr, data; + vec_uint4 cnt, gt, N; + char *dst; + + /* Determine the starting location to begin concatenation. + */ + dst = dest + strlen(dest); + + /* Copy the src image until either the src string terminates + * or n characters are copied. + */ + N = spu_promote(n, 0); + + /* Determine the string length, not including termination character, + * clamped to n characters. + */ + ptr = (vec_uchar16 *)src; + skip = (unsigned int)(ptr) & 15; + mask = 0xFFFF >> skip; + + data = *ptr++; + cmp = spu_extract(spu_gather(spu_cmpeq(data, 0)), 0); + cmp &= mask; + + cnt = spu_cntlz(spu_promote(cmp, 0)); + len = spu_extract(cnt, 0) - (skip + 16); + + gt = spu_cmpgt(spu_promote(len, 0), N); + + while (spu_extract(spu_andc(spu_cmpeq(cnt, 32), gt), 0)) { + data = *ptr++; + len -= 16; + cnt = spu_cntlz(spu_gather(spu_cmpeq(data, 0))); + len += spu_extract(cnt, 0); + + gt = spu_cmpgt(spu_promote(len, 0), N); + } + + /* len = MIN(len, n) + */ + len = spu_extract(spu_sel(spu_promote(len, 0), N, gt), 0); + + /* Perform a memcpy of the resulting length + */ + (void)memcpy((void *)dst, (const void *)src, len); + + /* Terminate the resulting concetenated string. + */ + dst[len] = '\0'; + + return (dest); +} diff --git a/newlib/libc/machine/spu/strncmp.c b/newlib/libc/machine/spu/strncmp.c new file mode 100644 index 000000000..0f5860903 --- /dev/null +++ b/newlib/libc/machine/spu/strncmp.c @@ -0,0 +1,131 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include "vec_literal.h" + +/* Compare the two strings s1 and s2 of length n. Returns an integer + * less than, equal to, or greater than zero if s1 is found, respectively, + * to be less than, to match, or be greater than s2. + */ + +int strncmp(const char *s1, const char *s2, size_t n) +{ + unsigned int offset1, offset2; + vec_int4 n_v; + vec_uint4 cnt1_v, cnt2_v, max_cnt_v; + vec_uint4 gt_v, lt_v, mask_v, end1_v, end2_v, end_v, neq_v; + vec_uint4 shift_n_v, shift_eos_v, max_shift_v; + vec_uchar16 shuffle1, shuffle2; + vec_uchar16 data1A, data1B, data1, data2A, data2B, data2; + vec_uchar16 *ptr1, *ptr2; + + data1 = data2 = VEC_SPLAT_U8(0); + + ptr1 = (vec_uchar16 *)s1; + ptr2 = (vec_uchar16 *)s2; + + offset1 = (unsigned int)(ptr1) & 15; + offset2 = (unsigned int)(ptr2) & 15; + + shuffle1 = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char)offset1), + VEC_LITERAL(vec_uint4, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + shuffle2 = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char)offset2), + VEC_LITERAL(vec_uint4, 0x00010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + data1A = *ptr1++; + data2A = *ptr2++; + + n_v = spu_promote((int)n, 0); + + do { + data1B = *ptr1++; + data2B = *ptr2++; + + /* Quadword align each of the input strings so that + * we operate on full quadwords. + */ + data1 = spu_shuffle(data1A, data1B, shuffle1); + data2 = spu_shuffle(data2A, data2B, shuffle2); + + data1A = data1B; + data2A = data2B; + + neq_v = spu_gather(spu_xor(spu_cmpeq(data1, data2), -1)); + + end1_v = spu_gather(spu_cmpeq(data1, 0)); + end2_v = spu_gather(spu_cmpeq(data2, 0)); + end_v = spu_or(end1_v, end2_v), 0; + + n_v = spu_add(n_v, -16); + + /* Repeat until either + * 1) the character count expired, + * 2) a null character is discovered in one of the input strings, or + * 3) the strings do not compare equal. + */ + } while (spu_extract(spu_and(spu_cmpeq(spu_or(end_v, neq_v), 0), spu_cmpgt(n_v, 0)), 0)); + + /* Construct a mask to eliminate characters that are not of interest + * in the comparison. Theses include characters that are beyond the + * n character count and beyond the first null character. + */ + cnt1_v = spu_cntlz(end1_v); + cnt2_v = spu_cntlz(end2_v); + + max_cnt_v = spu_sel(cnt1_v, cnt2_v, spu_cmpgt(cnt2_v, cnt1_v)); + + mask_v = spu_splats((unsigned int)0xFFFF); + + shift_n_v = spu_andc((vector unsigned int)spu_sub(0, n_v), spu_cmpgt(n_v, -1)); + shift_eos_v = spu_sub(32, max_cnt_v); + + max_shift_v = spu_sel(shift_n_v, shift_eos_v, spu_cmpgt(shift_eos_v, shift_n_v)); + + mask_v = spu_and(spu_sl(mask_v, spu_extract(max_shift_v, 0)), mask_v); + + /* Determine if greater then or less then in the case that they are + * not equal. gt_v is either 1 (in the case s1 is greater then s2), or + * -1 (in the case that s2 is greater then s1). + */ + gt_v = spu_gather(spu_cmpgt(data1, data2)); + lt_v = spu_gather(spu_cmpgt(data2, data1)); + + gt_v = spu_sub(-1, spu_sl(spu_cmpgt(gt_v, lt_v), 1)); + + /* Construct a mask to be applied to gt_v if the strings are discovered + * to be equal. + */ + mask_v = spu_cmpeq(spu_and(neq_v, mask_v), 0); + + return (spu_extract(spu_andc(gt_v, mask_v), 0)); +} diff --git a/newlib/libc/machine/spu/strncpy.c b/newlib/libc/machine/spu/strncpy.c new file mode 100644 index 000000000..f1c89f571 --- /dev/null +++ b/newlib/libc/machine/spu/strncpy.c @@ -0,0 +1,82 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include + +/* Copy the string up to n character from memory area src to + * memory area dest. The memory areas may not overlap. The + * strncpy subroutine returns a pointer to dest. + */ +char * strncpy(char * __restrict__ dest, const char * __restrict__ src, size_t n) +{ + size_t len; + unsigned int cmp, skip, mask; + vec_uchar16 *ptr, data; + vec_uint4 cnt, gt, N; + + N = spu_promote(n, 0); + + /* Determine the string length, including termination character, + * clamped to n characters. + */ + ptr = (vec_uchar16 *)src; + skip = (unsigned int)(ptr) & 15; + mask = 0xFFFF >> skip; + + data = *ptr++; + cmp = spu_extract(spu_gather(spu_cmpeq(data, 0)), 0); + cmp &= mask; + + cnt = spu_cntlz(spu_promote(cmp, 0)); + len = spu_extract(cnt, 0) - (skip + 15); + + gt = spu_cmpgt(spu_promote(len, 0), N); + + while (spu_extract(spu_andc(spu_cmpeq(cnt, 32), gt), 0)) { + data = *ptr++; + len -= 16; + cnt = spu_cntlz(spu_gather(spu_cmpeq(data, 0))); + len += spu_extract(cnt, 0); + + gt = spu_cmpgt(spu_promote(len, 0), N); + } + + /* len = MIN(len, n) + */ + len = spu_extract(spu_sel(spu_promote(len, 0), N, gt), 0); + + /* Perform a memcpy of the resulting length + */ + return ((char *)memcpy((void *)dest, (const void *)src, len)); +} diff --git a/newlib/libc/machine/spu/strpbrk.c b/newlib/libc/machine/spu/strpbrk.c new file mode 100644 index 000000000..461a58684 --- /dev/null +++ b/newlib/libc/machine/spu/strpbrk.c @@ -0,0 +1,96 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include "vec_literal.h" + +/* Locates the first occurance in string pointed to by s1 of + * any character in the string pointed to by s2. A null pointer + * is returned if no character in s2 occurs in s1. + */ +char * strpbrk(const char *s1, const char *s2) +{ + unsigned int offset; + vec_uint4 cnt; + vec_uchar16 shuffle, match, initial_splat, splat, eos; + vec_uchar16 data1, data2, dataA, dataB, *ptr1, *ptr2; + + ptr1 = (vec_uchar16 *)s1; + + offset = (unsigned int)(s1) & 15; + shuffle = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char) offset), + VEC_LITERAL(vec_uint4, 0x0010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + + dataA = *ptr1++; + dataB = *ptr1++; + + initial_splat = spu_splats((unsigned char)((unsigned int)(s2) & 0xF)); + + /* For each quadword of the string s1. + */ + do { + data1 = spu_shuffle(dataA, dataB, shuffle); + + eos = match = spu_cmpeq(data1, 0); + + ptr2 = (vec_uchar16 *)s2; + data2 = *ptr2; + data2 = spu_shuffle(data2, data2, initial_splat); + ptr2 = (vec_uchar16 *)((unsigned int)(ptr2) + 1); + splat = initial_splat; + + /* For each character of s2, compare agains a quadword of s1, + * accumulating match success in the variable match. + */ + while (spu_extract((vec_uint4)data2, 0)) { + match = spu_or(match, spu_cmpeq(data1, data2)); + + splat = spu_and((vec_uchar16)(spu_add((vec_uint4)splat, VEC_SPLAT_U32(0x01010101))), 0xF); + + data2 = *ptr2; + data2 = spu_shuffle(data2, data2, splat); + ptr2 = (vec_uchar16 *)((unsigned int)(ptr2) + 1); + } + + cnt = spu_cntlz(spu_gather(match)); + + dataA = dataB; + dataB = *ptr1++; + } while (spu_extract(cnt, 0) == 32); + + /* Compute the first match pointer, zeroing it (NIL) if it is the end of + * string. + */ + return ((char *)spu_extract(spu_andc(spu_add(spu_add(spu_promote((unsigned int)(ptr1), 0), -64), cnt), + spu_cmpeq(cnt, spu_cntlz(spu_gather(eos)))), 0)); +} diff --git a/newlib/libc/machine/spu/strrchr.c b/newlib/libc/machine/spu/strrchr.c new file mode 100644 index 000000000..ec80841c2 --- /dev/null +++ b/newlib/libc/machine/spu/strrchr.c @@ -0,0 +1,115 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include "vec_literal.h" + +/* Scans the string pointed to by s for the character c and + * returns a pointer to the last occurance of c. If + * c is not found, then NULL is returned. + */ +char * strrchr(const char *s, int c) +{ + int nskip; + vec_uchar16 *ptr, data, vc; + vec_uint4 cmp_c, cmp_0, cmp; + vec_uint4 res_ptr, res_cmp; + vec_uint4 mask, result; + + /* Scan memory array a quadword at a time. Skip leading + * mis-aligned bytes. + */ + ptr = (vec_uchar16 *)s; + + nskip = -((unsigned int)(ptr) & 15); + mask = spu_rlmask((vec_uint4)(0xFFFF), nskip); + + vc = spu_splats((unsigned char)(c)); + + data = *ptr++; + ptr = (vec_uchar16 *)((unsigned int)ptr & ~15); + + cmp_c = spu_and(spu_gather(spu_cmpeq(data, vc)), mask); + cmp_0 = spu_and(spu_gather(spu_cmpeq(data, 0)), mask); + + res_ptr = VEC_SPLAT_U32(0); + res_cmp = VEC_SPLAT_U32(0); + + while (spu_extract(cmp_0, 0) == 0) { + cmp = spu_cmpeq(cmp_c, 0); + + res_ptr = spu_sel(spu_promote((unsigned int)(ptr), 0), res_ptr, cmp); + res_cmp = spu_sel(cmp_c, res_cmp, cmp); + + data = *ptr++; + + cmp_c = spu_gather(spu_cmpeq(data, vc)); + cmp_0 = spu_gather(spu_cmpeq(data, 0)); + + cmp = spu_cmpeq(cmp_c, 0); + } + + /* Compute the location of the last character before termination + * character. + * + * First mask off compare results following the first termination character. + */ + mask = spu_sl(VEC_SPLAT_U32(-1), 31 - spu_extract(spu_cntlz(cmp_0), 0)); + cmp_c = spu_and(cmp_c, mask); + + /* Conditionally update res_ptr and res_cmd if a match was found in the last + * quadword. + */ + cmp = spu_cmpeq(cmp_c, 0); + + res_ptr = spu_sel(spu_promote((unsigned int)(ptr), 0), res_ptr, cmp); + res_cmp = spu_sel(cmp_c, res_cmp, cmp); + + /* Bit reserve res_cmp for locating last occurance. + */ + mask = spu_cmpeq(res_cmp, 0); + + res_cmp = (vec_uint4)spu_maskb(spu_extract(res_cmp, 0)); + res_cmp = spu_gather((vec_uchar16)spu_shuffle(res_cmp, res_cmp, + VEC_LITERAL(vec_uchar16, + 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))); + + /* Compute the location (ptr) of the last occurance of c. If no + * occurance was found (ie, element 0 of res_cmp == 0, then return + * NULL. + */ + result = spu_sub(spu_add(res_ptr, 15), spu_cntlz(res_cmp)); + result = spu_andc(result, mask); + + return ((char *)spu_extract(result, 0)); +} diff --git a/newlib/libc/machine/spu/strspn.c b/newlib/libc/machine/spu/strspn.c new file mode 100644 index 000000000..657a3bebf --- /dev/null +++ b/newlib/libc/machine/spu/strspn.c @@ -0,0 +1,95 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include "vec_literal.h" + +/* Computes the length of the maximum initial segement + * of the string pointed to by s1 which consists entirely + * of characters from the string pointed to by s2. + */ +size_t strspn(const char *s1, const char *s2) +{ + size_t len, cnt; + unsigned int offset; + vec_uchar16 shuffle, match, initial_splat, splat; + vec_uchar16 data1, data2, dataA, dataB, *ptr1, *ptr2; + + ptr1 = (vec_uchar16 *)s1; + + offset = (unsigned int)(s1) & 15; + shuffle = (vec_uchar16)spu_add((vec_uint4)spu_splats((unsigned char) offset), + VEC_LITERAL(vec_uint4, 0x0010203, 0x04050607, 0x08090A0B, 0x0C0D0E0F)); + + len = 0; + + dataA = *ptr1++; + dataB = *ptr1++; + + initial_splat = spu_splats((unsigned char)((unsigned int)(s2) & 0xF)); + + /* For each quadword of the string s1. + */ + do { + data1 = spu_shuffle(dataA, dataB, shuffle); + + match = VEC_SPLAT_U8(0); + + ptr2 = (vec_uchar16 *)s2; + data2 = *ptr2; + data2 = spu_shuffle(data2, data2, initial_splat); + ptr2 = (vec_uchar16 *)((unsigned int)(ptr2) + 1); + splat = initial_splat; + + /* For each character of s2, compare agains a quadword of s1, + * accumulating match success in the variable match. + */ + while (spu_extract((vec_uint4)data2, 0)) { + match = spu_or(match, spu_cmpeq(data1, data2)); + + splat = spu_and((vec_uchar16)(spu_add((vec_uint4)splat, VEC_SPLAT_U32(0x01010101))), 0xF); + + data2 = *ptr2; + data2 = spu_shuffle(data2, data2, splat); + ptr2 = (vec_uchar16 *)((unsigned int)(ptr2) + 1); + } + + cnt = spu_extract(spu_cntlz(spu_gather(spu_xor(match, -1))), 0); + len = (len - 16) + cnt; + + dataA = dataB; + dataB = *ptr1++; + } while (cnt == 32); + + return (len); +} diff --git a/newlib/libc/machine/spu/strxfrm.c b/newlib/libc/machine/spu/strxfrm.c new file mode 100644 index 000000000..6d449edf0 --- /dev/null +++ b/newlib/libc/machine/spu/strxfrm.c @@ -0,0 +1,66 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ +#include +#include +#include + + +/* The strxfrm() function transforms the src string into a form such that + * the result of strcmp() on two strings that have been transformed with + * strxfrm() is the same as the result of strcoll() on the two strings + * before their transformation. The first n characters of the transformed + * string are placed in dest. + * + * The strxfrm() function returns the number of bytes required to store + * the transformed string in dest excluding the terminating character + * If the value returned is n or more, the contents of dest are indeterminate. + * + * Note: Since this library/function only supports a single locale, no + * transformation is performed. + */ + +size_t strxfrm(char * __restrict__ dest, const char * __restrict__ src, size_t n) +{ + size_t len; + + len = strlen(src); + + /* Since the destination is indeterminant if n is less than of equal + * to the string length, we skip performing the copy (altogether) in + * this case. + */ + if (n > len) { + (void)memcpy((void *)dest, (void *)src, n); + } + return (len); +} diff --git a/newlib/libc/machine/spu/vec_literal.h b/newlib/libc/machine/spu/vec_literal.h new file mode 100644 index 000000000..87589393b --- /dev/null +++ b/newlib/libc/machine/spu/vec_literal.h @@ -0,0 +1,75 @@ +/* + (C) Copyright 2001,2006, + International Business Machines Corporation, + Sony Computer Entertainment, Incorporated, + Toshiba Corporation, + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the names of the copyright holders nor the names of their + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _VEC_LITERAL_H_ +#define _VEC_LITERAL_H_ + +/* This header files provides an abstraction for the various implementations + * of vector literal construction. The two formats are: + * + * 1) Altivec styled using parenthesis + * 2) C grammer friendly styled using curly braces + * + * The macro, VEC_LITERAL has been developed to provide some portability + * in these two styles. To achieve true portability, user must specify all + * elements of the vector being initialized. A single element can be provided + * but only the first element guarenteed across both construction styles. + * + * The VEC_SPLAT_* macros have been provided for portability of vector literal + * construction when all the elements of the vector contain the same value. + */ + +#ifdef __SPU__ +#include +#endif + + +/* Use curly brace style. + */ +#define VEC_LITERAL(_type, ...) ((_type){__VA_ARGS__}) + +#define VEC_SPLAT_U8(_val) ((vector unsigned char){_val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val}) +#define VEC_SPLAT_S8(_val) ((vector signed char){_val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val, _val}) + +#define VEC_SPLAT_U16(_val) ((vector unsigned short){_val, _val, _val, _val, _val, _val, _val, _val}) +#define VEC_SPLAT_S16(_val) ((vector signed short){_val, _val, _val, _val, _val, _val, _val, _val}) + +#define VEC_SPLAT_U32(_val) ((vector unsigned int){_val, _val, _val, _val}) +#define VEC_SPLAT_S32(_val) ((vector signed int){_val, _val, _val, _val}) +#define VEC_SPLAT_F32(_val) ((vector float){_val, _val, _val, _val}) + +#define VEC_SPLAT_U64(_val) ((vector unsigned long long){_val, _val}) +#define VEC_SPLAT_S64(_val) ((vector signed long long){_val, _val}) +#define VEC_SPLAT_F64(_val) ((vector double){_val, _val}) + +#endif /* _VEC_LITERAL_H_ */