1
/* SPARC _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, 1998,
5
* 2001 Free Software Foundation, Inc.
7
* This file is part of GnuPG.
9
* GnuPG is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* GnuPG is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
28
* mpihelp_add_n( mpi_ptr_t res_ptr,
44
.global C_SYMBOL_NAME(mpihelp_add_n)
45
C_SYMBOL_NAME(mpihelp_add_n):
46
xor s2_ptr,res_ptr,%g1
48
bne L1 ! branch if alignment differs
51
L0: andcc res_ptr,4,%g0 ! res_ptr unaligned? Side effect: cy=0
52
be L_v1 ! if no, branch
54
/* Add least significant limb separately to align res_ptr and s2_ptr */
63
L_v1: addx %g0,%g0,%o4 ! save cy in register
64
cmp size,2 ! if size < 2 ...
65
bl Lend2 ! ... branch to tail code
66
subcc %g0,%o4,%g0 ! restore cy
73
subcc %g0,%o4,%g0 ! restore cy
74
/* Add blocks of 8 limbs until less than 8 limbs remain */
75
Loop1: addxcc %g4,%g2,%o4
99
addx %g0,%g0,%o4 ! save cy in register
103
add res_ptr,32,res_ptr
105
subcc %g0,%o4,%g0 ! restore cy
107
Lfin1: addcc size,8-2,size
109
subcc %g0,%o4,%g0 ! restore cy
110
/* Add blocks of 2 limbs until less than 2 limbs remain */
111
Loope1: addxcc %g4,%g2,%o4
117
addx %g0,%g0,%o4 ! save cy in register
121
add res_ptr,8,res_ptr
123
subcc %g0,%o4,%g0 ! restore cy
124
Lend1: addxcc %g4,%g2,%o4
127
addx %g0,%g0,%o4 ! save cy in register
131
subcc %g0,%o4,%g0 ! restore cy
139
addx %g0,%g0,%o0 ! return carry-out from most sign. limb
141
L1: xor s1_ptr,res_ptr,%g1
152
/* If we come here, the alignment of s1_ptr and res_ptr as well as the
153
alignment of s2_ptr and res_ptr differ. Since there are only two ways
154
things can be aligned (that we care about) we now know that the alignment
155
of s1_ptr and s2_ptr are the same. */
160
andcc s1_ptr,4,%g0 ! s1_ptr unaligned? Side effect: cy=0
161
be L_v2 ! if no, branch
163
/* Add least significant limb separately to align s1_ptr and s2_ptr */
171
add res_ptr,4,res_ptr
173
L_v2: addx %g0,%g0,%o4 ! save cy in register
176
subcc %g0,%o4,%g0 ! restore cy
177
/* Add blocks of 8 limbs until less than 8 limbs remain */
178
Loop2: ldd [s1_ptr+0],%g2
202
addx %g0,%g0,%o4 ! save cy in register
206
add res_ptr,32,res_ptr
208
subcc %g0,%o4,%g0 ! restore cy
210
Lfin2: addcc size,8-2,size
212
subcc %g0,%o4,%g0 ! restore cy
213
Loope2: ldd [s1_ptr+0],%g2
219
addx %g0,%g0,%o4 ! save cy in register
223
add res_ptr,8,res_ptr
225
subcc %g0,%o4,%g0 ! restore cy
226
Lend2: andcc size,1,%g0
228
subcc %g0,%o4,%g0 ! restore cy
230
Ljone: ld [s1_ptr],%g4
236
addx %g0,%g0,%o0 ! return carry-out from most sign. limb