1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 /*
30 * This file contains bignum implementation code that
31 * is specific to AMD64, but which is still more appropriate
32 * to write in C, rather than assembly language.
33 * bignum_amd64_asm.s does all the assembly language code
34 * for AMD64 specific bignum support. The assembly language
35 * source file has pure code, no data. Let the C compiler
36 * generate what is needed to handle the variations in
37 * data representation and addressing, for example,
38 * statically linked vs PIC.
39 */
40
41 #include "bignum.h"
42
43 /*
44 * The bignum interface deals only with arrays of 32-bit "digits".
45 * The 64-bit bignum functions are internal implementation details.
46 * If a bignum happens to be aligned on a 64-bit boundary
47 * and its length is even, then the pure 64-bit implementation
48 * can be used.
49 */
50
51 #define ISALIGNED64(p) (((uintptr_t)(p) & 7) == 0)
52 #define ISBIGNUM64(p, len) (ISALIGNED64(p) && (((len) & 1) == 0))
53
54 #if defined(__lint)
55
56 extern uint64_t *P64(uint32_t *addr);
57
58 #else /* lint */
59
60 #define P64(addr) ((uint64_t *)addr)
61
62 #endif /* lint */
63
64 extern uint64_t big_mul_set_vec64(uint64_t *, uint64_t *, int, uint64_t);
65 extern uint64_t big_mul_add_vec64(uint64_t *, uint64_t *, int, uint64_t);
66 extern void big_mul_vec64(uint64_t *, uint64_t *, int, uint64_t *, int);
67 extern void big_sqr_vec64(uint64_t *, uint64_t *, int);
68
69 extern uint32_t big_mul_set_vec32(uint32_t *, uint32_t *, int, uint32_t);
70 extern uint32_t big_mul_add_vec32(uint32_t *, uint32_t *, int, uint32_t);
71 extern void big_mul_vec32(uint32_t *, uint32_t *, int, uint32_t *, int);
72 extern void big_sqr_vec32(uint32_t *, uint32_t *, int);
73
74 uint32_t big_mul_set_vec(uint32_t *, uint32_t *, int, uint32_t);
75 uint32_t big_mul_add_vec(uint32_t *, uint32_t *, int, uint32_t);
76 void big_mul_vec(uint32_t *, uint32_t *, int, uint32_t *, int);
77 void big_sqr_vec(uint32_t *, uint32_t *, int);
78
79
80 void
81 big_mul_vec(uint32_t *r, uint32_t *a, int alen, uint32_t *b, int blen)
82 {
83 if (!ISALIGNED64(r) || !ISBIGNUM64(a, alen) || !ISBIGNUM64(b, blen)) {
84 big_mul_vec32(r, a, alen, b, blen);
85 return;
86 }
87
88 big_mul_vec64(P64(r), P64(a), alen / 2, P64(b), blen / 2);
89 }
90
91 void
92 big_sqr_vec(uint32_t *r, uint32_t *a, int alen)
93 {
94 if (!ISALIGNED64(r) || !ISBIGNUM64(a, alen)) {
95 big_mul_vec32(r, a, alen, a, alen);
96 return;
97 }
98 big_sqr_vec64(P64(r), P64(a), alen / 2);
99 }
100
101 /*
102 * It is OK to cast the 64-bit carry to 32 bit.
103 * There will be no loss, because although we are multiplying the vector, a,
104 * by a uint64_t, its value cannot exceedthat of a uint32_t.
105 */
106
107 uint32_t
108 big_mul_set_vec(uint32_t *r, uint32_t *a, int alen, uint32_t digit)
109 {
110 if (!ISALIGNED64(r) || !ISBIGNUM64(a, alen))
111 return (big_mul_set_vec32(r, a, alen, digit));
112
113 return (big_mul_set_vec64(P64(r), P64(a), alen / 2, digit));
114 }
115 uint32_t
116 big_mul_add_vec(uint32_t *r, uint32_t *a, int alen, uint32_t digit)
117 {
118 if (!ISALIGNED64(r) || !ISBIGNUM64(a, alen))
119 return (big_mul_add_vec32(r, a, alen, digit));
120
121 return (big_mul_add_vec64(P64(r), P64(a), alen / 2, digit));
122 }
123
124
125 void
126 big_mul_vec64(uint64_t *r, uint64_t *a, int alen, uint64_t *b, int blen)
127 {
128 int i;
129
130 r[alen] = big_mul_set_vec64(r, a, alen, b[0]);
131 for (i = 1; i < blen; ++i)
132 r[alen + i] = big_mul_add_vec64(r+i, a, alen, b[i]);
133 }
134
135 void
136 big_mul_vec32(uint32_t *r, uint32_t *a, int alen, uint32_t *b, int blen)
137 {
138 int i;
139
140 r[alen] = big_mul_set_vec32(r, a, alen, b[0]);
141 for (i = 1; i < blen; ++i)
142 r[alen + i] = big_mul_add_vec32(r+i, a, alen, b[i]);
143 }
144
145 void
146 big_sqr_vec32(uint32_t *r, uint32_t *a, int alen)
147 {
148 big_mul_vec32(r, a, alen, a, alen);
149 }
150
151
152 uint32_t
153 big_mul_set_vec32(uint32_t *r, uint32_t *a, int alen, uint32_t digit)
154 {
155 uint64_t p, d, cy;
156
157 d = (uint64_t)digit;
158 cy = 0;
159 while (alen != 0) {
160 p = (uint64_t)a[0] * d + cy;
161 r[0] = (uint32_t)p;
162 cy = p >> 32;
163 ++r;
164 ++a;
165 --alen;
166 }
167 return ((uint32_t)cy);
168 }
169
170 uint32_t
171 big_mul_add_vec32(uint32_t *r, uint32_t *a, int alen, uint32_t digit)
172 {
173 uint64_t p, d, cy;
174
175 d = (uint64_t)digit;
176 cy = 0;
177 while (alen != 0) {
178 p = r[0] + (uint64_t)a[0] * d + cy;
179 r[0] = (uint32_t)p;
180 cy = p >> 32;
181 ++r;
182 ++a;
183 --alen;
184 }
185 return ((uint32_t)cy);
186 }
|
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * This file contains bignum implementation code that
28 * is specific to AMD64, but which is still more appropriate
29 * to write in C, rather than assembly language.
30 * bignum_amd64_asm.s does all the assembly language code
31 * for AMD64 specific bignum support. The assembly language
32 * source file has pure code, no data. Let the C compiler
33 * generate what is needed to handle the variations in
34 * data representation and addressing, for example,
35 * statically linked vs PIC.
36 */
37
38 #include "bignum.h"
39
40 /*
41 * The bignum interface deals with arrays of 64-bit "chunks" or "digits".
42 * Data should be aligned on 8-byte address boundaries for best performance.
43 */
44
45
46 void
47 big_mul_vec(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a, int alen,
48 BIG_CHUNK_TYPE *b, int blen)
49 {
50 int i;
51
52 r[alen] = big_mul_set_vec(r, a, alen, b[0]);
53 for (i = 1; i < blen; ++i)
54 r[alen + i] = big_mul_add_vec(r + i, a, alen, b[i]);
55 }
|