Switched to GPLv3.
[gnupg.git] / mpi / powerpc32 / mpih-add1.S
1 /* PowerPC-32 add_n -- Add two limb vectors of equal, non-zero length.
2  * Copyright (C) 1992, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "sysdep.h"
21 #include "asm-syntax.h"
22
23
24 #ifndef USE_PPC_PATCHES
25
26 /*******************
27  *  mpi_limb_t
28  *  mpihelp_add_n( mpi_ptr_t res_ptr,   (r3)
29  *                 mpi_ptr_t s1_ptr,    (r4)
30  *                 mpi_ptr_t s2_ptr,    (r5)
31  *                 mpi_size_t size)     (r6)
32  */
33
34         .toc
35         .extern mpihelp_add_n[DS]
36         .extern .mpihelp_add_n
37 .csect [PR]
38         .align 2
39         .globl mpihelp_add_n
40         .globl .mpihelp_add_n
41         .csect mpihelp_add_n[DS]
42 mpihelp_add_n:
43         .long .mpihelp_add_n, TOC[tc0], 0
44         .csect [PR]
45 .mpihelp_add_n:
46         mtctr   6               # copy size into CTR
47         lwz     8,0(4)          # load least significant s1 limb
48         lwz     0,0(5)          # load least significant s2 limb
49         addi    3,3,-4          # offset res_ptr, it is updated before used
50         addc    7,0,8           # add least significant limbs, set cy
51         bdz     Lend            # If done, skip loop
52 Loop:   lwzu    8,4(4)          # load s1 limb and update s1_ptr
53         lwzu    0,4(5)          # load s2 limb and update s2_ptr
54         stwu    7,4(3)          # store previous limb in load latency slot
55         adde    7,0,8           # add new limbs with cy, set cy
56         bdnz    Loop            # decrement CTR and loop back
57 Lend:   stw     7,4(3)          # store ultimate result limb
58         li      3,0             # load cy into ...
59         addze   3,3             # ... return value register
60         blr
61
62 #else
63 #include "sysdep.h"
64 #include "asm-syntax.h"
65
66
67 /* mp_limb_t mpn_add_n (mp_ptr res_ptr, mp_srcptr s1_ptr, mp_srcptr s2_ptr,
68                         mp_size_t size)
69    Calculate s1+s2 and put result in res_ptr; return carry, 0 or 1.  */
70
71 /* Note on optimisation: This code is optimal for the 601.  Almost every other
72    possible 2-unrolled inner loop will not be.  Also, watch out for the
73    alignment...  */
74
75 EALIGN(mpihelp_add_n,3,0)
76 /* Set up for loop below.  */
77        mtcrf 0x01,%r6
78        srwi. %r7,%r6,1
79        li    %r10,0
80        mtctr %r7
81        bt    31,2f
82
83 /* Clear the carry.  */
84        addic %r0,%r0,0
85 /* Adjust pointers for loop.  */
86        addi  %r3,%r3,-4
87        addi  %r4,%r4,-4
88        addi  %r5,%r5,-4
89        b     0f
90
91 2:     lwz  %r7,0(%r5)
92        lwz  %r6,0(%r4)
93        addc %r6,%r6,%r7
94        stw  %r6,0(%r3)
95         beq  1f
96
97 /* The loop.  */
98
99 /* Align start of loop to an odd word boundary to guarantee that the
100    last two words can be fetched in one access (for 601).  */
101 0:     lwz  %r9,4(%r4)
102        lwz  %r8,4(%r5)
103        lwzu %r6,8(%r4)
104        lwzu %r7,8(%r5)
105        adde %r8,%r9,%r8
106        stw  %r8,4(%r3)
107        adde %r6,%r6,%r7
108        stwu %r6,8(%r3)
109        bdnz 0b
110 /* Return the carry.  */
111 1:     addze %r3,%r10
112        blr
113 END(mpihelp_add_n)
114 #endif
115