mpi_sparc.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:8k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation. Portions created by Netscape are 
  16.  * Copyright (C) 2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above. If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  *  $Id: mpi_sparc.c,v 1.2.2.1 2000/11/29 01:45:46 nelsonb%netscape.com Exp $
  33.  */
  34. /* Multiplication performance enhancements for sparc v8+vis CPUs. */
  35. #include "mpi-priv.h"
  36. #include <stddef.h>
  37. #include <sys/systeminfo.h>
  38. #include <strings.h>
  39. /* In the functions below, */
  40. /* vector y must be 8-byte aligned, and n must be even */
  41. /* returns carry out of high order word of result */
  42. /* maximum n is 256 */
  43. /* vector x += vector y * scaler a; where y is of length n words. */
  44. extern mp_digit mul_add_inp(mp_digit *x, const mp_digit *y, int n, mp_digit a);
  45. /* vector z = vector x + vector y * scaler a; where y is of length n words. */
  46. extern mp_digit mul_add(mp_digit *z, const mp_digit *x, const mp_digit *y, 
  47. int n, mp_digit a);
  48. /* v8 versions of these functions run on any Sparc v8 CPU. */
  49. /* This trick works on Sparc V8 CPUs with the Workshop compilers. */
  50. #define MP_MUL_DxD(a, b, Phi, Plo) 
  51.   { unsigned long long product = (unsigned long long)a * b; 
  52.     Plo = (mp_digit)product; 
  53.     Phi = (mp_digit)(product >> MP_DIGIT_BIT); }
  54. /* c = a * b */
  55. static void 
  56. v8_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  57. {
  58. #if !defined(MP_NO_MP_WORD)
  59.   mp_digit   d = 0;
  60.   /* Inner product:  Digits of a */
  61.   while (a_len--) {
  62.     mp_word w = ((mp_word)b * *a++) + d;
  63.     *c++ = ACCUM(w);
  64.     d = CARRYOUT(w);
  65.   }
  66.   *c = d;
  67. #else
  68.   mp_digit carry = 0;
  69.   while (a_len--) {
  70.     mp_digit a_i = *a++;
  71.     mp_digit a0b0, a1b1;
  72.     MP_MUL_DxD(a_i, b, a1b1, a0b0);
  73.     a0b0 += carry;
  74.     if (a0b0 < carry)
  75.       ++a1b1;
  76.     *c++ = a0b0;
  77.     carry = a1b1;
  78.   }
  79.   *c = carry;
  80. #endif
  81. }
  82. /* c += a * b */
  83. static void 
  84. v8_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  85. {
  86. #if !defined(MP_NO_MP_WORD)
  87.   mp_digit   d = 0;
  88.   /* Inner product:  Digits of a */
  89.   while (a_len--) {
  90.     mp_word w = ((mp_word)b * *a++) + *c + d;
  91.     *c++ = ACCUM(w);
  92.     d = CARRYOUT(w);
  93.   }
  94.   *c = d;
  95. #else
  96.   mp_digit carry = 0;
  97.   while (a_len--) {
  98.     mp_digit a_i = *a++;
  99.     mp_digit a0b0, a1b1;
  100.     MP_MUL_DxD(a_i, b, a1b1, a0b0);
  101.     a0b0 += carry;
  102.     if (a0b0 < carry)
  103.       ++a1b1;
  104.     a0b0 += a_i = *c;
  105.     if (a0b0 < a_i)
  106.       ++a1b1;
  107.     *c++ = a0b0;
  108.     carry = a1b1;
  109.   }
  110.   *c = carry;
  111. #endif
  112. }
  113. /* Presently, this is only used by the Montgomery arithmetic code. */
  114. /* c += a * b */
  115. static void 
  116. v8_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  117. {
  118. #if !defined(MP_NO_MP_WORD)
  119.   mp_digit   d = 0;
  120.   /* Inner product:  Digits of a */
  121.   while (a_len--) {
  122.     mp_word w = ((mp_word)b * *a++) + *c + d;
  123.     *c++ = ACCUM(w);
  124.     d = CARRYOUT(w);
  125.   }
  126.   while (d) {
  127.     mp_word w = (mp_word)*c + d;
  128.     *c++ = ACCUM(w);
  129.     d = CARRYOUT(w);
  130.   }
  131. #else
  132.   mp_digit carry = 0;
  133.   while (a_len--) {
  134.     mp_digit a_i = *a++;
  135.     mp_digit a0b0, a1b1;
  136.     MP_MUL_DxD(a_i, b, a1b1, a0b0);
  137.     a0b0 += carry;
  138.     if (a0b0 < carry)
  139.       ++a1b1;
  140.     a0b0 += a_i = *c;
  141.     if (a0b0 < a_i)
  142.       ++a1b1;
  143.     *c++ = a0b0;
  144.     carry = a1b1;
  145.   }
  146.   while (carry) {
  147.     mp_digit c_i = *c;
  148.     carry += c_i;
  149.     *c++ = carry;
  150.     carry = carry < c_i;
  151.   }
  152. #endif
  153. }
  154. /* vis versions of these functions run only on v8+vis or v9+vis CPUs. */
  155. /* c = a * b */
  156. static void 
  157. vis_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  158. {
  159.     mp_digit d;
  160.     mp_digit x[258];
  161.     if (a_len <= 256) {
  162. if (a == c || ((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
  163.     mp_digit * px;
  164.     px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
  165.     memcpy(px, a, a_len * sizeof(*a));
  166.     a = px;
  167.     if (a_len & 1) {
  168. px[a_len] = 0;
  169.     }
  170. }
  171. s_mp_setz(c, a_len + 1);
  172. d = mul_add_inp(c, a, a_len, b);
  173. c[a_len] = d;
  174.     } else {
  175. v8_mpv_mul_d(a, a_len, b, c);
  176.     }
  177. }
  178. /* c += a * b, where a is a_len words long. */
  179. static void     
  180. vis_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  181. {
  182.     mp_digit d;
  183.     mp_digit x[258];
  184.     if (a_len <= 256) {
  185. if (((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
  186.     mp_digit * px;
  187.     px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
  188.     memcpy(px, a, a_len * sizeof(*a));
  189.     a = px;
  190.     if (a_len & 1) {
  191. px[a_len] = 0;
  192.     }
  193. }
  194. d = mul_add_inp(c, a, a_len, b);
  195. c[a_len] = d;
  196.     } else {
  197. v8_mpv_mul_d_add(a, a_len, b, c);
  198.     }
  199. }
  200. /* c += a * b, where a is y words long. */
  201. static void     
  202. vis_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, 
  203.  mp_digit *c)
  204. {
  205.     mp_digit d;
  206.     mp_digit x[258];
  207.     if (a_len <= 256) {
  208. if (((ptrdiff_t)a & 0x7) != 0 || (a_len & 1) != 0) {
  209.     mp_digit * px;
  210.     px = (((ptrdiff_t)x & 0x7) != 0) ? x + 1 : x;
  211.     memcpy(px, a, a_len * sizeof(*a));
  212.     a = px;
  213.     if (a_len & 1) {
  214. px[a_len] = 0;
  215.     }
  216. }
  217. d = mul_add_inp(c, a, a_len, b);
  218. if (d) {
  219.     c += a_len;
  220.     do {
  221. mp_digit sum = d + *c;
  222. *c++ = sum;
  223. d = sum < d;
  224.     } while (d);
  225. }
  226.     } else {
  227. v8_mpv_mul_d_add_prop(a, a_len, b, c);
  228.     }
  229. }
  230. #if defined(SOLARIS2_5)
  231. static int
  232. isSparcV8PlusVis(void)
  233. {
  234.     long buflen;
  235.     int  rv             = 0;    /* false */
  236.     char buf[256];
  237.     buflen = sysinfo(SI_MACHINE, buf, sizeof buf);
  238.     if (buflen > 0) {
  239.         rv = (!strcmp(buf, "sun4u") || !strcmp(buf, "sun4u1"));
  240.     }
  241.     return rv;
  242. }
  243. #else   /* SunOS2.6or higher has SI_ISALIST */
  244. static int
  245. isSparcV8PlusVis(void)
  246. {
  247.     long buflen;
  248.     int  rv             = 0;    /* false */
  249.     char buf[256];
  250.     buflen = sysinfo(SI_ISALIST, buf, sizeof buf);
  251.     if (buflen > 0) {
  252. #if defined(NSS_USE_64)
  253.         char * found = strstr(buf, "sparcv9+vis");
  254. #else
  255.         char * found = strstr(buf, "sparcv8plus+vis");
  256. #endif
  257.         rv = (found != 0);
  258.     }
  259.     return rv;
  260. }
  261. #endif
  262. typedef void MPVmpy(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c);
  263. /* forward static function declarations */
  264. static MPVmpy sp_mpv_mul_d;
  265. static MPVmpy sp_mpv_mul_d_add;
  266. static MPVmpy sp_mpv_mul_d_add_prop;
  267. static MPVmpy *p_mpv_mul_d = &sp_mpv_mul_d;
  268. static MPVmpy *p_mpv_mul_d_add = &sp_mpv_mul_d_add;
  269. static MPVmpy *p_mpv_mul_d_add_prop = &sp_mpv_mul_d_add_prop;
  270. static void
  271. initPtrs(void)
  272. {
  273.     if (isSparcV8PlusVis()) {
  274. p_mpv_mul_d =  &vis_mpv_mul_d;
  275. p_mpv_mul_d_add =  &vis_mpv_mul_d_add;
  276. p_mpv_mul_d_add_prop =  &vis_mpv_mul_d_add_prop;
  277.     } else {
  278. p_mpv_mul_d =  &v8_mpv_mul_d;
  279. p_mpv_mul_d_add =  &v8_mpv_mul_d_add;
  280. p_mpv_mul_d_add_prop =  &v8_mpv_mul_d_add_prop;
  281.     }
  282. }
  283. static void 
  284. sp_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  285. {
  286.     initPtrs();
  287.     (* p_mpv_mul_d)(a, a_len, b, c);
  288. }
  289. static void 
  290. sp_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  291. {
  292.     initPtrs();
  293.     (* p_mpv_mul_d_add)(a, a_len, b, c);
  294. }
  295. static void 
  296. sp_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  297. {
  298.     initPtrs();
  299.     (* p_mpv_mul_d_add_prop)(a, a_len, b, c);
  300. }
  301. /* This is the external interface */
  302. void 
  303. s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  304. {
  305.     (* p_mpv_mul_d)(a, a_len, b, c);
  306. }
  307. void 
  308. s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  309. {
  310.     (* p_mpv_mul_d_add)(a, a_len, b, c);
  311. }
  312. void 
  313. s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
  314. {
  315.     (* p_mpv_mul_d_add_prop)(a, a_len, b, c);
  316. }