Blame sysdeps/arm/memmove.S

Packit Service 82fcde
/* Copyright (C) 2006-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   Contributed by MontaVista Software, Inc. (written by Nicolas Pitre)
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library.  If not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* Thumb requires excessive IT insns here.  */
Packit Service 82fcde
#define NO_THUMB
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
#include <arm-features.h>
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Data preload for architectures that support it (ARM V5TE and above)
Packit Service 82fcde
 */
Packit Service 82fcde
#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
Packit Service 82fcde
     && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
Packit Service 82fcde
     && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
Packit Service 82fcde
     && !defined (__ARM_ARCH_5T__))
Packit Service 82fcde
#define PLD(code...)    code
Packit Service 82fcde
#else
Packit Service 82fcde
#define PLD(code...)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * This can be used to enable code to cacheline align the source pointer.
Packit Service 82fcde
 * Experiments on tested architectures (StrongARM and XScale) didn't show
Packit Service 82fcde
 * this a worthwhile thing to do.  That might be different in the future.
Packit Service 82fcde
 */
Packit Service 82fcde
//#define CALGN(code...)        code
Packit Service 82fcde
#define CALGN(code...)
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Endian independent macros for shifting bytes within registers.
Packit Service 82fcde
 */
Packit Service 82fcde
#ifndef __ARMEB__
Packit Service 82fcde
#define PULL            lsr
Packit Service 82fcde
#define PUSH            lsl
Packit Service 82fcde
#else
Packit Service 82fcde
#define PULL            lsl
Packit Service 82fcde
#define PUSH            lsr
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
		.text
Packit Service 82fcde
		.syntax unified
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Prototype: void *memmove(void *dest, const void *src, size_t n);
Packit Service 82fcde
 *
Packit Service 82fcde
 * Note:
Packit Service 82fcde
 *
Packit Service 82fcde
 * If the memory regions don't overlap, we simply branch to memcpy which is
Packit Service 82fcde
 * normally a bit faster. Otherwise the copy is done going downwards.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
ENTRY(memmove)
Packit Service 82fcde
Packit Service 82fcde
		subs	ip, r0, r1
Packit Service 82fcde
		cmphi	r2, ip
Packit Service 82fcde
#if !IS_IN (libc)
Packit Service 82fcde
		bls	memcpy
Packit Service 82fcde
#else
Packit Service 82fcde
		bls	HIDDEN_JUMPTARGET(memcpy)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
		push	{r0, r4, lr}
Packit Service 82fcde
		cfi_adjust_cfa_offset (12)
Packit Service 82fcde
		cfi_rel_offset (r4, 4)
Packit Service 82fcde
		cfi_rel_offset (lr, 8)
Packit Service 82fcde
Packit Service 82fcde
		cfi_remember_state
Packit Service 82fcde
Packit Service 82fcde
		add	r1, r1, r2
Packit Service 82fcde
		add	r0, r0, r2
Packit Service 82fcde
		subs	r2, r2, #4
Packit Service 82fcde
		blt	8f
Packit Service 82fcde
		ands	ip, r0, #3
Packit Service 82fcde
	PLD(	pld	[r1, #-4]		)
Packit Service 82fcde
		bne	9f
Packit Service 82fcde
		ands	ip, r1, #3
Packit Service 82fcde
		bne	10f
Packit Service 82fcde
Packit Service 82fcde
1:		subs	r2, r2, #(28)
Packit Service 82fcde
		push	{r5 - r8}
Packit Service 82fcde
		cfi_adjust_cfa_offset (16)
Packit Service 82fcde
		cfi_rel_offset (r5, 0)
Packit Service 82fcde
		cfi_rel_offset (r6, 4)
Packit Service 82fcde
		cfi_rel_offset (r7, 8)
Packit Service 82fcde
		cfi_rel_offset (r8, 12)
Packit Service 82fcde
		blt	5f
Packit Service 82fcde
Packit Service 82fcde
	CALGN(	ands	ip, r1, #31		)
Packit Service 82fcde
	CALGN(	sbcsne	r4, ip, r2		)  @ C is always set here
Packit Service 82fcde
	CALGN(	bcs	2f			)
Packit Service 82fcde
	CALGN(	adr	r4, 6f			)
Packit Service 82fcde
	CALGN(	subs	r2, r2, ip		)  @ C is set here
Packit Service 82fcde
#ifndef ARM_ALWAYS_BX
Packit Service 82fcde
	CALGN(	add	pc, r4, ip, lsl	#(ARM_BX_ALIGN_LOG2 - 2))
Packit Service 82fcde
#else
Packit Service 82fcde
	CALGN(	add	r4, r4, ip, lsl	#(ARM_BX_ALIGN_LOG2 - 2))
Packit Service 82fcde
	CALGN(	bx	r4			)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
	PLD(	pld	[r1, #-4]		)
Packit Service 82fcde
2:	PLD(	subs	r2, r2, #96		)
Packit Service 82fcde
	PLD(	pld	[r1, #-32]		)
Packit Service 82fcde
	PLD(	blt	4f			)
Packit Service 82fcde
	PLD(	pld	[r1, #-64]		)
Packit Service 82fcde
	PLD(	pld	[r1, #-96]		)
Packit Service 82fcde
Packit Service 82fcde
3:	PLD(	pld	[r1, #-128]		)
Packit Service 82fcde
4:		ldmdb	r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
Packit Service 82fcde
		subs	r2, r2, #32
Packit Service 82fcde
		stmdb	r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
Packit Service 82fcde
		bge	3b
Packit Service 82fcde
	PLD(	cmn	r2, #96			)
Packit Service 82fcde
	PLD(	bge	4b			)
Packit Service 82fcde
Packit Service 82fcde
5:		ands	ip, r2, #28
Packit Service 82fcde
		rsb	ip, ip, #32
Packit Service 82fcde
#ifndef ARM_ALWAYS_BX
Packit Service 82fcde
		/* C is always clear here.  */
Packit Service 82fcde
		addne	pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
Packit Service 82fcde
		b	7f
Packit Service 82fcde
#else
Packit Service 82fcde
		beq	7f
Packit Service 82fcde
		push	{r10}
Packit Service 82fcde
		cfi_adjust_cfa_offset (4)
Packit Service 82fcde
		cfi_rel_offset (r10, 0)
Packit Service 82fcde
0:		add	r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
Packit Service 82fcde
		/* If alignment is not perfect, then there will be some
Packit Service 82fcde
		   padding (nop) instructions between this BX and label 6.
Packit Service 82fcde
		   The computation above assumed that two instructions
Packit Service 82fcde
		   later is exactly the right spot.  */
Packit Service 82fcde
		add	r10, #(6f - (0b + PC_OFS))
Packit Service 82fcde
		bx	r10
Packit Service 82fcde
#endif
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
6:		nop
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		ldr	r3, [r1, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		ldr	r4, [r1, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		ldr	r5, [r1, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		ldr	r6, [r1, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		ldr	r7, [r1, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		ldr	r8, [r1, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		ldr	lr, [r1, #-4]!
Packit Service 82fcde
Packit Service 82fcde
#ifndef ARM_ALWAYS_BX
Packit Service 82fcde
		add	pc, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
Packit Service 82fcde
		nop
Packit Service 82fcde
#else
Packit Service 82fcde
0:		add	r10, pc, ip, lsl #(ARM_BX_ALIGN_LOG2 - 2)
Packit Service 82fcde
		/* If alignment is not perfect, then there will be some
Packit Service 82fcde
		   padding (nop) instructions between this BX and label 66.
Packit Service 82fcde
		   The computation above assumed that two instructions
Packit Service 82fcde
		   later is exactly the right spot.  */
Packit Service 82fcde
		add	r10, #(66f - (0b + PC_OFS))
Packit Service 82fcde
		bx	r10
Packit Service 82fcde
#endif
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
66:		nop
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		str	r3, [r0, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		str	r4, [r0, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		str	r5, [r0, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		str	r6, [r0, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		str	r7, [r0, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		str	r8, [r0, #-4]!
Packit Service 82fcde
		.p2align ARM_BX_ALIGN_LOG2
Packit Service 82fcde
		str	lr, [r0, #-4]!
Packit Service 82fcde
Packit Service 82fcde
#ifdef ARM_ALWAYS_BX
Packit Service 82fcde
		pop	{r10}
Packit Service 82fcde
		cfi_adjust_cfa_offset (-4)
Packit Service 82fcde
		cfi_restore (r10)
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
	CALGN(	bcs	2b			)
Packit Service 82fcde
Packit Service 82fcde
7:		pop	{r5 - r8}
Packit Service 82fcde
		cfi_adjust_cfa_offset (-16)
Packit Service 82fcde
		cfi_restore (r5)
Packit Service 82fcde
		cfi_restore (r6)
Packit Service 82fcde
		cfi_restore (r7)
Packit Service 82fcde
		cfi_restore (r8)
Packit Service 82fcde
Packit Service 82fcde
8:		movs	r2, r2, lsl #31
Packit Service 82fcde
		ldrbne	r3, [r1, #-1]!
Packit Service 82fcde
		ldrbcs	r4, [r1, #-1]!
Packit Service 82fcde
		ldrbcs	ip, [r1, #-1]
Packit Service 82fcde
		strbne	r3, [r0, #-1]!
Packit Service 82fcde
		strbcs	r4, [r0, #-1]!
Packit Service 82fcde
		strbcs	ip, [r0, #-1]
Packit Service 82fcde
Packit Service 82fcde
#if ((defined (__ARM_ARCH_4T__) && defined (__THUMB_INTERWORK__)) \
Packit Service 82fcde
     || defined (ARM_ALWAYS_BX))
Packit Service 82fcde
		pop	{r0, r4, lr}
Packit Service 82fcde
		cfi_adjust_cfa_offset (-12)
Packit Service 82fcde
		cfi_restore (r4)
Packit Service 82fcde
		cfi_restore (lr)
Packit Service 82fcde
		bx      lr
Packit Service 82fcde
#else
Packit Service 82fcde
		pop	{r0, r4, pc}
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
		cfi_restore_state
Packit Service 82fcde
Packit Service 82fcde
9:		cmp	ip, #2
Packit Service 82fcde
		ldrbgt	r3, [r1, #-1]!
Packit Service 82fcde
		ldrbge	r4, [r1, #-1]!
Packit Service 82fcde
		ldrb	lr, [r1, #-1]!
Packit Service 82fcde
		strbgt	r3, [r0, #-1]!
Packit Service 82fcde
		strbge	r4, [r0, #-1]!
Packit Service 82fcde
		subs	r2, r2, ip
Packit Service 82fcde
		strb	lr, [r0, #-1]!
Packit Service 82fcde
		blt	8b
Packit Service 82fcde
		ands	ip, r1, #3
Packit Service 82fcde
		beq	1b
Packit Service 82fcde
Packit Service 82fcde
10:		bic	r1, r1, #3
Packit Service 82fcde
		cmp	ip, #2
Packit Service 82fcde
		ldr	r3, [r1, #0]
Packit Service 82fcde
		beq	17f
Packit Service 82fcde
		blt	18f
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
		.macro	backward_copy_shift push pull
Packit Service 82fcde
Packit Service 82fcde
		subs	r2, r2, #28
Packit Service 82fcde
		blt	14f
Packit Service 82fcde
Packit Service 82fcde
	CALGN(	ands	ip, r1, #31		)
Packit Service 82fcde
	CALGN(	rsb	ip, ip, #32		)
Packit Service 82fcde
	CALGN(	sbcsne	r4, ip, r2		)  @ C is always set here
Packit Service 82fcde
	CALGN(	subcc	r2, r2, ip		)
Packit Service 82fcde
	CALGN(	bcc	15f			)
Packit Service 82fcde
Packit Service 82fcde
11:		push	{r5 - r8, r10}
Packit Service 82fcde
		cfi_adjust_cfa_offset (20)
Packit Service 82fcde
		cfi_rel_offset (r5, 0)
Packit Service 82fcde
		cfi_rel_offset (r6, 4)
Packit Service 82fcde
		cfi_rel_offset (r7, 8)
Packit Service 82fcde
		cfi_rel_offset (r8, 12)
Packit Service 82fcde
		cfi_rel_offset (r10, 16)
Packit Service 82fcde
Packit Service 82fcde
	PLD(	pld	[r1, #-4]		)
Packit Service 82fcde
	PLD(	subs	r2, r2, #96		)
Packit Service 82fcde
	PLD(	pld	[r1, #-32]		)
Packit Service 82fcde
	PLD(	blt	13f			)
Packit Service 82fcde
	PLD(	pld	[r1, #-64]		)
Packit Service 82fcde
	PLD(	pld	[r1, #-96]		)
Packit Service 82fcde
Packit Service 82fcde
12:	PLD(	pld	[r1, #-128]		)
Packit Service 82fcde
13:		ldmdb   r1!, {r7, r8, r10, ip}
Packit Service 82fcde
		mov     lr, r3, PUSH #\push
Packit Service 82fcde
		subs    r2, r2, #32
Packit Service 82fcde
		ldmdb   r1!, {r3, r4, r5, r6}
Packit Service 82fcde
		orr     lr, lr, ip, PULL #\pull
Packit Service 82fcde
		mov     ip, ip, PUSH #\push
Packit Service 82fcde
		orr     ip, ip, r10, PULL #\pull
Packit Service 82fcde
		mov     r10, r10, PUSH #\push
Packit Service 82fcde
		orr     r10, r10, r8, PULL #\pull
Packit Service 82fcde
		mov     r8, r8, PUSH #\push
Packit Service 82fcde
		orr     r8, r8, r7, PULL #\pull
Packit Service 82fcde
		mov     r7, r7, PUSH #\push
Packit Service 82fcde
		orr     r7, r7, r6, PULL #\pull
Packit Service 82fcde
		mov     r6, r6, PUSH #\push
Packit Service 82fcde
		orr     r6, r6, r5, PULL #\pull
Packit Service 82fcde
		mov     r5, r5, PUSH #\push
Packit Service 82fcde
		orr     r5, r5, r4, PULL #\pull
Packit Service 82fcde
		mov     r4, r4, PUSH #\push
Packit Service 82fcde
		orr     r4, r4, r3, PULL #\pull
Packit Service 82fcde
		stmdb   r0!, {r4 - r8, r10, ip, lr}
Packit Service 82fcde
		bge	12b
Packit Service 82fcde
	PLD(	cmn	r2, #96			)
Packit Service 82fcde
	PLD(	bge	13b			)
Packit Service 82fcde
Packit Service 82fcde
		pop	{r5 - r8, r10}
Packit Service 82fcde
		cfi_adjust_cfa_offset (-20)
Packit Service 82fcde
		cfi_restore (r5)
Packit Service 82fcde
		cfi_restore (r6)
Packit Service 82fcde
		cfi_restore (r7)
Packit Service 82fcde
		cfi_restore (r8)
Packit Service 82fcde
		cfi_restore (r10)
Packit Service 82fcde
Packit Service 82fcde
14:		ands	ip, r2, #28
Packit Service 82fcde
		beq	16f
Packit Service 82fcde
Packit Service 82fcde
15:		mov     lr, r3, PUSH #\push
Packit Service 82fcde
		ldr	r3, [r1, #-4]!
Packit Service 82fcde
		subs	ip, ip, #4
Packit Service 82fcde
		orr	lr, lr, r3, PULL #\pull
Packit Service 82fcde
		str	lr, [r0, #-4]!
Packit Service 82fcde
		bgt	15b
Packit Service 82fcde
	CALGN(	cmp	r2, #0			)
Packit Service 82fcde
	CALGN(	bge	11b			)
Packit Service 82fcde
Packit Service 82fcde
16:		add	r1, r1, #(\pull / 8)
Packit Service 82fcde
		b	8b
Packit Service 82fcde
Packit Service 82fcde
		.endm
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
		backward_copy_shift	push=8	pull=24
Packit Service 82fcde
Packit Service 82fcde
17:		backward_copy_shift	push=16	pull=16
Packit Service 82fcde
Packit Service 82fcde
18:		backward_copy_shift	push=24	pull=8
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
END(memmove)
Packit Service 82fcde
libc_hidden_builtin_def (memmove)