diff options
Diffstat (limited to 'ports/sysdeps/arm/memmove.S')
-rw-r--r-- | ports/sysdeps/arm/memmove.S | 29 |
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) |