From 64299d7bd853314bc3bc96853220461533f26069 Mon Sep 17 00:00:00 2001
From: "Shih-Yuan Lee (FourDollars)" <sylee@canonical.com>
Date: Wed, 3 Apr 2013 14:07:37 +0800
Subject: [PATCH 2/2] ARM: NEON detected memcpy.

---
 ports/sysdeps/arm/memcpy.S |  120 +++++++++++++++++++++++++++++---------------
 1 file changed, 79 insertions(+), 41 deletions(-)

diff --git a/ports/sysdeps/arm/memcpy.S b/ports/sysdeps/arm/memcpy.S
index c1b1357..94fe8e2 100644
--- a/ports/sysdeps/arm/memcpy.S
+++ b/ports/sysdeps/arm/memcpy.S
@@ -3,6 +3,8 @@
 
    Contributed by MontaVista Software, Inc. (written by Nicolas Pitre)
    NEON code contributed by Nokia Corporation (written by Siarhei Siamashka)
+   NEON detection contributed by Canonical Ltd. (written by Shih-Yuan Lee
+   aka FourDollars)
 
    The GNU C Library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -23,9 +25,36 @@
 #include <sysdep.h>
 #include <arm-features.h>
 
-#ifdef __ARM_NEON__
-		.text
-		.fpu    neon
+/*
+ * Data preload for architectures that support it (ARM V5TE and above)
+ */
+#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
+     && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
+     && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
+     && !defined (__ARM_ARCH_5T__))
+#define PLD(code...)    code
+#else
+#define PLD(code...)
+#endif
+
+/*
+ * This can be used to enable code to cacheline align the source pointer.
+ * Experiments on tested architectures (StrongARM and XScale) didn't show
+ * this a worthwhile thing to do.  That might be different in the future.
+ */
+//#define CALGN(code...)        code
+#define CALGN(code...)
+
+/*
+ * Endian independent macros for shifting bytes within registers.
+ */
+#ifndef __ARMEB__
+#define PULL            lsr
+#define PUSH            lsl
+#else
+#define PULL            lsl
+#define PUSH            lsr
+#endif
 
 /*
  * ENABLE_UNALIGNED_MEM_ACCESSES macro can be defined to permit the use
@@ -36,9 +65,44 @@
  * ordered/device memory.
  */
 
+#ifdef __ARM_FEATURE_UNALIGNED
+#define ENABLE_UNALIGNED_MEM_ACCESSES 1
+#endif
+
 #define NEON_MAX_PREFETCH_DISTANCE 320
 
+		.text
+		.fpu    neon
+
+/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
+
 ENTRY(memcpy)
+		stmfd	sp!, {r0, r1}
+
+		@ Check if there is a NEON extension.
+#ifdef IS_IN_rtld
+		ldr	a1, 5f
+		ldr	a2, Lrtld_local_ro
+0:		add	a1, pc, a1
+		add	a1, a1, a2
+		ldr	a1, [a1, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
+#else
+#ifdef PIC
+		ldr	a1, 5f
+		ldr	a2, Lrtld_global_ro
+0:		add	a1, pc, a1
+		ldr	a1, [a1, a2]
+		ldr	a1, [a1, #RTLD_GLOBAL_RO_DL_HWCAP_OFFSET]
+#else
+		ldr	a1, Lhwcap
+		ldr	a1, [a1, #0]
+#endif
+#endif
+		tst	a1, #HWCAP_ARM_NEON
+		ldmfd	sp!, {r0, r1}
+		beq	Lno_neon
+
+		@ Optimized memcpy by NEON extension.
 		mov	ip, r0
 		cmp	r2, #16
 		blt	4f	@ Have less than 16 bytes to copy
@@ -147,49 +211,24 @@ ENTRY(memcpy)
 		strmib	r3, [ip], #1
 #endif
 		bx	lr
-END(memcpy)
-libc_hidden_builtin_def (memcpy)
 
+#ifdef IS_IN_rtld
+5:	.long	_GLOBAL_OFFSET_TABLE_ - 0b - 8
+Lrtld_local_ro:
+	.long	C_SYMBOL_NAME(_rtld_local_ro)(GOTOFF)
 #else
-
-/*
- * Data preload for architectures that support it (ARM V5TE and above)
- */
-#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
-     && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
-     && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
-     && !defined (__ARM_ARCH_5T__))
-#define PLD(code...)    code
+#ifdef PIC
+5:	.long	_GLOBAL_OFFSET_TABLE_ - 0b - 8
+Lrtld_global_ro:
+	.long	C_SYMBOL_NAME(_rtld_global_ro)(GOT)
 #else
-#define PLD(code...)
+Lhwcap:
+	.long	C_SYMBOL_NAME(_dl_hwcap)
 #endif
-
-/*
- * This can be used to enable code to cacheline align the source pointer.
- * Experiments on tested architectures (StrongARM and XScale) didn't show
- * this a worthwhile thing to do.  That might be different in the future.
- */
-//#define CALGN(code...)        code
-#define CALGN(code...)
-
-/*
- * Endian independent macros for shifting bytes within registers.
- */
-#ifndef __ARMEB__
-#define PULL            lsr
-#define PUSH            lsl
-#else
-#define PULL            lsl
-#define PUSH            lsr
 #endif
 
-		.text
-		.syntax unified
-
-/* Prototype: void *memcpy(void *dest, const void *src, size_t n); */
-
-ENTRY(memcpy)
-
+Lno_neon:
+		@ Generic ARM memcpy.
 		push	{r0, r4, lr}
 		cfi_adjust_cfa_offset (12)
 		cfi_rel_offset (r4, 4)
@@ -473,4 +512,3 @@ ENTRY(memcpy)
 END(memcpy)
 libc_hidden_builtin_def (memcpy)
 
-#endif
-- 
1.7.10.4

