xref: /illumos-gate/usr/src/common/bignum/i386/bignum_i386.c (revision 4283d10e18fc3904736c7c067fb29de9bb67d25d)
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
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
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
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
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
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
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
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
156 kpr_disable()
157 {
158 	kpreempt_disable();
159 }
160 
161 void
162 kpr_enable()
163 {
164 	kpreempt_enable();
165 }
166 
167 #endif
168