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