.
[glibc/pb-stable.git] / sysdeps / sparc / sparc32 / sub_n.S
blob941efe1a27b01eb48e88416371bd188c80a6b930
1 ! SPARC __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
2 ! store difference in a third limb vector.
4 ! Copyright (C) 1995, 1996 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_sub_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         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         subcc   %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         subxcc  %g4,%g2,%o4
65         ld      [S1_PTR+8],%g4
66         subxcc  %g1,%g3,%o5
67         ld      [S1_PTR+12],%g1
68         ldd     [S2_PTR+8],%g2
69         std     %o4,[RES_PTR+0]
70         subxcc  %g4,%g2,%o4
71         ld      [S1_PTR+16],%g4
72         subxcc  %g1,%g3,%o5
73         ld      [S1_PTR+20],%g1
74         ldd     [S2_PTR+16],%g2
75         std     %o4,[RES_PTR+8]
76         subxcc  %g4,%g2,%o4
77         ld      [S1_PTR+24],%g4
78         subxcc  %g1,%g3,%o5
79         ld      [S1_PTR+28],%g1
80         ldd     [S2_PTR+24],%g2
81         std     %o4,[RES_PTR+16]
82         subxcc  %g4,%g2,%o4
83         ld      [S1_PTR+32],%g4
84         subxcc  %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         subxcc  %g4,%g2,%o4
103         ld      [S1_PTR+8],%g4
104         subxcc  %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         subxcc  %g4,%g2,%o4
117         subxcc  %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         subxcc  %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         andcc   RES_PTR,4,%g0           ! RES_PTR unaligned? Side effect: cy=0
140         be      LOC(v1b)                ! if no, branch
141         nop
142 /* Add least significant limb separately to align RES_PTR and S1_PTR */
143         ld      [S2_PTR],%g4
144         add     S2_PTR,4,S2_PTR
145         ld      [S1_PTR],%g2
146         add     S1_PTR,4,S1_PTR
147         add     SIZE,-1,SIZE
148         subcc   %g2,%g4,%o4
149         st      %o4,[RES_PTR]
150         add     RES_PTR,4,RES_PTR
151 LOC(v1b):
152         addx    %g0,%g0,%o4             ! save cy in register
153         cmp     SIZE,2                  ! if SIZE < 2 ...
154         bl      LOC(end2)               ! ... branch to tail code
155         subcc   %g0,%o4,%g0             ! restore cy
157         ld      [S2_PTR+0],%g4
158         addcc   SIZE,-10,SIZE
159         ld      [S2_PTR+4],%g1
160         ldd     [S1_PTR+0],%g2
161         blt     LOC(fin1b)
162         subcc   %g0,%o4,%g0             ! restore cy
163 /* Add blocks of 8 limbs until less than 8 limbs remain */
164 LOC(loop1b):
165         subxcc  %g2,%g4,%o4
166         ld      [S2_PTR+8],%g4
167         subxcc  %g3,%g1,%o5
168         ld      [S2_PTR+12],%g1
169         ldd     [S1_PTR+8],%g2
170         std     %o4,[RES_PTR+0]
171         subxcc  %g2,%g4,%o4
172         ld      [S2_PTR+16],%g4
173         subxcc  %g3,%g1,%o5
174         ld      [S2_PTR+20],%g1
175         ldd     [S1_PTR+16],%g2
176         std     %o4,[RES_PTR+8]
177         subxcc  %g2,%g4,%o4
178         ld      [S2_PTR+24],%g4
179         subxcc  %g3,%g1,%o5
180         ld      [S2_PTR+28],%g1
181         ldd     [S1_PTR+24],%g2
182         std     %o4,[RES_PTR+16]
183         subxcc  %g2,%g4,%o4
184         ld      [S2_PTR+32],%g4
185         subxcc  %g3,%g1,%o5
186         ld      [S2_PTR+36],%g1
187         ldd     [S1_PTR+32],%g2
188         std     %o4,[RES_PTR+24]
189         addx    %g0,%g0,%o4             ! save cy in register
190         addcc   SIZE,-8,SIZE
191         add     S1_PTR,32,S1_PTR
192         add     S2_PTR,32,S2_PTR
193         add     RES_PTR,32,RES_PTR
194         bge     LOC(loop1b)
195         subcc   %g0,%o4,%g0             ! restore cy
197 LOC(fin1b):
198         addcc   SIZE,8-2,SIZE
199         blt     LOC(end1b)
200         subcc   %g0,%o4,%g0             ! restore cy
201 /* Add blocks of 2 limbs until less than 2 limbs remain */
202 LOC(loope1b):
203         subxcc  %g2,%g4,%o4
204         ld      [S2_PTR+8],%g4
205         subxcc  %g3,%g1,%o5
206         ld      [S2_PTR+12],%g1
207         ldd     [S1_PTR+8],%g2
208         std     %o4,[RES_PTR+0]
209         addx    %g0,%g0,%o4             ! save cy in register
210         addcc   SIZE,-2,SIZE
211         add     S1_PTR,8,S1_PTR
212         add     S2_PTR,8,S2_PTR
213         add     RES_PTR,8,RES_PTR
214         bge     LOC(loope1b)
215         subcc   %g0,%o4,%g0             ! restore cy
216 LOC(end1b):
217         subxcc  %g2,%g4,%o4
218         subxcc  %g3,%g1,%o5
219         std     %o4,[RES_PTR+0]
220         addx    %g0,%g0,%o4             ! save cy in register
222         andcc   SIZE,1,%g0
223         be      LOC(ret1b)
224         subcc   %g0,%o4,%g0             ! restore cy
225 /* Add last limb */
226         ld      [S2_PTR+8],%g4
227         ld      [S1_PTR+8],%g2
228         subxcc  %g2,%g4,%o4
229         st      %o4,[RES_PTR+8]
231 LOC(ret1b):
232         retl
233         addx    %g0,%g0,%o0     ! return carry-out from most sign. limb
235 ! **  V2  **
236 /* If we come here, the alignment of S1_PTR and RES_PTR as well as the
237    alignment of S2_PTR and RES_PTR differ.  Since there are only two ways
238    things can be aligned (that we care about) we now know that the alignment
239    of S1_PTR and S2_PTR are the same.  */
241 LOC(2): cmp     SIZE,1
242         be      LOC(jone)
243         nop
244         andcc   S1_PTR,4,%g0            ! S1_PTR unaligned? Side effect: cy=0
245         be      LOC(v2)                 ! if no, branch
246         nop
247 /* Add least significant limb separately to align S1_PTR and S2_PTR */
248         ld      [S1_PTR],%g4
249         add     S1_PTR,4,S1_PTR
250         ld      [S2_PTR],%g2
251         add     S2_PTR,4,S2_PTR
252         add     SIZE,-1,SIZE
253         subcc   %g4,%g2,%o4
254         st      %o4,[RES_PTR]
255         add     RES_PTR,4,RES_PTR
257 LOC(v2):
258         addx    %g0,%g0,%o4             ! save cy in register
259         addcc   SIZE,-8,SIZE
260         blt     LOC(fin2)
261         subcc   %g0,%o4,%g0             ! restore cy
262 /* Add blocks of 8 limbs until less than 8 limbs remain */
263 LOC(loop2):
264         ldd     [S1_PTR+0],%g2
265         ldd     [S2_PTR+0],%o4
266         subxcc  %g2,%o4,%g2
267         st      %g2,[RES_PTR+0]
268         subxcc  %g3,%o5,%g3
269         st      %g3,[RES_PTR+4]
270         ldd     [S1_PTR+8],%g2
271         ldd     [S2_PTR+8],%o4
272         subxcc  %g2,%o4,%g2
273         st      %g2,[RES_PTR+8]
274         subxcc  %g3,%o5,%g3
275         st      %g3,[RES_PTR+12]
276         ldd     [S1_PTR+16],%g2
277         ldd     [S2_PTR+16],%o4
278         subxcc  %g2,%o4,%g2
279         st      %g2,[RES_PTR+16]
280         subxcc  %g3,%o5,%g3
281         st      %g3,[RES_PTR+20]
282         ldd     [S1_PTR+24],%g2
283         ldd     [S2_PTR+24],%o4
284         subxcc  %g2,%o4,%g2
285         st      %g2,[RES_PTR+24]
286         subxcc  %g3,%o5,%g3
287         st      %g3,[RES_PTR+28]
288         addx    %g0,%g0,%o4             ! save cy in register
289         addcc   SIZE,-8,SIZE
290         add     S1_PTR,32,S1_PTR
291         add     S2_PTR,32,S2_PTR
292         add     RES_PTR,32,RES_PTR
293         bge     LOC(loop2)
294         subcc   %g0,%o4,%g0             ! restore cy
296 LOC(fin2):
297         addcc   SIZE,8-2,SIZE
298         blt     LOC(end2)
299         subcc   %g0,%o4,%g0             ! restore cy
300 LOC(loope2):
301         ldd     [S1_PTR+0],%g2
302         ldd     [S2_PTR+0],%o4
303         subxcc  %g2,%o4,%g2
304         st      %g2,[RES_PTR+0]
305         subxcc  %g3,%o5,%g3
306         st      %g3,[RES_PTR+4]
307         addx    %g0,%g0,%o4             ! save cy in register
308         addcc   SIZE,-2,SIZE
309         add     S1_PTR,8,S1_PTR
310         add     S2_PTR,8,S2_PTR
311         add     RES_PTR,8,RES_PTR
312         bge     LOC(loope2)
313         subcc   %g0,%o4,%g0             ! restore cy
314 LOC(end2):
315         andcc   SIZE,1,%g0
316         be      LOC(ret2)
317         subcc   %g0,%o4,%g0             ! restore cy
318 /* Add last limb */
319 LOC(jone):
320         ld      [S1_PTR],%g4
321         ld      [S2_PTR],%g2
322         subxcc  %g4,%g2,%o4
323         st      %o4,[RES_PTR]
325 LOC(ret2):
326         retl
327         addx    %g0,%g0,%o0     ! return carry-out from most sign. limb
329 END(__mpn_sub_n)