Annotation of OpenXM_contrib/gmp/mpn/sparc32/sub_n.asm, Revision 1.1.1.1
1.1 maekawa 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)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>