diff --git a/newlib/ChangeLog b/newlib/ChangeLog index 90b13d764..b20a7ad1c 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,13 @@ +2008-02-11 Patrick Mansfield + + * libc/machine/spu/straddr.h: New file, supplies _straddr. + * libc/machine/spu/strcat.c: Use _straddr and _strcpy. + * libc/machine/spu/strcpy.c: Use _strcpy. + * libc/machine/spu/strcpy.h: Supply _strcpy for optimized SPU + str[n]cpy and str[n]cat. + * libc/machine/spu/strncat.c: Use _straddr and _strcpy. + * libc/machine/spu/strncpy.c: Use _strcpy. + 2008-02-11 Patrick Mansfield * libc/machine/spu/strlen.c: Remove the len variable and unneeded diff --git a/newlib/libc/machine/spu/straddr.h b/newlib/libc/machine/spu/straddr.h new file mode 100644 index 000000000..3de594df6 --- /dev/null +++ b/newlib/libc/machine/spu/straddr.h @@ -0,0 +1,75 @@ +/* + (C) Copyright 2008 + International Business Machines 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" + +/* + * Supply the inline _straddr for use by strncpy and strncat. +* +* _straddr: search the string s, and return the address of the first byte +* containing zero. +*/ +static inline char *_straddr(const char *s) +{ + unsigned int cnt, cmp, skip, mask; + vec_uchar16 *ptr, data; + + /* + * Compensate for unaligned strings. + */ + ptr = (vec_uchar16 *)s; /* implicit (s & ~0xf) */ + skip = (unsigned int)(ptr) & 0xf; + /* + * skip the first skip bytes starting at (s & ~0xf). + */ + 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); + + while (cnt == 32) { + data = *++ptr; + cnt = spu_extract(spu_cntlz(spu_gather(spu_cmpeq(data, 0))), 0); + /* + * The first 16 bits for gather on a byte vector are zero, so if cnt + * is 32, none of the 16 bytes in data was zero. And, there are (cnt - + * 16) non-zero bytes in data. + */ + } + /* + * The first non-zero byte is at ptr aligned down plus the number of + * non-zero bytes seen. + */ + return ((char*) (((int) ptr & ~0xf) + (cnt - 16))); +} diff --git a/newlib/libc/machine/spu/strcat.c b/newlib/libc/machine/spu/strcat.c index 902049e6c..5b57a9b66 100644 --- a/newlib/libc/machine/spu/strcat.c +++ b/newlib/libc/machine/spu/strcat.c @@ -1,9 +1,6 @@ /* - (C) Copyright 2001,2006, + (C) Copyright 2008 International Business Machines Corporation, - Sony Computer Entertainment, Incorporated, - Toshiba Corporation, - All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,26 +27,19 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include + #include #include +#include "straddr.h" +#include "strcpy.h" -/* Appends the string pointed to by src (up to and including the /0 - * character) to the array pointed to by dest (overwriting the +/* + * 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); + return _strncpy(_straddr(dest), src, 0, 0, 0); } diff --git a/newlib/libc/machine/spu/strcpy.c b/newlib/libc/machine/spu/strcpy.c index 4d71cf483..69045bae8 100644 --- a/newlib/libc/machine/spu/strcpy.c +++ b/newlib/libc/machine/spu/strcpy.c @@ -1,9 +1,6 @@ /* - (C) Copyright 2001,2006, + (C) Copyright 2008 International Business Machines Corporation, - Sony Computer Entertainment, Incorporated, - Toshiba Corporation, - All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,19 +27,15 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include +#include "strcpy.h" -/* Copy the string pointed to by src (up to and including the /0 +/* + * 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)); + return _strncpy(dest, src, 0, 0, 0); } diff --git a/newlib/libc/machine/spu/strncat.c b/newlib/libc/machine/spu/strncat.c index 4348a06ee..d0b891b3b 100644 --- a/newlib/libc/machine/spu/strncat.c +++ b/newlib/libc/machine/spu/strncat.c @@ -1,9 +1,6 @@ /* - (C) Copyright 2001,2006, + (C) Copyright 2008 International Business Machines Corporation, - Sony Computer Entertainment, Incorporated, - Toshiba Corporation, - All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,68 +27,19 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include +#include "straddr.h" +#include "strcpy.h" -/* Appends the string pointed to by src (up to and including the /0 +/* + * 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) +char * strncat(char * __restrict__ dest, const char * __restrict__ src, + size_t n) { - unsigned int cmp, skip, mask, len; - 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((unsigned int)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); + return _strncpy(_straddr(dest), src, n, 1, 1); } diff --git a/newlib/libc/machine/spu/strncpy.c b/newlib/libc/machine/spu/strncpy.c index 334c3bb6c..9c70b0401 100644 --- a/newlib/libc/machine/spu/strncpy.c +++ b/newlib/libc/machine/spu/strncpy.c @@ -1,9 +1,6 @@ /* - (C) Copyright 2001,2006, + (C) Copyright 2008 International Business Machines Corporation, - Sony Computer Entertainment, Incorporated, - Toshiba Corporation, - All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,58 +27,16 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include +#include "strcpy.h" -/* 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. +/* + * 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) { - unsigned int len; - unsigned int cmp, skip, mask; - vec_uchar16 *ptr, data; - vec_uint4 cnt, gt, N; - - N = spu_promote((unsigned int)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((unsigned int)len, 0), N, gt), 0); - - /* Padding - */ - if (len != n) { - memset(dest + len, 0, n - len); - } - /* Perform a memcpy of the resulting length - */ - return ((char *)memcpy((void *)dest, (const void *)src, len)); + return _strncpy(dest, src, n, 1, 0); }