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