1/* Add two limb vectors of the same length > 0 and store sum in a third
2   limb vector.
3   Copyright (C) 1992-2021 Free Software Foundation, Inc.
4   This file is part of the GNU MP Library.
5
6   The GNU MP Library is free software; you can redistribute it and/or modify
7   it under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or (at your
9   option) any later version.
10
11   The GNU MP Library is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with the GNU MP Library; see the file COPYING.LIB.  If not,
18   see <https://www.gnu.org/licenses/>.  */
19
20#include <sysdep.h>
21#include "asm-syntax.h"
22
23#define PARMS	4+8	/* space for 2 saved regs */
24#define RES	PARMS
25#define S1	RES+4
26#define S2	S1+4
27#define SIZE	S2+4
28
29	.text
30ENTRY (__mpn_add_n)
31
32	pushl %edi
33	cfi_adjust_cfa_offset (4)
34	pushl %esi
35	cfi_adjust_cfa_offset (4)
36
37	movl RES(%esp),%edi
38	cfi_rel_offset (edi, 4)
39	movl S1(%esp),%esi
40	cfi_rel_offset (esi, 0)
41	movl S2(%esp),%edx
42	movl SIZE(%esp),%ecx
43
44#if IBT_ENABLED
45	pushl	%ebx
46	cfi_adjust_cfa_offset (4)
47	cfi_rel_offset (ebx, 0)
48#endif
49
50	movl	%ecx,%eax
51	shrl	$3,%ecx			/* compute count for unrolled loop */
52	negl	%eax
53	andl	$7,%eax			/* get index where to start loop */
54	jz	L(oop)			/* necessary special case for 0 */
55	incl	%ecx			/* adjust loop count */
56	shll	$2,%eax			/* adjustment for pointers... */
57	subl	%eax,%edi		/* ... since they are offset ... */
58	subl	%eax,%esi		/* ... by a constant when we ... */
59	subl	%eax,%edx		/* ... enter the loop */
60	shrl	$2,%eax			/* restore previous value */
61#if IBT_ENABLED
62	leal	-4(,%eax,4),%ebx	/* Count for 4-byte endbr32 */
63#endif
64#ifdef PIC
65/* Calculate start address in loop for PIC.  Due to limitations in some
66   assemblers, Loop-L0-3 cannot be put into the leal */
67	call	L(0)
68	cfi_adjust_cfa_offset (4)
69L(0):	leal	(%eax,%eax,8),%eax
70	addl	(%esp),%eax
71	addl	$(L(oop)-L(0)-3),%eax
72	addl	$4,%esp
73	cfi_adjust_cfa_offset (-4)
74#else
75/* Calculate start address in loop for non-PIC.  */
76 	leal	(L(oop) - 3)(%eax,%eax,8),%eax
77#endif
78#if IBT_ENABLED
79	addl	%ebx,%eax		/* Adjust for endbr32 */
80#endif
81	jmp	*%eax			/* jump into loop */
82	ALIGN (3)
83L(oop):	movl	(%esi),%eax
84	adcl	(%edx),%eax
85	movl	%eax,(%edi)
86	_CET_ENDBR
87	movl	4(%esi),%eax
88	adcl	4(%edx),%eax
89	movl	%eax,4(%edi)
90	_CET_ENDBR
91	movl	8(%esi),%eax
92	adcl	8(%edx),%eax
93	movl	%eax,8(%edi)
94	_CET_ENDBR
95	movl	12(%esi),%eax
96	adcl	12(%edx),%eax
97	movl	%eax,12(%edi)
98	_CET_ENDBR
99	movl	16(%esi),%eax
100	adcl	16(%edx),%eax
101	movl	%eax,16(%edi)
102	_CET_ENDBR
103	movl	20(%esi),%eax
104	adcl	20(%edx),%eax
105	movl	%eax,20(%edi)
106	_CET_ENDBR
107	movl	24(%esi),%eax
108	adcl	24(%edx),%eax
109	movl	%eax,24(%edi)
110	_CET_ENDBR
111	movl	28(%esi),%eax
112	adcl	28(%edx),%eax
113	movl	%eax,28(%edi)
114	leal	32(%edi),%edi
115	leal	32(%esi),%esi
116	leal	32(%edx),%edx
117	decl	%ecx
118	jnz	L(oop)
119
120	sbbl	%eax,%eax
121	negl	%eax
122
123#if IBT_ENABLED
124	popl	%ebx
125	cfi_adjust_cfa_offset (-4)
126	cfi_restore (ebx)
127#endif
128	popl %esi
129	cfi_adjust_cfa_offset (-4)
130	cfi_restore (esi)
131	popl %edi
132	cfi_adjust_cfa_offset (-4)
133	cfi_restore (edi)
134
135	ret
136END (__mpn_add_n)
137