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