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 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * This file contains bignum implementation code that
29 * is specific to x86, but which is still more appropriate
30 * to write in C, rather than assembly language.
31 * bignum_i386_asm.s does all the assembly language code
32 * for x86 specific bignum support. The assembly language
33 * source file has pure code, no data. Let the C compiler
34 * generate what is needed to handle the variations in
35 * data representation and addressing, for example,
36 * statically linked vs PIC.
37 */
38
39 #include "bignum.h"
40
41 #if defined(_KERNEL)
42 #include <sys/cpuvar.h>
43 #include <sys/disp.h>
44 #endif
45
46 extern uint32_t big_mul_set_vec_sse2(uint32_t *, uint32_t *, int, uint32_t);
47 extern uint32_t big_mul_add_vec_sse2(uint32_t *, uint32_t *, int, uint32_t);
48 extern void big_mul_vec_sse2(uint32_t *, uint32_t *, int, uint32_t *, int);
49 extern void big_sqr_vec_sse2(uint32_t *, uint32_t *, int);
50
51 #if defined(MMX_MANAGE)
52
53 extern uint32_t big_mul_set_vec_sse2_nsv(uint32_t *, uint32_t *, int, uint32_t);
54 extern uint32_t big_mul_add_vec_sse2_nsv(uint32_t *, uint32_t *, int, uint32_t);
55 extern void big_mul_vec_sse2_nsv(uint32_t *, uint32_t *, int, uint32_t *, int);
56 extern void big_sqr_vec_sse2_nsv(uint32_t *, uint32_t *, int);
57
58 #endif
59
60 extern uint32_t big_mul_set_vec_umul(uint32_t *, uint32_t *, int, uint32_t);
61 extern uint32_t big_mul_add_vec_umul(uint32_t *, uint32_t *, int, uint32_t);
62 extern void big_mul_vec_umul(uint32_t *, uint32_t *, int, uint32_t *, int);
63 extern void big_sqr_vec_umul(uint32_t *, uint32_t *, int);
64
65 extern uint32_t bignum_use_sse2();
66
67 static void bignum_i386_init();
68
69 static uint32_t big_mul_set_vec_init(uint32_t *, uint32_t *, int, uint32_t);
70 static uint32_t big_mul_add_vec_init(uint32_t *, uint32_t *, int, uint32_t);
71 static void big_mul_vec_init(uint32_t *, uint32_t *, int, uint32_t *, int);
72 static void big_sqr_vec_init(uint32_t *, uint32_t *, int);
73
74 uint32_t
75 (*big_mul_set_vec_impl)(uint32_t *r, uint32_t *a, int len, uint32_t digit)
76 = &big_mul_set_vec_init;
77
78 uint32_t
79 (*big_mul_add_vec_impl)(uint32_t *r, uint32_t *a, int len, uint32_t digit)
80 = &big_mul_add_vec_init;
81
82 void
83 (*big_mul_vec_impl)(uint32_t *r, uint32_t *a, int alen, uint32_t *b, int blen)
84 = &big_mul_vec_init;
85 void
86 (*big_sqr_vec_impl)(uint32_t *r, uint32_t *a, int alen)
87 = &big_sqr_vec_init;
88
89 static uint32_t
big_mul_set_vec_init(uint32_t * r,uint32_t * a,int len,uint32_t digit)90 big_mul_set_vec_init(uint32_t *r, uint32_t *a, int len, uint32_t digit)
91 {
92 bignum_i386_init();
93 return ((*big_mul_set_vec_impl)(r, a, len, digit));
94 }
95
96 static uint32_t
big_mul_add_vec_init(uint32_t * r,uint32_t * a,int len,uint32_t digit)97 big_mul_add_vec_init(uint32_t *r, uint32_t *a, int len, uint32_t digit)
98 {
99 bignum_i386_init();
100 return ((*big_mul_add_vec_impl)(r, a, len, digit));
101 }
102
103 static void
big_mul_vec_init(uint32_t * r,uint32_t * a,int alen,uint32_t * b,int blen)104 big_mul_vec_init(uint32_t *r, uint32_t *a, int alen, uint32_t *b, int blen)
105 {
106 bignum_i386_init();
107 (*big_mul_vec_impl)(r, a, alen, b, blen);
108 }
109
110 static void
big_sqr_vec_init(uint32_t * r,uint32_t * a,int alen)111 big_sqr_vec_init(uint32_t *r, uint32_t *a, int alen)
112 {
113 bignum_i386_init();
114 (*big_sqr_vec_impl)(r, a, alen);
115 }
116
117 static void
bignum_i386_init()118 bignum_i386_init()
119 {
120 if (bignum_use_sse2() != 0) {
121 big_mul_set_vec_impl = &big_mul_set_vec_sse2;
122 big_mul_add_vec_impl = &big_mul_add_vec_sse2;
123 big_mul_vec_impl = &big_mul_vec_sse2;
124 big_sqr_vec_impl = &big_sqr_vec_sse2;
125 } else {
126 big_mul_set_vec_impl = &big_mul_set_vec_umul;
127 big_mul_add_vec_impl = &big_mul_add_vec_umul;
128 big_mul_vec_impl = &big_mul_vec_umul;
129 big_sqr_vec_impl = &big_sqr_vec_umul;
130 }
131 }
132
133 void
big_mul_vec_umul(uint32_t * r,uint32_t * a,int alen,uint32_t * b,int blen)134 big_mul_vec_umul(uint32_t *r, uint32_t *a, int alen, uint32_t *b, int blen)
135 {
136 int i;
137
138 r[alen] = big_mul_set_vec_umul(r, a, alen, b[0]);
139 for (i = 1; i < blen; ++i)
140 r[alen + i] = big_mul_add_vec_umul(r+i, a, alen, b[i]);
141 }
142
143 void
big_sqr_vec_umul(uint32_t * r,uint32_t * a,int alen)144 big_sqr_vec_umul(uint32_t *r, uint32_t *a, int alen)
145 {
146 int i;
147
148 r[alen] = big_mul_set_vec_umul(r, a, alen, a[0]);
149 for (i = 1; i < alen; ++i)
150 r[alen + i] = big_mul_add_vec_umul(r+i, a, alen, a[i]);
151 }
152
153 #if defined(_KERNEL)
154
155 void
kpr_disable()156 kpr_disable()
157 {
158 kpreempt_disable();
159 }
160
161 void
kpr_enable()162 kpr_enable()
163 {
164 kpreempt_enable();
165 }
166
167 #endif
168