summaryrefslogtreecommitdiffstats
path: root/libc/arch-mips64
diff options
context:
space:
mode:
authorNikola Veljkovic <Nikola.Veljkovic@imgtec.com>2015-05-26 12:06:09 +0200
committerChristopher Ferris <cferris@google.com>2015-06-17 17:02:11 -0700
commit1d824c39127764ab50b01ee2ed8bcdb6a59d48cc (patch)
tree4fa61a78bc67690c25bea97e3dca9b19d18e24df /libc/arch-mips64
parent4d0d31475f1584ed7bf4a52ce784c62c30ad522c (diff)
downloadbionic-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.mk10
-rw-r--r--libc/arch-mips64/string/memcpy.S423
-rw-r--r--libc/arch-mips64/string/memset.S242
-rw-r--r--libc/arch-mips64/string/mips-string-ops.h148
-rw-r--r--libc/arch-mips64/string/mips_strlen.c224
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