Blame sysdeps/arm/add_n.S

Packit 6c4009
/* mpn_add_n -- add (or subtract) bignums.
Packit 6c4009
   Copyright (C) 2013-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library.  If not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <sysdep.h>
Packit 6c4009
#include <arm-features.h>
Packit 6c4009
Packit 6c4009
	.syntax unified
Packit 6c4009
	.text
Packit 6c4009
Packit 6c4009
#ifdef USE_AS_SUB_N
Packit 6c4009
# define INITC	cmp r0, r0
Packit 6c4009
# define OPC	sbcs
Packit 6c4009
# define RETC	sbc r0, r0, r0; neg r0, r0
Packit 6c4009
# define FUNC	__mpn_sub_n
Packit 6c4009
#else
Packit 6c4009
# define INITC	cmn r0, #0
Packit 6c4009
# define OPC	adcs
Packit 6c4009
# define RETC	mov r0, #0; adc r0, r0, r0
Packit 6c4009
# define FUNC	__mpn_add_n
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* mp_limb_t mpn_add_n(res_ptr, src1_ptr, src2_ptr, size) */
Packit 6c4009
Packit 6c4009
ENTRY (FUNC)
Packit 6c4009
	push	{ r4, r5, r6, r7, r8, r10, lr }
Packit 6c4009
	cfi_adjust_cfa_offset (28)
Packit 6c4009
	cfi_rel_offset (r4, 0)
Packit 6c4009
	cfi_rel_offset (r5, 4)
Packit 6c4009
	cfi_rel_offset (r6, 8)
Packit 6c4009
	cfi_rel_offset (r7, 12)
Packit 6c4009
	cfi_rel_offset (r8, 16)
Packit 6c4009
	cfi_rel_offset (r10, 20)
Packit 6c4009
	cfi_rel_offset (lr, 24)
Packit 6c4009
Packit 6c4009
	INITC				/* initialize carry flag */
Packit 6c4009
	tst	r3, #1			/* count & 1 == 1? */
Packit 6c4009
	add	lr, r1, r3, lsl #2	/* compute end src1 */
Packit 6c4009
	beq	1f
Packit 6c4009
Packit 6c4009
	ldr	r4, [r1], #4		/* do one to make count even */
Packit 6c4009
	ldr	r5, [r2], #4
Packit 6c4009
	OPC	r4, r4, r5
Packit 6c4009
	teq	r1, lr			/* end of count? (preserve carry) */
Packit 6c4009
	str	r4, [r0], #4
Packit 6c4009
	beq	9f
Packit 6c4009
1:
Packit 6c4009
	tst	r3, #2			/* count & 2 == 2?  */
Packit 6c4009
	beq	2f
Packit 6c4009
	ldm	r1!, { r4, r5 }		/* do two to make count 0 mod 4 */
Packit 6c4009
	ldm	r2!, { r6, r7 }
Packit 6c4009
	OPC	r4, r4, r6
Packit 6c4009
	OPC	r5, r5, r7
Packit 6c4009
	teq	r1, lr			/* end of count? */
Packit 6c4009
	stm	r0!, { r4, r5 }
Packit 6c4009
	beq	9f
Packit 6c4009
2:
Packit 6c4009
	ldm	r1!, { r3, r5, r7, r10 }	/* do four each loop */
Packit 6c4009
	ldm	r2!, { r4, r6, r8, ip }
Packit 6c4009
	OPC	r3, r3, r4
Packit 6c4009
	OPC	r5, r5, r6
Packit 6c4009
	OPC	r7, r7, r8
Packit 6c4009
	OPC	r10, r10, ip
Packit 6c4009
	teq	r1, lr
Packit 6c4009
	stm	r0!, { r3, r5, r7, r10 }
Packit 6c4009
	bne	2b
Packit 6c4009
Packit 6c4009
9:
Packit 6c4009
	RETC				/* copy carry out */
Packit 6c4009
#ifndef ARM_ALWAYS_BX
Packit 6c4009
	pop	{ r4, r5, r6, r7, r8, r10, pc }
Packit 6c4009
#else
Packit 6c4009
	pop	{ r4, r5, r6, r7, r8, r10, lr }
Packit 6c4009
	bx	lr
Packit 6c4009
#endif
Packit 6c4009
END (FUNC)