Merge "Remove text-relocs support for apps targeting M+" into mnc-dev
diff --git a/libc/Android.mk b/libc/Android.mk
index 620f438..b50717d 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -1340,7 +1340,7 @@
 LOCAL_REQUIRED_MODULES := tzdata
 LOCAL_ADDITIONAL_DEPENDENCIES := \
     $(libc_common_additional_dependencies) \
-    $(LOCAL_PATH)/version_script.txt \
+    $(LOCAL_PATH)/libc.map \
 
 # Leave the symbols in the shared library so that stack unwinders can produce
 # meaningful name resolution.
@@ -1368,7 +1368,7 @@
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
 # Don't re-export new/delete and friends, even if the compiler really wants to.
-LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
+LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libc.map
 
 # We'd really like to do this for all architectures, but since this wasn't done
 # before, these symbols must continue to be exported on LP32 for binary
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index ffab9f6..2e2cd11 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -203,7 +203,7 @@
 int           nanosleep(const struct timespec*, struct timespec*)   all
 int           clock_settime(clockid_t, const struct timespec*)  all
 int           clock_getres(clockid_t, struct timespec*)   all
-int           __clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*)  all
+int           ___clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*)  all
 int           getitimer(int, const struct itimerval*)   all
 int           setitimer(int, const struct itimerval*, struct itimerval*)  all
 int           __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid)    all
diff --git a/libc/arch-arm/cortex-a53/cortex-a53.mk b/libc/arch-arm/cortex-a53/cortex-a53.mk
new file mode 100644
index 0000000..b5c337c
--- /dev/null
+++ b/libc/arch-arm/cortex-a53/cortex-a53.mk
@@ -0,0 +1 @@
+include bionic/libc/arch-arm/cortex-a7/cortex-a7.mk
diff --git a/libc/arch-arm/syscalls/__clock_nanosleep.S b/libc/arch-arm/syscalls/___clock_nanosleep.S
similarity index 78%
rename from libc/arch-arm/syscalls/__clock_nanosleep.S
rename to libc/arch-arm/syscalls/___clock_nanosleep.S
index ba7ffc4..31420bb 100644
--- a/libc/arch-arm/syscalls/__clock_nanosleep.S
+++ b/libc/arch-arm/syscalls/___clock_nanosleep.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__clock_nanosleep)
+ENTRY(___clock_nanosleep)
     mov     ip, r7
     ldr     r7, =__NR_clock_nanosleep
     swi     #0
@@ -11,4 +11,5 @@
     bxls    lr
     neg     r0, r0
     b       __set_errno_internal
-END(__clock_nanosleep)
+END(___clock_nanosleep)
+.hidden ___clock_nanosleep
diff --git a/libc/arch-arm64/cortex-a53/cortex-a53.mk b/libc/arch-arm64/cortex-a53/cortex-a53.mk
new file mode 100644
index 0000000..676e886
--- /dev/null
+++ b/libc/arch-arm64/cortex-a53/cortex-a53.mk
@@ -0,0 +1 @@
+include bionic/libc/arch-arm64/generic/generic.mk
diff --git a/libc/arch-arm64/syscalls/__clock_nanosleep.S b/libc/arch-arm64/syscalls/___clock_nanosleep.S
similarity index 75%
rename from libc/arch-arm64/syscalls/__clock_nanosleep.S
rename to libc/arch-arm64/syscalls/___clock_nanosleep.S
index 1df15d6..0dcfd4f 100644
--- a/libc/arch-arm64/syscalls/__clock_nanosleep.S
+++ b/libc/arch-arm64/syscalls/___clock_nanosleep.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__clock_nanosleep)
+ENTRY(___clock_nanosleep)
     mov     x8, __NR_clock_nanosleep
     svc     #0
 
@@ -11,5 +11,5 @@
     b.hi    __set_errno_internal
 
     ret
-END(__clock_nanosleep)
-.hidden __clock_nanosleep
+END(___clock_nanosleep)
+.hidden ___clock_nanosleep
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index 33eceab..05e7198 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -6,6 +6,9 @@
 
 libc_bionic_src_files_mips += \
     arch-mips/string/memcmp.c \
+    arch-mips/string/memcpy.S \
+    arch-mips/string/memset.S \
+    arch-mips/string/strcmp.S \
     bionic/__memcpy_chk.cpp \
     bionic/__memset_chk.cpp \
     bionic/__strcpy_chk.cpp \
@@ -31,7 +34,6 @@
     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 \
@@ -54,14 +56,10 @@
 
 ifndef ARCH_MIPS_REV6
 libc_bionic_src_files_mips += \
-    arch-mips/string/memcpy.S \
-    arch-mips/string/memset.S \
     arch-mips/string/mips_strlen.c \
 
 else
 libc_bionic_src_files_mips += \
-    arch-mips/string/memcpy.c \
-    arch-mips/string/memset.c \
     arch-mips/string/strlen.c \
 
 endif
diff --git a/libc/arch-mips/string/memcpy.S b/libc/arch-mips/string/memcpy.S
index dc91096..0b711bd 100644
--- a/libc/arch-mips/string/memcpy.S
+++ b/libc/arch-mips/string/memcpy.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009
+ * Copyright (c) 2012-2015
  *      MIPS Technologies, Inc., California.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,397 +27,826 @@
  * SUCH DAMAGE.
  */
 
-/************************************************************************
- *
- *  memcpy.S
- *  Version: "043009"
- *
- ************************************************************************/
+#ifdef __ANDROID__
+# include <private/bionic_asm.h>
+# define USE_MEMMOVE_FOR_OVERLAP
+# define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD_STREAMED
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif _LIBC
+# include <sysdep.h>
+# include <regdef.h>
+# include <sys/asm.h>
+# define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD_STREAMED
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif _COMPILING_NEWLIB
+# include "machine/asm.h"
+# include "machine/regdef.h"
+# define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD_STREAMED
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#else
+# include <regdef.h>
+# include <sys/asm.h>
+#endif
+
+/* Check to see if the MIPS architecture we are compiling for supports
+ * prefetching.
+ */
+
+#if (__mips == 4) || (__mips == 5) || (__mips == 32) || (__mips == 64)
+# ifndef DISABLE_PREFETCH
+#  define USE_PREFETCH
+# endif
+#endif
+
+#if defined(_MIPS_SIM) && ((_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32))
+# ifndef DISABLE_DOUBLE
+#  define USE_DOUBLE
+# endif
+#endif
 
 
-/************************************************************************
- *  Include files
- ************************************************************************/
+#if __mips_isa_rev > 5
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+#  undef PREFETCH_STORE_HINT
+#  define PREFETCH_STORE_HINT PREFETCH_HINT_STORE_STREAMED
+# endif
+# define R6_CODE
+#endif
 
-#include <private/bionic_asm.h>
+/* Some asm.h files do not have the L macro definition.  */
+#ifndef L
+# if _MIPS_SIM == _ABIO32
+#  define L(label) $L ## label
+# else
+#  define L(label) .L ## label
+# endif
+#endif
 
+/* Some asm.h files do not have the PTR_ADDIU macro definition.  */
+#ifndef PTR_ADDIU
+# if _MIPS_SIM == _ABIO32
+#  define PTR_ADDIU	addiu
+# else
+#  define PTR_ADDIU	daddiu
+# endif
+#endif
+
+/* Some asm.h files do not have the PTR_SRA macro definition.  */
+#ifndef PTR_SRA
+# if  _MIPS_SIM == _ABIO32
+#  define PTR_SRA	sra
+# else
+#  define PTR_SRA	dsra
+# endif
+#endif
+
+/* New R6 instructions that may not be in asm.h.  */
+#ifndef PTR_LSA
+# if _MIPS_SIM == _ABIO32
+#  define PTR_LSA	lsa
+# else
+#  define PTR_LSA	dlsa
+# endif
+#endif
 
 /*
- * This routine could be optimized for MIPS64. The current code only
- * uses MIPS32 instructions.
+ * Using PREFETCH_HINT_LOAD_STREAMED instead of PREFETCH_LOAD on load
+ * prefetches appears to offer a slight preformance advantage.
+ *
+ * Using PREFETCH_HINT_PREPAREFORSTORE instead of PREFETCH_STORE
+ * or PREFETCH_STORE_STREAMED offers a large performance advantage
+ * but PREPAREFORSTORE has some special restrictions to consider.
+ *
+ * Prefetch with the 'prepare for store' hint does not copy a memory
+ * location into the cache, it just allocates a cache line and zeros
+ * it out.  This means that if you do not write to the entire cache
+ * line before writing it out to memory some data will get zero'ed out
+ * when the cache line is written back to memory and data will be lost.
+ *
+ * Also if you are using this memcpy to copy overlapping buffers it may
+ * not behave correctly when using the 'prepare for store' hint.  If you
+ * use the 'prepare for store' prefetch on a memory area that is in the
+ * memcpy source (as well as the memcpy destination), then you will get
+ * some data zero'ed out before you have a chance to read it and data will
+ * be lost.
+ *
+ * If you are going to use this memcpy routine with the 'prepare for store'
+ * prefetch you may want to set USE_MEMMOVE_FOR_OVERLAP in order to avoid
+ * the problem of running memcpy on overlapping buffers.
+ *
+ * There are ifdef'ed sections of this memcpy to make sure that it does not
+ * do prefetches on cache lines that are not going to be completely written.
+ * This code is only needed and only used when PREFETCH_STORE_HINT is set to
+ * PREFETCH_HINT_PREPAREFORSTORE.  This code assumes that cache lines are
+ * 32 bytes and if the cache line is larger it will not work correctly.
  */
-#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	*/
+
+#ifdef USE_PREFETCH
+# define PREFETCH_HINT_LOAD		0
+# define PREFETCH_HINT_STORE		1
+# define PREFETCH_HINT_LOAD_STREAMED	4
+# define PREFETCH_HINT_STORE_STREAMED	5
+# define PREFETCH_HINT_LOAD_RETAINED	6
+# define PREFETCH_HINT_STORE_RETAINED	7
+# define PREFETCH_HINT_WRITEBACK_INVAL	25
+# define PREFETCH_HINT_PREPAREFORSTORE	30
+
+/*
+ * If we have not picked out what hints to use at this point use the
+ * standard load and store prefetch hints.
+ */
+# ifndef PREFETCH_STORE_HINT
+#  define PREFETCH_STORE_HINT PREFETCH_HINT_STORE
+# endif
+# ifndef PREFETCH_LOAD_HINT
+#  define PREFETCH_LOAD_HINT PREFETCH_HINT_LOAD
+# endif
+
+/*
+ * We double everything when USE_DOUBLE is true so we do 2 prefetches to
+ * get 64 bytes in that case.  The assumption is that each individual
+ * prefetch brings in 32 bytes.
+ */
+
+# ifdef USE_DOUBLE
+#  define PREFETCH_CHUNK 64
+#  define PREFETCH_FOR_LOAD(chunk, reg) \
+ pref PREFETCH_LOAD_HINT, (chunk)*64(reg); \
+ pref PREFETCH_LOAD_HINT, ((chunk)*64)+32(reg)
+#  define PREFETCH_FOR_STORE(chunk, reg) \
+ pref PREFETCH_STORE_HINT, (chunk)*64(reg); \
+ pref PREFETCH_STORE_HINT, ((chunk)*64)+32(reg)
+# else
+#  define PREFETCH_CHUNK 32
+#  define PREFETCH_FOR_LOAD(chunk, reg) \
+ pref PREFETCH_LOAD_HINT, (chunk)*32(reg)
+#  define PREFETCH_FOR_STORE(chunk, reg) \
+ pref PREFETCH_STORE_HINT, (chunk)*32(reg)
+# endif
+/* MAX_PREFETCH_SIZE is the maximum size of a prefetch, it must not be less
+ * than PREFETCH_CHUNK, the assumed size of each prefetch.  If the real size
+ * of a prefetch is greater than MAX_PREFETCH_SIZE and the PREPAREFORSTORE
+ * hint is used, the code will not work correctly.  If PREPAREFORSTORE is not
+ * used then MAX_PREFETCH_SIZE does not matter.  */
+# define MAX_PREFETCH_SIZE 128
+/* PREFETCH_LIMIT is set based on the fact that we never use an offset greater
+ * than 5 on a STORE prefetch and that a single prefetch can never be larger
+ * than MAX_PREFETCH_SIZE.  We add the extra 32 when USE_DOUBLE is set because
+ * we actually do two prefetches in that case, one 32 bytes after the other.  */
+# ifdef USE_DOUBLE
+#  define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + 32 + MAX_PREFETCH_SIZE
+# else
+#  define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + MAX_PREFETCH_SIZE
+# endif
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE) \
+    && ((PREFETCH_CHUNK * 4) < MAX_PREFETCH_SIZE)
+/* We cannot handle this because the initial prefetches may fetch bytes that
+ * are before the buffer being copied.  We start copies with an offset
+ * of 4 so avoid this situation when using PREPAREFORSTORE.  */
+#error "PREFETCH_CHUNK is too large and/or MAX_PREFETCH_SIZE is too small."
+# endif
+#else /* USE_PREFETCH not defined */
+# define PREFETCH_FOR_LOAD(offset, reg)
+# define PREFETCH_FOR_STORE(offset, reg)
 #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	*/
+/* Allow the routine to be named something else if desired.  */
+#ifndef MEMCPY_NAME
+# define MEMCPY_NAME memcpy
 #endif
 
-LEAF(memcpy,0)
+/* We use these 32/64 bit registers as temporaries to do the copying.  */
+#define REG0 t0
+#define REG1 t1
+#define REG2 t2
+#define REG3 t3
+#if defined(_MIPS_SIM) && (_MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIO64)
+# define REG4 t4
+# define REG5 t5
+# define REG6 t6
+# define REG7 t7
+#else
+# define REG4 ta0
+# define REG5 ta1
+# define REG6 ta2
+# define REG7 ta3
+#endif
 
+/* We load/store 64 bits at a time when USE_DOUBLE is true.
+ * The C_ prefix stands for CHUNK and is used to avoid macro name
+ * conflicts with system header files.  */
+
+#ifdef USE_DOUBLE
+# define C_ST	sd
+# define C_LD	ld
+# if __MIPSEB
+#  define C_LDHI	ldl	/* high part is left in big-endian	*/
+#  define C_STHI	sdl	/* high part is left in big-endian	*/
+#  define C_LDLO	ldr	/* low part is right in big-endian	*/
+#  define C_STLO	sdr	/* low part is right in big-endian	*/
+# else
+#  define C_LDHI	ldr	/* high part is right in little-endian	*/
+#  define C_STHI	sdr	/* high part is right in little-endian	*/
+#  define C_LDLO	ldl	/* low part is left in little-endian	*/
+#  define C_STLO	sdl	/* low part is left in little-endian	*/
+# endif
+# define C_ALIGN	dalign	/* r6 align instruction			*/
+#else
+# define C_ST	sw
+# define C_LD	lw
+# if __MIPSEB
+#  define C_LDHI	lwl	/* high part is left in big-endian	*/
+#  define C_STHI	swl	/* high part is left in big-endian	*/
+#  define C_LDLO	lwr	/* low part is right in big-endian	*/
+#  define C_STLO	swr	/* low part is right in big-endian	*/
+# else
+#  define C_LDHI	lwr	/* high part is right in little-endian	*/
+#  define C_STHI	swr	/* high part is right in little-endian	*/
+#  define C_LDLO	lwl	/* low part is left in little-endian	*/
+#  define C_STLO	swl	/* low part is left in little-endian	*/
+# endif
+# define C_ALIGN	align	/* r6 align instruction			*/
+#endif
+
+/* Bookkeeping values for 32 vs. 64 bit mode.  */
+#ifdef USE_DOUBLE
+# define NSIZE 8
+# define NSIZEMASK 0x3f
+# define NSIZEDMASK 0x7f
+#else
+# define NSIZE 4
+# define NSIZEMASK 0x1f
+# define NSIZEDMASK 0x3f
+#endif
+#define UNIT(unit) ((unit)*NSIZE)
+#define UNITM1(unit) (((unit)*NSIZE)-1)
+
+#ifdef __ANDROID__
+LEAF(MEMCPY_NAME, 0)
+#else
+LEAF(MEMCPY_NAME)
+#endif
+	.set	nomips16
 	.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.
+ * 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
+#ifdef USE_MEMMOVE_FOR_OVERLAP
+	PTR_SUBU t0,a0,a1
+	PTR_SRA	t2,t0,31
+	xor	t1,t0,t2
+	PTR_SUBU t0,t1,t2
+	sltu	t2,t0,a2
+	beq	t2,zero,L(memcpy)
+	nop
+#if defined(__LP64__)
+	daddiu	sp,sp,-8
+	SETUP_GP64(0,MEMCPY_NAME)
+	LA	t9,memmove
+	RESTORE_GP64
 	jr	t9
-	 nop
-.Lmemcpy:
-	slti	AT,a2,8
-	bne	AT,zero,.Llast8
-	 move	v0,a0	# memcpy returns the dst pointer
+	daddiu	sp,sp,8
+#else
+	LA	t9,memmove
+	jr	t9
+	nop
+#endif
+L(memcpy):
+#endif
+/*
+ * If the size is less than 2*NSIZE (8 or 16), go to L(lastb).  Regardless of
+ * size, copy dst pointer to v0 for the return value.
+ */
+	slti	t2,a2,(2 * NSIZE)
+	bne	t2,zero,L(lastb)
+#if defined(RETURN_FIRST_PREFETCH) || defined(RETURN_LAST_PREFETCH)
+	move	v0,zero
+#else
+	move	v0,a0
+#endif
 
-# Test if the src and dst are word-aligned, or can be made word-aligned
+#ifndef R6_CODE
+
+/*
+ * If src and dst have different alignments, go to L(unaligned), if they
+ * have the same alignment (but are not actually aligned) do a partial
+ * load/store to make them aligned.  If they are both already aligned
+ * we can start copying at L(aligned).
+ */
 	xor	t8,a1,a0
-	andi	t8,t8,0x3		# t8 is a0/a1 word-displacement
+	andi	t8,t8,(NSIZE-1)		/* t8 is a0/a1 word-displacement */
+	bne	t8,zero,L(unaligned)
+	PTR_SUBU a3, zero, a0
 
-	bne	t8,zero,.Lunaligned
-	 negu	a3,a0
+	andi	a3,a3,(NSIZE-1)		/* copy a3 bytes to align a0/a1	  */
+	beq	a3,zero,L(aligned)	/* if a3=0, it is already aligned */
+	PTR_SUBU a2,a2,a3		/* a2 is the remining bytes count */
 
-	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
+	C_LDHI	t8,0(a1)
+	PTR_ADDU a1,a1,a3
+	C_STHI	t8,0(a0)
+	PTR_ADDU a0,a0,a3
 
-	LWHI	t8,0(a1)
-	addu	a1,a1,a3
-	SWHI	t8,0(a0)
-	addu	a0,a0,a3
+#else /* R6_CODE */
 
-# 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
+/*
+ * Align the destination and hope that the source gets aligned too.  If it
+ * doesn't we jump to L(r6_unaligned*) to do unaligned copies using the r6
+ * align instruction.
+ */
+	andi	t8,a0,7
+	lapc	t9,L(atable)
+	PTR_LSA	t9,t8,t9,2
+	jrc	t9
+L(atable):
+	bc	L(lb0)
+	bc	L(lb7)
+	bc	L(lb6)
+	bc	L(lb5)
+	bc	L(lb4)
+	bc	L(lb3)
+	bc	L(lb2)
+	bc	L(lb1)
+L(lb7):
+	lb	a3, 6(a1)
+	sb	a3, 6(a0)
+L(lb6):
+	lb	a3, 5(a1)
+	sb	a3, 5(a0)
+L(lb5):
+	lb	a3, 4(a1)
+	sb	a3, 4(a0)
+L(lb4):
+	lb	a3, 3(a1)
+	sb	a3, 3(a0)
+L(lb3):
+	lb	a3, 2(a1)
+	sb	a3, 2(a0)
+L(lb2):
+	lb	a3, 1(a1)
+	sb	a3, 1(a0)
+L(lb1):
+	lb	a3, 0(a1)
+	sb	a3, 0(a0)
 
-	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
+	li	t9,8
+	subu	t8,t9,t8
+	PTR_SUBU a2,a2,t8
+	PTR_ADDU a0,a0,t8
+	PTR_ADDU a1,a1,t8
+L(lb0):
 
-	addu	t0,a0,a2	# t0 is the "past the end" address
+	andi	t8,a1,(NSIZE-1)
+	lapc	t9,L(jtable)
+	PTR_LSA	t9,t8,t9,2
+	jrc	t9
+L(jtable):
+	bc	L(aligned)
+	bc	L(r6_unaligned1)
+	bc	L(r6_unaligned2)
+	bc	L(r6_unaligned3)
+# ifdef USE_DOUBLE
+	bc	L(r6_unaligned4)
+	bc	L(r6_unaligned5)
+	bc	L(r6_unaligned6)
+	bc	L(r6_unaligned7)
+# endif
+#endif /* R6_CODE */
 
-# 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
+L(aligned):
 
-	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
+/*
+ * Now dst/src are both aligned to (word or double word) aligned addresses
+ * Set a2 to count how many bytes we have to copy after all the 64/128 byte
+ * chunks are copied and a3 to the dst pointer after all the 64/128 byte
+ * chunks have been copied.  We will loop, incrementing a0 and a1 until a0
+ * equals a3.
+ */
 
-	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)
+	andi	t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
+	beq	a2,t8,L(chkw)	 /* if a2==t8, no 64-byte/128-byte chunks */
+	PTR_SUBU a3,a2,t8	 /* subtract from a2 the reminder */
+	PTR_ADDU a3,a0,a3	 /* Now a3 is the final dst after loop */
 
-	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
+/* When in the loop we may prefetch with the 'prepare to store' hint,
+ * in this case 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 "prefetch hint,128(a0)", so "t0-160" is the limit.
+ */
+#if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+	PTR_ADDU t0,a0,a2		/* t0 is the "past the end" address */
+	PTR_SUBU t9,t0,PREFETCH_LIMIT	/* t9 is the "last safe pref" address */
+#endif
+	PREFETCH_FOR_LOAD  (0, a1)
+	PREFETCH_FOR_LOAD  (1, a1)
+	PREFETCH_FOR_LOAD  (2, a1)
+	PREFETCH_FOR_LOAD  (3, a1)
+#if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+	PREFETCH_FOR_STORE (1, a0)
+	PREFETCH_FOR_STORE (2, a0)
+	PREFETCH_FOR_STORE (3, a0)
+#endif
+#if defined(RETURN_FIRST_PREFETCH) && defined(USE_PREFETCH)
+# if PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE
+	sltu    v1,t9,a0
+	bgtz    v1,L(skip_set)
+	nop
+	PTR_ADDIU v0,a0,(PREFETCH_CHUNK*4)
+L(skip_set):
+# else
+	PTR_ADDIU v0,a0,(PREFETCH_CHUNK*1)
+# endif
+#endif
+#if defined(RETURN_LAST_PREFETCH) && defined(USE_PREFETCH) \
+    && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+	PTR_ADDIU v0,a0,(PREFETCH_CHUNK*3)
+# ifdef USE_DOUBLE
+	PTR_ADDIU v0,v0,32
+# endif
+#endif
+L(loop16w):
+	C_LD	t0,UNIT(0)(a1)
+#if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+	sltu	v1,t9,a0		/* If a0 > t9 don't use next prefetch */
+	bgtz	v1,L(skip_pref)
+#endif
+	C_LD	t1,UNIT(1)(a1)
+#ifndef R6_CODE
+	PREFETCH_FOR_STORE (4, a0)
+	PREFETCH_FOR_STORE (5, a0)
+#else
+	PREFETCH_FOR_STORE (2, a0)
+#endif
+#if defined(RETURN_LAST_PREFETCH) && defined(USE_PREFETCH)
+	PTR_ADDIU v0,a0,(PREFETCH_CHUNK*5)
+# ifdef USE_DOUBLE
+	PTR_ADDIU v0,v0,32
+# endif
+#endif
+L(skip_pref):
+	C_LD	REG2,UNIT(2)(a1)
+	C_LD	REG3,UNIT(3)(a1)
+	C_LD	REG4,UNIT(4)(a1)
+	C_LD	REG5,UNIT(5)(a1)
+	C_LD	REG6,UNIT(6)(a1)
+	C_LD	REG7,UNIT(7)(a1)
+#ifndef R6_CODE
+	PREFETCH_FOR_LOAD (4, a1)
+#else
+	PREFETCH_FOR_LOAD (3, a1)
+#endif
+	C_ST	t0,UNIT(0)(a0)
+	C_ST	t1,UNIT(1)(a0)
+	C_ST	REG2,UNIT(2)(a0)
+	C_ST	REG3,UNIT(3)(a0)
+	C_ST	REG4,UNIT(4)(a0)
+	C_ST	REG5,UNIT(5)(a0)
+	C_ST	REG6,UNIT(6)(a0)
+	C_ST	REG7,UNIT(7)(a0)
 
-	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
+	C_LD	t0,UNIT(8)(a1)
+	C_LD	t1,UNIT(9)(a1)
+	C_LD	REG2,UNIT(10)(a1)
+	C_LD	REG3,UNIT(11)(a1)
+	C_LD	REG4,UNIT(12)(a1)
+	C_LD	REG5,UNIT(13)(a1)
+	C_LD	REG6,UNIT(14)(a1)
+	C_LD	REG7,UNIT(15)(a1)
+#ifndef R6_CODE
+	PREFETCH_FOR_LOAD (5, a1)
+#endif
+	C_ST	t0,UNIT(8)(a0)
+	C_ST	t1,UNIT(9)(a0)
+	C_ST	REG2,UNIT(10)(a0)
+	C_ST	REG3,UNIT(11)(a0)
+	C_ST	REG4,UNIT(12)(a0)
+	C_ST	REG5,UNIT(13)(a0)
+	C_ST	REG6,UNIT(14)(a0)
+	C_ST	REG7,UNIT(15)(a0)
+	PTR_ADDIU a0,a0,UNIT(16)	/* adding 64/128 to dest */
+	bne	a0,a3,L(loop16w)
+	PTR_ADDIU a1,a1,UNIT(16)	/* adding 64/128 to src */
 	move	a2,t8
 
-# Here we have src and dest word-aligned but less than 64-bytes to go
+/* Here we have src and dest word-aligned but less than 64-bytes or
+ * 128 bytes to go.  Check for a 32(64) byte chunk and copy if if there
+ * is one.  Otherwise jump down to L(chk1w) to handle the tail end of
+ * the copy.
+ */
 
-.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
+L(chkw):
+	PREFETCH_FOR_LOAD (0, a1)
+	andi	t8,a2,NSIZEMASK	/* Is there a 32-byte/64-byte chunk.  */
+				/* The t8 is the reminder count past 32-bytes */
+	beq	a2,t8,L(chk1w)	/* When a2=t8, no 32-byte chunk  */
+	nop
+	C_LD	t0,UNIT(0)(a1)
+	C_LD	t1,UNIT(1)(a1)
+	C_LD	REG2,UNIT(2)(a1)
+	C_LD	REG3,UNIT(3)(a1)
+	C_LD	REG4,UNIT(4)(a1)
+	C_LD	REG5,UNIT(5)(a1)
+	C_LD	REG6,UNIT(6)(a1)
+	C_LD	REG7,UNIT(7)(a1)
+	PTR_ADDIU a1,a1,UNIT(8)
+	C_ST	t0,UNIT(0)(a0)
+	C_ST	t1,UNIT(1)(a0)
+	C_ST	REG2,UNIT(2)(a0)
+	C_ST	REG3,UNIT(3)(a0)
+	C_ST	REG4,UNIT(4)(a0)
+	C_ST	REG5,UNIT(5)(a0)
+	C_ST	REG6,UNIT(6)(a0)
+	C_ST	REG7,UNIT(7)(a0)
+	PTR_ADDIU a0,a0,UNIT(8)
 
-	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
+/*
+ * Here we have less than 32(64) bytes to copy.  Set up for a loop to
+ * copy one word (or double word) at a time.  Set a2 to count how many
+ * bytes we have to copy after all the word (or double word) chunks are
+ * copied and a3 to the dst pointer after all the (d)word chunks have
+ * been copied.  We will loop, incrementing a0 and a1 until a0 equals a3.
+ */
+L(chk1w):
+	andi	a2,t8,(NSIZE-1)	/* a2 is the reminder past one (d)word chunks */
+	beq	a2,t8,L(lastb)
+	PTR_SUBU a3,t8,a2	/* a3 is count of bytes in one (d)word chunks */
+	PTR_ADDU a3,a0,a3	/* a3 is the dst address after loop */
 
-	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
+/* copying in words (4-byte or 8-byte chunks) */
+L(wordCopy_loop):
+	C_LD	REG3,UNIT(0)(a1)
+	PTR_ADDIU a0,a0,UNIT(1)
+	PTR_ADDIU a1,a1,UNIT(1)
+	bne	a0,a3,L(wordCopy_loop)
+	C_ST	REG3,UNIT(-1)(a0)
 
-.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:
+/* Copy the last 8 (or 16) bytes */
+L(lastb):
+	blez	a2,L(leave)
+	PTR_ADDU a3,a0,a2	/* a3 is the last dst address */
+L(lastbloop):
 	lb	v1,0(a1)
-	addiu	a1,a1,1
-	addiu	a0,a0,1
-	bne	a0,a3,.Llast8loop
-	 sb	v1,-1(a0)
-
-.Lleave:
+	PTR_ADDIU a0,a0,1
+	PTR_ADDIU a1,a1,1
+	bne	a0,a3,L(lastbloop)
+	sb	v1,-1(a0)
+L(leave):
 	j	ra
-	 nop
+	nop
 
-#
-# UNALIGNED case
-#
+#ifndef R6_CODE
+/*
+ * UNALIGNED case, got here with a3 = "negu a0"
+ * This code is nearly identical to the aligned code above
+ * but only the destination (not the source) gets aligned
+ * so we need to do partial loads of the source followed
+ * by normal stores to the destination (once we have aligned
+ * the destination).
+ */
 
-.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
+L(unaligned):
+	andi	a3,a3,(NSIZE-1)	/* copy a3 bytes to align a0/a1 */
+	beqz	a3,L(ua_chk16w) /* if a3=0, it is already aligned */
+	PTR_SUBU a2,a2,a3	/* a2 is the remining bytes count */
 
-	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)
+	C_LDHI	v1,UNIT(0)(a1)
+	C_LDLO	v1,UNITM1(1)(a1)
+	PTR_ADDU a1,a1,a3
+	C_STHI	v1,UNIT(0)(a0)
+	PTR_ADDU a0,a0,a3
 
-.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
+/*
+ *  Now the destination (but not the source) is aligned
+ * Set a2 to count how many bytes we have to copy after all the 64/128 byte
+ * chunks are copied and a3 to the dst pointer after all the 64/128 byte
+ * chunks have been copied.  We will loop, incrementing a0 and a1 until a0
+ * equals a3.
+ */
 
-	addu	t0,a0,a2	# t0 is the "past the end" address
+L(ua_chk16w):
+	andi	t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
+	beq	a2,t8,L(ua_chkw) /* if a2==t8, no 64-byte/128-byte chunks */
+	PTR_SUBU a3,a2,t8	 /* subtract from a2 the reminder */
+	PTR_ADDU a3,a0,a3	 /* Now a3 is the final dst after loop */
 
-	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
+# if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+	PTR_ADDU t0,a0,a2	  /* t0 is the "past the end" address */
+	PTR_SUBU t9,t0,PREFETCH_LIMIT /* t9 is the "last safe pref" address */
+# endif
+	PREFETCH_FOR_LOAD  (0, a1)
+	PREFETCH_FOR_LOAD  (1, a1)
+	PREFETCH_FOR_LOAD  (2, a1)
+# if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+	PREFETCH_FOR_STORE (1, a0)
+	PREFETCH_FOR_STORE (2, a0)
+	PREFETCH_FOR_STORE (3, a0)
+# endif
+# if defined(RETURN_FIRST_PREFETCH) && defined(USE_PREFETCH)
+#  if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+	sltu    v1,t9,a0
+	bgtz    v1,L(ua_skip_set)
+	nop
+	PTR_ADDIU v0,a0,(PREFETCH_CHUNK*4)
+L(ua_skip_set):
+#  else
+	PTR_ADDIU v0,a0,(PREFETCH_CHUNK*1)
+#  endif
+# endif
+L(ua_loop16w):
+	PREFETCH_FOR_LOAD  (3, a1)
+	C_LDHI	t0,UNIT(0)(a1)
+	C_LDHI	t1,UNIT(1)(a1)
+	C_LDHI	REG2,UNIT(2)(a1)
+# if defined(USE_PREFETCH) && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+	sltu	v1,t9,a0
+	bgtz	v1,L(ua_skip_pref)
+# endif
+	C_LDHI	REG3,UNIT(3)(a1)
+	PREFETCH_FOR_STORE (4, a0)
+	PREFETCH_FOR_STORE (5, a0)
+L(ua_skip_pref):
+	C_LDHI	REG4,UNIT(4)(a1)
+	C_LDHI	REG5,UNIT(5)(a1)
+	C_LDHI	REG6,UNIT(6)(a1)
+	C_LDHI	REG7,UNIT(7)(a1)
+	C_LDLO	t0,UNITM1(1)(a1)
+	C_LDLO	t1,UNITM1(2)(a1)
+	C_LDLO	REG2,UNITM1(3)(a1)
+	C_LDLO	REG3,UNITM1(4)(a1)
+	C_LDLO	REG4,UNITM1(5)(a1)
+	C_LDLO	REG5,UNITM1(6)(a1)
+	C_LDLO	REG6,UNITM1(7)(a1)
+	C_LDLO	REG7,UNITM1(8)(a1)
+        PREFETCH_FOR_LOAD (4, a1)
+	C_ST	t0,UNIT(0)(a0)
+	C_ST	t1,UNIT(1)(a0)
+	C_ST	REG2,UNIT(2)(a0)
+	C_ST	REG3,UNIT(3)(a0)
+	C_ST	REG4,UNIT(4)(a0)
+	C_ST	REG5,UNIT(5)(a0)
+	C_ST	REG6,UNIT(6)(a0)
+	C_ST	REG7,UNIT(7)(a0)
+	C_LDHI	t0,UNIT(8)(a1)
+	C_LDHI	t1,UNIT(9)(a1)
+	C_LDHI	REG2,UNIT(10)(a1)
+	C_LDHI	REG3,UNIT(11)(a1)
+	C_LDHI	REG4,UNIT(12)(a1)
+	C_LDHI	REG5,UNIT(13)(a1)
+	C_LDHI	REG6,UNIT(14)(a1)
+	C_LDHI	REG7,UNIT(15)(a1)
+	C_LDLO	t0,UNITM1(9)(a1)
+	C_LDLO	t1,UNITM1(10)(a1)
+	C_LDLO	REG2,UNITM1(11)(a1)
+	C_LDLO	REG3,UNITM1(12)(a1)
+	C_LDLO	REG4,UNITM1(13)(a1)
+	C_LDLO	REG5,UNITM1(14)(a1)
+	C_LDLO	REG6,UNITM1(15)(a1)
+	C_LDLO	REG7,UNITM1(16)(a1)
+        PREFETCH_FOR_LOAD (5, a1)
+	C_ST	t0,UNIT(8)(a0)
+	C_ST	t1,UNIT(9)(a0)
+	C_ST	REG2,UNIT(10)(a0)
+	C_ST	REG3,UNIT(11)(a0)
+	C_ST	REG4,UNIT(12)(a0)
+	C_ST	REG5,UNIT(13)(a0)
+	C_ST	REG6,UNIT(14)(a0)
+	C_ST	REG7,UNIT(15)(a0)
+	PTR_ADDIU a0,a0,UNIT(16)	/* adding 64/128 to dest */
+	bne	a0,a3,L(ua_loop16w)
+	PTR_ADDIU a1,a1,UNIT(16)	/* adding 64/128 to src */
 	move	a2,t8
 
-# Here we have src and dest word-aligned but less than 64-bytes to go
+/* Here we have src and dest word-aligned but less than 64-bytes or
+ * 128 bytes to go.  Check for a 32(64) byte chunk and copy if if there
+ * is one.  Otherwise jump down to L(ua_chk1w) to handle the tail end of
+ * the copy.  */
 
-.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
+L(ua_chkw):
+	PREFETCH_FOR_LOAD (0, a1)
+	andi	t8,a2,NSIZEMASK	  /* Is there a 32-byte/64-byte chunk.  */
+				  /* t8 is the reminder count past 32-bytes */
+	beq	a2,t8,L(ua_chk1w) /* When a2=t8, no 32-byte chunk */
+	nop
+	C_LDHI	t0,UNIT(0)(a1)
+	C_LDHI	t1,UNIT(1)(a1)
+	C_LDHI	REG2,UNIT(2)(a1)
+	C_LDHI	REG3,UNIT(3)(a1)
+	C_LDHI	REG4,UNIT(4)(a1)
+	C_LDHI	REG5,UNIT(5)(a1)
+	C_LDHI	REG6,UNIT(6)(a1)
+	C_LDHI	REG7,UNIT(7)(a1)
+	C_LDLO	t0,UNITM1(1)(a1)
+	C_LDLO	t1,UNITM1(2)(a1)
+	C_LDLO	REG2,UNITM1(3)(a1)
+	C_LDLO	REG3,UNITM1(4)(a1)
+	C_LDLO	REG4,UNITM1(5)(a1)
+	C_LDLO	REG5,UNITM1(6)(a1)
+	C_LDLO	REG6,UNITM1(7)(a1)
+	C_LDLO	REG7,UNITM1(8)(a1)
+	PTR_ADDIU a1,a1,UNIT(8)
+	C_ST	t0,UNIT(0)(a0)
+	C_ST	t1,UNIT(1)(a0)
+	C_ST	REG2,UNIT(2)(a0)
+	C_ST	REG3,UNIT(3)(a0)
+	C_ST	REG4,UNIT(4)(a0)
+	C_ST	REG5,UNIT(5)(a0)
+	C_ST	REG6,UNIT(6)(a0)
+	C_ST	REG7,UNIT(7)(a0)
+	PTR_ADDIU a0,a0,UNIT(8)
+/*
+ * Here we have less than 32(64) bytes to copy.  Set up for a loop to
+ * copy one word (or double word) at a time.
+ */
+L(ua_chk1w):
+	andi	a2,t8,(NSIZE-1)	/* a2 is the reminder past one (d)word chunks */
+	beq	a2,t8,L(ua_smallCopy)
+	PTR_SUBU a3,t8,a2	/* a3 is count of bytes in one (d)word chunks */
+	PTR_ADDU a3,a0,a3	/* a3 is the dst address after loop */
 
-	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
+/* copying in words (4-byte or 8-byte chunks) */
+L(ua_wordCopy_loop):
+	C_LDHI	v1,UNIT(0)(a1)
+	C_LDLO	v1,UNITM1(1)(a1)
+	PTR_ADDIU a0,a0,UNIT(1)
+	PTR_ADDIU a1,a1,UNIT(1)
+	bne	a0,a3,L(ua_wordCopy_loop)
+	C_ST	v1,UNIT(-1)(a0)
 
-	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:
+/* Copy the last 8 (or 16) bytes */
+L(ua_smallCopy):
+	beqz	a2,L(leave)
+	PTR_ADDU a3,a0,a2	/* a3 is the last dst address */
+L(ua_smallCopy_loop):
 	lb	v1,0(a1)
-	addiu	a1,a1,1
-	addiu	a0,a0,1
-	bne	a0,a3,.Lua_smallCopy_loop
-	 sb	v1,-1(a0)
+	PTR_ADDIU a0,a0,1
+	PTR_ADDIU a1,a1,1
+	bne	a0,a3,L(ua_smallCopy_loop)
+	sb	v1,-1(a0)
 
 	j	ra
-	 nop
+	nop
+
+#else /* R6_CODE */
+
+# if __MIPSEB
+#  define SWAP_REGS(X,Y) X, Y
+#  define ALIGN_OFFSET(N) (N)
+# else
+#  define SWAP_REGS(X,Y) Y, X
+#  define ALIGN_OFFSET(N) (NSIZE-N)
+# endif
+# define R6_UNALIGNED_WORD_COPY(BYTEOFFSET) \
+	andi	REG7, a2, (NSIZE-1);/* REG7 is # of bytes to by bytes.     */ \
+	beq	REG7, a2, L(lastb); /* Check for bytes to copy by word	   */ \
+	PTR_SUBU a3, a2, REG7;	/* a3 is number of bytes to be copied in   */ \
+				/* (d)word chunks.			   */ \
+	move	a2, REG7;	/* a2 is # of bytes to copy byte by byte   */ \
+				/* after word loop is finished.		   */ \
+	PTR_ADDU REG6, a0, a3;	/* REG6 is the dst address after loop.	   */ \
+	PTR_SUBU REG2, a1, t8;	/* REG2 is the aligned src address.	   */ \
+	PTR_ADDU a1, a1, a3;	/* a1 is addr of source after word loop.   */ \
+	C_LD	t0, UNIT(0)(REG2);  /* Load first part of source.	   */ \
+L(r6_ua_wordcopy##BYTEOFFSET):						      \
+	C_LD	t1, UNIT(1)(REG2);  /* Load second part of source.	   */ \
+	C_ALIGN	REG3, SWAP_REGS(t1,t0), ALIGN_OFFSET(BYTEOFFSET);	      \
+	PTR_ADDIU a0, a0, UNIT(1);  /* Increment destination pointer.	   */ \
+	PTR_ADDIU REG2, REG2, UNIT(1); /* Increment aligned source pointer.*/ \
+	move	t0, t1;		/* Move second part of source to first.	   */ \
+	bne	a0, REG6,L(r6_ua_wordcopy##BYTEOFFSET);			      \
+	C_ST	REG3, UNIT(-1)(a0);					      \
+	j	L(lastb);						      \
+	nop
+
+	/* We are generating R6 code, the destination is 4 byte aligned and
+	   the source is not 4 byte aligned. t8 is 1, 2, or 3 depending on the
+           alignment of the source.  */
+
+L(r6_unaligned1):
+	R6_UNALIGNED_WORD_COPY(1)
+L(r6_unaligned2):
+	R6_UNALIGNED_WORD_COPY(2)
+L(r6_unaligned3):
+	R6_UNALIGNED_WORD_COPY(3)
+# ifdef USE_DOUBLE
+L(r6_unaligned4):
+	R6_UNALIGNED_WORD_COPY(4)
+L(r6_unaligned5):
+	R6_UNALIGNED_WORD_COPY(5)
+L(r6_unaligned6):
+	R6_UNALIGNED_WORD_COPY(6)
+L(r6_unaligned7):
+	R6_UNALIGNED_WORD_COPY(7)
+# endif
+#endif /* R6_CODE */
 
 	.set	at
 	.set	reorder
-
-END(memcpy)
-
-
-/************************************************************************
- *  Implementation : Static functions
- ************************************************************************/
+END(MEMCPY_NAME)
+#ifndef __ANDROID__
+# ifdef _LIBC
+libc_hidden_builtin_def (MEMCPY_NAME)
+# endif
+#endif
diff --git a/libc/arch-mips/string/memcpy.c b/libc/arch-mips/string/memcpy.c
deleted file mode 100644
index 5551a6d..0000000
--- a/libc/arch-mips/string/memcpy.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*	$OpenBSD: memcpy.c,v 1.1 2014/11/30 19:43:56 deraadt Exp $ */
-/*-
- * Copyright (c) 1990 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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 University 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 REGENTS 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 REGENTS 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 <stdlib.h>
-#include <syslog.h>
-
-/*
- * sizeof(word) MUST BE A POWER OF TWO
- * SO THAT wmask BELOW IS ALL ONES
- */
-typedef	long word;		/* "word" used for optimal copy speed */
-
-#define	wsize	sizeof(word)
-#define	wmask	(wsize - 1)
-
-/*
- * Copy a block of memory, not handling overlap.
- */
-void *
-memcpy(void *dst0, const void *src0, size_t length)
-{
-	char *dst = dst0;
-	const char *src = src0;
-	size_t t;
-
-	if (length == 0 || dst == src)		/* nothing to do */
-		goto done;
-
-	/*
-	 * Macros: loop-t-times; and loop-t-times, t>0
-	 */
-#define	TLOOP(s) if (t) TLOOP1(s)
-#define	TLOOP1(s) do { s; } while (--t)
-
-	/*
-	 * Copy forward.
-	 */
-	t = (long)src;	/* only need low bits */
-	if ((t | (long)dst) & wmask) {
-		/*
-		 * Try to align operands.  This cannot be done
-		 * unless the low bits match.
-		 */
-		if ((t ^ (long)dst) & wmask || length < wsize)
-			t = length;
-		else
-			t = wsize - (t & wmask);
-		length -= t;
-		TLOOP1(*dst++ = *src++);
-	}
-	/*
-	 * Copy whole words, then mop up any trailing bytes.
-	 */
-	t = length / wsize;
-	TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
-	t = length & wmask;
-	TLOOP(*dst++ = *src++);
-done:
-	return (dst0);
-}
diff --git a/libc/arch-mips/string/memset.S b/libc/arch-mips/string/memset.S
index 09b756b..65bb5b5 100644
--- a/libc/arch-mips/string/memset.S
+++ b/libc/arch-mips/string/memset.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009
+ * Copyright (c) 2013
  *      MIPS Technologies, Inc., California.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,216 +27,410 @@
  * 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 #
+#ifdef __ANDROID__
+# include <private/bionic_asm.h>
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif _LIBC
+# include <sysdep.h>
+# include <regdef.h>
+# include <sys/asm.h>
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
+#elif _COMPILING_NEWLIB
+# include "machine/asm.h"
+# include "machine/regdef.h"
+# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
 #else
-#define DBG
+# include <regdef.h>
+# include <sys/asm.h>
 #endif
 
-LEAF(memset,0)
+/* Check to see if the MIPS architecture we are compiling for supports
+   prefetching.  */
 
+#if (__mips == 4) || (__mips == 5) || (__mips == 32) || (__mips == 64)
+# ifndef DISABLE_PREFETCH
+#  define USE_PREFETCH
+# endif
+#endif
+
+#if defined(_MIPS_SIM) && ((_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32))
+# ifndef DISABLE_DOUBLE
+#  define USE_DOUBLE
+# endif
+#endif
+
+#ifndef USE_DOUBLE
+# ifndef DISABLE_DOUBLE_ALIGN
+#  define DOUBLE_ALIGN
+# endif
+#endif
+
+/* Some asm.h files do not have the L macro definition.  */
+#ifndef L
+# if _MIPS_SIM == _ABIO32
+#  define L(label) $L ## label
+# else
+#  define L(label) .L ## label
+# endif
+#endif
+
+/* Some asm.h files do not have the PTR_ADDIU macro definition.  */
+#ifndef PTR_ADDIU
+# if _MIPS_SIM == _ABIO32
+#  define PTR_ADDIU	addiu
+# else
+#  define PTR_ADDIU	daddiu
+# endif
+#endif
+
+/* New R6 instructions that may not be in asm.h.  */
+#ifndef PTR_LSA
+# if _MIPS_SIM == _ABIO32
+#  define PTR_LSA        lsa
+# else
+#  define PTR_LSA        dlsa
+# endif
+#endif
+
+/* Using PREFETCH_HINT_PREPAREFORSTORE instead of PREFETCH_STORE
+   or PREFETCH_STORE_STREAMED offers a large performance advantage
+   but PREPAREFORSTORE has some special restrictions to consider.
+
+   Prefetch with the 'prepare for store' hint does not copy a memory
+   location into the cache, it just allocates a cache line and zeros
+   it out.  This means that if you do not write to the entire cache
+   line before writing it out to memory some data will get zero'ed out
+   when the cache line is written back to memory and data will be lost.
+
+   There are ifdef'ed sections of this memcpy to make sure that it does not
+   do prefetches on cache lines that are not going to be completely written.
+   This code is only needed and only used when PREFETCH_STORE_HINT is set to
+   PREFETCH_HINT_PREPAREFORSTORE.  This code assumes that cache lines are
+   less than MAX_PREFETCH_SIZE bytes and if the cache line is larger it will
+   not work correctly.  */
+
+#ifdef USE_PREFETCH
+# define PREFETCH_HINT_STORE		1
+# define PREFETCH_HINT_STORE_STREAMED	5
+# define PREFETCH_HINT_STORE_RETAINED	7
+# define PREFETCH_HINT_PREPAREFORSTORE	30
+
+/* If we have not picked out what hints to use at this point use the
+   standard load and store prefetch hints.  */
+# ifndef PREFETCH_STORE_HINT
+#  define PREFETCH_STORE_HINT PREFETCH_HINT_STORE
+# endif
+
+/* We double everything when USE_DOUBLE is true so we do 2 prefetches to
+   get 64 bytes in that case.  The assumption is that each individual
+   prefetch brings in 32 bytes.  */
+# ifdef USE_DOUBLE
+#  define PREFETCH_CHUNK 64
+#  define PREFETCH_FOR_STORE(chunk, reg) \
+    pref PREFETCH_STORE_HINT, (chunk)*64(reg); \
+    pref PREFETCH_STORE_HINT, ((chunk)*64)+32(reg)
+# else
+#  define PREFETCH_CHUNK 32
+#  define PREFETCH_FOR_STORE(chunk, reg) \
+    pref PREFETCH_STORE_HINT, (chunk)*32(reg)
+# endif
+
+/* MAX_PREFETCH_SIZE is the maximum size of a prefetch, it must not be less
+   than PREFETCH_CHUNK, the assumed size of each prefetch.  If the real size
+   of a prefetch is greater than MAX_PREFETCH_SIZE and the PREPAREFORSTORE
+   hint is used, the code will not work correctly.  If PREPAREFORSTORE is not
+   used than MAX_PREFETCH_SIZE does not matter.  */
+# define MAX_PREFETCH_SIZE 128
+/* PREFETCH_LIMIT is set based on the fact that we never use an offset greater
+   than 5 on a STORE prefetch and that a single prefetch can never be larger
+   than MAX_PREFETCH_SIZE.  We add the extra 32 when USE_DOUBLE is set because
+   we actually do two prefetches in that case, one 32 bytes after the other.  */
+# ifdef USE_DOUBLE
+#  define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + 32 + MAX_PREFETCH_SIZE
+# else
+#  define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + MAX_PREFETCH_SIZE
+# endif
+
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE) \
+    && ((PREFETCH_CHUNK * 4) < MAX_PREFETCH_SIZE)
+/* We cannot handle this because the initial prefetches may fetch bytes that
+   are before the buffer being copied.  We start copies with an offset
+   of 4 so avoid this situation when using PREPAREFORSTORE.  */
+#  error "PREFETCH_CHUNK is too large and/or MAX_PREFETCH_SIZE is too small."
+# endif
+#else /* USE_PREFETCH not defined */
+# define PREFETCH_FOR_STORE(offset, reg)
+#endif
+
+#if __mips_isa_rev > 5
+# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+#  undef PREFETCH_STORE_HINT
+#  define PREFETCH_STORE_HINT PREFETCH_HINT_STORE_STREAMED
+# endif
+# define R6_CODE
+#endif
+
+/* Allow the routine to be named something else if desired.  */
+#ifndef MEMSET_NAME
+# define MEMSET_NAME memset
+#endif
+
+/* We load/store 64 bits at a time when USE_DOUBLE is true.
+   The C_ prefix stands for CHUNK and is used to avoid macro name
+   conflicts with system header files.  */
+
+#ifdef USE_DOUBLE
+# define C_ST	sd
+# if __MIPSEB
+#  define C_STHI	sdl	/* high part is left in big-endian	*/
+# else
+#  define C_STHI	sdr	/* high part is right in little-endian	*/
+# endif
+#else
+# define C_ST	sw
+# if __MIPSEB
+#  define C_STHI	swl	/* high part is left in big-endian	*/
+# else
+#  define C_STHI	swr	/* high part is right in little-endian	*/
+# endif
+#endif
+
+/* Bookkeeping values for 32 vs. 64 bit mode.  */
+#ifdef USE_DOUBLE
+# define NSIZE 8
+# define NSIZEMASK 0x3f
+# define NSIZEDMASK 0x7f
+#else
+# define NSIZE 4
+# define NSIZEMASK 0x1f
+# define NSIZEDMASK 0x3f
+#endif
+#define UNIT(unit) ((unit)*NSIZE)
+#define UNITM1(unit) (((unit)*NSIZE)-1)
+
+#ifdef __ANDROID__
+LEAF(MEMSET_NAME,0)
+#else
+LEAF(MEMSET_NAME)
+#endif
+
+	.set	nomips16
 	.set	noreorder
-	.set	noat
+/* If the size is less than 2*NSIZE (8 or 16), go to L(lastb).  Regardless of
+   size, copy dst pointer to v0 for the return value.  */
+	slti	t2,a2,(2 * NSIZE)
+	bne	t2,zero,L(lastb)
+	move	v0,a0
 
-	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
+/* If memset value is not zero, we copy it to all the bytes in a 32 or 64
+   bit word.  */
+	beq	a1,zero,L(set0)		/* If memset value is zero no smear  */
+	PTR_SUBU a3,zero,a0
+	nop
 
-	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.
+	/* smear byte into 32 or 64 bit word */
+#if ((__mips == 64) || (__mips == 32)) && (__mips_isa_rev >= 2)
+# ifdef USE_DOUBLE
+	dins	a1, a1, 8, 8        /* Replicate fill byte into half-word.  */
+	dins	a1, a1, 16, 16      /* Replicate fill byte into word.       */
+	dins	a1, a1, 32, 32      /* Replicate fill byte into dbl word.   */
+# else
+	ins	a1, a1, 8, 8        /* Replicate fill byte into half-word.  */
+	ins	a1, a1, 16, 16      /* Replicate fill byte into word.       */
+# endif
 #else
-	and	a1,0xff
-	sll	AT,a1,8
-	or	a1,AT
-	sll	AT,a1,16
-	or	a1,AT
+# ifdef USE_DOUBLE
+        and     a1,0xff
+	dsll	t2,a1,8
+	or	a1,t2
+	dsll	t2,a1,16
+	or	a1,t2
+	dsll	t2,a1,32
+	or	a1,t2
+# else
+        and     a1,0xff
+	sll	t2,a1,8
+	or	a1,t2
+	sll	t2,a1,16
+	or	a1,t2
+# endif
 #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
+/* If the destination address is not aligned do a partial store to get it
+   aligned.  If it is already aligned just jump to L(aligned).  */
+L(set0):
+#ifndef R6_CODE
+	andi	t2,a3,(NSIZE-1)		/* word-unaligned address?          */
+	beq	t2,zero,L(aligned)	/* t2 is the unalignment count      */
+	PTR_SUBU a2,a2,t2
+	C_STHI	a1,0(a0)
+	PTR_ADDU a0,a0,t2
+#else /* R6_CODE */
+	andi	t2,a0,(NSIZE-1)
+	lapc	t9,L(atable)
+	PTR_LSA	t9,t2,t9,2
+	jrc	t9
+L(atable):
+	bc	L(aligned)
+# ifdef USE_DOUBLE
+	bc	L(lb7)
+	bc	L(lb6)
+	bc	L(lb5)
+	bc	L(lb4)
+# endif
+	bc	L(lb3)
+	bc	L(lb2)
+	bc	L(lb1)
+L(lb7):
+	sb	a1,6(a0)
+L(lb6):
+	sb	a1,5(a0)
+L(lb5):
+	sb	a1,4(a0)
+L(lb4):
+	sb	a1,3(a0)
+L(lb3):
+	sb	a1,2(a0)
+L(lb2):
+	sb	a1,1(a0)
+L(lb1):
+	sb	a1,0(a0)
 
-# 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
+	li	t9,NSIZE
+	subu	t2,t9,t2
+	PTR_SUBU a2,a2,t2
+	PTR_ADDU a0,a0,t2
+#endif /* R6_CODE */
 
-# 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
-
+L(aligned):
+/* If USE_DOUBLE is not set we may still want to align the data on a 16
+   byte boundry instead of an 8 byte boundry to maximize the opportunity
+   of proAptiv chips to do memory bonding (combining two sequential 4
+   byte stores into one 8 byte store).  We know there are at least 4 bytes
+   left to store or we would have jumped to L(lastb) earlier in the code.  */
+#ifdef DOUBLE_ALIGN
+	andi	t2,a3,4
+	beq	t2,zero,L(double_aligned)
+	PTR_SUBU a2,a2,t2
 	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
+	PTR_ADDU a0,a0,t2
+L(double_aligned):
+#endif
 
-.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
+/* Now the destination is aligned to (word or double word) aligned address
+   Set a2 to count how many bytes we have to copy after all the 64/128 byte
+   chunks are copied and a3 to the dest pointer after all the 64/128 byte
+   chunks have been copied.  We will loop, incrementing a0 until it equals
+   a3.  */
+	andi	t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
+	beq	a2,t8,L(chkw)	 /* if a2==t8, no 64-byte/128-byte chunks */
+	PTR_SUBU a3,a2,t8	 /* subtract from a2 the reminder */
+	PTR_ADDU a3,a0,a3	 /* Now a3 is the final dst after loop */
 
-# copying in words (4-byte chunks)
-.LwordCopy_loop:
-	addiu	a0,a0,4
-	bne	a0,a3,.LwordCopy_loop
-	 sw	a1,-4(a0)
+/* When in the loop we may prefetch with the 'prepare to store' hint,
+   in this case 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 "prefetch hint,128(a0)", so "t0-160" is the limit.  */
+#if defined(USE_PREFETCH) \
+    && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+	PTR_ADDU t0,a0,a2		/* t0 is the "past the end" address */
+	PTR_SUBU t9,t0,PREFETCH_LIMIT	/* t9 is the "last safe pref" address */
+#endif
+#if defined(USE_PREFETCH) \
+    && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
+	PREFETCH_FOR_STORE (1, a0)
+	PREFETCH_FOR_STORE (2, a0)
+	PREFETCH_FOR_STORE (3, a0)
+#endif
 
-# store last 0-3 bytes
-# this will repeat the last store if the memset finishes on a word boundary
-.Llast4aligned:
+L(loop16w):
+#if defined(USE_PREFETCH) \
+    && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
+	sltu	v1,t9,a0		/* If a0 > t9 don't use next prefetch */
+	bgtz	v1,L(skip_pref)
+	nop
+#endif
+#ifndef R6_CODE
+	PREFETCH_FOR_STORE (4, a0)
+	PREFETCH_FOR_STORE (5, a0)
+#else
+	PREFETCH_FOR_STORE (2, a0)
+#endif
+L(skip_pref):
+	C_ST	a1,UNIT(0)(a0)
+	C_ST	a1,UNIT(1)(a0)
+	C_ST	a1,UNIT(2)(a0)
+	C_ST	a1,UNIT(3)(a0)
+	C_ST	a1,UNIT(4)(a0)
+	C_ST	a1,UNIT(5)(a0)
+	C_ST	a1,UNIT(6)(a0)
+	C_ST	a1,UNIT(7)(a0)
+	C_ST	a1,UNIT(8)(a0)
+	C_ST	a1,UNIT(9)(a0)
+	C_ST	a1,UNIT(10)(a0)
+	C_ST	a1,UNIT(11)(a0)
+	C_ST	a1,UNIT(12)(a0)
+	C_ST	a1,UNIT(13)(a0)
+	C_ST	a1,UNIT(14)(a0)
+	C_ST	a1,UNIT(15)(a0)
+	PTR_ADDIU a0,a0,UNIT(16)	/* adding 64/128 to dest */
+	bne	a0,a3,L(loop16w)
+	nop
+	move	a2,t8
+
+/* Here we have dest word-aligned but less than 64-bytes or 128 bytes to go.
+   Check for a 32(64) byte chunk and copy if if there is one.  Otherwise
+   jump down to L(chk1w) to handle the tail end of the copy.  */
+L(chkw):
+	andi	t8,a2,NSIZEMASK	/* is there a 32-byte/64-byte chunk.  */
+				/* the t8 is the reminder count past 32-bytes */
+	beq	a2,t8,L(chk1w)/* when a2==t8, no 32-byte chunk */
+	nop
+	C_ST	a1,UNIT(0)(a0)
+	C_ST	a1,UNIT(1)(a0)
+	C_ST	a1,UNIT(2)(a0)
+	C_ST	a1,UNIT(3)(a0)
+	C_ST	a1,UNIT(4)(a0)
+	C_ST	a1,UNIT(5)(a0)
+	C_ST	a1,UNIT(6)(a0)
+	C_ST	a1,UNIT(7)(a0)
+	PTR_ADDIU a0,a0,UNIT(8)
+
+/* Here we have less than 32(64) bytes to set.  Set up for a loop to
+   copy one word (or double word) at a time.  Set a2 to count how many
+   bytes we have to copy after all the word (or double word) chunks are
+   copied and a3 to the dest pointer after all the (d)word chunks have
+   been copied.  We will loop, incrementing a0 until a0 equals a3.  */
+L(chk1w):
+	andi	a2,t8,(NSIZE-1)	/* a2 is the reminder past one (d)word chunks */
+	beq	a2,t8,L(lastb)
+	PTR_SUBU a3,t8,a2	/* a3 is count of bytes in one (d)word chunks */
+	PTR_ADDU a3,a0,a3	/* a3 is the dst address after loop */
+
+/* copying in words (4-byte or 8 byte chunks) */
+L(wordCopy_loop):
+	PTR_ADDIU a0,a0,UNIT(1)
+	bne	a0,a3,L(wordCopy_loop)
+	C_ST	a1,UNIT(-1)(a0)
+
+/* Copy the last 8 (or 16) bytes */
+L(lastb):
+	blez	a2,L(leave)
+	PTR_ADDU a3,a0,a2       /* a3 is the last dst address */
+L(lastbloop):
+	PTR_ADDIU a0,a0,1
+	bne	a0,a3,L(lastbloop)
+	sb	a1,-1(a0)
+L(leave):
 	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
+	nop
 
 	.set	at
 	.set	reorder
-
-END(memset)
-
-
-/************************************************************************
- *  Implementation : Static functions
- ************************************************************************/
+END(MEMSET_NAME)
+#ifndef __ANDROID__
+# ifdef _LIBC
+libc_hidden_builtin_def (MEMSET_NAME)
+# endif
+#endif
diff --git a/libc/arch-mips/string/strcmp.S b/libc/arch-mips/string/strcmp.S
new file mode 100644
index 0000000..2b67f5a
--- /dev/null
+++ b/libc/arch-mips/string/strcmp.S
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2014
+ *      Imagination Technologies Limited.
+ *
+ * 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 IMAGINATION TECHNOLOGIES LIMITED ``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 IMAGINATION TECHNOLOGIES LIMITED 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.
+ */
+
+#ifdef __ANDROID__
+# include <private/bionic_asm.h>
+#elif _LIBC
+# include <sysdep.h>
+# include <regdef.h>
+# include <sys/asm.h>
+#elif _COMPILING_NEWLIB
+# include "machine/asm.h"
+# include "machine/regdef.h"
+#else
+# include <regdef.h>
+# include <sys/asm.h>
+#endif
+
+/* Technically strcmp should not read past the end of the strings being
+   compared.  We will read a full word that may contain excess bits beyond
+   the NULL string terminator but unless ENABLE_READAHEAD is set, we will not
+   read the next word after the end of string.  Setting ENABLE_READAHEAD will
+   improve performance but is technically illegal based on the definition of
+   strcmp.  */
+#ifdef ENABLE_READAHEAD
+# define DELAY_READ
+#else
+# define DELAY_READ nop
+#endif
+
+/* Testing on a little endian machine showed using CLZ was a
+   performance loss, so we are not turning it on by default.  */
+#if defined(ENABLE_CLZ) && (__mips_isa_rev > 1)
+# define USE_CLZ
+#endif
+
+/* Some asm.h files do not have the L macro definition.  */
+#ifndef L
+# if _MIPS_SIM == _ABIO32
+#  define L(label) $L ## label
+# else
+#  define L(label) .L ## label
+# endif
+#endif
+
+/* Some asm.h files do not have the PTR_ADDIU macro definition.  */
+#ifndef PTR_ADDIU
+# if _MIPS_SIM == _ABIO32
+#  define PTR_ADDIU       addiu
+# else
+#  define PTR_ADDIU       daddiu
+# endif
+#endif
+
+/* Allow the routine to be named something else if desired.  */
+#ifndef STRCMP_NAME
+# define STRCMP_NAME strcmp
+#endif
+
+#ifdef __ANDROID__
+LEAF(STRCMP_NAME, 0)
+#else
+LEAF(STRCMP_NAME)
+#endif
+	.set	nomips16
+	.set	noreorder
+
+	or	t0, a0, a1
+	andi	t0,0x3
+	bne	t0, zero, L(byteloop)
+
+/* Both strings are 4 byte aligned at this point.  */
+
+	lui	t8, 0x0101
+	ori	t8, t8, 0x0101
+	lui	t9, 0x7f7f
+	ori	t9, 0x7f7f
+
+#define STRCMP32(OFFSET) \
+	lw	v0, OFFSET(a0); \
+	lw	v1, OFFSET(a1); \
+	subu	t0, v0, t8; \
+	bne	v0, v1, L(worddiff); \
+	nor	t1, v0, t9; \
+	and	t0, t0, t1; \
+	bne	t0, zero, L(returnzero)
+
+L(wordloop):
+	STRCMP32(0)
+	DELAY_READ
+	STRCMP32(4)
+	DELAY_READ
+	STRCMP32(8)
+	DELAY_READ
+	STRCMP32(12)
+	DELAY_READ
+	STRCMP32(16)
+	DELAY_READ
+	STRCMP32(20)
+	DELAY_READ
+	STRCMP32(24)
+	DELAY_READ
+	STRCMP32(28)
+	PTR_ADDIU a0, a0, 32
+	b	L(wordloop)
+	PTR_ADDIU a1, a1, 32
+
+L(returnzero):
+	j	ra
+	move	v0, zero
+
+L(worddiff):
+#ifdef USE_CLZ
+	subu	t0, v0, t8
+	nor	t1, v0, t9
+	and	t1, t0, t1
+	xor	t0, v0, v1
+	or	t0, t0, t1
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	wsbh	t0, t0
+	rotr	t0, t0, 16
+# endif
+	clz	t1, t0
+	and	t1, 0xf8
+# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+	neg	t1
+	addu	t1, 24
+# endif
+	rotrv	v0, v0, t1
+	rotrv	v1, v1, t1
+	and	v0, v0, 0xff
+	and	v1, v1, 0xff
+	j	ra
+	subu	v0, v0, v1
+#else /* USE_CLZ */
+# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	andi	t0, v0, 0xff
+	beq	t0, zero, L(wexit01)
+	andi	t1, v1, 0xff
+	bne	t0, t1, L(wexit01)
+
+	srl	t8, v0, 8
+	srl	t9, v1, 8
+	andi	t8, t8, 0xff
+	beq	t8, zero, L(wexit89)
+	andi	t9, t9, 0xff
+	bne	t8, t9, L(wexit89)
+
+	srl	t0, v0, 16
+	srl	t1, v1, 16
+	andi	t0, t0, 0xff
+	beq	t0, zero, L(wexit01)
+	andi	t1, t1, 0xff
+	bne	t0, t1, L(wexit01)
+
+	srl	t8, v0, 24
+	srl	t9, v1, 24
+# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
+	srl	t0, v0, 24
+	beq	t0, zero, L(wexit01)
+	srl	t1, v1, 24
+	bne	t0, t1, L(wexit01)
+
+	srl	t8, v0, 16
+	srl	t9, v1, 16
+	andi	t8, t8, 0xff
+	beq	t8, zero, L(wexit89)
+	andi	t9, t9, 0xff
+	bne	t8, t9, L(wexit89)
+
+	srl	t0, v0, 8
+	srl	t1, v1, 8
+	andi	t0, t0, 0xff
+	beq	t0, zero, L(wexit01)
+	andi	t1, t1, 0xff
+	bne	t0, t1, L(wexit01)
+
+	andi	t8, v0, 0xff
+	andi	t9, v1, 0xff
+# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
+
+L(wexit89):
+	j	ra
+	subu	v0, t8, t9
+L(wexit01):
+	j	ra
+	subu	v0, t0, t1
+#endif /* USE_CLZ */
+
+/* It might seem better to do the 'beq' instruction between the two 'lbu'
+   instructions so that the nop is not needed but testing showed that this
+   code is actually faster (based on glibc strcmp test).  */
+#define BYTECMP01(OFFSET) \
+	lbu	v0, OFFSET(a0); \
+	lbu	v1, OFFSET(a1); \
+	beq	v0, zero, L(bexit01); \
+	nop; \
+	bne	v0, v1, L(bexit01)
+
+#define BYTECMP89(OFFSET) \
+	lbu	t8, OFFSET(a0); \
+	lbu	t9, OFFSET(a1); \
+	beq	t8, zero, L(bexit89); \
+	nop;	\
+	bne	t8, t9, L(bexit89)
+
+L(byteloop):
+	BYTECMP01(0)
+	BYTECMP89(1)
+	BYTECMP01(2)
+	BYTECMP89(3)
+	BYTECMP01(4)
+	BYTECMP89(5)
+	BYTECMP01(6)
+	BYTECMP89(7)
+	PTR_ADDIU a0, a0, 8
+	b	L(byteloop)
+	PTR_ADDIU a1, a1, 8
+
+L(bexit01):
+	j	ra
+	subu	v0, v0, v1
+L(bexit89):
+	j	ra
+	subu	v0, t8, t9
+
+	.set	at
+	.set	reorder
+
+END(STRCMP_NAME)
+#ifndef __ANDROID__
+# ifdef _LIBC
+libc_hidden_builtin_def (STRCMP_NAME)
+# endif
+#endif
diff --git a/libc/arch-mips/syscalls/__clock_nanosleep.S b/libc/arch-mips/syscalls/___clock_nanosleep.S
similarity index 78%
rename from libc/arch-mips/syscalls/__clock_nanosleep.S
rename to libc/arch-mips/syscalls/___clock_nanosleep.S
index 97bfa27..4879489 100644
--- a/libc/arch-mips/syscalls/__clock_nanosleep.S
+++ b/libc/arch-mips/syscalls/___clock_nanosleep.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__clock_nanosleep)
+ENTRY(___clock_nanosleep)
     .set noreorder
     .cpload t9
     li v0, __NR_clock_nanosleep
@@ -16,4 +16,5 @@
     j t9
     nop
     .set reorder
-END(__clock_nanosleep)
+END(___clock_nanosleep)
+.hidden ___clock_nanosleep
diff --git a/libc/arch-mips64/bionic/stat.cpp b/libc/arch-mips64/bionic/stat.cpp
index 2767fbd..29a50ed 100644
--- a/libc/arch-mips64/bionic/stat.cpp
+++ b/libc/arch-mips64/bionic/stat.cpp
@@ -32,29 +32,28 @@
 #include <unistd.h>
 
 struct kernel_stat {
- unsigned int st_dev;
- unsigned int st_pad0[3];
- unsigned long st_ino;
- mode_t st_mode;
- __u32 st_nlink;
- uid_t st_uid;
- gid_t st_gid;
- unsigned int st_rdev;
- unsigned int st_pad1[3];
- __kernel_off_t st_size;
- unsigned int _st_atime;
- unsigned int st_atime_nsec;
- unsigned int _st_mtime;
- unsigned int st_mtime_nsec;
- unsigned int _st_ctime;
- unsigned int st_ctime_nsec;
- unsigned int st_blksize;
- unsigned int st_pad2;
- unsigned long st_blocks;
+  unsigned int st_dev;
+  unsigned int st_pad0[3];
+  unsigned long st_ino;
+  mode_t st_mode;
+  __u32 st_nlink;
+  uid_t st_uid;
+  gid_t st_gid;
+  unsigned int st_rdev;
+  unsigned int st_pad1[3];
+  __kernel_off_t st_size;
+  unsigned int _st_atime;
+  unsigned int st_atime_nsec;
+  unsigned int _st_mtime;
+  unsigned int st_mtime_nsec;
+  unsigned int _st_ctime;
+  unsigned int st_ctime_nsec;
+  unsigned int st_blksize;
+  unsigned int st_pad2;
+  unsigned long st_blocks;
 };
 
-void copy_stat(struct stat *st, struct kernel_stat *s)
-{
+static void copy_stat(struct stat* st, struct kernel_stat* s) {
   st->st_dev = static_cast<dev_t>(s->st_dev);
   st->st_ino = static_cast<ino_t>(s->st_ino);
   st->st_mode = static_cast<mode_t>(s->st_mode);
@@ -73,30 +72,17 @@
   st->st_ctim.tv_nsec = static_cast<long>(s->st_ctime_nsec);
 }
 
-int fstat(int fp, struct stat *st)
-{
+int fstat(int fp, struct stat* st) {
   kernel_stat s;
-  int ret;
-  ret = syscall (__NR_fstat, fp, &s);
-  copy_stat (st, &s);
+  int ret = syscall(__NR_fstat, fp, &s);
+  copy_stat(st, &s);
   return ret;
 }
 __strong_alias(fstat64, fstat);
 
-int newfstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
-{
+int fstatat(int dirfd, const char* pathname, struct stat* buf, int flags) {
    kernel_stat s;
-   int ret;
-   ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
-   copy_stat(buf, &s);
-   return ret;
-}
-
-int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
-{
-   kernel_stat s;
-   int ret;
-   ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
+   int ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
    copy_stat(buf, &s);
    return ret;
 }
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 @@
     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 @@
     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
diff --git a/libc/arch-mips64/syscalls/__clock_nanosleep.S b/libc/arch-mips64/syscalls/___clock_nanosleep.S
similarity index 82%
rename from libc/arch-mips64/syscalls/__clock_nanosleep.S
rename to libc/arch-mips64/syscalls/___clock_nanosleep.S
index 204675f..e9fb316 100644
--- a/libc/arch-mips64/syscalls/__clock_nanosleep.S
+++ b/libc/arch-mips64/syscalls/___clock_nanosleep.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__clock_nanosleep)
+ENTRY(___clock_nanosleep)
     .set push
     .set noreorder
     li v0, __NR_clock_nanosleep
@@ -22,5 +22,5 @@
     j t9
     move ra, t0
     .set pop
-END(__clock_nanosleep)
-.hidden __clock_nanosleep
+END(___clock_nanosleep)
+.hidden ___clock_nanosleep
diff --git a/libc/arch-x86/syscalls/__clock_nanosleep.S b/libc/arch-x86/syscalls/___clock_nanosleep.S
similarity index 90%
rename from libc/arch-x86/syscalls/__clock_nanosleep.S
rename to libc/arch-x86/syscalls/___clock_nanosleep.S
index 75a54d1..088a92e 100644
--- a/libc/arch-x86/syscalls/__clock_nanosleep.S
+++ b/libc/arch-x86/syscalls/___clock_nanosleep.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__clock_nanosleep)
+ENTRY(___clock_nanosleep)
     pushl   %ebx
     .cfi_def_cfa_offset 8
     .cfi_rel_offset ebx, 0
@@ -33,4 +33,5 @@
     popl    %ecx
     popl    %ebx
     ret
-END(__clock_nanosleep)
+END(___clock_nanosleep)
+.hidden ___clock_nanosleep
diff --git a/libc/arch-x86_64/syscalls/__clock_nanosleep.S b/libc/arch-x86_64/syscalls/___clock_nanosleep.S
similarity index 78%
rename from libc/arch-x86_64/syscalls/__clock_nanosleep.S
rename to libc/arch-x86_64/syscalls/___clock_nanosleep.S
index 37726c0..3286eb2 100644
--- a/libc/arch-x86_64/syscalls/__clock_nanosleep.S
+++ b/libc/arch-x86_64/syscalls/___clock_nanosleep.S
@@ -2,7 +2,7 @@
 
 #include <private/bionic_asm.h>
 
-ENTRY(__clock_nanosleep)
+ENTRY(___clock_nanosleep)
     movq    %rcx, %r10
     movl    $__NR_clock_nanosleep, %eax
     syscall
@@ -13,5 +13,5 @@
     call    __set_errno_internal
 1:
     ret
-END(__clock_nanosleep)
-.hidden __clock_nanosleep
+END(___clock_nanosleep)
+.hidden ___clock_nanosleep
diff --git a/libc/bionic/clock_nanosleep.cpp b/libc/bionic/clock_nanosleep.cpp
index 15b8fe7..8e2146f 100644
--- a/libc/bionic/clock_nanosleep.cpp
+++ b/libc/bionic/clock_nanosleep.cpp
@@ -30,9 +30,9 @@
 
 #include "private/ErrnoRestorer.h"
 
-extern "C" int __clock_nanosleep(clockid_t, int, const timespec*, timespec*);
+extern "C" int ___clock_nanosleep(clockid_t, int, const timespec*, timespec*);
 
 int clock_nanosleep(clockid_t clock_id, int flags, const timespec* in, timespec* out) {
   ErrnoRestorer errno_restorer;
-  return (__clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
+  return (___clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
 }
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index f10a8a2..40f610f 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -73,6 +73,13 @@
    */
   ANDROID_DLEXT_FORCE_LOAD = 0x40,
 
+  /* When set, if the minimum p_vaddr of the ELF file's PT_LOAD segments is non-zero,
+   * the dynamic linker will load it at that address.
+   *
+   * This flag is for ART internal use only.
+   */
+  ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80,
+
   /* Mask of valid bits */
   ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
                                         ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
@@ -80,7 +87,8 @@
                                         ANDROID_DLEXT_USE_RELRO |
                                         ANDROID_DLEXT_USE_LIBRARY_FD |
                                         ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
-                                        ANDROID_DLEXT_FORCE_LOAD,
+                                        ANDROID_DLEXT_FORCE_LOAD |
+                                        ANDROID_DLEXT_FORCE_FIXED_VADDR,
 };
 
 typedef struct {
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 260ae5b..6fb06fb 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -46,6 +46,9 @@
 
 typedef long pthread_mutexattr_t;
 
+#define  PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP  PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+#define  PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
+
 enum {
     PTHREAD_MUTEX_NORMAL = 0,
     PTHREAD_MUTEX_RECURSIVE = 1,
diff --git a/libc/arch-mips/string/memset.c b/libc/include/sys/procfs.h
similarity index 74%
rename from libc/arch-mips/string/memset.c
rename to libc/include/sys/procfs.h
index 41dafb2..b5b1a46 100644
--- a/libc/arch-mips/string/memset.c
+++ b/libc/include/sys/procfs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -25,20 +25,26 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-#include <string.h>
-#include <stdint.h>
 
-void*  memset(void*  dst, int c, size_t n)
-{
-    char*  q   = dst;
-    char*  end = q + n;
+#ifndef _SYS_PROCFS_H_
+#define _SYS_PROCFS_H_
 
-    for (;;) {
-        if (q >= end) break; *q++ = (char) c;
-        if (q >= end) break; *q++ = (char) c;
-        if (q >= end) break; *q++ = (char) c;
-        if (q >= end) break; *q++ = (char) c;
-    }
+#include <sys/cdefs.h>
+#include <sys/ucontext.h>
 
-  return dst;
-}
+__BEGIN_DECLS
+
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[NGREG];
+
+typedef fpregset_t elf_fpregset_t;
+
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+
+typedef pid_t lwpid_t;
+typedef void* psaddr_t;
+
+__END_DECLS
+
+#endif /* _SYS_PROCFS_H_ */
diff --git a/libc/include/sys/ptrace.h b/libc/include/sys/ptrace.h
index 8bba9fe..4b881e7 100644
--- a/libc/include/sys/ptrace.h
+++ b/libc/include/sys/ptrace.h
@@ -34,11 +34,31 @@
 
 __BEGIN_DECLS
 
-/* glibc uses different names from the kernel for these two... */
+/* glibc uses different PTRACE_ names from the kernel for these two... */
 #define PTRACE_POKEUSER PTRACE_POKEUSR
 #define PTRACE_PEEKUSER PTRACE_PEEKUSR
 
-extern long ptrace(int, ...);
+/* glibc exports a different set of PT_ names too... */
+#define PT_TRACE_ME PTRACE_TRACEME
+#define PT_READ_I PTRACE_PEEKTEXT
+#define PT_READ_D PTRACE_PEEKDATA
+#define PT_READ_U PTRACE_PEEKUSR
+#define PT_WRITE_I PTRACE_POKETEXT
+#define PT_WRITE_D PTRACE_POKEDATA
+#define PT_WRITE_U PTRACE_POKEUSR
+#define PT_CONT PTRACE_CONT
+#define PT_KILL PTRACE_KILL
+#define PT_STEP PTRACE_SINGLESTEP
+#define PT_GETFPREGS PTRACE_GETFPREGS
+#define PT_ATTACH PTRACE_ATTACH
+#define PT_DETACH PTRACE_DETACH
+#define PT_SYSCALL PTRACE_SYSCALL
+#define PT_SETOPTIONS PTRACE_SETOPTIONS
+#define PT_GETEVENTMSG PTRACE_GETEVENTMSG
+#define PT_GETSIGINFO PTRACE_GETSIGINFO
+#define PT_SETSIGINFO PTRACE_SETSIGINFO
+
+long ptrace(int, ...);
 
 __END_DECLS
 
diff --git a/libc/include/sys/ucontext.h b/libc/include/sys/ucontext.h
index b68d704..399458e 100644
--- a/libc/include/sys/ucontext.h
+++ b/libc/include/sys/ucontext.h
@@ -59,6 +59,7 @@
 
 typedef int greg_t;
 typedef greg_t gregset_t[NGREG];
+typedef struct user_fpregs fpregset_t;
 
 #include <asm/sigcontext.h>
 typedef struct sigcontext mcontext_t;
@@ -82,6 +83,13 @@
 typedef unsigned long greg_t;
 typedef greg_t gregset_t[NGREG];
 
+struct user_fpsimd_struct {
+  long double vregs[32];
+  uint32_t fpsr;
+  uint32_t fpcr;
+};
+typedef struct user_fpsimd_struct fpregset_t;
+
 #include <asm/sigcontext.h>
 typedef struct sigcontext mcontext_t;
 
diff --git a/libc/include/sys/wait.h b/libc/include/sys/wait.h
index 8d9a5f6..12b7308 100644
--- a/libc/include/sys/wait.h
+++ b/libc/include/sys/wait.h
@@ -45,6 +45,9 @@
 #define WIFSTOPPED(s)   (WTERMSIG(s) == 0x7f)
 #define WIFSIGNALED(s)  (WTERMSIG((s)+1) >= 2)
 
+#define W_EXITCODE(ret, sig)    ((ret) << 8 | (sig))
+#define W_STOPCODE(sig)         ((sig) << 8 | 0x7f)
+
 extern pid_t  wait(int *);
 extern pid_t  waitpid(pid_t, int *, int);
 extern pid_t  wait4(pid_t, int *, int, struct rusage *);
diff --git a/libc/libc.map b/libc/libc.map
new file mode 100644
index 0000000..4e17515
--- /dev/null
+++ b/libc/libc.map
@@ -0,0 +1,1455 @@
+LIBC {
+  global:
+    __assert;
+    __assert2;
+    __atomic_cmpxchg; # arm
+    __atomic_dec; # arm
+    __atomic_inc; # arm
+    __atomic_swap; # arm
+    __b64_ntop;
+    __b64_pton;
+    __brk; # arm x86 mips
+    __cmpdf2; # arm
+    __cmsg_nxthdr;
+    __connect; # arm x86 mips
+    __ctype_get_mb_cur_max;
+    __cxa_atexit;
+    __cxa_finalize;
+    __cxa_thread_atexit_impl;
+    __divdf3; # arm
+    __divdi3; # arm x86 mips
+    __divsf3; # arm
+    __divsi3; # arm
+    __dn_comp;
+    __dn_count_labels;
+    __dn_skipname;
+    __epoll_pwait; # arm x86 mips
+    __eqdf2; # arm
+    __errno;
+    __exit; # arm x86 mips
+    __extendsfdf2; # arm
+    __fadvise64; # x86 mips
+    __fbufsize;
+    __fcntl64; # arm x86 mips
+    __FD_CLR_chk;
+    __FD_ISSET_chk;
+    __FD_SET_chk;
+    __fgets_chk;
+    __fixdfsi; # arm
+    __fixsfsi; # arm
+    __fixunssfsi; # arm
+    __flbf;
+    __floatdidf; # arm
+    __floatdisf; # arm
+    __floatsidf; # arm
+    __floatsisf; # arm
+    __floatundidf; # arm
+    __floatundisf; # arm
+    __floatunsidf; # arm
+    __floatunsisf; # arm
+    __fp_nquery;
+    __fp_query;
+    __fpclassify;
+    __fpclassifyd;
+    __fpclassifyf;
+    __fpclassifyl;
+    __fpending;
+    __fpurge;
+    __freadable;
+    __fsetlocking;
+    __fstatfs64; # arm x86 mips
+    __futex_wait; # arm x86 mips
+    __futex_wake; # arm x86 mips
+    __fwritable;
+    __gedf2; # arm
+    __get_h_errno;
+    __get_thread; # arm x86 mips
+    __get_tls; # arm x86 mips
+    __getcpu; # arm x86 mips
+    __getcwd; # arm x86 mips
+    __getdents64; # arm x86 mips
+    __getpid; # arm x86 mips
+    __getpriority; # arm x86 mips
+    __gnu_basename;
+    __gnu_ldivmod_helper; # arm
+    __gnu_strerror_r;
+    __gnu_uldivmod_helper; # arm
+    __gtdf2; # arm
+    __hostalias;
+    __ioctl; # arm x86 mips
+    __isfinite;
+    __isfinitef;
+    __isfinitel;
+    __isinf;
+    __isinff;
+    __isinfl;
+    __isnan;
+    __isnanf;
+    __isnanl;
+    __isnormal;
+    __isnormalf;
+    __isnormall;
+    __isthreaded;
+    __ledf2; # arm
+    __libc_current_sigrtmax;
+    __libc_current_sigrtmin;
+    __libc_init;
+    __llseek; # arm x86 mips
+    __loc_aton;
+    __loc_ntoa;
+    __lshrdi3; # arm
+    __ltdf2; # arm
+    __memchr_chk;
+    __memcpy_chk;
+    __memmove_chk;
+    __memrchr_chk;
+    __memset_chk;
+    __mmap2; # arm x86 mips
+    __moddi3; # x86 mips
+    __muldf3; # arm
+    __muldi3; # arm
+    __mulsf3; # arm
+    __nedf2; # arm
+    __ns_format_ttl; # arm x86 mips
+    __ns_get16; # arm x86 mips
+    __ns_get32; # arm x86 mips
+    __ns_initparse; # arm x86 mips
+    __ns_makecanon; # arm x86 mips
+    __ns_msg_getflag; # arm x86 mips
+    __ns_name_compress; # arm x86 mips
+    __ns_name_ntol; # arm x86 mips
+    __ns_name_ntop; # arm x86 mips
+    __ns_name_pack; # arm x86 mips
+    __ns_name_pton; # arm x86 mips
+    __ns_name_rollback; # arm x86 mips
+    __ns_name_skip; # arm x86 mips
+    __ns_name_uncompress; # arm x86 mips
+    __ns_name_unpack; # arm x86 mips
+    __ns_parserr; # arm x86 mips
+    __ns_put16; # arm x86 mips
+    __ns_put32; # arm x86 mips
+    __ns_samename; # arm x86 mips
+    __ns_skiprr; # arm x86 mips
+    __ns_sprintrr; # arm x86 mips
+    __ns_sprintrrf; # arm x86 mips
+    __open; # arm x86 mips
+    __open_2;
+    __openat; # arm x86 mips
+    __openat_2;
+    __p_cdname;
+    __p_cdnname;
+    __p_class;
+    __p_class_syms;
+    __p_fqname;
+    __p_fqnname;
+    __p_option;
+    __p_query;
+    __p_rcode;
+    __p_secstodate;
+    __p_time;
+    __p_type;
+    __p_type_syms;
+    __page_shift; # arm x86 mips
+    __page_size; # arm x86 mips
+    __poll_chk;
+    __popcount_tab; # arm
+    __popcountsi2; # arm x86 mips
+    __ppoll; # arm x86 mips
+    __ppoll_chk;
+    __pread64_chk;
+    __pread_chk;
+    __progname;
+    __pselect6; # arm x86 mips
+    __pthread_cleanup_pop;
+    __pthread_cleanup_push;
+    __pthread_gettid; # arm x86 mips
+    __ptrace; # arm x86 mips
+    __putlong;
+    __putshort;
+    __read_chk;
+    __readlink_chk;
+    __readlinkat_chk;
+    __reboot; # arm x86 mips
+    __recvfrom_chk;
+    __register_atfork;
+    __res_close;
+    __res_dnok;
+    __res_hnok;
+    __res_hostalias;
+    __res_isourserver;
+    __res_mailok;
+    __res_nameinquery;
+    __res_nclose;
+    __res_ninit;
+    __res_nmkquery;
+    __res_nquery;
+    __res_nquerydomain;
+    __res_nsearch;
+    __res_nsend;
+    __res_ownok;
+    __res_queriesmatch;
+    __res_querydomain;
+    __res_send;
+    __res_send_setqhook;
+    __res_send_setrhook;
+    __restore_core_regs; # arm
+    __rt_sigaction; # arm x86 mips
+    __rt_sigpending; # arm x86 mips
+    __rt_sigprocmask; # arm x86 mips
+    __rt_sigsuspend; # arm x86 mips
+    __rt_sigtimedwait; # arm x86 mips
+    __sched_cpualloc;
+    __sched_cpucount;
+    __sched_cpufree;
+    __sched_getaffinity; # arm x86 mips
+    __sclose; # arm x86 mips
+    __sdidinit; # arm x86 mips
+    __set_errno; # arm x86 mips
+    __set_thread_area; # x86
+    __set_tid_address; # arm x86 mips
+    __set_tls; # arm mips
+    __sF;
+    __sflags; # arm x86 mips
+    __sflush; # arm x86 mips
+    __sfp; # arm x86 mips
+    __sglue; # arm x86 mips
+    __sigaction; # arm x86 mips
+    __signalfd4; # arm x86 mips
+    __sinit; # arm x86 mips
+    __smakebuf; # arm x86 mips
+    __snprintf_chk;
+    __socket; # arm x86 mips
+    __sprintf_chk;
+    __sread; # arm x86 mips
+    __srefill; # arm x86 mips
+    __srget; # arm x86 mips
+    __sseek; # arm x86 mips
+    __stack_chk_fail;
+    __stack_chk_guard;
+    __statfs64; # arm x86 mips
+    __stpcpy_chk;
+    __stpncpy_chk;
+    __stpncpy_chk2;
+    __strcat_chk;
+    __strchr_chk;
+    __strcpy_chk;
+    __strlcat_chk;
+    __strlcpy_chk;
+    __strlen_chk;
+    __strncat_chk;
+    __strncpy_chk;
+    __strncpy_chk2;
+    __strrchr_chk;
+    __subdf3; # arm
+    __subsf3; # arm
+    __swbuf; # arm x86 mips
+    __swrite; # arm x86 mips
+    __swsetup; # arm x86 mips
+    __sym_ntop;
+    __sym_ntos;
+    __sym_ston;
+    __system_properties_init;
+    __system_property_add;
+    __system_property_area__;
+    __system_property_area_init;
+    __system_property_area_serial;
+    __system_property_find;
+    __system_property_find_nth;
+    __system_property_foreach;
+    __system_property_get;
+    __system_property_read;
+    __system_property_serial;
+    __system_property_set;
+    __system_property_set_filename;
+    __system_property_update;
+    __system_property_wait_any;
+    __timer_create; # arm x86 mips
+    __timer_delete; # arm x86 mips
+    __timer_getoverrun; # arm x86 mips
+    __timer_gettime; # arm x86 mips
+    __timer_settime; # arm x86 mips
+    __truncdfsf2; # arm
+    __udivdi3; # arm x86 mips
+    __udivsi3; # arm
+    __umask_chk;
+    __umoddi3; # x86 mips
+    __unorddf2; # arm
+    __unordsf2; # arm
+    __vsnprintf_chk;
+    __vsprintf_chk;
+    __wait4; # arm x86 mips
+    __waitid; # arm x86 mips
+    _ctype_;
+    _Exit;
+    _exit;
+    _flush_cache; # mips
+    _flushlbf;
+    _fwalk; # arm x86 mips
+    _getlong;
+    _getshort;
+    _longjmp;
+    _resolv_delete_cache_for_net;
+    _resolv_flush_cache_for_net;
+    _resolv_set_nameservers_for_net;
+    _setjmp;
+    _tolower;
+    _tolower_tab_; # arm x86 mips
+    _toupper;
+    _toupper_tab_; # arm x86 mips
+    abort;
+    abs;
+    accept;
+    accept4;
+    access;
+    acct;
+    alarm;
+    alphasort;
+    alphasort64;
+    android_getaddrinfofornet;
+    android_gethostbyaddrfornet;
+    android_gethostbynamefornet;
+    android_set_abort_message;
+    arc4random;
+    arc4random_addrandom; # arm x86 mips
+    arc4random_buf;
+    arc4random_stir; # arm x86 mips
+    arc4random_uniform;
+    asctime;
+    asctime64; # arm x86 mips
+    asctime64_r; # arm x86 mips
+    asctime_r;
+    asprintf;
+    at_quick_exit;
+    atof;
+    atoi;
+    atol;
+    atoll;
+    basename;
+    basename_r; # arm x86 mips
+    bcopy; # arm x86 mips
+    bind;
+    bindresvport;
+    brk;
+    bsd_signal; # arm x86 mips
+    bsearch;
+    btowc;
+    bzero; # arm x86 mips
+    c16rtomb;
+    c32rtomb;
+    cacheflush; # arm mips
+    calloc;
+    capget;
+    capset;
+    cfgetispeed;
+    cfgetospeed;
+    cfmakeraw;
+    cfsetispeed;
+    cfsetospeed;
+    cfsetspeed;
+    chdir;
+    chmod;
+    chown;
+    chroot;
+    clearenv;
+    clearerr;
+    clearerr_unlocked;
+    clock;
+    clock_getcpuclockid;
+    clock_getres;
+    clock_gettime;
+    clock_nanosleep;
+    clock_settime;
+    clone;
+    close;
+    closedir;
+    closelog;
+    connect;
+    creat;
+    creat64;
+    ctime;
+    ctime64; # arm x86 mips
+    ctime64_r; # arm x86 mips
+    ctime_r;
+    daemon;
+    daylight;
+    delete_module;
+    difftime;
+    dirfd;
+    dirname;
+    dirname_r; # arm x86 mips
+    div;
+    dn_expand;
+    dprintf;
+    drand48;
+    dup;
+    dup2;
+    dup3;
+    duplocale;
+    endmntent;
+    endpwent;
+    endservent;
+    endusershell;
+    endutent;
+    environ;
+    epoll_create;
+    epoll_create1;
+    epoll_ctl;
+    epoll_pwait;
+    epoll_wait;
+    erand48;
+    err;
+    error;
+    error_at_line;
+    error_message_count;
+    error_one_per_line;
+    error_print_progname;
+    errx;
+    ether_aton;
+    ether_aton_r;
+    ether_ntoa;
+    ether_ntoa_r;
+    eventfd;
+    eventfd_read;
+    eventfd_write;
+    execl;
+    execle;
+    execlp;
+    execv;
+    execve;
+    execvp;
+    execvpe;
+    exit;
+    faccessat;
+    fake_gmtime_r; # arm x86 mips
+    fake_localtime_r; # arm x86 mips
+    fallocate;
+    fallocate64;
+    fchdir;
+    fchmod;
+    fchmodat;
+    fchown;
+    fchownat;
+    fclose;
+    fcntl;
+    fdatasync;
+    fdopen;
+    fdopendir;
+    fdprintf; # arm x86 mips
+    feof;
+    feof_unlocked;
+    ferror;
+    ferror_unlocked;
+    fflush;
+    ffs;
+    fgetc;
+    fgetln;
+    fgetpos;
+    fgets;
+    fgetwc;
+    fgetws;
+    fgetxattr;
+    fileno;
+    flistxattr;
+    flock;
+    flockfile;
+    fmemopen;
+    fnmatch;
+    fopen;
+    fork;
+    forkpty;
+    fpathconf;
+    fprintf;
+    fpurge;
+    fputc;
+    fputs;
+    fputwc;
+    fputws;
+    fread;
+    free;
+    free_malloc_leak_info;
+    freeaddrinfo;
+    freelocale;
+    fremovexattr;
+    freopen;
+    fscanf;
+    fseek;
+    fseeko;
+    fsetpos;
+    fsetxattr;
+    fstat;
+    fstat64;
+    fstatat;
+    fstatat64;
+    fstatfs;
+    fstatfs64;
+    fstatvfs;
+    fstatvfs64;
+    fsync;
+    ftell;
+    ftello;
+    ftime; # arm x86 mips
+    ftok;
+    ftruncate;
+    ftruncate64;
+    ftrylockfile;
+    fts_children;
+    fts_close;
+    fts_open;
+    fts_read;
+    fts_set;
+    ftw;
+    ftw64;
+    funlockfile;
+    funopen;
+    futimens;
+    fwide;
+    fwprintf;
+    fwrite;
+    fwscanf;
+    gai_strerror;
+    get_avphys_pages;
+    get_malloc_leak_info;
+    get_nprocs;
+    get_nprocs_conf;
+    get_phys_pages;
+    getaddrinfo;
+    getauxval;
+    getc;
+    getc_unlocked;
+    getchar;
+    getchar_unlocked;
+    getcwd;
+    getdelim;
+    getdents; # arm x86 mips
+    getdtablesize; # arm x86 mips
+    getegid;
+    getenv;
+    geteuid;
+    getgid;
+    getgrgid;
+    getgrnam;
+    getgrouplist;
+    getgroups;
+    gethostbyaddr;
+    gethostbyaddr_r;
+    gethostbyname;
+    gethostbyname2;
+    gethostbyname2_r;
+    gethostbyname_r;
+    gethostent;
+    gethostname;
+    getitimer;
+    getline;
+    getlogin;
+    getmntent;
+    getmntent_r;
+    getnameinfo;
+    getnetbyaddr;
+    getnetbyname;
+    getopt;
+    getopt_long;
+    getopt_long_only;
+    getpagesize;
+    getpeername;
+    getpgid;
+    getpgrp;
+    getpid;
+    getppid;
+    getpriority;
+    getprogname;
+    getprotobyname;
+    getprotobynumber;
+    getpt;
+    getpwnam;
+    getpwnam_r;
+    getpwuid;
+    getpwuid_r;
+    getresgid;
+    getresuid;
+    getrlimit;
+    getrlimit64;
+    getrusage;
+    gets;
+    getservbyname;
+    getservbyport;
+    getservent;
+    getsid;
+    getsockname;
+    getsockopt;
+    gettid;
+    gettimeofday;
+    getuid;
+    getusershell;
+    getutent;
+    getwc;
+    getwchar;
+    getxattr;
+    gmtime;
+    gmtime64; # arm x86 mips
+    gmtime64_r; # arm x86 mips
+    gmtime_r;
+    grantpt;
+    herror;
+    hstrerror;
+    htonl;
+    htons;
+    if_indextoname;
+    if_nametoindex;
+    imaxabs;
+    imaxdiv;
+    index; # arm x86 mips
+    inet_addr;
+    inet_aton;
+    inet_lnaof;
+    inet_makeaddr;
+    inet_netof;
+    inet_network;
+    inet_nsap_addr;
+    inet_nsap_ntoa;
+    inet_ntoa;
+    inet_ntop;
+    inet_pton;
+    init_module;
+    initgroups;
+    initstate;
+    inotify_add_watch;
+    inotify_init;
+    inotify_init1;
+    inotify_rm_watch;
+    insque;
+    ioctl;
+    isalnum;
+    isalnum_l;
+    isalpha;
+    isalpha_l;
+    isascii;
+    isatty;
+    isblank;
+    isblank_l;
+    iscntrl;
+    iscntrl_l;
+    isdigit;
+    isdigit_l;
+    isfinite;
+    isfinitef;
+    isfinitel;
+    isgraph;
+    isgraph_l;
+    isinf;
+    isinff;
+    isinfl;
+    islower;
+    islower_l;
+    isnan;
+    isnanf;
+    isnanl;
+    isnormal;
+    isnormalf;
+    isnormall;
+    isprint;
+    isprint_l;
+    ispunct;
+    ispunct_l;
+    issetugid; # arm x86 mips
+    isspace;
+    isspace_l;
+    isupper;
+    isupper_l;
+    iswalnum;
+    iswalnum_l;
+    iswalpha;
+    iswalpha_l;
+    iswblank;
+    iswblank_l;
+    iswcntrl;
+    iswcntrl_l;
+    iswctype;
+    iswctype_l;
+    iswdigit;
+    iswdigit_l;
+    iswgraph;
+    iswgraph_l;
+    iswlower;
+    iswlower_l;
+    iswprint;
+    iswprint_l;
+    iswpunct;
+    iswpunct_l;
+    iswspace;
+    iswspace_l;
+    iswupper;
+    iswupper_l;
+    iswxdigit;
+    iswxdigit_l;
+    isxdigit;
+    isxdigit_l;
+    jrand48;
+    kill;
+    killpg;
+    klogctl;
+    labs;
+    lchown;
+    lcong48;
+    ldexp;
+    ldiv;
+    lfind;
+    lgetxattr;
+    link;
+    linkat;
+    listen;
+    listxattr;
+    llabs;
+    lldiv;
+    llistxattr;
+    localeconv;
+    localtime;
+    localtime64; # arm x86 mips
+    localtime64_r; # arm x86 mips
+    localtime_r;
+    login_tty;
+    longjmp;
+    lrand48;
+    lremovexattr;
+    lsearch;
+    lseek;
+    lseek64;
+    lsetxattr;
+    lstat;
+    lstat64;
+    madvise;
+    mallinfo;
+    malloc;
+    malloc_info;
+    malloc_usable_size;
+    mbrlen;
+    mbrtoc16;
+    mbrtoc32;
+    mbrtowc;
+    mbsinit;
+    mbsnrtowcs;
+    mbsrtowcs;
+    mbstowcs;
+    mbtowc;
+    memalign;
+    memccpy;
+    memchr;
+    memcmp;
+    memcpy;
+    memmem;
+    memmove;
+    mempcpy;
+    memrchr;
+    memset;
+    memswap; # arm x86 mips
+    mincore;
+    mkdir;
+    mkdirat;
+    mkdtemp;
+    mkfifo;
+    mkfifoat;
+    mknod;
+    mknodat;
+    mkostemp;
+    mkostemp64;
+    mkostemps;
+    mkostemps64;
+    mkstemp;
+    mkstemp64;
+    mkstemps;
+    mkstemps64;
+    mktemp;
+    mktime;
+    mktime64; # arm x86 mips
+    mktime_tz;
+    mlock;
+    mlockall;
+    mmap;
+    mmap64;
+    mount;
+    mprotect;
+    mrand48;
+    mremap;
+    msync;
+    munlock;
+    munlockall;
+    munmap;
+    nanosleep;
+    newlocale;
+    nftw;
+    nftw64;
+    nice;
+    nrand48;
+    ns_format_ttl; # arm64 x86_64 mips64
+    ns_get16; # arm64 x86_64 mips64
+    ns_get32; # arm64 x86_64 mips64
+    ns_initparse; # arm64 x86_64 mips64
+    ns_makecanon; # arm64 x86_64 mips64
+    ns_msg_getflag; # arm64 x86_64 mips64
+    ns_name_compress; # arm64 x86_64 mips64
+    ns_name_ntol; # arm64 x86_64 mips64
+    ns_name_ntop; # arm64 x86_64 mips64
+    ns_name_pack; # arm64 x86_64 mips64
+    ns_name_pton; # arm64 x86_64 mips64
+    ns_name_rollback; # arm64 x86_64 mips64
+    ns_name_skip; # arm64 x86_64 mips64
+    ns_name_uncompress; # arm64 x86_64 mips64
+    ns_name_unpack; # arm64 x86_64 mips64
+    ns_parserr; # arm64 x86_64 mips64
+    ns_put16; # arm64 x86_64 mips64
+    ns_put32; # arm64 x86_64 mips64
+    ns_samename; # arm64 x86_64 mips64
+    ns_skiprr; # arm64 x86_64 mips64
+    ns_sprintrr; # arm64 x86_64 mips64
+    ns_sprintrrf; # arm64 x86_64 mips64
+    nsdispatch;
+    ntohl;
+    ntohs;
+    open;
+    open64;
+    open_memstream;
+    open_wmemstream;
+    openat;
+    openat64;
+    opendir;
+    openlog;
+    openpty;
+    optarg;
+    opterr;
+    optind;
+    optopt;
+    optreset;
+    pathconf;
+    pause;
+    pclose;
+    perror;
+    personality;
+    pipe;
+    pipe2;
+    poll;
+    popen;
+    posix_fadvise;
+    posix_fadvise64;
+    posix_fallocate;
+    posix_fallocate64;
+    posix_madvise;
+    posix_memalign;
+    posix_openpt;
+    ppoll;
+    prctl;
+    pread;
+    pread64;
+    printf;
+    prlimit; # arm64 x86_64 mips64
+    prlimit64;
+    process_vm_readv;
+    process_vm_writev;
+    pselect;
+    psiginfo;
+    psignal;
+    pthread_atfork;
+    pthread_attr_destroy;
+    pthread_attr_getdetachstate;
+    pthread_attr_getguardsize;
+    pthread_attr_getschedparam;
+    pthread_attr_getschedpolicy;
+    pthread_attr_getscope;
+    pthread_attr_getstack;
+    pthread_attr_getstackaddr; # arm x86 mips
+    pthread_attr_getstacksize;
+    pthread_attr_init;
+    pthread_attr_setdetachstate;
+    pthread_attr_setguardsize;
+    pthread_attr_setschedparam;
+    pthread_attr_setschedpolicy;
+    pthread_attr_setscope;
+    pthread_attr_setstack;
+    pthread_attr_setstackaddr; # arm x86 mips
+    pthread_attr_setstacksize;
+    pthread_cond_broadcast;
+    pthread_cond_destroy;
+    pthread_cond_init;
+    pthread_cond_signal;
+    pthread_cond_timedwait;
+    pthread_cond_timedwait_monotonic; # arm x86 mips
+    pthread_cond_timedwait_monotonic_np; # arm x86 mips
+    pthread_cond_timedwait_relative_np; # arm x86 mips
+    pthread_cond_timeout_np; # arm x86 mips
+    pthread_cond_wait;
+    pthread_condattr_destroy;
+    pthread_condattr_getclock;
+    pthread_condattr_getpshared;
+    pthread_condattr_init;
+    pthread_condattr_setclock;
+    pthread_condattr_setpshared;
+    pthread_create;
+    pthread_detach;
+    pthread_equal;
+    pthread_exit;
+    pthread_getattr_np;
+    pthread_getcpuclockid;
+    pthread_getschedparam;
+    pthread_getspecific;
+    pthread_gettid_np;
+    pthread_join;
+    pthread_key_create;
+    pthread_key_delete;
+    pthread_kill;
+    pthread_mutex_destroy;
+    pthread_mutex_init;
+    pthread_mutex_lock;
+    pthread_mutex_lock_timeout_np; # arm x86 mips
+    pthread_mutex_timedlock;
+    pthread_mutex_trylock;
+    pthread_mutex_unlock;
+    pthread_mutexattr_destroy;
+    pthread_mutexattr_getpshared;
+    pthread_mutexattr_gettype;
+    pthread_mutexattr_init;
+    pthread_mutexattr_setpshared;
+    pthread_mutexattr_settype;
+    pthread_once;
+    pthread_rwlock_destroy;
+    pthread_rwlock_init;
+    pthread_rwlock_rdlock;
+    pthread_rwlock_timedrdlock;
+    pthread_rwlock_timedwrlock;
+    pthread_rwlock_tryrdlock;
+    pthread_rwlock_trywrlock;
+    pthread_rwlock_unlock;
+    pthread_rwlock_wrlock;
+    pthread_rwlockattr_destroy;
+    pthread_rwlockattr_getkind_np;
+    pthread_rwlockattr_getpshared;
+    pthread_rwlockattr_init;
+    pthread_rwlockattr_setkind_np;
+    pthread_rwlockattr_setpshared;
+    pthread_self;
+    pthread_setname_np;
+    pthread_setschedparam;
+    pthread_setspecific;
+    pthread_sigmask;
+    ptrace;
+    ptsname;
+    ptsname_r;
+    putc;
+    putc_unlocked;
+    putchar;
+    putchar_unlocked;
+    putenv;
+    puts;
+    pututline;
+    putw; # arm x86 mips
+    putwc;
+    putwchar;
+    pvalloc; # arm x86 mips
+    pwrite;
+    pwrite64;
+    qsort;
+    quick_exit;
+    raise;
+    rand;
+    rand_r;
+    random;
+    read;
+    readahead;
+    readdir;
+    readdir64;
+    readdir64_r;
+    readdir_r;
+    readlink;
+    readlinkat;
+    readv;
+    realloc;
+    realpath;
+    reboot;
+    recv;
+    recvfrom;
+    recvmmsg;
+    recvmsg;
+    regcomp;
+    regerror;
+    regexec;
+    regfree;
+    remove;
+    removexattr;
+    remque;
+    rename;
+    renameat;
+    res_init;
+    res_mkquery;
+    res_query;
+    res_search;
+    restore_core_regs; # arm
+    rewind;
+    rewinddir;
+    rmdir;
+    sbrk;
+    scandir;
+    scandir64;
+    scanf;
+    sched_get_priority_max;
+    sched_get_priority_min;
+    sched_getaffinity;
+    sched_getcpu;
+    sched_getparam;
+    sched_getscheduler;
+    sched_rr_get_interval;
+    sched_setaffinity;
+    sched_setparam;
+    sched_setscheduler;
+    sched_yield;
+    seed48;
+    seekdir;
+    select;
+    sem_close;
+    sem_destroy;
+    sem_getvalue;
+    sem_init;
+    sem_open;
+    sem_post;
+    sem_timedwait;
+    sem_trywait;
+    sem_unlink;
+    sem_wait;
+    send;
+    sendfile;
+    sendfile64;
+    sendmmsg;
+    sendmsg;
+    sendto;
+    setbuf;
+    setbuffer;
+    setegid;
+    setenv;
+    seteuid;
+    setfsgid;
+    setfsuid;
+    setgid;
+    setgroups;
+    sethostname;
+    setitimer;
+    setjmp;
+    setlinebuf;
+    setlocale;
+    setlogmask;
+    setmntent;
+    setns;
+    setpgid;
+    setpgrp;
+    setpriority;
+    setprogname;
+    setregid;
+    setresgid;
+    setresuid;
+    setreuid;
+    setrlimit;
+    setrlimit64;
+    setservent;
+    setsid;
+    setsockopt;
+    setstate;
+    settimeofday;
+    setuid;
+    setusershell;
+    setutent;
+    setvbuf;
+    setxattr;
+    shutdown;
+    sigaction;
+    sigaddset;
+    sigaltstack;
+    sigblock;
+    sigdelset;
+    sigemptyset;
+    sigfillset;
+    siginterrupt;
+    sigismember;
+    siglongjmp;
+    signal;
+    signalfd;
+    sigpending;
+    sigprocmask;
+    sigqueue;
+    sigsetjmp;
+    sigsetmask;
+    sigsuspend;
+    sigtimedwait;
+    sigwait;
+    sigwaitinfo;
+    sleep;
+    snprintf;
+    socket;
+    socketpair;
+    splice;
+    sprintf;
+    srand;
+    srand48;
+    srandom;
+    sscanf;
+    stat;
+    stat64;
+    statfs;
+    statfs64;
+    statvfs;
+    statvfs64;
+    stderr;
+    stdin;
+    stdout;
+    stpcpy;
+    stpncpy;
+    strcasecmp;
+    strcasecmp_l;
+    strcasestr;
+    strcat;
+    strchr;
+    strcmp;
+    strcoll;
+    strcoll_l;
+    strcpy;
+    strcspn;
+    strdup;
+    strerror;
+    strerror_l;
+    strerror_r;
+    strftime;
+    strftime_l;
+    strlcat;
+    strlcpy;
+    strlen;
+    strncasecmp;
+    strncasecmp_l;
+    strncat;
+    strncmp;
+    strncpy;
+    strndup;
+    strnlen;
+    strntoimax; # arm x86 mips
+    strntoumax; # arm x86 mips
+    strpbrk;
+    strptime;
+    strrchr;
+    strsep;
+    strsignal;
+    strspn;
+    strstr;
+    strtod;
+    strtof;
+    strtoimax;
+    strtok;
+    strtok_r;
+    strtol;
+    strtold;
+    strtold_l;
+    strtoll;
+    strtoll_l;
+    strtoq;
+    strtotimeval; # arm x86 mips
+    strtoul;
+    strtoull;
+    strtoull_l;
+    strtoumax;
+    strtouq;
+    strxfrm;
+    strxfrm_l;
+    swapoff;
+    swapon;
+    swprintf;
+    swscanf;
+    symlink;
+    symlinkat;
+    sync;
+    sys_siglist;
+    sys_signame;
+    syscall;
+    sysconf;
+    sysinfo;
+    syslog;
+    system;
+    sysv_signal; # arm x86 mips
+    tcdrain;
+    tcflow;
+    tcflush;
+    tcgetattr;
+    tcgetpgrp;
+    tcgetsid;
+    tcsendbreak;
+    tcsetattr;
+    tcsetpgrp;
+    tdelete;
+    tdestroy;
+    tee;
+    telldir;
+    tempnam;
+    tfind;
+    tgkill;
+    time;
+    timegm;
+    timegm64; # arm x86 mips
+    timelocal;
+    timelocal64; # arm x86 mips
+    timer_create;
+    timer_delete;
+    timer_getoverrun;
+    timer_gettime;
+    timer_settime;
+    timerfd_create;
+    timerfd_gettime;
+    timerfd_settime;
+    times;
+    timezone;
+    tkill; # arm x86 mips
+    tmpfile;
+    tmpnam;
+    toascii;
+    tolower;
+    tolower_l;
+    toupper;
+    toupper_l;
+    towlower;
+    towlower_l;
+    towupper;
+    towupper_l;
+    truncate;
+    truncate64;
+    tsearch;
+    ttyname;
+    ttyname_r;
+    twalk;
+    tzname;
+    tzset;
+    umask;
+    umount;
+    umount2;
+    uname;
+    ungetc;
+    ungetwc;
+    unlink;
+    unlinkat;
+    unlockpt;
+    unsetenv;
+    unshare;
+    uselocale;
+    usleep;
+    utime;
+    utimensat;
+    utimes;
+    utmpname;
+    valloc; # arm x86 mips
+    vasprintf;
+    vdprintf;
+    verr;
+    verrx;
+    vfdprintf; # arm x86 mips
+    vfork;
+    vfprintf;
+    vfscanf;
+    vfwprintf;
+    vfwscanf;
+    vmsplice;
+    vprintf;
+    vscanf;
+    vsnprintf;
+    vsprintf;
+    vsscanf;
+    vswprintf;
+    vswscanf;
+    vsyslog;
+    vwarn;
+    vwarnx;
+    vwprintf;
+    vwscanf;
+    wait;
+    wait3; # arm x86 mips
+    wait4;
+    waitid;
+    waitpid;
+    warn;
+    warnx;
+    wcpcpy;
+    wcpncpy;
+    wcrtomb;
+    wcscasecmp;
+    wcscasecmp_l;
+    wcscat;
+    wcschr;
+    wcscmp;
+    wcscoll;
+    wcscoll_l;
+    wcscpy;
+    wcscspn;
+    wcsdup;
+    wcsftime;
+    wcslcat;
+    wcslcpy;
+    wcslen;
+    wcsncasecmp;
+    wcsncasecmp_l;
+    wcsncat;
+    wcsncmp;
+    wcsncpy;
+    wcsnlen;
+    wcsnrtombs;
+    wcspbrk;
+    wcsrchr;
+    wcsrtombs;
+    wcsspn;
+    wcsstr;
+    wcstod;
+    wcstof;
+    wcstoimax;
+    wcstok;
+    wcstol;
+    wcstold;
+    wcstold_l;
+    wcstoll;
+    wcstoll_l;
+    wcstombs;
+    wcstoul;
+    wcstoull;
+    wcstoull_l;
+    wcstoumax;
+    wcswcs; # arm x86 mips
+    wcswidth;
+    wcsxfrm;
+    wcsxfrm_l;
+    wctob;
+    wctomb;
+    wctype;
+    wctype_l;
+    wcwidth;
+    wmemchr;
+    wmemcmp;
+    wmemcpy;
+    wmemmove;
+    wmempcpy;
+    wmemset;
+    wprintf;
+    write;
+    writev;
+    wscanf;
+  local:
+    *;
+};
+
+LIBC_PRIVATE {
+  global:
+    ___Unwind_Backtrace; # arm
+    ___Unwind_ForcedUnwind; # arm
+    ___Unwind_RaiseException; # arm
+    ___Unwind_Resume; # arm
+    ___Unwind_Resume_or_Rethrow; # arm
+    __accept4; # arm x86 mips
+    __adddf3; # arm
+    __addsf3; # arm
+    __aeabi_atexit; # arm
+    __aeabi_cdcmpeq; # arm
+    __aeabi_cdcmple; # arm
+    __aeabi_cdrcmple; # arm
+    __aeabi_d2f; # arm
+    __aeabi_d2iz; # arm
+    __aeabi_dadd; # arm
+    __aeabi_dcmpeq; # arm
+    __aeabi_dcmpge; # arm
+    __aeabi_dcmpgt; # arm
+    __aeabi_dcmple; # arm
+    __aeabi_dcmplt; # arm
+    __aeabi_dcmpun; # arm
+    __aeabi_ddiv; # arm
+    __aeabi_dmul; # arm
+    __aeabi_drsub; # arm
+    __aeabi_dsub; # arm
+    __aeabi_f2d; # arm
+    __aeabi_f2iz; # arm
+    __aeabi_f2uiz; # arm
+    __aeabi_fadd; # arm
+    __aeabi_fcmpun; # arm
+    __aeabi_fdiv; # arm
+    __aeabi_fmul; # arm
+    __aeabi_frsub; # arm
+    __aeabi_fsub; # arm
+    __aeabi_i2d; # arm
+    __aeabi_i2f; # arm
+    __aeabi_idiv; # arm
+    __aeabi_idiv0; # arm
+    __aeabi_idivmod; # arm
+    __aeabi_l2d; # arm
+    __aeabi_l2f; # arm
+    __aeabi_lasr; # arm
+    __aeabi_ldiv0; # arm
+    __aeabi_ldivmod; # arm
+    __aeabi_llsl; # arm
+    __aeabi_llsr; # arm
+    __aeabi_lmul; # arm
+    __aeabi_memclr; # arm
+    __aeabi_memclr4; # arm
+    __aeabi_memclr8; # arm
+    __aeabi_memcpy; # arm
+    __aeabi_memcpy4; # arm
+    __aeabi_memcpy8; # arm
+    __aeabi_memmove; # arm
+    __aeabi_memmove4; # arm
+    __aeabi_memmove8; # arm
+    __aeabi_memset; # arm
+    __aeabi_memset4; # arm
+    __aeabi_memset8; # arm
+    __aeabi_ui2d; # arm
+    __aeabi_ui2f; # arm
+    __aeabi_uidiv; # arm
+    __aeabi_uidivmod; # arm
+    __aeabi_ul2d; # arm
+    __aeabi_ul2f; # arm
+    __aeabi_uldivmod; # arm
+    __aeabi_unwind_cpp_pr0; # arm
+    __aeabi_unwind_cpp_pr1; # arm
+    __aeabi_unwind_cpp_pr2; # arm
+    __arm_fadvise64_64; # arm
+    __ashldi3; # arm
+    __ashrdi3; # arm
+    __bionic_brk; # arm x86 mips
+    __bionic_libgcc_compat_symbols; # arm x86
+    __bionic_libgcc_unwind_symbols; # arm
+    __dso_handle; # arm
+    __gnu_Unwind_Backtrace; # arm
+    __gnu_unwind_execute; # arm
+    __gnu_Unwind_Find_exidx; # arm
+    __gnu_Unwind_ForcedUnwind; # arm
+    __gnu_unwind_frame; # arm
+    __gnu_Unwind_RaiseException; # arm
+    __gnu_Unwind_Restore_VFP; # arm
+    __gnu_Unwind_Restore_VFP_D; # arm
+    __gnu_Unwind_Restore_VFP_D_16_to_31; # arm
+    __gnu_Unwind_Restore_WMMXC; # arm
+    __gnu_Unwind_Restore_WMMXD; # arm
+    __gnu_Unwind_Resume; # arm
+    __gnu_Unwind_Resume_or_Rethrow; # arm
+    __gnu_Unwind_Save_VFP; # arm
+    __gnu_Unwind_Save_VFP_D; # arm
+    __gnu_Unwind_Save_VFP_D_16_to_31; # arm
+    __gnu_Unwind_Save_WMMXC; # arm
+    __gnu_Unwind_Save_WMMXD; # arm
+    _Unwind_Backtrace; # arm
+    _Unwind_Complete; # arm
+    _Unwind_DeleteException; # arm
+    _Unwind_ForcedUnwind; # arm
+    _Unwind_GetCFA; # arm
+    _Unwind_GetDataRelBase; # arm
+    _Unwind_GetLanguageSpecificData; # arm
+    _Unwind_GetRegionStart; # arm
+    _Unwind_GetTextRelBase; # arm
+    _Unwind_RaiseException; # arm
+    _Unwind_Resume; # arm
+    _Unwind_Resume_or_Rethrow; # arm
+    _Unwind_VRS_Get; # arm
+    _Unwind_VRS_Pop; # arm
+    _Unwind_VRS_Set; # arm
+    atexit; # arm
+    dlmalloc; # arm x86 mips
+    dlmalloc_inspect_all;
+    dlmalloc_trim;
+    dlmalloc_usable_size; # arm x86 mips
+    gMallocLeakZygoteChild;
+    SHA1Final; # arm x86 mips
+    SHA1Init; # arm x86 mips
+    SHA1Transform; # arm x86 mips
+    SHA1Update; # arm x86 mips
+} LIBC;
diff --git a/libm/Android.mk b/libm/Android.mk
index 4a5bbad..e919129 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -513,10 +513,14 @@
 # -----------------------------------------------------------------------------
 include $(CLEAR_VARS)
 
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/libm.map
+
 # TODO: This is to work around b/19059885. Remove after root cause is fixed
 LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
 LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
 
+LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libm.map
+
 LOCAL_MODULE := libm
 LOCAL_CLANG := $(libm_clang)
 LOCAL_SYSTEM_SHARED_LIBRARIES := libc
diff --git a/libm/libm.map b/libm/libm.map
new file mode 100644
index 0000000..7f02f42
--- /dev/null
+++ b/libm/libm.map
@@ -0,0 +1,378 @@
+LIBC {
+  global:
+    __fe_dfl_env;
+    __signbit;
+    __signbitf;
+    __signbitl;
+    acos;
+    acosf;
+    acosh;
+    acoshf;
+    acoshl;
+    acosl;
+    asin;
+    asinf;
+    asinh;
+    asinhf;
+    asinhl;
+    asinl;
+    atan;
+    atan2;
+    atan2f;
+    atan2l;
+    atanf;
+    atanh;
+    atanhf;
+    atanhl;
+    atanl;
+    cabs;
+    cabsf;
+    cabsl;
+    cacos;
+    cacosf;
+    cacosh;
+    cacoshf;
+    carg;
+    cargf;
+    cargl;
+    casin;
+    casinf;
+    casinh;
+    casinhf;
+    catan;
+    catanf;
+    catanh;
+    catanhf;
+    cbrt;
+    cbrtf;
+    cbrtl;
+    ccos;
+    ccosf;
+    ccosh;
+    ccoshf;
+    ceil;
+    ceilf;
+    ceill;
+    cexp;
+    cexpf;
+    cimag;
+    cimagf;
+    cimagl;
+    conj;
+    conjf;
+    conjl;
+    copysign;
+    copysignf;
+    copysignl;
+    cos;
+    cosf;
+    cosh;
+    coshf;
+    coshl;
+    cosl;
+    cproj;
+    cprojf;
+    cprojl;
+    creal;
+    crealf;
+    creall;
+    csin;
+    csinf;
+    csinh;
+    csinhf;
+    csqrt;
+    csqrtf;
+    csqrtl;
+    ctan;
+    ctanf;
+    ctanh;
+    ctanhf;
+    drem;
+    dremf;
+    erf;
+    erfc;
+    erfcf;
+    erfcl;
+    erff;
+    erfl;
+    exp;
+    exp2;
+    exp2f;
+    exp2l;
+    expf;
+    expl;
+    expm1;
+    expm1f;
+    expm1l;
+    fabs;
+    fabsf;
+    fabsl;
+    fdim;
+    fdimf;
+    fdiml;
+    feclearexcept;
+    fedisableexcept;
+    feenableexcept;
+    fegetenv;
+    fegetexcept;
+    fegetexceptflag;
+    fegetround;
+    feholdexcept;
+    feraiseexcept;
+    fesetenv;
+    fesetexceptflag;
+    fesetround;
+    fetestexcept;
+    feupdateenv;
+    finite;
+    finitef;
+    floor;
+    floorf;
+    floorl;
+    fma;
+    fmaf;
+    fmal;
+    fmax;
+    fmaxf;
+    fmaxl;
+    fmin;
+    fminf;
+    fminl;
+    fmod;
+    fmodf;
+    fmodl;
+    frexp;
+    frexpf;
+    frexpl;
+    gamma;
+    gamma_r;
+    gammaf;
+    gammaf_r;
+    hypot;
+    hypotf;
+    hypotl;
+    ilogb;
+    ilogbf;
+    ilogbl;
+    j0;
+    j0f;
+    j1;
+    j1f;
+    jn;
+    jnf;
+    ldexpf;
+    ldexpl;
+    lgamma;
+    lgamma_r;
+    lgammaf;
+    lgammaf_r;
+    lgammal;
+    lgammal_r;
+    llrint;
+    llrintf;
+    llrintl;
+    llround;
+    llroundf;
+    llroundl;
+    log;
+    log10;
+    log10f;
+    log10l;
+    log1p;
+    log1pf;
+    log1pl;
+    log2;
+    log2f;
+    log2l;
+    logb;
+    logbf;
+    logbl;
+    logf;
+    logl;
+    lrint;
+    lrintf;
+    lrintl;
+    lround;
+    lroundf;
+    lroundl;
+    modf;
+    modff;
+    modfl;
+    nan;
+    nanf;
+    nanl;
+    nearbyint;
+    nearbyintf;
+    nearbyintl;
+    nextafter;
+    nextafterf;
+    nextafterl;
+    nexttoward;
+    nexttowardf;
+    nexttowardl;
+    pow;
+    powf;
+    powl;
+    remainder;
+    remainderf;
+    remainderl;
+    remquo;
+    remquof;
+    remquol;
+    rint;
+    rintf;
+    rintl;
+    round;
+    roundf;
+    roundl;
+    scalb;
+    scalbf;
+    scalbln;
+    scalblnf;
+    scalblnl;
+    scalbn;
+    scalbnf;
+    scalbnl;
+    signgam;
+    significand;
+    significandf;
+    significandl;
+    sin;
+    sincos;
+    sincosf;
+    sincosl;
+    sinf;
+    sinh;
+    sinhf;
+    sinhl;
+    sinl;
+    sqrt;
+    sqrtf;
+    sqrtl;
+    tan;
+    tanf;
+    tanh;
+    tanhf;
+    tanhl;
+    tanl;
+    tgamma;
+    tgammaf;
+    tgammal;
+    trunc;
+    truncf;
+    truncl;
+    y0;
+    y0f;
+    y1;
+    y1f;
+    yn;
+    ynf;
+  local:
+    *;
+};
+
+LIBC_PRIVATE {
+  global:
+    ___Unwind_Backtrace; # arm
+    ___Unwind_ForcedUnwind; # arm
+    ___Unwind_RaiseException; # arm
+    ___Unwind_Resume; # arm
+    ___Unwind_Resume_or_Rethrow; # arm
+    __adddf3; # arm
+    __aeabi_cdcmpeq; # arm
+    __aeabi_cdcmple; # arm
+    __aeabi_cdrcmple; # arm
+    __aeabi_cfcmpeq; # arm
+    __aeabi_cfcmple; # arm
+    __aeabi_cfrcmple; # arm
+    __aeabi_d2lz; # arm
+    __aeabi_d2uiz; # arm
+    __aeabi_d2ulz; # arm
+    __aeabi_dadd; # arm
+    __aeabi_dcmpeq; # arm
+    __aeabi_dcmpge; # arm
+    __aeabi_dcmpgt; # arm
+    __aeabi_dcmple; # arm
+    __aeabi_dcmplt; # arm
+    __aeabi_ddiv; # arm
+    __aeabi_dmul; # arm
+    __aeabi_drsub; # arm
+    __aeabi_dsub; # arm
+    __aeabi_f2d; # arm
+    __aeabi_f2lz; # arm
+    __aeabi_f2ulz; # arm
+    __aeabi_fcmpeq; # arm
+    __aeabi_fcmpge; # arm
+    __aeabi_fcmpgt; # arm
+    __aeabi_fcmple; # arm
+    __aeabi_fcmplt; # arm
+    __aeabi_i2d; # arm
+    __aeabi_l2d; # arm
+    __aeabi_ui2d; # arm
+    __aeabi_ul2d; # arm
+    __aeabi_unwind_cpp_pr0; # arm
+    __aeabi_unwind_cpp_pr1; # arm
+    __aeabi_unwind_cpp_pr2; # arm
+    __cmpdf2; # arm
+    __cmpsf2; # arm
+    __divdf3; # arm
+    __eqdf2; # arm
+    __eqsf2; # arm
+    __extendsfdf2; # arm
+    __fixdfdi; # arm mips
+    __fixsfdi; # arm mips
+    __fixunsdfdi; # arm mips
+    __fixunsdfsi; # arm
+    __fixunssfdi; # arm mips
+    __floatdidf; # arm
+    __floatsidf; # arm
+    __floatundidf; # arm
+    __floatunsidf; # arm
+    __gedf2; # arm
+    __gesf2; # arm
+    __gnu_Unwind_Backtrace; # arm
+    __gnu_unwind_execute; # arm
+    __gnu_Unwind_ForcedUnwind; # arm
+    __gnu_unwind_frame; # arm
+    __gnu_Unwind_RaiseException; # arm
+    __gnu_Unwind_Restore_VFP; # arm
+    __gnu_Unwind_Restore_VFP_D; # arm
+    __gnu_Unwind_Restore_VFP_D_16_to_31; # arm
+    __gnu_Unwind_Restore_WMMXC; # arm
+    __gnu_Unwind_Restore_WMMXD; # arm
+    __gnu_Unwind_Resume; # arm
+    __gnu_Unwind_Resume_or_Rethrow; # arm
+    __gnu_Unwind_Save_VFP; # arm
+    __gnu_Unwind_Save_VFP_D; # arm
+    __gnu_Unwind_Save_VFP_D_16_to_31; # arm
+    __gnu_Unwind_Save_WMMXC; # arm
+    __gnu_Unwind_Save_WMMXD; # arm
+    __gtdf2; # arm
+    __gtsf2; # arm
+    __ledf2; # arm
+    __lesf2; # arm
+    __ltdf2; # arm
+    __ltsf2; # arm
+    __muldc3; # arm x86 mips
+    __muldf3; # arm
+    __nedf2; # arm
+    __nesf2; # arm
+    __restore_core_regs; # arm
+    __subdf3; # arm
+    _Unwind_Backtrace; # arm
+    _Unwind_Complete; # arm
+    _Unwind_DeleteException; # arm
+    _Unwind_ForcedUnwind; # arm
+    _Unwind_GetCFA; # arm
+    _Unwind_GetDataRelBase; # arm
+    _Unwind_GetLanguageSpecificData; # arm
+    _Unwind_GetRegionStart; # arm
+    _Unwind_GetTextRelBase; # arm
+    _Unwind_RaiseException; # arm
+    _Unwind_Resume; # arm
+    _Unwind_Resume_or_Rethrow; # arm
+    _Unwind_VRS_Get; # arm
+    _Unwind_VRS_Pop; # arm
+    _Unwind_VRS_Set; # arm
+    restore_core_regs; # arm
+} LIBC;
diff --git a/linker/linker.cpp b/linker/linker.cpp
index d1b2ad2..e147a13 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1343,30 +1343,63 @@
   return result;
 }
 
-static soinfo *find_loaded_library_by_soname(const char* name) {
+// Returns true if library was found and false in 2 cases
+// 1. The library was found but loaded under different target_sdk_version
+//    (*candidate != nullptr)
+// 2. The library was not found by soname (*candidate is nullptr)
+static bool find_loaded_library_by_soname(const char* name, soinfo** candidate) {
+  *candidate = nullptr;
+
   // Ignore filename with path.
   if (strchr(name, '/') != nullptr) {
-    return nullptr;
+    return false;
   }
 
+  uint32_t target_sdk_version = get_application_target_sdk_version();
+
   for (soinfo* si = solist; si != nullptr; si = si->next) {
     const char* soname = si->get_soname();
     if (soname != nullptr && (strcmp(name, soname) == 0)) {
-      return si;
+      // If the library was opened under different target sdk version
+      // skip this step and try to reopen it. The exceptions are
+      // "libdl.so" and global group. There is no point in skipping
+      // them because relocation process is going to use them
+      // in any case.
+      bool is_libdl = si == solist;
+      if (is_libdl || (si->get_dt_flags_1() & DF_1_GLOBAL) != 0 ||
+          !si->is_linked() || si->get_target_sdk_version() == target_sdk_version) {
+        *candidate = si;
+        return true;
+      } else if (*candidate == nullptr) {
+        // for the different sdk version - remember the first library.
+        *candidate = si;
+      }
     }
   }
-  return nullptr;
+
+  return false;
 }
 
 static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name,
                                      int rtld_flags, const android_dlextinfo* extinfo) {
-  soinfo* si = find_loaded_library_by_soname(name);
+  soinfo* candidate;
+
+  if (find_loaded_library_by_soname(name, &candidate)) {
+    return candidate;
+  }
 
   // Library might still be loaded, the accurate detection
   // of this fact is done by load_library.
-  if (si == nullptr) {
-    TRACE("[ '%s' has not been found by soname.  Trying harder...]", name);
-    si = load_library(load_tasks, name, rtld_flags, extinfo);
+  TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]",
+      name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
+
+  soinfo* si = load_library(load_tasks, name, rtld_flags, extinfo);
+
+  // In case we were unable to load the library but there
+  // is a candidate loaded under the same soname but different
+  // sdk level - return it anyways.
+  if (si == nullptr && candidate != nullptr) {
+    si = candidate;
   }
 
   return si;
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 638c9d6..f586b08 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -316,6 +316,8 @@
   void* start;
   size_t reserved_size = 0;
   bool reserved_hint = true;
+  // Assume position independent executable by default.
+  uint8_t* mmap_hint = nullptr;
 
   if (extinfo != nullptr) {
     if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) {
@@ -324,6 +326,10 @@
     } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) {
       reserved_size = extinfo->reserved_size;
     }
+
+    if ((extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) {
+      mmap_hint = addr;
+    }
   }
 
   if (load_size_ > reserved_size) {
@@ -333,7 +339,7 @@
       return false;
     }
     int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
-    start = mmap(nullptr, load_size_, PROT_NONE, mmap_flags, -1, 0);
+    start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0);
     if (start == MAP_FAILED) {
       DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_);
       return false;
diff --git a/linker/linker_sdk_versions.cpp b/linker/linker_sdk_versions.cpp
index e9ad3dc..9aebb06 100644
--- a/linker/linker_sdk_versions.cpp
+++ b/linker/linker_sdk_versions.cpp
@@ -21,6 +21,10 @@
 static std::atomic<uint32_t> g_target_sdk_version(__ANDROID_API__);
 
 void set_application_target_sdk_version(uint32_t target) {
+  // translate current sdk_version to platform sdk_version
+  if (target == 0) {
+    target = __ANDROID_API__;
+  }
   g_target_sdk_version = target;
 }
 
diff --git a/tests/Android.mk b/tests/Android.mk
index 29e9e1e..964a34a 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -96,6 +96,7 @@
     sys_epoll_test.cpp \
     sys_mman_test.cpp \
     sys_personality_test.cpp \
+    sys_procfs_test.cpp \
     sys_resource_test.cpp \
     sys_select_test.cpp \
     sys_sendfile_test.cpp \
diff --git a/tests/sys_procfs_test.cpp b/tests/sys_procfs_test.cpp
new file mode 100644
index 0000000..8054869
--- /dev/null
+++ b/tests/sys_procfs_test.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <sys/procfs.h>
+
+TEST(sys_procfs, smoke) {
+  elf_greg_t reg;
+  memset(&reg, 0, sizeof(reg));
+
+  elf_gregset_t regs;
+  memset(&regs, 0, sizeof(regs));
+
+  elf_fpregset_t fp_regs;
+  memset(&fp_regs, 0, sizeof(fp_regs));
+
+  prgregset_t pr_g_regs;
+  memset(&pr_g_regs, 0, sizeof(pr_g_regs));
+
+  prfpregset_t pr_fp_regs;
+  memset(&pr_fp_regs, 0, sizeof(pr_fp_regs));
+
+  static_assert(sizeof(prgregset_t) == sizeof(elf_gregset_t), "");
+  static_assert(sizeof(prfpregset_t) == sizeof(elf_fpregset_t), "");
+}
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index c37df36..90de8d8 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -166,7 +166,7 @@
   ts.it_value.tv_nsec = value_ns;
   ts.it_interval.tv_sec = interval_s;
   ts.it_interval.tv_nsec = interval_ns;
-  ASSERT_EQ(0, timer_settime(t, TIMER_ABSTIME, &ts, NULL));
+  ASSERT_EQ(0, timer_settime(t, 0, &ts, NULL));
 }
 
 static void NoOpNotifyFunction(sigval_t) {
@@ -381,8 +381,8 @@
   ASSERT_EQ(0, counter2.Value());
   ASSERT_EQ(0, counter3.Value());
 
-  counter2.SetTime(0, 1, 0, 0);
-  usleep(500000);
+  counter2.SetTime(0, 500000000, 0, 0);
+  sleep(1);
 
   EXPECT_EQ(0, counter1.Value());
   EXPECT_EQ(1, counter2.Value());