about summary refs log tree commit diff
path: root/ports/sysdeps/arm/memmove.S
diff options
context:
space:
mode:
Diffstat (limited to 'ports/sysdeps/arm/memmove.S')
-rw-r--r--ports/sysdeps/arm/memmove.S29
1 files changed, 28 insertions, 1 deletions
diff --git a/ports/sysdeps/arm/memmove.S b/ports/sysdeps/arm/memmove.S
index 9e8ad65f44..4a2cb92ea4 100644
--- a/ports/sysdeps/arm/memmove.S
+++ b/ports/sysdeps/arm/memmove.S
@@ -20,6 +20,7 @@
 /* Thumb requires excessive IT insns here.  */
 #define NO_THUMB
 #include <sysdep.h>
+#include <arm-features.h>
 
 /*
  * Data preload for architectures that support it (ARM V5TE and above)
@@ -105,7 +106,12 @@ ENTRY(memmove)
 	CALGN(	bcs	2f			)
 	CALGN(	adr	r4, 6f			)
 	CALGN(	subs	r2, r2, ip		)  @ C is set here
+#ifndef ARM_ALWAYS_BX
 	CALGN(	add	pc, r4, ip		)
+#else
+	CALGN(	add	r4, r4, ip		)
+	CALGN(	bx	r4			)
+#endif
 
 	PLD(	pld	[r1, #-4]		)
 2:	PLD(	subs	r2, r2, #96		)
@@ -124,8 +130,17 @@ ENTRY(memmove)
 
 5:		ands	ip, r2, #28
 		rsb	ip, ip, #32
+#ifndef ARM_ALWAYS_BX
 		addne	pc, pc, ip		@ C is always clear here
 		b	7f
+#else
+		beq	7f
+		push	{r10}
+		cfi_adjust_cfa_offset (4)
+		cfi_rel_offset (r10, 0)
+		add	r10, pc, ip
+		bx	r10
+#endif
 6:		nop
 		ldr	r3, [r1, #-4]!
 		ldr	r4, [r1, #-4]!
@@ -135,8 +150,13 @@ ENTRY(memmove)
 		ldr	r8, [r1, #-4]!
 		ldr	lr, [r1, #-4]!
 
+#ifndef ARM_ALWAYS_BX
 		add	pc, pc, ip
 		nop
+#else
+		add	r10, pc, ip
+		bx	r10
+#endif
 		nop
 		str	r3, [r0, #-4]!
 		str	r4, [r0, #-4]!
@@ -146,6 +166,12 @@ ENTRY(memmove)
 		str	r8, [r0, #-4]!
 		str	lr, [r0, #-4]!
 
+#ifdef ARM_ALWAYS_BX
+		pop	{r10}
+		cfi_adjust_cfa_offset (-4)
+		cfi_restore (r10)
+#endif
+
 	CALGN(	bcs	2b			)
 
 7:		pop	{r5 - r8}
@@ -163,7 +189,8 @@ ENTRY(memmove)
 		strbcs	r4, [r0, #-1]!
 		strbcs	ip, [r0, #-1]
 
-#if defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)
+#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
+     || defined (ARM_ALWAYS_BX))
 		pop	{r0, r4, lr}
 		cfi_adjust_cfa_offset (-12)
 		cfi_restore (r4)