[BZ #22142] powerpc: Fix the carry bit on mpn_[add|sub]_n on POWER7
[glibc.git] / sysdeps / arm / add_n.S
blob811a769959c558230d9b99588330cb27f9aa4f4a
1 /* mpn_add_n -- add (or subtract) bignums.
2    Copyright (C) 2013-2017 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         ldr     r4, [r1], #4            /* do one to make count even */
56         ldr     r5, [r2], #4
57         OPC     r4, r4, r5
58         teq     r1, lr                  /* end of count? (preserve carry) */
59         str     r4, [r0], #4
60         beq     9f
62         tst     r3, #2                  /* count & 2 == 2?  */
63         beq     2f
64         ldm     r1!, { r4, r5 }         /* do two to make count 0 mod 4 */
65         ldm     r2!, { r6, r7 }
66         OPC     r4, r4, r6
67         OPC     r5, r5, r7
68         teq     r1, lr                  /* end of count? */
69         stm     r0!, { r4, r5 }
70         beq     9f
72         ldm     r1!, { r3, r5, r7, r10 }        /* do four each loop */
73         ldm     r2!, { r4, r6, r8, ip }
74         OPC     r3, r3, r4
75         OPC     r5, r5, r6
76         OPC     r7, r7, r8
77         OPC     r10, r10, ip
78         teq     r1, lr
79         stm     r0!, { r3, r5, r7, r10 }
80         bne     2b
83         RETC                            /* copy carry out */
84 #ifndef ARM_ALWAYS_BX
85         pop     { r4, r5, r6, r7, r8, r10, pc }
86 #else
87         pop     { r4, r5, r6, r7, r8, r10, lr }
88         bx      lr
89 #endif
90 END (FUNC)