remove empty dir
[ghc-hetmet.git] / rts / gmp / mpn / sparc32 / sub_n.asm
1 dnl  SPARC mpn_sub_n -- Subtract two limb vectors of the same length > 0 and
2 dnl  store difference in a third limb vector.
3
4 dnl  Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc.
5
6 dnl  This file is part of the GNU MP Library.
7
8 dnl  The GNU MP Library is free software; you can redistribute it and/or modify
9 dnl  it under the terms of the GNU Lesser General Public License as published
10 dnl  by the Free Software Foundation; either version 2.1 of the License, or (at
11 dnl  your option) any later version.
12
13 dnl  The GNU MP Library is distributed in the hope that it will be useful, but
14 dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 dnl  License for more details.
17
18 dnl  You should have received a copy of the GNU Lesser General Public License
19 dnl  along with the GNU MP Library; see the file COPYING.LIB.  If not, write to
20 dnl  the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21 dnl  MA 02111-1307, USA.
22
23
24 include(`../config.m4')
25
26 C INPUT PARAMETERS
27 define(res_ptr,%o0)
28 define(s1_ptr,%o1)
29 define(s2_ptr,%o2)
30 define(n,%o3)
31
32 ASM_START()
33 PROLOGUE(mpn_sub_n)
34         xor     s2_ptr,res_ptr,%g1
35         andcc   %g1,4,%g0
36         bne     L(1)                    C branch if alignment differs
37         nop
38 C **  V1a  **
39         andcc   res_ptr,4,%g0           C res_ptr unaligned? Side effect: cy=0
40         be      L(v1)                   C if no, branch
41         nop
42 C Add least significant limb separately to align res_ptr and s2_ptr
43         ld      [s1_ptr],%g4
44         add     s1_ptr,4,s1_ptr
45         ld      [s2_ptr],%g2
46         add     s2_ptr,4,s2_ptr
47         add     n,-1,n
48         subcc   %g4,%g2,%o4
49         st      %o4,[res_ptr]
50         add     res_ptr,4,res_ptr
51 L(v1):  addx    %g0,%g0,%o4             C save cy in register
52         cmp     n,2                     C if n < 2 ...
53         bl      L(end2)                 C ... branch to tail code
54         subcc   %g0,%o4,%g0             C restore cy
55
56         ld      [s1_ptr+0],%g4
57         addcc   n,-10,n
58         ld      [s1_ptr+4],%g1
59         ldd     [s2_ptr+0],%g2
60         blt     L(fin1)
61         subcc   %g0,%o4,%g0             C restore cy
62 C Add blocks of 8 limbs until less than 8 limbs remain
63 L(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             C save cy in register
89         addcc   n,-8,n
90         add     s1_ptr,32,s1_ptr
91         add     s2_ptr,32,s2_ptr
92         add     res_ptr,32,res_ptr
93         bge     L(loop1)
94         subcc   %g0,%o4,%g0             C restore cy
95
96 L(fin1):
97         addcc   n,8-2,n
98         blt     L(end1)
99         subcc   %g0,%o4,%g0             C restore cy
100 C Add blocks of 2 limbs until less than 2 limbs remain
101 L(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             C save cy in register
109         addcc   n,-2,n
110         add     s1_ptr,8,s1_ptr
111         add     s2_ptr,8,s2_ptr
112         add     res_ptr,8,res_ptr
113         bge     L(loope1)
114         subcc   %g0,%o4,%g0             C restore cy
115 L(end1):
116         subxcc  %g4,%g2,%o4
117         subxcc  %g1,%g3,%o5
118         std     %o4,[res_ptr+0]
119         addx    %g0,%g0,%o4             C save cy in register
120
121         andcc   n,1,%g0
122         be      L(ret1)
123         subcc   %g0,%o4,%g0             C restore cy
124 C 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]
129
130 L(ret1):
131         retl
132         addx    %g0,%g0,%o0     C return carry-out from most sign. limb
133
134 L(1):   xor     s1_ptr,res_ptr,%g1
135         andcc   %g1,4,%g0
136         bne     L(2)
137         nop
138 C **  V1b  **
139         andcc   res_ptr,4,%g0           C res_ptr unaligned? Side effect: cy=0
140         be      L(v1b)                  C if no, branch
141         nop
142 C 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     n,-1,n
148         subcc   %g2,%g4,%o4
149         st      %o4,[res_ptr]
150         add     res_ptr,4,res_ptr
151 L(v1b): addx    %g0,%g0,%o4             C save cy in register
152         cmp     n,2                     C if n < 2 ...
153         bl      L(end2)                 C ... branch to tail code
154         subcc   %g0,%o4,%g0             C restore cy
155
156         ld      [s2_ptr+0],%g4
157         addcc   n,-10,n
158         ld      [s2_ptr+4],%g1
159         ldd     [s1_ptr+0],%g2
160         blt     L(fin1b)
161         subcc   %g0,%o4,%g0             C restore cy
162 C Add blocks of 8 limbs until less than 8 limbs remain
163 L(loop1b):
164         subxcc  %g2,%g4,%o4
165         ld      [s2_ptr+8],%g4
166         subxcc  %g3,%g1,%o5
167         ld      [s2_ptr+12],%g1
168         ldd     [s1_ptr+8],%g2
169         std     %o4,[res_ptr+0]
170         subxcc  %g2,%g4,%o4
171         ld      [s2_ptr+16],%g4
172         subxcc  %g3,%g1,%o5
173         ld      [s2_ptr+20],%g1
174         ldd     [s1_ptr+16],%g2
175         std     %o4,[res_ptr+8]
176         subxcc  %g2,%g4,%o4
177         ld      [s2_ptr+24],%g4
178         subxcc  %g3,%g1,%o5
179         ld      [s2_ptr+28],%g1
180         ldd     [s1_ptr+24],%g2
181         std     %o4,[res_ptr+16]
182         subxcc  %g2,%g4,%o4
183         ld      [s2_ptr+32],%g4
184         subxcc  %g3,%g1,%o5
185         ld      [s2_ptr+36],%g1
186         ldd     [s1_ptr+32],%g2
187         std     %o4,[res_ptr+24]
188         addx    %g0,%g0,%o4             C save cy in register
189         addcc   n,-8,n
190         add     s1_ptr,32,s1_ptr
191         add     s2_ptr,32,s2_ptr
192         add     res_ptr,32,res_ptr
193         bge     L(loop1b)
194         subcc   %g0,%o4,%g0             C restore cy
195
196 L(fin1b):
197         addcc   n,8-2,n
198         blt     L(end1b)
199         subcc   %g0,%o4,%g0             C restore cy
200 C Add blocks of 2 limbs until less than 2 limbs remain
201 L(loope1b):
202         subxcc  %g2,%g4,%o4
203         ld      [s2_ptr+8],%g4
204         subxcc  %g3,%g1,%o5
205         ld      [s2_ptr+12],%g1
206         ldd     [s1_ptr+8],%g2
207         std     %o4,[res_ptr+0]
208         addx    %g0,%g0,%o4             C save cy in register
209         addcc   n,-2,n
210         add     s1_ptr,8,s1_ptr
211         add     s2_ptr,8,s2_ptr
212         add     res_ptr,8,res_ptr
213         bge     L(loope1b)
214         subcc   %g0,%o4,%g0             C restore cy
215 L(end1b):
216         subxcc  %g2,%g4,%o4
217         subxcc  %g3,%g1,%o5
218         std     %o4,[res_ptr+0]
219         addx    %g0,%g0,%o4             C save cy in register
220
221         andcc   n,1,%g0
222         be      L(ret1b)
223         subcc   %g0,%o4,%g0             C restore cy
224 C Add last limb
225         ld      [s2_ptr+8],%g4
226         ld      [s1_ptr+8],%g2
227         subxcc  %g2,%g4,%o4
228         st      %o4,[res_ptr+8]
229
230 L(ret1b):
231         retl
232         addx    %g0,%g0,%o0             C return carry-out from most sign. limb
233
234 C **  V2  **
235 C If we come here, the alignment of s1_ptr and res_ptr as well as the
236 C alignment of s2_ptr and res_ptr differ.  Since there are only two ways
237 C things can be aligned (that we care about) we now know that the alignment
238 C of s1_ptr and s2_ptr are the same.
239
240 L(2):   cmp     n,1
241         be      L(jone)
242         nop
243         andcc   s1_ptr,4,%g0            C s1_ptr unaligned? Side effect: cy=0
244         be      L(v2)                   C if no, branch
245         nop
246 C Add least significant limb separately to align s1_ptr and s2_ptr
247         ld      [s1_ptr],%g4
248         add     s1_ptr,4,s1_ptr
249         ld      [s2_ptr],%g2
250         add     s2_ptr,4,s2_ptr
251         add     n,-1,n
252         subcc   %g4,%g2,%o4
253         st      %o4,[res_ptr]
254         add     res_ptr,4,res_ptr
255
256 L(v2):  addx    %g0,%g0,%o4             C save cy in register
257         addcc   n,-8,n
258         blt     L(fin2)
259         subcc   %g0,%o4,%g0             C restore cy
260 C Add blocks of 8 limbs until less than 8 limbs remain
261 L(loop2):
262         ldd     [s1_ptr+0],%g2
263         ldd     [s2_ptr+0],%o4
264         subxcc  %g2,%o4,%g2
265         st      %g2,[res_ptr+0]
266         subxcc  %g3,%o5,%g3
267         st      %g3,[res_ptr+4]
268         ldd     [s1_ptr+8],%g2
269         ldd     [s2_ptr+8],%o4
270         subxcc  %g2,%o4,%g2
271         st      %g2,[res_ptr+8]
272         subxcc  %g3,%o5,%g3
273         st      %g3,[res_ptr+12]
274         ldd     [s1_ptr+16],%g2
275         ldd     [s2_ptr+16],%o4
276         subxcc  %g2,%o4,%g2
277         st      %g2,[res_ptr+16]
278         subxcc  %g3,%o5,%g3
279         st      %g3,[res_ptr+20]
280         ldd     [s1_ptr+24],%g2
281         ldd     [s2_ptr+24],%o4
282         subxcc  %g2,%o4,%g2
283         st      %g2,[res_ptr+24]
284         subxcc  %g3,%o5,%g3
285         st      %g3,[res_ptr+28]
286         addx    %g0,%g0,%o4             C save cy in register
287         addcc   n,-8,n
288         add     s1_ptr,32,s1_ptr
289         add     s2_ptr,32,s2_ptr
290         add     res_ptr,32,res_ptr
291         bge     L(loop2)
292         subcc   %g0,%o4,%g0             C restore cy
293
294 L(fin2):
295         addcc   n,8-2,n
296         blt     L(end2)
297         subcc   %g0,%o4,%g0             C restore cy
298 L(loope2):
299         ldd     [s1_ptr+0],%g2
300         ldd     [s2_ptr+0],%o4
301         subxcc  %g2,%o4,%g2
302         st      %g2,[res_ptr+0]
303         subxcc  %g3,%o5,%g3
304         st      %g3,[res_ptr+4]
305         addx    %g0,%g0,%o4             C save cy in register
306         addcc   n,-2,n
307         add     s1_ptr,8,s1_ptr
308         add     s2_ptr,8,s2_ptr
309         add     res_ptr,8,res_ptr
310         bge     L(loope2)
311         subcc   %g0,%o4,%g0             C restore cy
312 L(end2):
313         andcc   n,1,%g0
314         be      L(ret2)
315         subcc   %g0,%o4,%g0             C restore cy
316 C Add last limb
317 L(jone):
318         ld      [s1_ptr],%g4
319         ld      [s2_ptr],%g2
320         subxcc  %g4,%g2,%o4
321         st      %o4,[res_ptr]
322
323 L(ret2):
324         retl
325         addx    %g0,%g0,%o0             C return carry-out from most sign. limb
326 EPILOGUE(mpn_sub_n)