diff options
author | Nikola Veljkovic <Nikola.Veljkovic@imgtec.com> | 2015-05-26 12:06:09 +0200 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2015-06-17 17:02:11 -0700 |
commit | 1d824c39127764ab50b01ee2ed8bcdb6a59d48cc (patch) | |
tree | 4fa61a78bc67690c25bea97e3dca9b19d18e24df /libc/arch-mips64 | |
parent | 4d0d31475f1584ed7bf4a52ce784c62c30ad522c (diff) | |
download | bionic-1d824c39127764ab50b01ee2ed8bcdb6a59d48cc.zip bionic-1d824c39127764ab50b01ee2ed8bcdb6a59d48cc.tar.gz bionic-1d824c39127764ab50b01ee2ed8bcdb6a59d48cc.tar.bz2 |
[MIPS] Add optimized string functions
Use same string functions for all MIPS architectures.
Bug: 21555893
(cherry picked from commit 38f2eaa07b0ad2e01a40607d3a0ac240ff53abbf)
Change-Id: I94521f023d0bb136a4672782148a9f6e77cc6f1e
Diffstat (limited to 'libc/arch-mips64')
-rw-r--r-- | libc/arch-mips64/mips64.mk | 10 | ||||
-rw-r--r-- | libc/arch-mips64/string/memcpy.S | 423 | ||||
-rw-r--r-- | libc/arch-mips64/string/memset.S | 242 | ||||
-rw-r--r-- | libc/arch-mips64/string/mips-string-ops.h | 148 | ||||
-rw-r--r-- | libc/arch-mips64/string/mips_strlen.c | 224 |
5 files changed, 5 insertions, 1042 deletions
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk index 2b81e63..7757385 100644 --- a/libc/arch-mips64/mips64.mk +++ b/libc/arch-mips64/mips64.mk @@ -5,6 +5,11 @@ # libc_bionic_src_files_mips64 += \ + arch-mips/string/memcmp.c \ + arch-mips/string/memcpy.S \ + arch-mips/string/memset.S \ + arch-mips/string/strcmp.S \ + arch-mips/string/strlen.c \ bionic/__memcpy_chk.cpp \ bionic/__memset_chk.cpp \ bionic/__strcpy_chk.cpp \ @@ -12,10 +17,6 @@ libc_bionic_src_files_mips64 += \ bionic/strchr.cpp \ bionic/strnlen.c \ bionic/strrchr.cpp \ - arch-mips/string/memcmp.c \ - arch-mips/string/memcpy.c \ - arch-mips/string/memset.c \ - arch-mips/string/strlen.c \ libc_freebsd_src_files_mips64 += \ upstream-freebsd/lib/libc/string/wcscat.c \ @@ -34,7 +35,6 @@ libc_openbsd_src_files_mips64 += \ upstream-openbsd/lib/libc/string/stpcpy.c \ upstream-openbsd/lib/libc/string/stpncpy.c \ upstream-openbsd/lib/libc/string/strcat.c \ - upstream-openbsd/lib/libc/string/strcmp.c \ upstream-openbsd/lib/libc/string/strcpy.c \ upstream-openbsd/lib/libc/string/strlcat.c \ upstream-openbsd/lib/libc/string/strlcpy.c \ diff --git a/libc/arch-mips64/string/memcpy.S b/libc/arch-mips64/string/memcpy.S deleted file mode 100644 index dc91096..0000000 --- a/libc/arch-mips64/string/memcpy.S +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (c) 2009 - * MIPS Technologies, Inc., California. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``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 MIPS TECHNOLOGIES, INC. 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. - */ - -/************************************************************************ - * - * memcpy.S - * Version: "043009" - * - ************************************************************************/ - - -/************************************************************************ - * Include files - ************************************************************************/ - -#include <private/bionic_asm.h> - - -/* - * This routine could be optimized for MIPS64. The current code only - * uses MIPS32 instructions. - */ -#if defined(__MIPSEB__) -# define LWHI lwl /* high part is left in big-endian */ -# define SWHI swl /* high part is left in big-endian */ -# define LWLO lwr /* low part is right in big-endian */ -# define SWLO swr /* low part is right in big-endian */ -#endif - -#if defined(__MIPSEL__) -# define LWHI lwr /* high part is right in little-endian */ -# define SWHI swr /* high part is right in little-endian */ -# define LWLO lwl /* low part is left in big-endian */ -# define SWLO swl /* low part is left in big-endian */ -#endif - -LEAF(memcpy,0) - - .set noreorder - .set noat -/* - * Below we handle the case where memcpy is called with overlapping src and dst. - * Although memcpy is not required to handle this case, some parts of Android like Skia - * rely on such usage. We call memmove to handle such cases. - */ - subu t0,a0,a1 - sra AT,t0,31 - xor t1,t0,AT - subu t0,t1,AT - sltu AT,t0,a2 - beq AT,zero,.Lmemcpy - la t9,memmove - jr t9 - nop -.Lmemcpy: - slti AT,a2,8 - bne AT,zero,.Llast8 - move v0,a0 # memcpy returns the dst pointer - -# Test if the src and dst are word-aligned, or can be made word-aligned - xor t8,a1,a0 - andi t8,t8,0x3 # t8 is a0/a1 word-displacement - - bne t8,zero,.Lunaligned - negu a3,a0 - - andi a3,a3,0x3 # we need to copy a3 bytes to make a0/a1 aligned - beq a3,zero,.Lchk16w # when a3=0 then the dst (a0) is word-aligned - subu a2,a2,a3 # now a2 is the remining bytes count - - LWHI t8,0(a1) - addu a1,a1,a3 - SWHI t8,0(a0) - addu a0,a0,a3 - -# Now the dst/src are mutually word-aligned with word-aligned addresses -.Lchk16w: - andi t8,a2,0x3f # any whole 64-byte chunks? - # t8 is the byte count after 64-byte chunks - - beq a2,t8,.Lchk8w # if a2==t8, no 64-byte chunks - # There will be at most 1 32-byte chunk after it - subu a3,a2,t8 # subtract from a2 the reminder - # Here a3 counts bytes in 16w chunks - addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks - - addu t0,a0,a2 # t0 is the "past the end" address - -# When in the loop we exercise "pref 30,x(a0)", the a0+x should not be past -# the "t0-32" address -# This means: for x=128 the last "safe" a0 address is "t0-160" -# Alternatively, for x=64 the last "safe" a0 address is "t0-96" -# In the current version we will use "pref 30,128(a0)", so "t0-160" is the limit - subu t9,t0,160 # t9 is the "last safe pref 30,128(a0)" address - - pref 0,0(a1) # bring the first line of src, addr 0 - pref 0,32(a1) # bring the second line of src, addr 32 - pref 0,64(a1) # bring the third line of src, addr 64 - pref 30,32(a0) # safe, as we have at least 64 bytes ahead -# In case the a0 > t9 don't use "pref 30" at all - sgtu v1,a0,t9 - bgtz v1,.Lloop16w # skip "pref 30,64(a0)" for too short arrays - nop -# otherwise, start with using pref30 - pref 30,64(a0) -.Lloop16w: - pref 0,96(a1) - lw t0,0(a1) - bgtz v1,.Lskip_pref30_96 # skip "pref 30,96(a0)" - lw t1,4(a1) - pref 30,96(a0) # continue setting up the dest, addr 96 -.Lskip_pref30_96: - lw t2,8(a1) - lw t3,12(a1) - lw t4,16(a1) - lw t5,20(a1) - lw t6,24(a1) - lw t7,28(a1) - pref 0,128(a1) # bring the next lines of src, addr 128 - - sw t0,0(a0) - sw t1,4(a0) - sw t2,8(a0) - sw t3,12(a0) - sw t4,16(a0) - sw t5,20(a0) - sw t6,24(a0) - sw t7,28(a0) - - lw t0,32(a1) - bgtz v1,.Lskip_pref30_128 # skip "pref 30,128(a0)" - lw t1,36(a1) - pref 30,128(a0) # continue setting up the dest, addr 128 -.Lskip_pref30_128: - lw t2,40(a1) - lw t3,44(a1) - lw t4,48(a1) - lw t5,52(a1) - lw t6,56(a1) - lw t7,60(a1) - pref 0, 160(a1) # bring the next lines of src, addr 160 - - sw t0,32(a0) - sw t1,36(a0) - sw t2,40(a0) - sw t3,44(a0) - sw t4,48(a0) - sw t5,52(a0) - sw t6,56(a0) - sw t7,60(a0) - - addiu a0,a0,64 # adding 64 to dest - sgtu v1,a0,t9 - bne a0,a3,.Lloop16w - addiu a1,a1,64 # adding 64 to src - move a2,t8 - -# Here we have src and dest word-aligned but less than 64-bytes to go - -.Lchk8w: - pref 0, 0x0(a1) - andi t8,a2,0x1f # is there a 32-byte chunk? - # the t8 is the reminder count past 32-bytes - beq a2,t8,.Lchk1w # when a2=t8, no 32-byte chunk - nop - - lw t0,0(a1) - lw t1,4(a1) - lw t2,8(a1) - lw t3,12(a1) - lw t4,16(a1) - lw t5,20(a1) - lw t6,24(a1) - lw t7,28(a1) - addiu a1,a1,32 - - sw t0,0(a0) - sw t1,4(a0) - sw t2,8(a0) - sw t3,12(a0) - sw t4,16(a0) - sw t5,20(a0) - sw t6,24(a0) - sw t7,28(a0) - addiu a0,a0,32 - -.Lchk1w: - andi a2,t8,0x3 # now a2 is the reminder past 1w chunks - beq a2,t8,.Llast8 - subu a3,t8,a2 # a3 is count of bytes in 1w chunks - addu a3,a0,a3 # now a3 is the dst address past the 1w chunks - -# copying in words (4-byte chunks) -.LwordCopy_loop: - lw t3,0(a1) # the first t3 may be equal t0 ... optimize? - addiu a1,a1,4 - addiu a0,a0,4 - bne a0,a3,.LwordCopy_loop - sw t3,-4(a0) - -# For the last (<8) bytes -.Llast8: - blez a2,.Lleave - addu a3,a0,a2 # a3 is the last dst address -.Llast8loop: - lb v1,0(a1) - addiu a1,a1,1 - addiu a0,a0,1 - bne a0,a3,.Llast8loop - sb v1,-1(a0) - -.Lleave: - j ra - nop - -# -# UNALIGNED case -# - -.Lunaligned: - # got here with a3="negu a0" - andi a3,a3,0x3 # test if the a0 is word aligned - beqz a3,.Lua_chk16w - subu a2,a2,a3 # bytes left after initial a3 bytes - - LWHI v1,0(a1) - LWLO v1,3(a1) - addu a1,a1,a3 # a3 may be here 1, 2 or 3 - SWHI v1,0(a0) - addu a0,a0,a3 # below the dst will be word aligned (NOTE1) - -.Lua_chk16w: - andi t8,a2,0x3f # any whole 64-byte chunks? - # t8 is the byte count after 64-byte chunks - beq a2,t8,.Lua_chk8w # if a2==t8, no 64-byte chunks - # There will be at most 1 32-byte chunk after it - subu a3,a2,t8 # subtract from a2 the reminder - # Here a3 counts bytes in 16w chunks - addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks - - addu t0,a0,a2 # t0 is the "past the end" address - - subu t9,t0,160 # t9 is the "last safe pref 30,128(a0)" address - - pref 0,0(a1) # bring the first line of src, addr 0 - pref 0,32(a1) # bring the second line of src, addr 32 - pref 0,64(a1) # bring the third line of src, addr 64 - pref 30,32(a0) # safe, as we have at least 64 bytes ahead -# In case the a0 > t9 don't use "pref 30" at all - sgtu v1,a0,t9 - bgtz v1,.Lua_loop16w # skip "pref 30,64(a0)" for too short arrays - nop -# otherwise, start with using pref30 - pref 30,64(a0) -.Lua_loop16w: - pref 0,96(a1) - LWHI t0,0(a1) - LWLO t0,3(a1) - LWHI t1,4(a1) - bgtz v1,.Lua_skip_pref30_96 - LWLO t1,7(a1) - pref 30,96(a0) # continue setting up the dest, addr 96 -.Lua_skip_pref30_96: - LWHI t2,8(a1) - LWLO t2,11(a1) - LWHI t3,12(a1) - LWLO t3,15(a1) - LWHI t4,16(a1) - LWLO t4,19(a1) - LWHI t5,20(a1) - LWLO t5,23(a1) - LWHI t6,24(a1) - LWLO t6,27(a1) - LWHI t7,28(a1) - LWLO t7,31(a1) - pref 0,128(a1) # bring the next lines of src, addr 128 - - sw t0,0(a0) - sw t1,4(a0) - sw t2,8(a0) - sw t3,12(a0) - sw t4,16(a0) - sw t5,20(a0) - sw t6,24(a0) - sw t7,28(a0) - - LWHI t0,32(a1) - LWLO t0,35(a1) - LWHI t1,36(a1) - bgtz v1,.Lua_skip_pref30_128 - LWLO t1,39(a1) - pref 30,128(a0) # continue setting up the dest, addr 128 -.Lua_skip_pref30_128: - LWHI t2,40(a1) - LWLO t2,43(a1) - LWHI t3,44(a1) - LWLO t3,47(a1) - LWHI t4,48(a1) - LWLO t4,51(a1) - LWHI t5,52(a1) - LWLO t5,55(a1) - LWHI t6,56(a1) - LWLO t6,59(a1) - LWHI t7,60(a1) - LWLO t7,63(a1) - pref 0, 160(a1) # bring the next lines of src, addr 160 - - sw t0,32(a0) - sw t1,36(a0) - sw t2,40(a0) - sw t3,44(a0) - sw t4,48(a0) - sw t5,52(a0) - sw t6,56(a0) - sw t7,60(a0) - - addiu a0,a0,64 # adding 64 to dest - sgtu v1,a0,t9 - bne a0,a3,.Lua_loop16w - addiu a1,a1,64 # adding 64 to src - move a2,t8 - -# Here we have src and dest word-aligned but less than 64-bytes to go - -.Lua_chk8w: - pref 0, 0x0(a1) - andi t8,a2,0x1f # is there a 32-byte chunk? - # the t8 is the reminder count - beq a2,t8,.Lua_chk1w # when a2=t8, no 32-byte chunk - nop - - LWHI t0,0(a1) - LWLO t0,3(a1) - LWHI t1,4(a1) - LWLO t1,7(a1) - LWHI t2,8(a1) - LWLO t2,11(a1) - LWHI t3,12(a1) - LWLO t3,15(a1) - LWHI t4,16(a1) - LWLO t4,19(a1) - LWHI t5,20(a1) - LWLO t5,23(a1) - LWHI t6,24(a1) - LWLO t6,27(a1) - LWHI t7,28(a1) - LWLO t7,31(a1) - addiu a1,a1,32 - - sw t0,0(a0) - sw t1,4(a0) - sw t2,8(a0) - sw t3,12(a0) - sw t4,16(a0) - sw t5,20(a0) - sw t6,24(a0) - sw t7,28(a0) - addiu a0,a0,32 - -.Lua_chk1w: - andi a2,t8,0x3 # now a2 is the reminder past 1w chunks - beq a2,t8,.Lua_smallCopy - subu a3,t8,a2 # a3 is count of bytes in 1w chunks - addu a3,a0,a3 # now a3 is the dst address past the 1w chunks - -# copying in words (4-byte chunks) -.Lua_wordCopy_loop: - LWHI v1,0(a1) - LWLO v1,3(a1) - addiu a1,a1,4 - addiu a0,a0,4 # note: dst=a0 is word aligned here, see NOTE1 - bne a0,a3,.Lua_wordCopy_loop - sw v1,-4(a0) - -# Now less than 4 bytes (value in a2) left to copy -.Lua_smallCopy: - beqz a2,.Lleave - addu a3,a0,a2 # a3 is the last dst address -.Lua_smallCopy_loop: - lb v1,0(a1) - addiu a1,a1,1 - addiu a0,a0,1 - bne a0,a3,.Lua_smallCopy_loop - sb v1,-1(a0) - - j ra - nop - - .set at - .set reorder - -END(memcpy) - - -/************************************************************************ - * Implementation : Static functions - ************************************************************************/ diff --git a/libc/arch-mips64/string/memset.S b/libc/arch-mips64/string/memset.S deleted file mode 100644 index 09b756b..0000000 --- a/libc/arch-mips64/string/memset.S +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2009 - * MIPS Technologies, Inc., California. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``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 MIPS TECHNOLOGIES, INC. 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. - */ - -/************************************************************************ - * - * memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops - * Version: "043009" - * - ************************************************************************/ - - -/************************************************************************ - * Include files - ************************************************************************/ - -#include <private/bionic_asm.h> - -/* - * This routine could be optimized for MIPS64. The current code only - * uses MIPS32 instructions. - */ - -#if defined(__MIPSEB__) -# define SWHI swl /* high part is left in big-endian */ -# define SWLO swr /* low part is right in big-endian */ -#endif - -#if defined(__MIPSEL__) -# define SWHI swr /* high part is right in little-endian */ -# define SWLO swl /* low part is left in little-endian */ -#endif - -#if !(defined(XGPROF) || defined(XPROF)) -#undef SETUP_GP -#define SETUP_GP -#endif - -#ifdef NDEBUG -#define DBG # -#else -#define DBG -#endif - -LEAF(memset,0) - - .set noreorder - .set noat - - addu t0,a0,a2 # t0 is the "past the end" address - slti AT,a2,4 # is a2 less than 4? - bne AT,zero,.Llast4 # if yes, go to last4 - move v0,a0 # memset returns the dst pointer - - beq a1,zero,.Lset0 - subu v1,zero,a0 - - # smear byte into 32 bit word -#if (__mips==32) && (__mips_isa_rev>=2) - ins a1, a1, 8, 8 # Replicate fill byte into half-word. - ins a1, a1, 16, 16 # Replicate fill byte into word. -#else - and a1,0xff - sll AT,a1,8 - or a1,AT - sll AT,a1,16 - or a1,AT -#endif - -.Lset0: - andi v1,v1,0x3 # word-unaligned address? - beq v1,zero,.Laligned # v1 is the unalignment count - subu a2,a2,v1 - SWHI a1,0(a0) - addu a0,a0,v1 - -# Here we have the "word-aligned" a0 (until the "last4") -.Laligned: - andi t8,a2,0x3f # any 64-byte chunks? - # t8 is the byte count past 64-byte chunks - beq a2,t8,.Lchk8w # when a2==t8, no 64-byte chunks - # There will be at most 1 32-byte chunk then - subu a3,a2,t8 # subtract from a2 the reminder - # Here a3 counts bytes in 16w chunks - addu a3,a0,a3 # Now a3 is the final dst after 64-byte chunks - -# Find out, if there are any 64-byte chunks after which will be still at least -# 96 bytes left. The value "96" is calculated as needed buffer for -# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after -# incrementing "a0" by 64. -# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk. -# - sltiu v1,a2,160 - bgtz v1,.Lloop16w_nopref30 # skip "pref 30,0(a0)" - subu t7,a2,96 # subtract "pref 30 unsafe" region - # below we have at least 1 64-byte chunk which is "pref 30 safe" - andi t6,t7,0x3f # t6 is past "64-byte safe chunks" reminder - subu t5,t7,t6 # subtract from t7 the reminder - # Here t5 counts bytes in 16w "safe" chunks - addu t4,a0,t5 # Now t4 is the dst after 64-byte "safe" chunks - -# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line -# pref 30,0(a0) -# Here we are in the region, where it is safe to use "pref 30,64(a0)" -.Lloop16w: - addiu a0,a0,64 - pref 30,-32(a0) # continue setting up the dest, addr 64-32 - sw a1,-64(a0) - sw a1,-60(a0) - sw a1,-56(a0) - sw a1,-52(a0) - sw a1,-48(a0) - sw a1,-44(a0) - sw a1,-40(a0) - sw a1,-36(a0) - nop - nop # the extra nop instructions help to balance - nop # cycles needed for "store" + "fill" + "evict" - nop # For 64byte store there are needed 8 fill - nop # and 8 evict cycles, i.e. at least 32 instr. - nop - nop - pref 30,0(a0) # continue setting up the dest, addr 64-0 - sw a1,-32(a0) - sw a1,-28(a0) - sw a1,-24(a0) - sw a1,-20(a0) - sw a1,-16(a0) - sw a1,-12(a0) - sw a1,-8(a0) - sw a1,-4(a0) - nop - nop - nop - nop # NOTE: adding 14 nop-s instead of 12 nop-s - nop # gives better results for "fast" memory - nop - bne a0,t4,.Lloop16w - nop - - beq a0,a3,.Lchk8w # maybe no more 64-byte chunks? - nop # this "delayed slot" is useless ... - -.Lloop16w_nopref30: # there could be up to 3 "64-byte nopref30" chunks - addiu a0,a0,64 - sw a1,-64(a0) - sw a1,-60(a0) - sw a1,-56(a0) - sw a1,-52(a0) - sw a1,-48(a0) - sw a1,-44(a0) - sw a1,-40(a0) - sw a1,-36(a0) - sw a1,-32(a0) - sw a1,-28(a0) - sw a1,-24(a0) - sw a1,-20(a0) - sw a1,-16(a0) - sw a1,-12(a0) - sw a1,-8(a0) - bne a0,a3,.Lloop16w_nopref30 - sw a1,-4(a0) - -.Lchk8w: # t8 here is the byte count past 64-byte chunks - - andi t7,t8,0x1f # is there a 32-byte chunk? - # the t7 is the reminder count past 32-bytes - beq t8,t7,.Lchk1w # when t8==t7, no 32-byte chunk - move a2,t7 - - sw a1,0(a0) - sw a1,4(a0) - sw a1,8(a0) - sw a1,12(a0) - sw a1,16(a0) - sw a1,20(a0) - sw a1,24(a0) - sw a1,28(a0) - addiu a0,a0,32 - -.Lchk1w: - andi t8,a2,0x3 # now t8 is the reminder past 1w chunks - beq a2,t8,.Llast4aligned - subu a3,a2,t8 # a3 is the count of bytes in 1w chunks - addu a3,a0,a3 # now a3 is the dst address past the 1w chunks - -# copying in words (4-byte chunks) -.LwordCopy_loop: - addiu a0,a0,4 - bne a0,a3,.LwordCopy_loop - sw a1,-4(a0) - -# store last 0-3 bytes -# this will repeat the last store if the memset finishes on a word boundary -.Llast4aligned: - j ra - SWLO a1,-1(t0) - -.Llast4: - beq a0,t0,.Llast4e -.Llast4l: - addiu a0,a0,1 - bne a0,t0,.Llast4l - sb a1,-1(a0) -.Llast4e: - j ra - nop - - .set at - .set reorder - -END(memset) - - -/************************************************************************ - * Implementation : Static functions - ************************************************************************/ diff --git a/libc/arch-mips64/string/mips-string-ops.h b/libc/arch-mips64/string/mips-string-ops.h deleted file mode 100644 index e635ba1..0000000 --- a/libc/arch-mips64/string/mips-string-ops.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2010 MIPS Technologies, Inc. - * - * 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 name of MIPS Technologies Inc. nor the names of its - * 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 __MIPS_STRING_OPS_H -#define __MIPS_STRING_OPS_H - /* This definition of the byte bitfields uses the - assumption that the layout of the bitfields is - equivalent to the layout in memory. Generally, - for the MIPS ABIs, this is true. If you compile - the strcmp.c file with -DSMOKE_TEST_NEW_STRCMP, - this assumption will be tested. - - Also, regardless of char signedness, ANSI C dictates that - strcmp() treats each character as unsigned char. For - strlen and the like, signedness doesn't matter. - - Also, this code assumes that there are 8-bits per 'char'. */ - -#if __mips64 -typedef struct bits -{ - unsigned long B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8; -} bits_t; -#else -typedef struct bits -{ - unsigned long B0:8, B1:8, B2:8, B3:8; -} bits_t; -#endif - -#ifndef _ULW - /* for MIPS GCC, there is no unaligned builtins - so this code forces - the compiler to treat the pointer access as unaligned. */ -struct ulw -{ - unsigned long b; -} __attribute__ ((packed)); - -#define _ULW(__x) ((struct ulw *) ((char *)(&__x)))->b; -#endif - -/* This union assumes that small structures can be in registers. If - not, then memory accesses will be done - not optimal, but ok. */ -typedef union -{ - unsigned long v; - bits_t b; -} bitfields_t; - -#ifndef detect_zero -/* __mips_dsp, __mips_dspr2, and __mips64 are predefined by - the compiler, based on command line options. */ -#if (__mips_dsp || __mips_dspr2) && !__mips64 -#define __mips_using_dsp 1 - -/* DSP 4-lane (8 unsigned bits per line) subtract and saturate - * Intrinsic operation. How this works: - * Given a 4-byte string of "ABC\0", subtract this as - * an unsigned integer from 0x01010101: - * 0x01010101 - * - 0x41424300 - * ----------- - ( 0xbfbebe01 <-- answer without saturation - * 0x00000001 <-- answer with saturation - * When this 4-lane vector is treated as an unsigned int value, - * a non-zero answer indicates the presence of a zero in the - * original 4-byte argument. */ - -typedef signed char v4i8 __attribute__ ((vector_size (4))); - -#define detect_zero(__x,__y,__01s,__80s)\ - ((unsigned) __builtin_mips_subu_s_qb((v4i8) __01s,(v4i8) __x)) - - /* sets all 4 lanes to requested byte. */ -#define set_byte_lanes(__x) ((unsigned) __builtin_mips_repl_qb(__x)) - - /* sets all 4 lanes to 0x01. */ -#define def_and_set_01(__x) unsigned long __x = (unsigned) __builtin_mips_repl_qb(0x01) - - /* sets all 4 lanes to 0x80. Not needed when subu_s.qb used. */ -#define def_and_set_80(__x) /* do nothing */ - -#else - /* this version, originally published in the 80's, uses - a reverse-carry-set like determination of the zero byte. - The steps are, for __x = 0x31ff0001: - __x - _01s = 0x30fdff00 - ~__x = 0xce00fffe - ((__x - _01s) & ~__x) = 0x0000ff00 - x & _80s = 0x00008000 <- byte 3 was zero - Some implementaions naively assume that characters are - always 7-bit unsigned ASCII. With that assumption, the - "& ~x" is usually discarded. Since character strings - are 8-bit, the and is needed to catch the case of - a false positive when the byte is 0x80. */ - -#define detect_zero(__x,__y,_01s,_80s)\ - ((unsigned) (((__x) - _01s) & ~(__x)) & _80s) - -#if __mips64 -#define def_and_set_80(__x) unsigned long __x = 0x8080808080808080ul -#define def_and_set_01(__x) unsigned long __x = 0x0101010101010101ul -#else -#define def_and_set_80(__x) unsigned long __x = 0x80808080ul -#define def_and_set_01(__x) unsigned long __x = 0x01010101ul -#endif - -#endif -#endif - -/* dealing with 'void *' conversions without using extra variables. */ -#define get_byte(__x,__idx) (((unsigned char *) (__x))[__idx]) -#define set_byte(__x,__idx,__fill) ((unsigned char *) (__x))[__idx] = (__fill) -#define get_word(__x,__idx) (((unsigned long *) (__x))[__idx]) -#define set_word(__x,__idx,__fill) ((unsigned long *) (__x))[__idx] = (__fill) -#define inc_ptr_as(__type,__x,__inc) __x = (void *) (((__type) __x) + (__inc)) -#define cvt_ptr_to(__type,__x) ((__type) (__x)) - -#endif diff --git a/libc/arch-mips64/string/mips_strlen.c b/libc/arch-mips64/string/mips_strlen.c deleted file mode 100644 index 37e5865..0000000 --- a/libc/arch-mips64/string/mips_strlen.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2010 MIPS Technologies, Inc. - * - * 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 name of MIPS Technologies Inc. nor the names of its - * 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 <string.h> -#include "mips-string-ops.h" - -#define do_strlen_word(__av) {\ - if (detect_zero(x,x,_01s,_80s)) break;\ - x = __av;\ - cnt += sizeof (unsigned);\ - } - -#define do_strlen_byte(__x) {\ - if ((bx.b.B##__x) == 0) break;\ - ++cnt;\ - } - -#if SMOKE_TEST_MIPS_STRLEN -#define strlen my_strlen -#endif - -size_t -strlen (const char *_a) -{ - int cnt = 0; - unsigned long x; - - /* align the string to word boundary so we can do word at a time. */ - if ((cvt_ptr_to (unsigned long, _a) & (sizeof (unsigned long) - 1)) != 0) - { - if ((cvt_ptr_to (unsigned long, _a) & 1) != 0) - { - if (get_byte (_a, 0) == 0) - return cnt; - /* set bit 1 so 2-bytes are checked and incremented. */ - inc_ptr_as (char *, _a, 1); - ++cnt; - } - if ((cvt_ptr_to (unsigned long, _a) & 2) != 0) - { - if (get_byte (_a, 0) == 0) - return cnt + 0; - if (get_byte (_a, 1) == 0) - return cnt + 1; - inc_ptr_as (char *, _a, 2); - cnt += 2; - } - } - -#if __mips64 -#error strlen: mips64 check for 4-byte alignment not implemented. -#endif - - if (1) - { - def_and_set_01 (_01s); - def_and_set_80 (_80s); - - /* as advantagous as it is to performance, this code cannot pre-load - the following word, nor can it prefetch the next line at the start - of the loop since the string can be at the end of a page with the - following page unmapped. There are tests in the suite to catch - any attempt to go beyond the current word. */ - x = get_word (_a, 0); - while (1) - { - /* doing 8 words should cover most strings. */ - do_strlen_word (get_word (_a, 1)); - do_strlen_word (get_word (_a, 2)); - do_strlen_word (get_word (_a, 3)); - do_strlen_word (get_word (_a, 4)); - do_strlen_word (get_word (_a, 5)); - do_strlen_word (get_word (_a, 6)); - do_strlen_word (get_word (_a, 7)); - do_strlen_word (get_word (_a, 8)); - inc_ptr_as (unsigned long*, _a, 8); - } - } - while (1) - { - /* pull apart the last word processed and find the zero. */ - bitfields_t bx; - bx.v = x; -#if __mips64 - do_strlen_byte (0); - do_strlen_byte (1); - do_strlen_byte (2); - do_strlen_byte (3); - do_strlen_byte (4); - do_strlen_byte (5); - do_strlen_byte (6); -#else - do_strlen_byte (0); - do_strlen_byte (1); - do_strlen_byte (2); -#endif - /* last byte is zero */ - break; - } - return cnt; -} - -#undef do_strlen_byte -#undef do_strlen_word - -#if SMOKE_TEST_MIPS_STRLEN -#include <stdio.h> -char str1[] = "DHRYSTONE PROGRAM, 1'ST STRING"; -char str2[] = "DHRYSTONE PROGRAM, 2'ST STRING"; - -char str3[] = "another string"; -char str4[] = "another"; - -char str5[] = "somes tring"; -char str6[] = "somes_tring"; - -char str7[16], str8[16]; - -static char * -chk (unsigned long mine, unsigned long libs, int *errors) -{ - static char answer[1024]; - char *result = mine == libs ? "PASS" : "FAIL"; - sprintf (answer, "new_strlen=%d: lib_strlen=%d: %s!", mine, libs, result); - if (mine != libs) - (*errors)++; - return answer; -} - -int -main (int argc, char **argv) -{ - int errors = 0; - /* set -1 in one position */ - str6[5] = 0xff; - /* set zero in same position with junk in following 3 */ - str7[0] = str8[0] = 0; - str7[1] = 0xff; - str7[2] = 'a'; - str7[3] = 2; - str8[1] = 's'; - str8[2] = -2; - str8[3] = 0; - - fprintf (stderr, "========== mips_strlen%s test...\n", - argv[0] ? argv[0] : "unknown strlen"); -#define P(__x,__y) {\ - int a = my_strlen(__x + __y);\ - int b = (strlen)(__x + __y) /* library version */;\ - fprintf(stderr,"%s+%d: %s\n",#__x,__y,chk(a,b,&errors));\ - } - - P (str1, 0); - P (str1, 1); - P (str1, 2); - P (str1, 3); - - P (str2, 0); - P (str2, 1); - P (str2, 2); - P (str2, 3); - - P (str3, 0); - P (str3, 1); - P (str3, 2); - P (str3, 3); - - P (str4, 0); - P (str4, 1); - P (str4, 2); - P (str4, 3); - - P (str5, 0); - P (str5, 1); - P (str5, 2); - P (str5, 3); - - P (str6, 0); - P (str6, 1); - P (str6, 2); - P (str6, 3); - - P (str7, 0); - P (str7, 1); - P (str7, 2); - P (str7, 3); - - P (str8, 0); - P (str8, 1); - P (str8, 2); - P (str8, 3); - - return errors; -} -#endif |