.
[glibc/pb-stable.git] / sysdeps / sparc / sparc32 / add_n.S
blob0db7c650bbf58f07c82f9ead5e990a207d651cd9
1 ! SPARC __mpn_add_n -- Add two limb vectors of the same length > 0 and store
2 ! sum in a third limb vector.
4 ! Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
6 ! This file is part of the GNU MP Library.
8 ! The GNU MP Library is free software; you can redistribute it and/or modify
9 ! it under the terms of the GNU Lesser General Public License as published by
10 ! the Free Software Foundation; either version 2.1 of the License, or (at your
11 ! option) any later version.
13 ! The GNU MP Library is distributed in the hope that it will be useful, but
14 ! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 ! or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 ! License for more details.
18 ! You should have received a copy of the GNU Lesser General Public License
19 ! along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
20 ! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21 ! MA 02111-1307, USA.
24 ! INPUT PARAMETERS
25 #define RES_PTR %o0
26 #define S1_PTR  %o1
27 #define S2_PTR  %o2
28 #define SIZE    %o3
30 #include <sysdep.h>
32 ENTRY(__mpn_add_n)
33         xor     S2_PTR,RES_PTR,%g1
34         andcc   %g1,4,%g0
35         bne     LOC(1)                  ! branch if alignment differs
36          nop
37 ! **  V1a  **
38 LOC(0): andcc   RES_PTR,4,%g0           ! RES_PTR unaligned? Side effect: cy=0
39         be      LOC(v1)                 ! if no, branch
40          nop
41 /* Add least significant limb separately to align RES_PTR and S2_PTR */
42         ld      [S1_PTR],%g4
43         add     S1_PTR,4,S1_PTR
44         ld      [S2_PTR],%g2
45         add     S2_PTR,4,S2_PTR
46         add     SIZE,-1,SIZE
47         addcc   %g4,%g2,%o4
48         st      %o4,[RES_PTR]
49         add     RES_PTR,4,RES_PTR
50 LOC(v1):
51         addx    %g0,%g0,%o4             ! save cy in register
52         cmp     SIZE,2                  ! if SIZE < 2 ...
53         bl      LOC(end2)               ! ... branch to tail code
54         subcc   %g0,%o4,%g0             ! restore cy
56         ld      [S1_PTR+0],%g4
57         addcc   SIZE,-10,SIZE
58         ld      [S1_PTR+4],%g1
59         ldd     [S2_PTR+0],%g2
60         blt     LOC(fin1)
61         subcc   %g0,%o4,%g0             ! restore cy
62 /* Add blocks of 8 limbs until less than 8 limbs remain */
63 LOC(loop1):
64         addxcc  %g4,%g2,%o4
65         ld      [S1_PTR+8],%g4
66         addxcc  %g1,%g3,%o5
67         ld      [S1_PTR+12],%g1
68         ldd     [S2_PTR+8],%g2
69         std     %o4,[RES_PTR+0]
70         addxcc  %g4,%g2,%o4
71         ld      [S1_PTR+16],%g4
72         addxcc  %g1,%g3,%o5
73         ld      [S1_PTR+20],%g1
74         ldd     [S2_PTR+16],%g2
75         std     %o4,[RES_PTR+8]
76         addxcc  %g4,%g2,%o4
77         ld      [S1_PTR+24],%g4
78         addxcc  %g1,%g3,%o5
79         ld      [S1_PTR+28],%g1
80         ldd     [S2_PTR+24],%g2
81         std     %o4,[RES_PTR+16]
82         addxcc  %g4,%g2,%o4
83         ld      [S1_PTR+32],%g4
84         addxcc  %g1,%g3,%o5
85         ld      [S1_PTR+36],%g1
86         ldd     [S2_PTR+32],%g2
87         std     %o4,[RES_PTR+24]
88         addx    %g0,%g0,%o4             ! save cy in register
89         addcc   SIZE,-8,SIZE
90         add     S1_PTR,32,S1_PTR
91         add     S2_PTR,32,S2_PTR
92         add     RES_PTR,32,RES_PTR
93         bge     LOC(loop1)
94         subcc   %g0,%o4,%g0             ! restore cy
96 LOC(fin1):
97         addcc   SIZE,8-2,SIZE
98         blt     LOC(end1)
99         subcc   %g0,%o4,%g0             ! restore cy
100 /* Add blocks of 2 limbs until less than 2 limbs remain */
101 LOC(loope1):
102         addxcc  %g4,%g2,%o4
103         ld      [S1_PTR+8],%g4
104         addxcc  %g1,%g3,%o5
105         ld      [S1_PTR+12],%g1
106         ldd     [S2_PTR+8],%g2
107         std     %o4,[RES_PTR+0]
108         addx    %g0,%g0,%o4             ! save cy in register
109         addcc   SIZE,-2,SIZE
110         add     S1_PTR,8,S1_PTR
111         add     S2_PTR,8,S2_PTR
112         add     RES_PTR,8,RES_PTR
113         bge     LOC(loope1)
114         subcc   %g0,%o4,%g0             ! restore cy
115 LOC(end1):
116         addxcc  %g4,%g2,%o4
117         addxcc  %g1,%g3,%o5
118         std     %o4,[RES_PTR+0]
119         addx    %g0,%g0,%o4             ! save cy in register
121         andcc   SIZE,1,%g0
122         be      LOC(ret1)
123         subcc   %g0,%o4,%g0             ! restore cy
124 /* Add last limb */
125         ld      [S1_PTR+8],%g4
126         ld      [S2_PTR+8],%g2
127         addxcc  %g4,%g2,%o4
128         st      %o4,[RES_PTR+8]
130 LOC(ret1):
131         retl
132         addx    %g0,%g0,%o0     ! return carry-out from most sign. limb
134 LOC(1): xor     S1_PTR,RES_PTR,%g1
135         andcc   %g1,4,%g0
136         bne     LOC(2)
137         nop
138 ! **  V1b  **
139         mov     S2_PTR,%g1
140         mov     S1_PTR,S2_PTR
141         b       LOC(0)
142         mov     %g1,S1_PTR
144 ! **  V2  **
145 /* If we come here, the alignment of S1_PTR and RES_PTR as well as the
146    alignment of S2_PTR and RES_PTR differ.  Since there are only two ways
147    things can be aligned (that we care about) we now know that the alignment
148    of S1_PTR and S2_PTR are the same.  */
150 LOC(2): cmp     SIZE,1
151         be      LOC(jone)
152         nop
153         andcc   S1_PTR,4,%g0            ! S1_PTR unaligned? Side effect: cy=0
154         be      LOC(v2)                 ! if no, branch
155         nop
156 /* Add least significant limb separately to align S1_PTR and S2_PTR */
157         ld      [S1_PTR],%g4
158         add     S1_PTR,4,S1_PTR
159         ld      [S2_PTR],%g2
160         add     S2_PTR,4,S2_PTR
161         add     SIZE,-1,SIZE
162         addcc   %g4,%g2,%o4
163         st      %o4,[RES_PTR]
164         add     RES_PTR,4,RES_PTR
166 LOC(v2):
167         addx    %g0,%g0,%o4             ! save cy in register
168         addcc   SIZE,-8,SIZE
169         blt     LOC(fin2)
170         subcc   %g0,%o4,%g0             ! restore cy
171 /* Add blocks of 8 limbs until less than 8 limbs remain */
172 LOC(loop2):
173         ldd     [S1_PTR+0],%g2
174         ldd     [S2_PTR+0],%o4
175         addxcc  %g2,%o4,%g2
176         st      %g2,[RES_PTR+0]
177         addxcc  %g3,%o5,%g3
178         st      %g3,[RES_PTR+4]
179         ldd     [S1_PTR+8],%g2
180         ldd     [S2_PTR+8],%o4
181         addxcc  %g2,%o4,%g2
182         st      %g2,[RES_PTR+8]
183         addxcc  %g3,%o5,%g3
184         st      %g3,[RES_PTR+12]
185         ldd     [S1_PTR+16],%g2
186         ldd     [S2_PTR+16],%o4
187         addxcc  %g2,%o4,%g2
188         st      %g2,[RES_PTR+16]
189         addxcc  %g3,%o5,%g3
190         st      %g3,[RES_PTR+20]
191         ldd     [S1_PTR+24],%g2
192         ldd     [S2_PTR+24],%o4
193         addxcc  %g2,%o4,%g2
194         st      %g2,[RES_PTR+24]
195         addxcc  %g3,%o5,%g3
196         st      %g3,[RES_PTR+28]
197         addx    %g0,%g0,%o4             ! save cy in register
198         addcc   SIZE,-8,SIZE
199         add     S1_PTR,32,S1_PTR
200         add     S2_PTR,32,S2_PTR
201         add     RES_PTR,32,RES_PTR
202         bge     LOC(loop2)
203         subcc   %g0,%o4,%g0             ! restore cy
205 LOC(fin2):
206         addcc   SIZE,8-2,SIZE
207         blt     LOC(end2)
208         subcc   %g0,%o4,%g0             ! restore cy
209 LOC(loope2):
210         ldd     [S1_PTR+0],%g2
211         ldd     [S2_PTR+0],%o4
212         addxcc  %g2,%o4,%g2
213         st      %g2,[RES_PTR+0]
214         addxcc  %g3,%o5,%g3
215         st      %g3,[RES_PTR+4]
216         addx    %g0,%g0,%o4             ! save cy in register
217         addcc   SIZE,-2,SIZE
218         add     S1_PTR,8,S1_PTR
219         add     S2_PTR,8,S2_PTR
220         add     RES_PTR,8,RES_PTR
221         bge     LOC(loope2)
222         subcc   %g0,%o4,%g0             ! restore cy
223 LOC(end2):
224         andcc   SIZE,1,%g0
225         be      LOC(ret2)
226         subcc   %g0,%o4,%g0             ! restore cy
227 /* Add last limb */
228 LOC(jone):
229         ld      [S1_PTR],%g4
230         ld      [S2_PTR],%g2
231         addxcc  %g4,%g2,%o4
232         st      %o4,[RES_PTR]
234 LOC(ret2):
235         retl
236         addx    %g0,%g0,%o0     ! return carry-out from most sign. limb
238 END(__mpn_add_n)