summaryrefslogtreecommitdiffstats
path: root/libc/arch-arm/bionic
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:28:35 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 19:28:35 -0800
commit1dc9e472e19acfe6dc7f41e429236e7eef7ceda1 (patch)
tree3be0c520fae17689bbf5584e1136fb820caef26f /libc/arch-arm/bionic
parent1767f908af327fa388b1c66883760ad851267013 (diff)
downloadbionic-1dc9e472e19acfe6dc7f41e429236e7eef7ceda1.zip
bionic-1dc9e472e19acfe6dc7f41e429236e7eef7ceda1.tar.gz
bionic-1dc9e472e19acfe6dc7f41e429236e7eef7ceda1.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'libc/arch-arm/bionic')
-rw-r--r--libc/arch-arm/bionic/__get_pc.S33
-rw-r--r--libc/arch-arm/bionic/__get_sp.S33
-rw-r--r--libc/arch-arm/bionic/_exit_with_stack_teardown.S55
-rw-r--r--libc/arch-arm/bionic/_setjmp.S106
-rw-r--r--libc/arch-arm/bionic/atomics_arm.S178
-rw-r--r--libc/arch-arm/bionic/clone.S74
-rw-r--r--libc/arch-arm/bionic/crtbegin_dynamic.S92
-rw-r--r--libc/arch-arm/bionic/crtbegin_static.S92
-rw-r--r--libc/arch-arm/bionic/crtend.S40
-rw-r--r--libc/arch-arm/bionic/exidx_dynamic.c47
-rw-r--r--libc/arch-arm/bionic/exidx_static.c45
-rw-r--r--libc/arch-arm/bionic/ffs.S82
-rw-r--r--libc/arch-arm/bionic/kill.S53
-rw-r--r--libc/arch-arm/bionic/memcmp.S285
-rw-r--r--libc/arch-arm/bionic/memcmp16.S236
-rw-r--r--libc/arch-arm/bionic/memcpy.S387
-rw-r--r--libc/arch-arm/bionic/memset.S117
-rw-r--r--libc/arch-arm/bionic/setjmp.S136
-rw-r--r--libc/arch-arm/bionic/sigsetjmp.S62
-rw-r--r--libc/arch-arm/bionic/strlen.c129
-rw-r--r--libc/arch-arm/bionic/syscall.S71
-rw-r--r--libc/arch-arm/bionic/tkill.S53
22 files changed, 2406 insertions, 0 deletions
diff --git a/libc/arch-arm/bionic/__get_pc.S b/libc/arch-arm/bionic/__get_pc.S
new file mode 100644
index 0000000..d1377c7
--- /dev/null
+++ b/libc/arch-arm/bionic/__get_pc.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+.global __get_pc
+
+__get_pc:
+ mov r0, pc
+ bx lr
+
diff --git a/libc/arch-arm/bionic/__get_sp.S b/libc/arch-arm/bionic/__get_sp.S
new file mode 100644
index 0000000..9acaf3d
--- /dev/null
+++ b/libc/arch-arm/bionic/__get_sp.S
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+.global __get_sp
+
+__get_sp:
+ mov r0, sp
+ bx lr
+
diff --git a/libc/arch-arm/bionic/_exit_with_stack_teardown.S b/libc/arch-arm/bionic/_exit_with_stack_teardown.S
new file mode 100644
index 0000000..89f6c90
--- /dev/null
+++ b/libc/arch-arm/bionic/_exit_with_stack_teardown.S
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <asm/unistd.h>
+
+.text
+.type _exit_with_stack_teardown, #function
+.globl _exit_with_stack_teardown
+.align 4
+
+@ void _exit_with_stack_teardown(void * stackBase, int stackSize, int retCode)
+
+_exit_with_stack_teardown:
+
+#if __ARM_EABI__
+ mov lr, r2
+ ldr r7, =__NR_munmap
+ swi #0 @ the stack is destroyed by this call
+ mov r0, lr
+ ldr r7, =__NR_exit
+ swi #0
+#else
+ mov lr, r2
+ swi # __NR_munmap @ the stack is destroyed by this call
+ mov r0, lr
+ swi # __NR_exit
+#endif
+
+ @ exit() should never return, cause a crash if it does
+ mov r0, #0
+ ldr r0, [r0]
diff --git a/libc/arch-arm/bionic/_setjmp.S b/libc/arch-arm/bionic/_setjmp.S
new file mode 100644
index 0000000..6a27af2
--- /dev/null
+++ b/libc/arch-arm/bionic/_setjmp.S
@@ -0,0 +1,106 @@
+/* $OpenBSD: _setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
+/* $NetBSD: _setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1997 Mark Brinicombe
+ * All rights reserved.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. 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 AUTHOR 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 AUTHOR 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 <machine/asm.h>
+#include <machine/setjmp.h>
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * _setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is NOT restored.
+ *
+ * Note: r0 is the return value
+ * r1-r3 are scratch registers in functions
+ */
+
+ENTRY(_setjmp)
+ ldr r1, .L_setjmp_magic
+ str r1, [r0], #4
+#ifdef SOFTFLOAT
+ add r0, r0, #52
+#else
+ /* Store fp registers */
+ sfm f4, 4, [r0], #48
+ /* Store fpsr */
+ rfs r1
+ str r1, [r0], #0x0004
+#endif /* SOFTFLOAT */
+ /* Store integer registers */
+ stmia r0, {r4-r14}
+
+ mov r0, #0x00000000
+ bx lr
+
+.L_setjmp_magic:
+ .word _JB_MAGIC__SETJMP
+
+ENTRY(_longjmp)
+ ldr r2, .L_setjmp_magic
+ ldr r3, [r0], #4
+ teq r2, r3
+ bne botch
+
+#ifdef SOFTFLOAT
+ add r0, r0, #52
+#else
+ /* Restore fp registers */
+ lfm f4, 4, [r0], #48
+ /* Restore fpsr */
+ ldr r4, [r0], #0x0004
+ wfs r4
+#endif /* SOFTFLOAT */
+ /* Restore integer registers */
+ ldmia r0, {r4-r14}
+
+ /* Validate sp and r14 */
+ teq sp, #0
+ teqne r14, #0
+ beq botch
+
+ /* Set return value */
+ mov r0, r1
+ teq r0, #0x00000000
+ moveq r0, #0x00000001
+ bx lr
+
+ /* validation failed, die die die. */
+botch:
+ bl PIC_SYM(_C_LABEL(longjmperror), PLT)
+ bl PIC_SYM(_C_LABEL(abort), PLT)
+ b . - 8 /* Cannot get here */
diff --git a/libc/arch-arm/bionic/atomics_arm.S b/libc/arch-arm/bionic/atomics_arm.S
new file mode 100644
index 0000000..b2da09f
--- /dev/null
+++ b/libc/arch-arm/bionic/atomics_arm.S
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <sys/linux-syscalls.h>
+
+.global __atomic_cmpxchg
+.global __atomic_swap
+.global __atomic_dec
+.global __atomic_inc
+.global __futex_wait
+.global __futex_wake
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+#if 1
+ .equ kernel_cmpxchg, 0xFFFF0FC0
+ .equ kernel_atomic_base, 0xFFFF0FFF
+__atomic_dec:
+ stmdb sp!, {r4, lr}
+ mov r2, r0
+1: @ atomic_dec
+ ldr r0, [r2]
+ mov r3, #kernel_atomic_base
+ add lr, pc, #4
+ sub r1, r0, #1
+ add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+ bcc 1b
+ add r0, r1, #1
+ ldmia sp!, {r4, lr}
+ bx lr
+
+__atomic_inc:
+ stmdb sp!, {r4, lr}
+ mov r2, r0
+1: @ atomic_inc
+ ldr r0, [r2]
+ mov r3, #kernel_atomic_base
+ add lr, pc, #4
+ add r1, r0, #1
+ add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+ bcc 1b
+ sub r0, r1, #1
+ ldmia sp!, {r4, lr}
+ bx lr
+
+/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
+__atomic_cmpxchg:
+ stmdb sp!, {r4, lr}
+ mov r4, r0 /* r4 = save oldvalue */
+1: @ atomic_cmpxchg
+ mov r3, #kernel_atomic_base
+ add lr, pc, #4
+ mov r0, r4 /* r0 = oldvalue */
+ add pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
+ bcs 2f /* swap was made. we're good, return. */
+ ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
+ cmp r3, r4
+ beq 1b
+2: @ atomic_cmpxchg
+ ldmia sp!, {r4, lr}
+ bx lr
+#else
+#define KUSER_CMPXCHG 0xffffffc0
+
+/* r0(old) r1(new) r2(addr) -> r0(zero_if_succeeded) */
+__atomic_cmpxchg:
+ stmdb sp!, {r4, lr}
+ mov r4, r0 /* r4 = save oldvalue */
+1: add lr, pc, #4
+ mov r0, r4 /* r0 = oldvalue */
+ mov pc, #KUSER_CMPXCHG
+ bcs 2f /* swap was made. we're good, return. */
+ ldr r3, [r2] /* swap not made, see if it's because *ptr!=oldvalue */
+ cmp r3, r4
+ beq 1b
+2: ldmia sp!, {r4, lr}
+ bx lr
+
+/* r0(addr) -> r0(old) */
+__atomic_dec:
+ stmdb sp!, {r4, lr}
+ mov r2, r0 /* address */
+1: ldr r0, [r2] /* oldvalue */
+ add lr, pc, #4
+ sub r1, r0, #1 /* newvalue = oldvalue - 1 */
+ mov pc, #KUSER_CMPXCHG
+ bcc 1b /* no swap, try again until we get it right */
+ mov r0, ip /* swapped, return the old value */
+ ldmia sp!, {r4, lr}
+ bx lr
+
+/* r0(addr) -> r0(old) */
+__atomic_inc:
+ stmdb sp!, {r4, lr}
+ mov r2, r0 /* address */
+1: ldr r0, [r2] /* oldvalue */
+ add lr, pc, #4
+ add r1, r0, #1 /* newvalue = oldvalue + 1 */
+ mov pc, #KUSER_CMPXCHG
+ bcc 1b /* no swap, try again until we get it right */
+ mov r0, ip /* swapped, return the old value */
+ ldmia sp!, {r4, lr}
+ bx lr
+#endif
+
+/* r0(new) r1(addr) -> r0(old) */
+__atomic_swap:
+ swp r0, r0, [r1]
+ bx lr
+
+/* __futex_wait(*ftx, val, *timespec) */
+/* __futex_syscall(*ftx, op, val, *timespec, *addr2, val3) */
+
+#if __ARM_EABI__
+
+__futex_wait:
+ .fnstart
+ stmdb sp!, {r4, r7}
+ .save {r4, r7}
+ mov r3, r2
+ mov r2, r1
+ mov r1, #FUTEX_WAIT
+ ldr r7, =__NR_futex
+ swi #0
+ ldmia sp!, {r4, r7}
+ bx lr
+ .fnend
+
+__futex_wake:
+ stmdb sp!, {r4, r7}
+ mov r2, r1
+ mov r1, #FUTEX_WAKE
+ ldr r7, =__NR_futex
+ swi #0
+ ldmia sp!, {r4, r7}
+ bx lr
+
+#else
+
+__futex_wait:
+ mov r3, r2
+ mov r2, r1
+ mov r1, #FUTEX_WAIT
+ swi #__NR_futex
+ bx lr
+
+__futex_wake:
+ mov r2, r1
+ mov r1, #FUTEX_WAKE
+ swi #__NR_futex
+ bx lr
+
+#endif
diff --git a/libc/arch-arm/bionic/clone.S b/libc/arch-arm/bionic/clone.S
new file mode 100644
index 0000000..791c73d
--- /dev/null
+++ b/libc/arch-arm/bionic/clone.S
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <sys/linux-syscalls.h>
+
+ .text
+ .type __pthread_clone, #function
+ .global __pthread_clone
+ .align 4
+
+__pthread_clone:
+ @ insert the args onto the new stack
+ str r0, [r1, #-4]
+ str r3, [r1, #-8]
+
+ @ do the system call
+ @ get flags
+
+ mov r0, r2
+
+ @ new sp is already in r1
+
+#if __ARM_EABI__
+ stmfd sp!, {r4, r7}
+ ldr r7, =__NR_clone
+ swi #0
+#else
+ swi #__NR_clone
+#endif
+
+ movs r0, r0
+#if __ARM_EABI__
+ ldmnefd sp!, {r4, r7}
+#endif
+ blt __error
+ bxne lr
+
+
+ @ pick the function arg and call address off the stack and jump
+ @ to the C __thread_entry function which does some setup and then
+ @ calls the thread's start function
+
+ ldr r0, [sp, #-4]
+ ldr r1, [sp, #-8]
+ mov r2, sp @ __thread_entry needs the TLS pointer
+ b __thread_entry
+
+__error:
+ mov r0, #-1
+ bx lr
diff --git a/libc/arch-arm/bionic/crtbegin_dynamic.S b/libc/arch-arm/bionic/crtbegin_dynamic.S
new file mode 100644
index 0000000..e265923
--- /dev/null
+++ b/libc/arch-arm/bionic/crtbegin_dynamic.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+ .text
+ .align 4
+ .type _start,#function
+ .globl _start
+
+# this is the small startup code that is first run when
+# any executable that is statically-linked with Bionic
+# runs.
+#
+# it's purpose is to call __libc_init with appropriate
+# arguments, which are:
+#
+# - the address of the raw data block setup by the Linux
+# kernel ELF loader
+#
+# - address of an "onexit" function, not used on any
+# platform supported by Bionic
+#
+# - address of the "main" function of the program. We
+# can't hard-code it in the adr pseudo instruction
+# so we use a tiny trampoline that will get relocated
+# by the dynamic linker before this code runs
+#
+# - address of the constructor list
+#
+_start:
+ mov r0, sp
+ mov r1, #0
+ adr r2, 0f
+ adr r3, 1f
+ b __libc_init
+
+0: b main
+
+1: .long __PREINIT_ARRAY__
+ .long __INIT_ARRAY__
+ .long __FINI_ARRAY__
+ .long __CTOR_LIST__
+
+# the .ctors section contains a list of pointers to "constructor"
+# functions that need to be called in order during C library initialization,
+# just before the program is being run. This is a C++ requirement
+#
+# the last entry shall be 0, and is defined in crtend.S
+#
+ .section .preinit_array, "aw"
+ .globl __PREINIT_ARRAY__
+__PREINIT_ARRAY__:
+ .long -1
+
+ .section .init_array, "aw"
+ .globl __INIT_ARRAY__
+__INIT_ARRAY__:
+ .long -1
+
+ .section .fini_array, "aw"
+ .globl __FINI_ARRAY__
+__FINI_ARRAY__:
+ .long -1
+
+ .section .ctors, "aw"
+ .globl __CTOR_LIST__
+__CTOR_LIST__:
+ .long -1
+
diff --git a/libc/arch-arm/bionic/crtbegin_static.S b/libc/arch-arm/bionic/crtbegin_static.S
new file mode 100644
index 0000000..e265923
--- /dev/null
+++ b/libc/arch-arm/bionic/crtbegin_static.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+ .text
+ .align 4
+ .type _start,#function
+ .globl _start
+
+# this is the small startup code that is first run when
+# any executable that is statically-linked with Bionic
+# runs.
+#
+# it's purpose is to call __libc_init with appropriate
+# arguments, which are:
+#
+# - the address of the raw data block setup by the Linux
+# kernel ELF loader
+#
+# - address of an "onexit" function, not used on any
+# platform supported by Bionic
+#
+# - address of the "main" function of the program. We
+# can't hard-code it in the adr pseudo instruction
+# so we use a tiny trampoline that will get relocated
+# by the dynamic linker before this code runs
+#
+# - address of the constructor list
+#
+_start:
+ mov r0, sp
+ mov r1, #0
+ adr r2, 0f
+ adr r3, 1f
+ b __libc_init
+
+0: b main
+
+1: .long __PREINIT_ARRAY__
+ .long __INIT_ARRAY__
+ .long __FINI_ARRAY__
+ .long __CTOR_LIST__
+
+# the .ctors section contains a list of pointers to "constructor"
+# functions that need to be called in order during C library initialization,
+# just before the program is being run. This is a C++ requirement
+#
+# the last entry shall be 0, and is defined in crtend.S
+#
+ .section .preinit_array, "aw"
+ .globl __PREINIT_ARRAY__
+__PREINIT_ARRAY__:
+ .long -1
+
+ .section .init_array, "aw"
+ .globl __INIT_ARRAY__
+__INIT_ARRAY__:
+ .long -1
+
+ .section .fini_array, "aw"
+ .globl __FINI_ARRAY__
+__FINI_ARRAY__:
+ .long -1
+
+ .section .ctors, "aw"
+ .globl __CTOR_LIST__
+__CTOR_LIST__:
+ .long -1
+
diff --git a/libc/arch-arm/bionic/crtend.S b/libc/arch-arm/bionic/crtend.S
new file mode 100644
index 0000000..2f3b1ed
--- /dev/null
+++ b/libc/arch-arm/bionic/crtend.S
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+
+ .section .preinit_array, "aw"
+ .long 0
+
+ .section .init_array, "aw"
+ .long 0
+
+ .section .fini_array, "aw"
+ .long 0
+
+ .section .ctors, "aw"
+ .long 0
+
diff --git a/libc/arch-arm/bionic/exidx_dynamic.c b/libc/arch-arm/bionic/exidx_dynamic.c
new file mode 100644
index 0000000..962606f
--- /dev/null
+++ b/libc/arch-arm/bionic/exidx_dynamic.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+typedef long unsigned int *_Unwind_Ptr;
+
+/* Stubbed out in libdl and defined in the dynamic linker.
+ * Same semantics as __gnu_Unwind_Find_exidx().
+ */
+extern _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount);
+
+/* For a given PC, find the .so that it belongs to.
+ * Returns the base address of the .ARM.exidx section
+ * for that .so, and the number of 8-byte entries
+ * in that section (via *pcount).
+ *
+ * libgcc declares __gnu_Unwind_Find_exidx() as a weak symbol, with
+ * the expectation that libc will define it and call through to
+ * a differently-named function in the dynamic linker.
+ */
+_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int *pcount)
+{
+ return dl_unwind_find_exidx(pc, pcount);
+}
diff --git a/libc/arch-arm/bionic/exidx_static.c b/libc/arch-arm/bionic/exidx_static.c
new file mode 100644
index 0000000..e79e951
--- /dev/null
+++ b/libc/arch-arm/bionic/exidx_static.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+typedef long unsigned int *_Unwind_Ptr;
+
+/* Find the .ARM.exidx section (which in the case of a static executable
+ * can be identified through its start and end symbols), and return its
+ * beginning and numbe of entries to the caller. Note that for static
+ * executables we do not need to use the value of the PC to find the
+ * EXIDX section.
+ */
+
+extern unsigned __exidx_end;
+extern unsigned __exidx_start;
+
+_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc __attribute__((unused)),
+ int *pcount)
+{
+ *pcount = (__exidx_end-__exidx_start)/8;
+ return (_Unwind_Ptr)__exidx_start;
+}
diff --git a/libc/arch-arm/bionic/ffs.S b/libc/arch-arm/bionic/ffs.S
new file mode 100644
index 0000000..f11141c
--- /dev/null
+++ b/libc/arch-arm/bionic/ffs.S
@@ -0,0 +1,82 @@
+/* $NetBSD: ffs.S,v 1.5 2003/04/05 23:08:52 bjh21 Exp $ */
+/*
+ * Copyright (c) 2001 Christopher Gilbert
+ * All rights reserved.
+ *
+ * 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. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 <machine/asm.h>
+
+/*
+ * ffs - find first set bit, this algorithm isolates the first set
+ * bit, then multiplies the number by 0x0450fbaf which leaves the top
+ * 6 bits as an index into the table. This algorithm should be a win
+ * over the checking each bit in turn as per the C compiled version.
+ *
+ * under ARMv5 there's an instruction called CLZ (count leading Zero's) that
+ * could be used
+ *
+ * This is the ffs algorithm devised by d.seal and posted to comp.sys.arm on
+ * 16 Feb 1994.
+ */
+
+ENTRY(ffs)
+ /* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */
+ rsb r1, r0, #0
+ ands r0, r0, r1
+#ifndef __ARM_ARCH_5__
+ /*
+ * now r0 has at most one set bit, call this X
+ * if X = 0, all further instructions are skipped
+ */
+ adrne r2, .L_ffs_table
+ orrne r0, r0, r0, lsl #4 /* r0 = X * 0x11 */
+ orrne r0, r0, r0, lsl #6 /* r0 = X * 0x451 */
+ rsbne r0, r0, r0, lsl #16 /* r0 = X * 0x0450fbaf */
+
+ /* now lookup in table indexed on top 6 bits of r0 */
+ ldrneb r0, [ r2, r0, lsr #26 ]
+
+ bx lr
+
+.text;
+.type .L_ffs_table, _ASM_TYPE_OBJECT;
+.L_ffs_table:
+/* 0 1 2 3 4 5 6 7 */
+ .byte 0, 1, 2, 13, 3, 7, 0, 14 /* 0- 7 */
+ .byte 4, 0, 8, 0, 0, 0, 0, 15 /* 8-15 */
+ .byte 11, 5, 0, 0, 9, 0, 0, 26 /* 16-23 */
+ .byte 0, 0, 0, 0, 0, 22, 28, 16 /* 24-31 */
+ .byte 32, 12, 6, 0, 0, 0, 0, 0 /* 32-39 */
+ .byte 10, 0, 0, 25, 0, 0, 21, 27 /* 40-47 */
+ .byte 31, 0, 0, 0, 0, 24, 0, 20 /* 48-55 */
+ .byte 30, 0, 23, 19, 29, 18, 17, 0 /* 56-63 */
+#else
+ clzne r0, r0
+ rsbne r0, r0, #32
+ bx lr
+#endif
+
diff --git a/libc/arch-arm/bionic/kill.S b/libc/arch-arm/bionic/kill.S
new file mode 100644
index 0000000..2954091
--- /dev/null
+++ b/libc/arch-arm/bionic/kill.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+/* unlike our auto-generated syscall stubs, this code saves lr
+ on the stack, as well as a few other registers. this makes
+ our stack unwinder happy, when we generate debug stack
+ traces after the C library or other parts of the system
+ abort due to a fatal runtime error (e.g. detection
+ of a corrupted malloc heap).
+*/
+#include <sys/linux-syscalls.h>
+
+#ifndef __NR_kill
+#define __NR_kill 37
+#endif
+
+ .text
+ .type kill, #function
+ .globl kill
+ .align 4
+
+kill:
+ stmfd sp!, {r4-r7, ip, lr}
+ ldr r7, =__NR_kill
+ swi #0
+ ldmfd sp!, {r4-r7, ip, lr}
+ movs r0, r0
+ bxpl lr
+ b __set_syscall_errno
diff --git a/libc/arch-arm/bionic/memcmp.S b/libc/arch-arm/bionic/memcmp.S
new file mode 100644
index 0000000..f45b56b
--- /dev/null
+++ b/libc/arch-arm/bionic/memcmp.S
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <machine/cpu-features.h>
+
+ .text
+
+ .global memcmp
+ .type memcmp, %function
+ .align 4
+
+/*
+ * Optimized memcmp() for ARM9.
+ * This would not be optimal on XScale or ARM11, where more prefetching
+ * and use of PLD will be needed.
+ * The 2 major optimzations here are
+ * (1) The main loop compares 16 bytes at a time
+ * (2) The loads are scheduled in a way they won't stall
+ */
+
+memcmp:
+ PLD (r0, #0)
+ PLD (r1, #0)
+
+ /* take of the case where length is 0 or the buffers are the same */
+ cmp r0, r1
+ cmpne r2, #0
+ moveq r0, #0
+ bxeq lr
+
+ /* save registers */
+ stmfd sp!, {r4, lr}
+
+ PLD (r0, #32)
+ PLD (r1, #32)
+
+ /* since r0 hold the result, move the first source
+ * pointer somewhere else
+ */
+
+ mov r4, r0
+
+ /* make sure we have at least 8+4 bytes, this simplify things below
+ * and avoid some overhead for small blocks
+ */
+ cmp r2, #(8+4)
+ bmi 8f
+
+ /* align first pointer to word boundary
+ * offset = -src & 3
+ */
+ rsb r3, r4, #0
+ ands r3, r3, #3
+ beq 0f
+
+ /* align first pointer */
+ sub r2, r2, r3
+1: ldrb r0, [r4], #1
+ ldrb ip, [r1], #1
+ subs r0, r0, ip
+ bne 9f
+ subs r3, r3, #1
+ bne 1b
+
+
+0: /* here the first pointer is aligned, and we have at least 4 bytes
+ * to process.
+ */
+
+ /* see if the pointers are congruent */
+ eor r0, r4, r1
+ ands r0, r0, #3
+ bne 5f
+
+ /* congruent case, 32 bytes per iteration
+ * We need to make sure there are at least 32+4 bytes left
+ * because we effectively read ahead one word, and we could
+ * read past the buffer (and segfault) if we're not careful.
+ */
+
+ ldr ip, [r1]
+ subs r2, r2, #(32 + 4)
+ bmi 1f
+
+0: PLD (r4, #64)
+ PLD (r1, #64)
+ ldr r0, [r4], #4
+ ldr lr, [r1, #4]!
+ eors r0, r0, ip
+ ldreq r0, [r4], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ ldreq r0, [r4], #4
+ ldreq lr, [r1, #4]!
+ eoreqs r0, r0, ip
+ ldreq r0, [r4], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ ldreq r0, [r4], #4
+ ldreq lr, [r1, #4]!
+ eoreqs r0, r0, ip
+ ldreq r0, [r4], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ ldreq r0, [r4], #4
+ ldreq lr, [r1, #4]!
+ eoreqs r0, r0, ip
+ ldreq r0, [r4], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ bne 2f
+ subs r2, r2, #32
+ bhs 0b
+
+ /* do we have at least 4 bytes left? */
+1: adds r2, r2, #(32 - 4 + 4)
+ bmi 4f
+
+ /* finish off 4 bytes at a time */
+3: ldr r0, [r4], #4
+ ldr ip, [r1], #4
+ eors r0, r0, ip
+ bne 2f
+ subs r2, r2, #4
+ bhs 3b
+
+ /* are we done? */
+4: adds r2, r2, #4
+ moveq r0, #0
+ beq 9f
+
+ /* finish off the remaining bytes */
+ b 8f
+
+2: /* the last 4 bytes are different, restart them */
+ sub r4, r4, #4
+ sub r1, r1, #4
+ mov r2, #4
+
+ /* process the last few bytes */
+8: ldrb r0, [r4], #1
+ ldrb ip, [r1], #1
+ // stall
+ subs r0, r0, ip
+ bne 9f
+ subs r2, r2, #1
+ bne 8b
+
+9: /* restore registers and return */
+ ldmfd sp!, {r4, lr}
+ bx lr
+
+
+
+
+
+5: /*************** non-congruent case ***************/
+ and r0, r1, #3
+ cmp r0, #2
+ bne 4f
+
+ /* here, offset is 2 (16-bits aligned, special cased) */
+
+ /* make sure we have at least 16 bytes to process */
+ subs r2, r2, #16
+ addmi r2, r2, #16
+ bmi 8b
+
+ /* align the unaligned pointer */
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+
+6: PLD (r1, #64)
+ PLD (r4, #64)
+ mov ip, lr, lsr #16
+ ldr lr, [r1], #4
+ ldr r0, [r4], #4
+ orr ip, ip, lr, lsl #16
+ eors r0, r0, ip
+ moveq ip, lr, lsr #16
+ ldreq lr, [r1], #4
+ ldreq r0, [r4], #4
+ orreq ip, ip, lr, lsl #16
+ eoreqs r0, r0, ip
+ moveq ip, lr, lsr #16
+ ldreq lr, [r1], #4
+ ldreq r0, [r4], #4
+ orreq ip, ip, lr, lsl #16
+ eoreqs r0, r0, ip
+ moveq ip, lr, lsr #16
+ ldreq lr, [r1], #4
+ ldreq r0, [r4], #4
+ orreq ip, ip, lr, lsl #16
+ eoreqs r0, r0, ip
+ bne 7f
+ subs r2, r2, #16
+ bhs 6b
+ sub r1, r1, #2
+ /* are we done? */
+ adds r2, r2, #16
+ moveq r0, #0
+ beq 9b
+ /* finish off the remaining bytes */
+ b 8b
+
+7: /* fix up the 2 pointers and fallthrough... */
+ sub r1, r1, #(4+2)
+ sub r4, r4, #4
+ mov r2, #4
+ b 8b
+
+
+4: /*************** offset is 1 or 3 (less optimized) ***************/
+
+ stmfd sp!, {r5, r6, r7}
+
+ // r5 = rhs
+ // r6 = lhs
+ // r7 = scratch
+
+ mov r5, r0, lsl #3 /* r5 = right shift */
+ rsb r6, r5, #32 /* r6 = left shift */
+
+ /* align the unaligned pointer */
+ bic r1, r1, #3
+ ldr r7, [r1], #4
+ sub r2, r2, #8
+
+6: mov ip, r7, lsr r5
+ ldr r7, [r1], #4
+ ldr r0, [r4], #4
+ orr ip, ip, r7, lsl r6
+ eors r0, r0, ip
+ moveq ip, r7, lsr r5
+ ldreq r7, [r1], #4
+ ldreq r0, [r4], #4
+ orreq ip, ip, r7, lsl r6
+ eoreqs r0, r0, ip
+ bne 7f
+ subs r2, r2, #8
+ bhs 6b
+
+ sub r1, r1, r6, lsr #3
+ ldmfd sp!, {r5, r6, r7}
+
+ /* are we done? */
+ adds r2, r2, #8
+ moveq r0, #0
+ beq 9b
+
+ /* finish off the remaining bytes */
+ b 8b
+
+7: /* fix up the 2 pointers and fallthrough... */
+ sub r1, r1, #4
+ sub r1, r1, r6, lsr #3
+ sub r4, r4, #4
+ mov r2, #4
+ ldmfd sp!, {r5, r6, r7}
+ b 8b
diff --git a/libc/arch-arm/bionic/memcmp16.S b/libc/arch-arm/bionic/memcmp16.S
new file mode 100644
index 0000000..38d8b62
--- /dev/null
+++ b/libc/arch-arm/bionic/memcmp16.S
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <machine/cpu-features.h>
+
+ .text
+
+ .global __memcmp16
+ .type __memcmp16, %function
+ .align 4
+
+/*
+ * Optimized memcmp16() for ARM9.
+ * This would not be optimal on XScale or ARM11, where more prefetching
+ * and use of PLD will be needed.
+ * The 2 major optimzations here are
+ * (1) The main loop compares 16 bytes at a time
+ * (2) The loads are scheduled in a way they won't stall
+ */
+
+__memcmp16:
+ PLD (r0, #0)
+ PLD (r1, #0)
+
+ /* take of the case where length is nul or the buffers are the same */
+ cmp r0, r1
+ cmpne r2, #0
+ moveq r0, #0
+ bxeq lr
+
+ /* since r0 hold the result, move the first source
+ * pointer somewhere else
+ */
+
+ mov r3, r0
+
+ /* make sure we have at least 12 words, this simplify things below
+ * and avoid some overhead for small blocks
+ */
+
+ cmp r2, #12
+ bpl 0f
+
+ /* small blocks (less then 12 words) */
+ PLD (r0, #32)
+ PLD (r1, #32)
+
+1: ldrh r0, [r3], #2
+ ldrh ip, [r1], #2
+ subs r0, r0, ip
+ bxne lr
+ subs r2, r2, #1
+ bne 1b
+ bx lr
+
+
+ /* save registers */
+0: stmfd sp!, {r4, lr}
+
+ /* align first pointer to word boundary */
+ tst r3, #2
+ beq 0f
+
+ ldrh r0, [r3], #2
+ ldrh ip, [r1], #2
+ sub r2, r2, #1
+ subs r0, r0, ip
+ /* restore registers and return */
+ ldmnefd sp!, {r4, lr}
+ bxne lr
+
+
+
+0: /* here the first pointer is aligned, and we have at least 3 words
+ * to process.
+ */
+
+ /* see if the pointers are congruent */
+ eor r0, r3, r1
+ ands r0, r0, #2
+ bne 5f
+
+ /* congruent case, 16 half-words per iteration
+ * We need to make sure there are at least 16+2 words left
+ * because we effectively read ahead one long word, and we could
+ * read past the buffer (and segfault) if we're not careful.
+ */
+
+ ldr ip, [r1]
+ subs r2, r2, #(16 + 2)
+ bmi 1f
+
+0:
+ PLD (r3, #64)
+ PLD (r1, #64)
+ ldr r0, [r3], #4
+ ldr lr, [r1, #4]!
+ eors r0, r0, ip
+ ldreq r0, [r3], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ ldreq r0, [r3], #4
+ ldreq lr, [r1, #4]!
+ eoreqs r0, r0, ip
+ ldreq r0, [r3], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ ldreq r0, [r3], #4
+ ldreq lr, [r1, #4]!
+ eoreqs r0, r0, ip
+ ldreq r0, [r3], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ ldreq r0, [r3], #4
+ ldreq lr, [r1, #4]!
+ eoreqs r0, r0, ip
+ ldreq r0, [r3], #4
+ ldreq ip, [r1, #4]!
+ eoreqs r0, r0, lr
+ bne 2f
+ subs r2, r2, #16
+ bhs 0b
+
+ /* do we have at least 2 words left? */
+1: adds r2, r2, #(16 - 2 + 2)
+ bmi 4f
+
+ /* finish off 2 words at a time */
+3: ldr r0, [r3], #4
+ ldr ip, [r1], #4
+ eors r0, r0, ip
+ bne 2f
+ subs r2, r2, #2
+ bhs 3b
+
+ /* are we done? */
+4: adds r2, r2, #2
+ bne 8f
+ /* restore registers and return */
+ mov r0, #0
+ ldmfd sp!, {r4, lr}
+ bx lr
+
+2: /* the last 2 words are different, restart them */
+ ldrh r0, [r3, #-4]
+ ldrh ip, [r1, #-4]
+ subs r0, r0, ip
+ ldreqh r0, [r3, #-2]
+ ldreqh ip, [r1, #-2]
+ subeqs r0, r0, ip
+ /* restore registers and return */
+ ldmfd sp!, {r4, lr}
+ bx lr
+
+ /* process the last few words */
+8: ldrh r0, [r3], #2
+ ldrh ip, [r1], #2
+ subs r0, r0, ip
+ bne 9f
+ subs r2, r2, #1
+ bne 8b
+
+9: /* restore registers and return */
+ ldmfd sp!, {r4, lr}
+ bx lr
+
+
+5: /*************** non-congruent case ***************/
+
+ /* align the unaligned pointer */
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+ sub r2, r2, #8
+
+6:
+ PLD (r3, #64)
+ PLD (r1, #64)
+ mov ip, lr, lsr #16
+ ldr lr, [r1], #4
+ ldr r0, [r3], #4
+ orr ip, ip, lr, lsl #16
+ eors r0, r0, ip
+ moveq ip, lr, lsr #16
+ ldreq lr, [r1], #4
+ ldreq r0, [r3], #4
+ orreq ip, ip, lr, lsl #16
+ eoreqs r0, r0, ip
+ moveq ip, lr, lsr #16
+ ldreq lr, [r1], #4
+ ldreq r0, [r3], #4
+ orreq ip, ip, lr, lsl #16
+ eoreqs r0, r0, ip
+ moveq ip, lr, lsr #16
+ ldreq lr, [r1], #4
+ ldreq r0, [r3], #4
+ orreq ip, ip, lr, lsl #16
+ eoreqs r0, r0, ip
+ bne 7f
+ subs r2, r2, #8
+ bhs 6b
+ sub r1, r1, #2
+ /* are we done? */
+ adds r2, r2, #8
+ moveq r0, #0
+ beq 9b
+ /* finish off the remaining bytes */
+ b 8b
+
+7: /* fix up the 2 pointers and fallthrough... */
+ sub r1, r1, #2
+ b 2b
diff --git a/libc/arch-arm/bionic/memcpy.S b/libc/arch-arm/bionic/memcpy.S
new file mode 100644
index 0000000..fcb58cd
--- /dev/null
+++ b/libc/arch-arm/bionic/memcpy.S
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <machine/cpu-features.h>
+
+ .text
+
+ .global memcpy
+ .type memcpy, %function
+ .align 4
+
+ /*
+ * Optimized memcpy() for ARM.
+ *
+ * note that memcpy() always returns the destination pointer,
+ * so we have to preserve R0.
+ */
+
+memcpy:
+ /* The stack must always be 64-bits aligned to be compliant with the
+ * ARM ABI. Since we have to save R0, we might as well save R4
+ * which we can use for better pipelining of the reads below
+ */
+ .fnstart
+ .save {r0, r4, lr}
+ stmfd sp!, {r0, r4, lr}
+ /* Making room for r5-r11 which will be spilled later */
+ .pad #28
+ sub sp, sp, #28
+
+ // preload the destination because we'll align it to a cache line
+ // with small writes. Also start the source "pump".
+ PLD (r0, #0)
+ PLD (r1, #0)
+ PLD (r1, #32)
+
+ /* it simplifies things to take care of len<4 early */
+ cmp r2, #4
+ blo copy_last_3_and_return
+
+ /* compute the offset to align the source
+ * offset = (4-(src&3))&3 = -src & 3
+ */
+ rsb r3, r1, #0
+ ands r3, r3, #3
+ beq src_aligned
+
+ /* align source to 32 bits. We need to insert 2 instructions between
+ * a ldr[b|h] and str[b|h] because byte and half-word instructions
+ * stall 2 cycles.
+ */
+ movs r12, r3, lsl #31
+ sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
+ ldrmib r3, [r1], #1
+ ldrcsb r4, [r1], #1
+ ldrcsb r12,[r1], #1
+ strmib r3, [r0], #1
+ strcsb r4, [r0], #1
+ strcsb r12,[r0], #1
+
+src_aligned:
+
+ /* see if src and dst are aligned together (congruent) */
+ eor r12, r0, r1
+ tst r12, #3
+ bne non_congruent
+
+ /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
+ * frame. Don't update sp.
+ */
+ stmea sp, {r5-r11}
+
+ /* align the destination to a cache-line */
+ rsb r3, r0, #0
+ ands r3, r3, #0x1C
+ beq congruent_aligned32
+ cmp r3, r2
+ andhi r3, r2, #0x1C
+
+ /* conditionnaly copies 0 to 7 words (length in r3) */
+ movs r12, r3, lsl #28
+ ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
+ ldmmiia r1!, {r8, r9} /* 8 bytes */
+ stmcsia r0!, {r4, r5, r6, r7}
+ stmmiia r0!, {r8, r9}
+ tst r3, #0x4
+ ldrne r10,[r1], #4 /* 4 bytes */
+ strne r10,[r0], #4
+ sub r2, r2, r3
+
+congruent_aligned32:
+ /*
+ * here source is aligned to 32 bytes.
+ */
+
+cached_aligned32:
+ subs r2, r2, #32
+ blo less_than_32_left
+
+ /*
+ * We preload a cache-line up to 64 bytes ahead. On the 926, this will
+ * stall only until the requested world is fetched, but the linefill
+ * continues in the the background.
+ * While the linefill is going, we write our previous cache-line
+ * into the write-buffer (which should have some free space).
+ * When the linefill is done, the writebuffer will
+ * start dumping its content into memory
+ *
+ * While all this is going, we then load a full cache line into
+ * 8 registers, this cache line should be in the cache by now
+ * (or partly in the cache).
+ *
+ * This code should work well regardless of the source/dest alignment.
+ *
+ */
+
+ // Align the preload register to a cache-line because the cpu does
+ // "critical word first" (the first word requested is loaded first).
+ bic r12, r1, #0x1F
+ add r12, r12, #64
+
+1: ldmia r1!, { r4-r11 }
+ PLD (r12, #64)
+ subs r2, r2, #32
+
+ // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi
+ // for ARM9 preload will not be safely guarded by the preceding subs.
+ // When it is safely guarded the only possibility to have SIGSEGV here
+ // is because the caller overstates the length.
+ ldrhi r3, [r12], #32 /* cheap ARM9 preload */
+ stmia r0!, { r4-r11 }
+ bhs 1b
+
+ add r2, r2, #32
+
+
+
+
+less_than_32_left:
+ /*
+ * less than 32 bytes left at this point (length in r2)
+ */
+
+ /* skip all this if there is nothing to do, which should
+ * be a common case (if not executed the code below takes
+ * about 16 cycles)
+ */
+ tst r2, #0x1F
+ beq 1f
+
+ /* conditionnaly copies 0 to 31 bytes */
+ movs r12, r2, lsl #28
+ ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
+ ldmmiia r1!, {r8, r9} /* 8 bytes */
+ stmcsia r0!, {r4, r5, r6, r7}
+ stmmiia r0!, {r8, r9}
+ movs r12, r2, lsl #30
+ ldrcs r3, [r1], #4 /* 4 bytes */
+ ldrmih r4, [r1], #2 /* 2 bytes */
+ strcs r3, [r0], #4
+ strmih r4, [r0], #2
+ tst r2, #0x1
+ ldrneb r3, [r1] /* last byte */
+ strneb r3, [r0]
+
+ /* we're done! restore everything and return */
+1: ldmfd sp!, {r5-r11}
+ ldmfd sp!, {r0, r4, lr}
+ bx lr
+
+ /********************************************************************/
+
+non_congruent:
+ /*
+ * here source is aligned to 4 bytes
+ * but destination is not.
+ *
+ * in the code below r2 is the number of bytes read
+ * (the number of bytes written is always smaller, because we have
+ * partial words in the shift queue)
+ */
+ cmp r2, #4
+ blo copy_last_3_and_return
+
+ /* Use post-incriment mode for stm to spill r5-r11 to reserved stack
+ * frame. Don't update sp.
+ */
+ stmea sp, {r5-r11}
+
+ /* compute shifts needed to align src to dest */
+ rsb r5, r0, #0
+ and r5, r5, #3 /* r5 = # bytes in partial words */
+ mov r12, r5, lsl #3 /* r12 = right */
+ rsb lr, r12, #32 /* lr = left */
+
+ /* read the first word */
+ ldr r3, [r1], #4
+ sub r2, r2, #4
+
+ /* write a partial word (0 to 3 bytes), such that destination
+ * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
+ */
+ movs r5, r5, lsl #31
+ strmib r3, [r0], #1
+ movmi r3, r3, lsr #8
+ strcsb r3, [r0], #1
+ movcs r3, r3, lsr #8
+ strcsb r3, [r0], #1
+ movcs r3, r3, lsr #8
+
+ cmp r2, #4
+ blo partial_word_tail
+
+ /* Align destination to 32 bytes (cache line boundary) */
+1: tst r0, #0x1c
+ beq 2f
+ ldr r5, [r1], #4
+ sub r2, r2, #4
+ orr r4, r3, r5, lsl lr
+ mov r3, r5, lsr r12
+ str r4, [r0], #4
+ cmp r2, #4
+ bhs 1b
+ blo partial_word_tail
+
+ /* copy 32 bytes at a time */
+2: subs r2, r2, #32
+ blo less_than_thirtytwo
+
+ /* Use immediate mode for the shifts, because there is an extra cycle
+ * for register shifts, which could account for up to 50% of
+ * performance hit.
+ */
+
+ cmp r12, #24
+ beq loop24
+ cmp r12, #8
+ beq loop8
+
+loop16:
+ ldr r12, [r1], #4
+1: mov r4, r12
+ ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
+ PLD (r1, #64)
+ subs r2, r2, #32
+ ldrhs r12, [r1], #4
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, r8, lsl #16
+ mov r8, r8, lsr #16
+ orr r8, r8, r9, lsl #16
+ mov r9, r9, lsr #16
+ orr r9, r9, r10, lsl #16
+ mov r10, r10, lsr #16
+ orr r10, r10, r11, lsl #16
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsr #16
+ bhs 1b
+ b less_than_thirtytwo
+
+loop8:
+ ldr r12, [r1], #4
+1: mov r4, r12
+ ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
+ PLD (r1, #64)
+ subs r2, r2, #32
+ ldrhs r12, [r1], #4
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, r8, lsl #24
+ mov r8, r8, lsr #8
+ orr r8, r8, r9, lsl #24
+ mov r9, r9, lsr #8
+ orr r9, r9, r10, lsl #24
+ mov r10, r10, lsr #8
+ orr r10, r10, r11, lsl #24
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsr #8
+ bhs 1b
+ b less_than_thirtytwo
+
+loop24:
+ ldr r12, [r1], #4
+1: mov r4, r12
+ ldmia r1!, { r5,r6,r7, r8,r9,r10,r11}
+ PLD (r1, #64)
+ subs r2, r2, #32
+ ldrhs r12, [r1], #4
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, r8, lsl #8
+ mov r8, r8, lsr #24
+ orr r8, r8, r9, lsl #8
+ mov r9, r9, lsr #24
+ orr r9, r9, r10, lsl #8
+ mov r10, r10, lsr #24
+ orr r10, r10, r11, lsl #8
+ stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10}
+ mov r3, r11, lsr #24
+ bhs 1b
+
+
+less_than_thirtytwo:
+ /* copy the last 0 to 31 bytes of the source */
+ rsb r12, lr, #32 /* we corrupted r12, recompute it */
+ add r2, r2, #32
+ cmp r2, #4
+ blo partial_word_tail
+
+1: ldr r5, [r1], #4
+ sub r2, r2, #4
+ orr r4, r3, r5, lsl lr
+ mov r3, r5, lsr r12
+ str r4, [r0], #4
+ cmp r2, #4
+ bhs 1b
+
+partial_word_tail:
+ /* we have a partial word in the input buffer */
+ movs r5, lr, lsl #(31-3)
+ strmib r3, [r0], #1
+ movmi r3, r3, lsr #8
+ strcsb r3, [r0], #1
+ movcs r3, r3, lsr #8
+ strcsb r3, [r0], #1
+
+ /* Refill spilled registers from the stack. Don't update sp. */
+ ldmfd sp, {r5-r11}
+
+copy_last_3_and_return:
+ movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
+ ldrmib r2, [r1], #1
+ ldrcsb r3, [r1], #1
+ ldrcsb r12,[r1]
+ strmib r2, [r0], #1
+ strcsb r3, [r0], #1
+ strcsb r12,[r0]
+
+ /* we're done! restore sp and spilled registers and return */
+ add sp, sp, #28
+ ldmfd sp!, {r0, r4, lr}
+ bx lr
+ .fnend
+
diff --git a/libc/arch-arm/bionic/memset.S b/libc/arch-arm/bionic/memset.S
new file mode 100644
index 0000000..d52d622
--- /dev/null
+++ b/libc/arch-arm/bionic/memset.S
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+ .text
+
+ .global memset
+ .type memset, %function
+
+ .global bzero
+ .type bzero, %function
+
+ .align
+
+ /*
+ * Optimized memset() for ARM.
+ *
+ * memset() returns its first argument.
+ */
+
+bzero:
+ mov r2, r1
+ mov r1, #0
+
+memset:
+ /* compute the offset to align the destination
+ * offset = (4-(src&3))&3 = -src & 3
+ */
+ .fnstart
+ .save {r0, r4-r7, lr}
+ stmfd sp!, {r0, r4-r7, lr}
+ rsb r3, r0, #0
+ ands r3, r3, #3
+ cmp r3, r2
+ movhi r3, r2
+
+ /* splat r1 */
+ mov r1, r1, lsl #24
+ orr r1, r1, r1, lsr #8
+ orr r1, r1, r1, lsr #16
+
+ movs r12, r3, lsl #31
+ strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
+ strcsb r1, [r0], #1
+ strmib r1, [r0], #1
+ subs r2, r2, r3
+ ldmlsfd sp!, {r0, r4-r7, lr} /* return */
+ bxls lr
+
+ /* align the destination to a cache-line */
+ mov r12, r1
+ mov lr, r1
+ mov r4, r1
+ mov r5, r1
+ mov r6, r1
+ mov r7, r1
+
+ rsb r3, r0, #0
+ ands r3, r3, #0x1C
+ beq aligned32
+ cmp r3, r2
+ andhi r3, r2, #0x1C
+ sub r2, r2, r3
+
+ /* conditionnaly writes 0 to 7 words (length in r3) */
+ movs r3, r3, lsl #28
+ stmcsia r0!, {r1, lr}
+ stmcsia r0!, {r1, lr}
+ stmmiia r0!, {r1, lr}
+ movs r3, r3, lsl #2
+ strcs r1, [r0], #4
+
+aligned32:
+ subs r2, r2, #32
+ mov r3, r1
+ bmi 2f
+1: subs r2, r2, #32
+ stmia r0!, {r1,r3,r4,r5,r6,r7,r12,lr}
+ bhs 1b
+2: add r2, r2, #32
+
+ /* conditionnaly stores 0 to 31 bytes */
+ movs r2, r2, lsl #28
+ stmcsia r0!, {r1,r3,r12,lr}
+ stmmiia r0!, {r1, lr}
+ movs r2, r2, lsl #2
+ strcs r1, [r0], #4
+ strmih r1, [r0], #2
+ movs r2, r2, lsl #2
+ strcsb r1, [r0]
+ ldmfd sp!, {r0, r4-r7, lr}
+ bx lr
+ .fnend
+
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
new file mode 100644
index 0000000..a9f6ea4
--- /dev/null
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -0,0 +1,136 @@
+/* $OpenBSD: setjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
+/* $NetBSD: setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1997 Mark Brinicombe
+ * All rights reserved.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. 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 AUTHOR 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 AUTHOR 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 <machine/asm.h>
+#include <machine/setjmp.h>
+
+/*
+ * C library -- setjmp, longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is restored.
+ */
+
+ENTRY(setjmp)
+ /* Block all signals and retrieve the old signal mask */
+ stmfd sp!, {r0, r14}
+ mov r0, #0x00000000
+
+ bl PIC_SYM(_C_LABEL(sigblock), PLT)
+ mov r1, r0
+
+ ldmfd sp!, {r0, r14}
+
+ /* Store signal mask */
+ str r1, [r0, #(25 * 4)]
+
+ ldr r1, .Lsetjmp_magic
+ str r1, [r0], #4
+
+#ifdef SOFTFLOAT
+ add r0, r0, #52
+#else
+ /* Store fp registers */
+ sfm f4, 4, [r0], #48
+ /* Store fpsr */
+ rfs r1
+ str r1, [r0], #0x0004
+#endif /*SOFTFLOAT*/
+ /* Store integer registers */
+ stmia r0, {r4-r14}
+ mov r0, #0x00000000
+ bx lr
+
+.Lsetjmp_magic:
+ .word _JB_MAGIC_SETJMP
+
+
+ENTRY(longjmp)
+ ldr r2, .Lsetjmp_magic
+ ldr r3, [r0]
+ teq r2, r3
+ bne botch
+
+ /* Fetch signal mask */
+ ldr r2, [r0, #(25 * 4)]
+
+ /* Set signal mask */
+ stmfd sp!, {r0, r1, r14}
+ sub sp, sp, #4 /* align the stack */
+
+ mov r0, r2
+ bl PIC_SYM(_C_LABEL(sigsetmask), PLT)
+
+ add sp, sp, #4 /* unalign the stack */
+ ldmfd sp!, {r0, r1, r14}
+
+ add r0, r0, #4
+#ifdef SOFTFLOAT
+ add r0, r0, #52
+#else
+ /* Restore fp registers */
+ lfm f4, 4, [r0], #48
+ /* Restore FPSR */
+ ldr r4, [r0], #0x0004
+ wfs r4
+#endif /* SOFTFLOAT */
+ /* Restore integer registers */
+ ldmia r0, {r4-r14}
+
+ /* Validate sp and r14 */
+ teq sp, #0
+ teqne r14, #0
+ beq botch
+
+ /* Set return value */
+
+ mov r0, r1
+ teq r0, #0x00000000
+ moveq r0, #0x00000001
+ bx lr
+#ifdef __ARM_26__
+ mov r15, r14
+#else
+ mov r15, r14
+#endif
+
+ /* validation failed, die die die. */
+botch:
+ bl PIC_SYM(_C_LABEL(longjmperror), PLT)
+ bl PIC_SYM(_C_LABEL(abort), PLT)
+ b . - 8 /* Cannot get here */
diff --git a/libc/arch-arm/bionic/sigsetjmp.S b/libc/arch-arm/bionic/sigsetjmp.S
new file mode 100644
index 0000000..50e6429
--- /dev/null
+++ b/libc/arch-arm/bionic/sigsetjmp.S
@@ -0,0 +1,62 @@
+/* $OpenBSD: sigsetjmp.S,v 1.2 2004/02/01 05:40:52 drahn Exp $ */
+/* $NetBSD: sigsetjmp.S,v 1.3 2002/08/17 19:54:30 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1997 Mark Brinicombe
+ * All rights reserved.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. 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 AUTHOR 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 AUTHOR 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 <machine/asm.h>
+#include <machine/setjmp.h>
+
+/*
+ * C library -- sigsetjmp, siglongjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * setjmp(a, m)
+ * by restoring registers from the stack.
+ * The previous signal state is restored.
+ */
+
+ENTRY(sigsetjmp)
+ teq r1, #0
+ beq PIC_SYM(_C_LABEL(_setjmp), PLT)
+ b PIC_SYM(_C_LABEL(setjmp), PLT)
+
+.L_setjmp_magic:
+ .word _JB_MAGIC__SETJMP
+
+ENTRY(siglongjmp)
+ ldr r2, .L_setjmp_magic
+ ldr r3, [r0]
+ teq r2, r3
+ beq PIC_SYM(_C_LABEL(_longjmp), PLT)
+ b PIC_SYM(_C_LABEL(longjmp), PLT)
diff --git a/libc/arch-arm/bionic/strlen.c b/libc/arch-arm/bionic/strlen.c
new file mode 100644
index 0000000..01632e3
--- /dev/null
+++ b/libc/arch-arm/bionic/strlen.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <stdint.h>
+#include <machine/cpu-features.h>
+
+size_t strlen(const char *s)
+{
+ __builtin_prefetch(s);
+ __builtin_prefetch(s+32);
+
+ union {
+ const char *b;
+ const uint32_t *w;
+ uintptr_t i;
+ } u;
+
+ // these are some scratch variables for the asm code below
+ uint32_t v, t;
+
+ // initialize the string length to zero
+ size_t l = 0;
+
+ // align the pointer to a 32-bit word boundary
+ u.b = s;
+ while (u.i & 0x3) {
+ if (__builtin_expect(*u.b++ == 0, 0)) {
+ goto done;
+ }
+ l++;
+ }
+
+ // loop for each word, testing if it contains a zero byte
+ // if so, exit the loop and update the length.
+ // We need to process 32 bytes per loop to schedule PLD properly
+ // and achieve the maximum bus speed.
+ asm(
+ "ldr %[v], [ %[s] ], #4 \n"
+ "sub %[l], %[l], %[s] \n"
+ "0: \n"
+#if __ARM_HAVE_PLD
+ "pld [ %[s], #64 ] \n"
+#endif
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+#if !defined(__OPTIMIZE_SIZE__)
+ "bne 1f \n"
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+ "bne 1f \n"
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+ "bne 1f \n"
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+ "bne 1f \n"
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+ "bne 1f \n"
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+ "bne 1f \n"
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+ "bne 1f \n"
+ "sub %[t], %[v], %[mask], lsr #7\n"
+ "and %[t], %[t], %[mask] \n"
+ "bics %[t], %[t], %[v] \n"
+ "ldreq %[v], [ %[s] ], #4 \n"
+#endif
+ "beq 0b \n"
+ "1: \n"
+ "add %[l], %[l], %[s] \n"
+ "tst %[v], #0xFF \n"
+ "beq 2f \n"
+ "add %[l], %[l], #1 \n"
+ "tst %[v], #0xFF00 \n"
+ "beq 2f \n"
+ "add %[l], %[l], #1 \n"
+ "tst %[v], #0xFF0000 \n"
+ "addne %[l], %[l], #1 \n"
+ "2: \n"
+ : [l]"=&r"(l), [v]"=&r"(v), [t]"=&r"(t), [s]"=&r"(u.b)
+ : "%[l]"(l), "%[s]"(u.b), [mask]"r"(0x80808080UL)
+ : "cc"
+ );
+
+done:
+ return l;
+}
diff --git a/libc/arch-arm/bionic/syscall.S b/libc/arch-arm/bionic/syscall.S
new file mode 100644
index 0000000..ada12a6
--- /dev/null
+++ b/libc/arch-arm/bionic/syscall.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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 <sys/linux-syscalls.h>
+
+
+ .text
+ .align 4
+ .type syscall,#function
+ .globl syscall
+
+ .text
+ .align
+
+#if __ARM_EABI__
+
+syscall:
+ mov ip, sp
+ stmfd sp!, {r4, r5, r6, r7}
+ mov r7, r0
+ mov r0, r1
+ mov r1, r2
+ mov r2, r3
+ ldmfd ip, {r3, r4, r5, r6}
+ swi #0
+ ldmfd sp!, {r4, r5, r6, r7}
+ movs r0, r0
+ bxpl lr
+ b __set_syscall_errno
+
+#else
+
+#ifndef __NR_syscall
+#define __NR_syscall 113
+#endif
+
+syscall:
+ stmfd sp!, {r4, r5, lr}
+ ldr r4, [sp, #12]
+ ldr r5, [sp, #16]
+ swi __NR_syscall
+ ldmfd sp!, {r4, r5, lr}
+ movs r0, r0
+ bxpl lr
+ b __set_syscall_errno
+
+#endif
diff --git a/libc/arch-arm/bionic/tkill.S b/libc/arch-arm/bionic/tkill.S
new file mode 100644
index 0000000..7b3301a
--- /dev/null
+++ b/libc/arch-arm/bionic/tkill.S
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+/* unlike our auto-generated syscall stubs, this code saves lr
+ on the stack, as well as a few other registers. this makes
+ our stack unwinder happy, when we generate debug stack
+ traces after the C library or other parts of the system
+ abort due to a fatal runtime error (e.g. detection
+ of a corrupted malloc heap).
+*/
+#include <sys/linux-syscalls.h>
+
+#ifndef __NR_tkill
+#define __NR_tkill 238
+#endif
+
+ .text
+ .type tkill, #function
+ .globl tkill
+ .align 4
+
+tkill:
+ stmfd sp!, {r4-r7, ip, lr}
+ ldr r7, =__NR_tkill
+ swi #0
+ ldmfd sp!, {r4-r7, ip, lr}
+ movs r0, r0
+ bxpl lr
+ b __set_syscall_errno