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