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(®, 0, sizeof(reg));
+
+ elf_gregset_t regs;
+ memset(®s, 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());