Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / arm / add_n.S
blob278a94a8cfffec7341f3b420c51240d15598aa3b
1 /* mpn_add_n -- add (or subtract) bignums.
2    Copyright (C) 2013-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library.  If not, see
17    <http://www.gnu.org/licenses/>.  */
19 #include <sysdep.h>
20 #include <arm-features.h>
22         .syntax unified
23         .text
25 #ifdef USE_AS_SUB_N
26 # define INITC  cmp r0, r0
27 # define OPC    sbcs
28 # define RETC   sbc r0, r0, r0; neg r0, r0
29 # define FUNC   __mpn_sub_n
30 #else
31 # define INITC  cmn r0, #0
32 # define OPC    adcs
33 # define RETC   mov r0, #0; adc r0, r0, r0
34 # define FUNC   __mpn_add_n
35 #endif
37 /* mp_limb_t mpn_add_n(res_ptr, src1_ptr, src2_ptr, size) */
39 ENTRY (FUNC)
40         push    { r4, r5, r6, r7, r8, r10, lr }
41         cfi_adjust_cfa_offset (28)
42         cfi_rel_offset (r4, 0)
43         cfi_rel_offset (r5, 4)
44         cfi_rel_offset (r6, 8)
45         cfi_rel_offset (r7, 12)
46         cfi_rel_offset (r8, 16)
47         cfi_rel_offset (r10, 20)
48         cfi_rel_offset (lr, 24)
50         INITC                           /* initialize carry flag */
51         tst     r3, #1                  /* count & 1 == 1? */
52         add     lr, r1, r3, lsl #2      /* compute end src1 */
53         beq     1f
55         sfi_breg r1, \
56         ldr     r4, [\B], #4            /* do one to make count even */
57         sfi_breg r2, \
58         ldr     r5, [\B], #4
59         OPC     r4, r4, r5
60         teq     r1, lr                  /* end of count? (preserve carry) */
61         sfi_breg r0, \
62         str     r4, [\B], #4
63         beq     9f
65         tst     r3, #2                  /* count & 2 == 2?  */
66         beq     2f
67         sfi_breg r1, \
68         ldm     \B!, { r4, r5 }         /* do two to make count 0 mod 4 */
69         sfi_breg r2, \
70         ldm     \B!, { r6, r7 }
71         OPC     r4, r4, r6
72         OPC     r5, r5, r7
73         teq     r1, lr                  /* end of count? */
74         sfi_breg r0, \
75         stm     \B!, { r4, r5 }
76         beq     9f
78         sfi_breg r1, \
79         ldm     \B!, { r3, r5, r7, r10 }        /* do four each loop */
80         sfi_breg r2, \
81         ldm     \B!, { r4, r6, r8, ip }
82         OPC     r3, r3, r4
83         OPC     r5, r5, r6
84         OPC     r7, r7, r8
85         OPC     r10, r10, ip
86         teq     r1, lr
87         sfi_breg r0, \
88         stm     \B!, { r3, r5, r7, r10 }
89         bne     2b
92         RETC                            /* copy carry out */
93 #ifndef ARM_ALWAYS_BX
94         pop     { r4, r5, r6, r7, r8, r10, pc }
95 #else
96         pop     { r4, r5, r6, r7, r8, r10, lr }
97         bx      lr
98 #endif
99 END (FUNC)