1e71b7053SJung-uk Kim /* 2e71b7053SJung-uk Kim * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. 3e71b7053SJung-uk Kim * 4e71b7053SJung-uk Kim * Licensed under the OpenSSL license (the "License"). You may not use 5e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy 6e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at 7e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html 8e71b7053SJung-uk Kim */ 9e71b7053SJung-uk Kim 106a599222SSimon L. B. Nielsen #include "../bn_lcl.h" 111f13597dSJung-uk Kim #if !(defined(__GNUC__) && __GNUC__>=2) 12ed5d4f9aSSimon L. B. Nielsen # include "../bn_asm.c" /* kind of dirty hack for Sun Studio */ 13ed5d4f9aSSimon L. B. Nielsen #else 146f9291ceSJung-uk Kim /*- 155c87c606SMark Murray * x86_64 BIGNUM accelerator version 0.1, December 2002. 165c87c606SMark Murray * 17e71b7053SJung-uk Kim * Implemented by Andy Polyakov <appro@openssl.org> for the OpenSSL 185c87c606SMark Murray * project. 195c87c606SMark Murray * 205c87c606SMark Murray * Rights for redistribution and usage in source and binary forms are 215c87c606SMark Murray * granted according to the OpenSSL license. Warranty of any kind is 225c87c606SMark Murray * disclaimed. 235c87c606SMark Murray * 245c87c606SMark Murray * Q. Version 0.1? It doesn't sound like Andy, he used to assign real 255c87c606SMark Murray * versions, like 1.0... 265c87c606SMark Murray * A. Well, that's because this code is basically a quick-n-dirty 275c87c606SMark Murray * proof-of-concept hack. As you can see it's implemented with 285c87c606SMark Murray * inline assembler, which means that you're bound to GCC and that 293b4e3dcbSSimon L. B. Nielsen * there might be enough room for further improvement. 305c87c606SMark Murray * 315c87c606SMark Murray * Q. Why inline assembler? 323b4e3dcbSSimon L. B. Nielsen * A. x86_64 features own ABI which I'm not familiar with. This is 333b4e3dcbSSimon L. B. Nielsen * why I decided to let the compiler take care of subroutine 343b4e3dcbSSimon L. B. Nielsen * prologue/epilogue as well as register allocation. For reference. 353b4e3dcbSSimon L. B. Nielsen * Win64 implements different ABI for AMD64, different from Linux. 365c87c606SMark Murray * 375c87c606SMark Murray * Q. How much faster does it get? 383b4e3dcbSSimon L. B. Nielsen * A. 'apps/openssl speed rsa dsa' output with no-asm: 393b4e3dcbSSimon L. B. Nielsen * 403b4e3dcbSSimon L. B. Nielsen * sign verify sign/s verify/s 413b4e3dcbSSimon L. B. Nielsen * rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2 423b4e3dcbSSimon L. B. Nielsen * rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0 433b4e3dcbSSimon L. B. Nielsen * rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8 443b4e3dcbSSimon L. B. Nielsen * rsa 4096 bits 0.1155s 0.0018s 8.7 555.6 453b4e3dcbSSimon L. B. Nielsen * sign verify sign/s verify/s 463b4e3dcbSSimon L. B. Nielsen * dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3 473b4e3dcbSSimon L. B. Nielsen * dsa 1024 bits 0.0014s 0.0018s 692.3 559.2 483b4e3dcbSSimon L. B. Nielsen * dsa 2048 bits 0.0049s 0.0061s 204.7 165.0 493b4e3dcbSSimon L. B. Nielsen * 503b4e3dcbSSimon L. B. Nielsen * 'apps/openssl speed rsa dsa' output with this module: 513b4e3dcbSSimon L. B. Nielsen * 523b4e3dcbSSimon L. B. Nielsen * sign verify sign/s verify/s 533b4e3dcbSSimon L. B. Nielsen * rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9 543b4e3dcbSSimon L. B. Nielsen * rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7 553b4e3dcbSSimon L. B. Nielsen * rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0 563b4e3dcbSSimon L. B. Nielsen * rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8 573b4e3dcbSSimon L. B. Nielsen * sign verify sign/s verify/s 583b4e3dcbSSimon L. B. Nielsen * dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3 593b4e3dcbSSimon L. B. Nielsen * dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4 603b4e3dcbSSimon L. B. Nielsen * dsa 2048 bits 0.0016s 0.0020s 620.4 504.6 613b4e3dcbSSimon L. B. Nielsen * 623b4e3dcbSSimon L. B. Nielsen * For the reference. IA-32 assembler implementation performs 633b4e3dcbSSimon L. B. Nielsen * very much like 64-bit code compiled with no-asm on the same 643b4e3dcbSSimon L. B. Nielsen * machine. 655c87c606SMark Murray */ 665c87c606SMark Murray 677bded2dbSJung-uk Kim # if defined(_WIN64) || !defined(__LP64__) 681f13597dSJung-uk Kim # define BN_ULONG unsigned long long 691f13597dSJung-uk Kim # else 705c87c606SMark Murray # define BN_ULONG unsigned long 711f13597dSJung-uk Kim # endif 725c87c606SMark Murray 736a599222SSimon L. B. Nielsen # undef mul 746a599222SSimon L. B. Nielsen # undef mul_add 756a599222SSimon L. B. Nielsen 766f9291ceSJung-uk Kim /*- 7780815a77SJung-uk Kim * "m"(a), "+m"(r) is the way to favor DirectPath µ-code; 785c87c606SMark Murray * "g"(0) let the compiler to decide where does it 795c87c606SMark Murray * want to keep the value of zero; 805c87c606SMark Murray */ 815c87c606SMark Murray # define mul_add(r,a,word,carry) do { \ 825c87c606SMark Murray register BN_ULONG high,low; \ 835c87c606SMark Murray asm ("mulq %3" \ 845c87c606SMark Murray : "=a"(low),"=d"(high) \ 855c87c606SMark Murray : "a"(word),"m"(a) \ 865c87c606SMark Murray : "cc"); \ 875c87c606SMark Murray asm ("addq %2,%0; adcq %3,%1" \ 885c87c606SMark Murray : "+r"(carry),"+d"(high)\ 895c87c606SMark Murray : "a"(low),"g"(0) \ 905c87c606SMark Murray : "cc"); \ 915c87c606SMark Murray asm ("addq %2,%0; adcq %3,%1" \ 925c87c606SMark Murray : "+m"(r),"+d"(high) \ 935c87c606SMark Murray : "r"(carry),"g"(0) \ 945c87c606SMark Murray : "cc"); \ 955c87c606SMark Murray carry=high; \ 965c87c606SMark Murray } while (0) 975c87c606SMark Murray 985c87c606SMark Murray # define mul(r,a,word,carry) do { \ 995c87c606SMark Murray register BN_ULONG high,low; \ 1005c87c606SMark Murray asm ("mulq %3" \ 1015c87c606SMark Murray : "=a"(low),"=d"(high) \ 1025c87c606SMark Murray : "a"(word),"g"(a) \ 1035c87c606SMark Murray : "cc"); \ 1045c87c606SMark Murray asm ("addq %2,%0; adcq %3,%1" \ 1055c87c606SMark Murray : "+r"(carry),"+d"(high)\ 1065c87c606SMark Murray : "a"(low),"g"(0) \ 1075c87c606SMark Murray : "cc"); \ 1085c87c606SMark Murray (r)=carry, carry=high; \ 1095c87c606SMark Murray } while (0) 1107bded2dbSJung-uk Kim # undef sqr 1115c87c606SMark Murray # define sqr(r0,r1,a) \ 1125c87c606SMark Murray asm ("mulq %2" \ 1135c87c606SMark Murray : "=a"(r0),"=d"(r1) \ 1145c87c606SMark Murray : "a"(a) \ 1155c87c606SMark Murray : "cc"); 1165c87c606SMark Murray 1176f9291ceSJung-uk Kim BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, 1186f9291ceSJung-uk Kim BN_ULONG w) 1195c87c606SMark Murray { 1205c87c606SMark Murray BN_ULONG c1 = 0; 1215c87c606SMark Murray 1226f9291ceSJung-uk Kim if (num <= 0) 123e71b7053SJung-uk Kim return c1; 1245c87c606SMark Murray 1256f9291ceSJung-uk Kim while (num & ~3) { 1265c87c606SMark Murray mul_add(rp[0], ap[0], w, c1); 1275c87c606SMark Murray mul_add(rp[1], ap[1], w, c1); 1285c87c606SMark Murray mul_add(rp[2], ap[2], w, c1); 1295c87c606SMark Murray mul_add(rp[3], ap[3], w, c1); 1306f9291ceSJung-uk Kim ap += 4; 1316f9291ceSJung-uk Kim rp += 4; 1326f9291ceSJung-uk Kim num -= 4; 1335c87c606SMark Murray } 1346f9291ceSJung-uk Kim if (num) { 1356f9291ceSJung-uk Kim mul_add(rp[0], ap[0], w, c1); 1366f9291ceSJung-uk Kim if (--num == 0) 1376f9291ceSJung-uk Kim return c1; 1386f9291ceSJung-uk Kim mul_add(rp[1], ap[1], w, c1); 1396f9291ceSJung-uk Kim if (--num == 0) 1406f9291ceSJung-uk Kim return c1; 1416f9291ceSJung-uk Kim mul_add(rp[2], ap[2], w, c1); 1426f9291ceSJung-uk Kim return c1; 1435c87c606SMark Murray } 1445c87c606SMark Murray 145e71b7053SJung-uk Kim return c1; 1465c87c606SMark Murray } 1475c87c606SMark Murray 1486a599222SSimon L. B. Nielsen BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) 1495c87c606SMark Murray { 1505c87c606SMark Murray BN_ULONG c1 = 0; 1515c87c606SMark Murray 1526f9291ceSJung-uk Kim if (num <= 0) 153e71b7053SJung-uk Kim return c1; 1545c87c606SMark Murray 1556f9291ceSJung-uk Kim while (num & ~3) { 1565c87c606SMark Murray mul(rp[0], ap[0], w, c1); 1575c87c606SMark Murray mul(rp[1], ap[1], w, c1); 1585c87c606SMark Murray mul(rp[2], ap[2], w, c1); 1595c87c606SMark Murray mul(rp[3], ap[3], w, c1); 1606f9291ceSJung-uk Kim ap += 4; 1616f9291ceSJung-uk Kim rp += 4; 1626f9291ceSJung-uk Kim num -= 4; 1635c87c606SMark Murray } 1646f9291ceSJung-uk Kim if (num) { 1656f9291ceSJung-uk Kim mul(rp[0], ap[0], w, c1); 1666f9291ceSJung-uk Kim if (--num == 0) 1676f9291ceSJung-uk Kim return c1; 1686f9291ceSJung-uk Kim mul(rp[1], ap[1], w, c1); 1696f9291ceSJung-uk Kim if (--num == 0) 1706f9291ceSJung-uk Kim return c1; 1715c87c606SMark Murray mul(rp[2], ap[2], w, c1); 1725c87c606SMark Murray } 173e71b7053SJung-uk Kim return c1; 1745c87c606SMark Murray } 1755c87c606SMark Murray 1766a599222SSimon L. B. Nielsen void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) 1775c87c606SMark Murray { 1786f9291ceSJung-uk Kim if (n <= 0) 1796f9291ceSJung-uk Kim return; 1805c87c606SMark Murray 1816f9291ceSJung-uk Kim while (n & ~3) { 1825c87c606SMark Murray sqr(r[0], r[1], a[0]); 1835c87c606SMark Murray sqr(r[2], r[3], a[1]); 1845c87c606SMark Murray sqr(r[4], r[5], a[2]); 1855c87c606SMark Murray sqr(r[6], r[7], a[3]); 1866f9291ceSJung-uk Kim a += 4; 1876f9291ceSJung-uk Kim r += 8; 1886f9291ceSJung-uk Kim n -= 4; 1895c87c606SMark Murray } 1906f9291ceSJung-uk Kim if (n) { 1916f9291ceSJung-uk Kim sqr(r[0], r[1], a[0]); 1926f9291ceSJung-uk Kim if (--n == 0) 1936f9291ceSJung-uk Kim return; 1946f9291ceSJung-uk Kim sqr(r[2], r[3], a[1]); 1956f9291ceSJung-uk Kim if (--n == 0) 1966f9291ceSJung-uk Kim return; 1975c87c606SMark Murray sqr(r[4], r[5], a[2]); 1985c87c606SMark Murray } 1995c87c606SMark Murray } 2005c87c606SMark Murray 2015c87c606SMark Murray BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) 2026f9291ceSJung-uk Kim { 2036f9291ceSJung-uk Kim BN_ULONG ret, waste; 2045c87c606SMark Murray 2056f9291ceSJung-uk Kim asm("divq %4":"=a"(ret), "=d"(waste) 206aeb5019cSJung-uk Kim : "a"(l), "d"(h), "r"(d) 2075c87c606SMark Murray : "cc"); 2085c87c606SMark Murray 2095c87c606SMark Murray return ret; 2105c87c606SMark Murray } 2115c87c606SMark Murray 2126f9291ceSJung-uk Kim BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, 2136f9291ceSJung-uk Kim int n) 2146f9291ceSJung-uk Kim { 2157bded2dbSJung-uk Kim BN_ULONG ret; 2167bded2dbSJung-uk Kim size_t i = 0; 2175c87c606SMark Murray 2186f9291ceSJung-uk Kim if (n <= 0) 2196f9291ceSJung-uk Kim return 0; 2205c87c606SMark Murray 2217bded2dbSJung-uk Kim asm volatile (" subq %0,%0 \n" /* clear carry */ 2227bded2dbSJung-uk Kim " jmp 1f \n" 2231f13597dSJung-uk Kim ".p2align 4 \n" 2245c87c606SMark Murray "1: movq (%4,%2,8),%0 \n" 2255c87c606SMark Murray " adcq (%5,%2,8),%0 \n" 2265c87c606SMark Murray " movq %0,(%3,%2,8) \n" 2277bded2dbSJung-uk Kim " lea 1(%2),%2 \n" 228e71b7053SJung-uk Kim " dec %1 \n" 229e71b7053SJung-uk Kim " jnz 1b \n" 230e71b7053SJung-uk Kim " sbbq %0,%0 \n" 231e71b7053SJung-uk Kim :"=&r" (ret), "+c"(n), "+r"(i) 2325c87c606SMark Murray :"r"(rp), "r"(ap), "r"(bp) 2336f9291ceSJung-uk Kim :"cc", "memory"); 2345c87c606SMark Murray 2355c87c606SMark Murray return ret & 1; 2365c87c606SMark Murray } 2375c87c606SMark Murray 2385c87c606SMark Murray # ifndef SIMICS 2396f9291ceSJung-uk Kim BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, 2406f9291ceSJung-uk Kim int n) 2416f9291ceSJung-uk Kim { 2427bded2dbSJung-uk Kim BN_ULONG ret; 2437bded2dbSJung-uk Kim size_t i = 0; 2445c87c606SMark Murray 2456f9291ceSJung-uk Kim if (n <= 0) 2466f9291ceSJung-uk Kim return 0; 2475c87c606SMark Murray 2487bded2dbSJung-uk Kim asm volatile (" subq %0,%0 \n" /* clear borrow */ 2497bded2dbSJung-uk Kim " jmp 1f \n" 2501f13597dSJung-uk Kim ".p2align 4 \n" 2515c87c606SMark Murray "1: movq (%4,%2,8),%0 \n" 2525c87c606SMark Murray " sbbq (%5,%2,8),%0 \n" 2535c87c606SMark Murray " movq %0,(%3,%2,8) \n" 2547bded2dbSJung-uk Kim " lea 1(%2),%2 \n" 255e71b7053SJung-uk Kim " dec %1 \n" 256e71b7053SJung-uk Kim " jnz 1b \n" 257e71b7053SJung-uk Kim " sbbq %0,%0 \n" 258e71b7053SJung-uk Kim :"=&r" (ret), "+c"(n), "+r"(i) 2595c87c606SMark Murray :"r"(rp), "r"(ap), "r"(bp) 2606f9291ceSJung-uk Kim :"cc", "memory"); 2615c87c606SMark Murray 2625c87c606SMark Murray return ret & 1; 2635c87c606SMark Murray } 2645c87c606SMark Murray # else 2655c87c606SMark Murray /* Simics 1.4<7 has buggy sbbq:-( */ 2665c87c606SMark Murray # define BN_MASK2 0xffffffffffffffffL 2675c87c606SMark Murray BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) 2685c87c606SMark Murray { 2695c87c606SMark Murray BN_ULONG t1, t2; 2705c87c606SMark Murray int c = 0; 2715c87c606SMark Murray 2726f9291ceSJung-uk Kim if (n <= 0) 273e71b7053SJung-uk Kim return (BN_ULONG)0; 2745c87c606SMark Murray 2756f9291ceSJung-uk Kim for (;;) { 2766f9291ceSJung-uk Kim t1 = a[0]; 2776f9291ceSJung-uk Kim t2 = b[0]; 2785c87c606SMark Murray r[0] = (t1 - t2 - c) & BN_MASK2; 2796f9291ceSJung-uk Kim if (t1 != t2) 2806f9291ceSJung-uk Kim c = (t1 < t2); 2816f9291ceSJung-uk Kim if (--n <= 0) 2826f9291ceSJung-uk Kim break; 2835c87c606SMark Murray 2846f9291ceSJung-uk Kim t1 = a[1]; 2856f9291ceSJung-uk Kim t2 = b[1]; 2865c87c606SMark Murray r[1] = (t1 - t2 - c) & BN_MASK2; 2876f9291ceSJung-uk Kim if (t1 != t2) 2886f9291ceSJung-uk Kim c = (t1 < t2); 2896f9291ceSJung-uk Kim if (--n <= 0) 2906f9291ceSJung-uk Kim break; 2915c87c606SMark Murray 2926f9291ceSJung-uk Kim t1 = a[2]; 2936f9291ceSJung-uk Kim t2 = b[2]; 2945c87c606SMark Murray r[2] = (t1 - t2 - c) & BN_MASK2; 2956f9291ceSJung-uk Kim if (t1 != t2) 2966f9291ceSJung-uk Kim c = (t1 < t2); 2976f9291ceSJung-uk Kim if (--n <= 0) 2986f9291ceSJung-uk Kim break; 2995c87c606SMark Murray 3006f9291ceSJung-uk Kim t1 = a[3]; 3016f9291ceSJung-uk Kim t2 = b[3]; 3025c87c606SMark Murray r[3] = (t1 - t2 - c) & BN_MASK2; 3036f9291ceSJung-uk Kim if (t1 != t2) 3046f9291ceSJung-uk Kim c = (t1 < t2); 3056f9291ceSJung-uk Kim if (--n <= 0) 3066f9291ceSJung-uk Kim break; 3075c87c606SMark Murray 3085c87c606SMark Murray a += 4; 3095c87c606SMark Murray b += 4; 3105c87c606SMark Murray r += 4; 3115c87c606SMark Murray } 312e71b7053SJung-uk Kim return c; 3135c87c606SMark Murray } 3145c87c606SMark Murray # endif 3155c87c606SMark Murray 3165c87c606SMark Murray /* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */ 3175c87c606SMark Murray /* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */ 3185c87c606SMark Murray /* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */ 3196f9291ceSJung-uk Kim /* 3206f9291ceSJung-uk Kim * sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number 3216f9291ceSJung-uk Kim * c=(c2,c1,c0) 3226f9291ceSJung-uk Kim */ 3235c87c606SMark Murray 324751d2991SJung-uk Kim /* 325751d2991SJung-uk Kim * Keep in mind that carrying into high part of multiplication result 326751d2991SJung-uk Kim * can not overflow, because it cannot be all-ones. 327751d2991SJung-uk Kim */ 3285c87c606SMark Murray # if 0 3295c87c606SMark Murray /* original macros are kept for reference purposes */ 3307bded2dbSJung-uk Kim # define mul_add_c(a,b,c0,c1,c2) do { \ 3315c87c606SMark Murray BN_ULONG ta = (a), tb = (b); \ 3327bded2dbSJung-uk Kim BN_ULONG lo, hi; \ 3337bded2dbSJung-uk Kim BN_UMULT_LOHI(lo,hi,ta,tb); \ 3347bded2dbSJung-uk Kim c0 += lo; hi += (c0<lo)?1:0; \ 3357bded2dbSJung-uk Kim c1 += hi; c2 += (c1<hi)?1:0; \ 3367bded2dbSJung-uk Kim } while(0) 3375c87c606SMark Murray 3387bded2dbSJung-uk Kim # define mul_add_c2(a,b,c0,c1,c2) do { \ 3397bded2dbSJung-uk Kim BN_ULONG ta = (a), tb = (b); \ 3407bded2dbSJung-uk Kim BN_ULONG lo, hi, tt; \ 3417bded2dbSJung-uk Kim BN_UMULT_LOHI(lo,hi,ta,tb); \ 3427bded2dbSJung-uk Kim c0 += lo; tt = hi+((c0<lo)?1:0); \ 3437bded2dbSJung-uk Kim c1 += tt; c2 += (c1<tt)?1:0; \ 3447bded2dbSJung-uk Kim c0 += lo; hi += (c0<lo)?1:0; \ 3457bded2dbSJung-uk Kim c1 += hi; c2 += (c1<hi)?1:0; \ 3467bded2dbSJung-uk Kim } while(0) 3477bded2dbSJung-uk Kim 3487bded2dbSJung-uk Kim # define sqr_add_c(a,i,c0,c1,c2) do { \ 3497bded2dbSJung-uk Kim BN_ULONG ta = (a)[i]; \ 3507bded2dbSJung-uk Kim BN_ULONG lo, hi; \ 3517bded2dbSJung-uk Kim BN_UMULT_LOHI(lo,hi,ta,ta); \ 3527bded2dbSJung-uk Kim c0 += lo; hi += (c0<lo)?1:0; \ 3537bded2dbSJung-uk Kim c1 += hi; c2 += (c1<hi)?1:0; \ 3547bded2dbSJung-uk Kim } while(0) 3555c87c606SMark Murray # else 3565c87c606SMark Murray # define mul_add_c(a,b,c0,c1,c2) do { \ 3577bded2dbSJung-uk Kim BN_ULONG t1,t2; \ 3585c87c606SMark Murray asm ("mulq %3" \ 3595c87c606SMark Murray : "=a"(t1),"=d"(t2) \ 3605c87c606SMark Murray : "a"(a),"m"(b) \ 3615c87c606SMark Murray : "cc"); \ 3627bded2dbSJung-uk Kim asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \ 3637bded2dbSJung-uk Kim : "+r"(c0),"+r"(c1),"+r"(c2) \ 3647bded2dbSJung-uk Kim : "r"(t1),"r"(t2),"g"(0) \ 3655c87c606SMark Murray : "cc"); \ 3665c87c606SMark Murray } while (0) 3675c87c606SMark Murray 3685c87c606SMark Murray # define sqr_add_c(a,i,c0,c1,c2) do { \ 3697bded2dbSJung-uk Kim BN_ULONG t1,t2; \ 3705c87c606SMark Murray asm ("mulq %2" \ 3715c87c606SMark Murray : "=a"(t1),"=d"(t2) \ 3725c87c606SMark Murray : "a"(a[i]) \ 3735c87c606SMark Murray : "cc"); \ 3747bded2dbSJung-uk Kim asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \ 3757bded2dbSJung-uk Kim : "+r"(c0),"+r"(c1),"+r"(c2) \ 3767bded2dbSJung-uk Kim : "r"(t1),"r"(t2),"g"(0) \ 3775c87c606SMark Murray : "cc"); \ 3785c87c606SMark Murray } while (0) 3795c87c606SMark Murray 3805c87c606SMark Murray # define mul_add_c2(a,b,c0,c1,c2) do { \ 3817bded2dbSJung-uk Kim BN_ULONG t1,t2; \ 3825c87c606SMark Murray asm ("mulq %3" \ 3835c87c606SMark Murray : "=a"(t1),"=d"(t2) \ 3845c87c606SMark Murray : "a"(a),"m"(b) \ 3855c87c606SMark Murray : "cc"); \ 386751d2991SJung-uk Kim asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \ 387751d2991SJung-uk Kim : "+r"(c0),"+r"(c1),"+r"(c2) \ 388751d2991SJung-uk Kim : "r"(t1),"r"(t2),"g"(0) \ 3895c87c606SMark Murray : "cc"); \ 390751d2991SJung-uk Kim asm ("addq %3,%0; adcq %4,%1; adcq %5,%2" \ 391751d2991SJung-uk Kim : "+r"(c0),"+r"(c1),"+r"(c2) \ 392751d2991SJung-uk Kim : "r"(t1),"r"(t2),"g"(0) \ 3935c87c606SMark Murray : "cc"); \ 3945c87c606SMark Murray } while (0) 3955c87c606SMark Murray # endif 3965c87c606SMark Murray 3975c87c606SMark Murray # define sqr_add_c2(a,i,j,c0,c1,c2) \ 3985c87c606SMark Murray mul_add_c2((a)[i],(a)[j],c0,c1,c2) 3995c87c606SMark Murray 4005c87c606SMark Murray void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) 4015c87c606SMark Murray { 4025c87c606SMark Murray BN_ULONG c1, c2, c3; 4035c87c606SMark Murray 4045c87c606SMark Murray c1 = 0; 4055c87c606SMark Murray c2 = 0; 4065c87c606SMark Murray c3 = 0; 4075c87c606SMark Murray mul_add_c(a[0], b[0], c1, c2, c3); 4085c87c606SMark Murray r[0] = c1; 4095c87c606SMark Murray c1 = 0; 4105c87c606SMark Murray mul_add_c(a[0], b[1], c2, c3, c1); 4115c87c606SMark Murray mul_add_c(a[1], b[0], c2, c3, c1); 4125c87c606SMark Murray r[1] = c2; 4135c87c606SMark Murray c2 = 0; 4145c87c606SMark Murray mul_add_c(a[2], b[0], c3, c1, c2); 4155c87c606SMark Murray mul_add_c(a[1], b[1], c3, c1, c2); 4165c87c606SMark Murray mul_add_c(a[0], b[2], c3, c1, c2); 4175c87c606SMark Murray r[2] = c3; 4185c87c606SMark Murray c3 = 0; 4195c87c606SMark Murray mul_add_c(a[0], b[3], c1, c2, c3); 4205c87c606SMark Murray mul_add_c(a[1], b[2], c1, c2, c3); 4215c87c606SMark Murray mul_add_c(a[2], b[1], c1, c2, c3); 4225c87c606SMark Murray mul_add_c(a[3], b[0], c1, c2, c3); 4235c87c606SMark Murray r[3] = c1; 4245c87c606SMark Murray c1 = 0; 4255c87c606SMark Murray mul_add_c(a[4], b[0], c2, c3, c1); 4265c87c606SMark Murray mul_add_c(a[3], b[1], c2, c3, c1); 4275c87c606SMark Murray mul_add_c(a[2], b[2], c2, c3, c1); 4285c87c606SMark Murray mul_add_c(a[1], b[3], c2, c3, c1); 4295c87c606SMark Murray mul_add_c(a[0], b[4], c2, c3, c1); 4305c87c606SMark Murray r[4] = c2; 4315c87c606SMark Murray c2 = 0; 4325c87c606SMark Murray mul_add_c(a[0], b[5], c3, c1, c2); 4335c87c606SMark Murray mul_add_c(a[1], b[4], c3, c1, c2); 4345c87c606SMark Murray mul_add_c(a[2], b[3], c3, c1, c2); 4355c87c606SMark Murray mul_add_c(a[3], b[2], c3, c1, c2); 4365c87c606SMark Murray mul_add_c(a[4], b[1], c3, c1, c2); 4375c87c606SMark Murray mul_add_c(a[5], b[0], c3, c1, c2); 4385c87c606SMark Murray r[5] = c3; 4395c87c606SMark Murray c3 = 0; 4405c87c606SMark Murray mul_add_c(a[6], b[0], c1, c2, c3); 4415c87c606SMark Murray mul_add_c(a[5], b[1], c1, c2, c3); 4425c87c606SMark Murray mul_add_c(a[4], b[2], c1, c2, c3); 4435c87c606SMark Murray mul_add_c(a[3], b[3], c1, c2, c3); 4445c87c606SMark Murray mul_add_c(a[2], b[4], c1, c2, c3); 4455c87c606SMark Murray mul_add_c(a[1], b[5], c1, c2, c3); 4465c87c606SMark Murray mul_add_c(a[0], b[6], c1, c2, c3); 4475c87c606SMark Murray r[6] = c1; 4485c87c606SMark Murray c1 = 0; 4495c87c606SMark Murray mul_add_c(a[0], b[7], c2, c3, c1); 4505c87c606SMark Murray mul_add_c(a[1], b[6], c2, c3, c1); 4515c87c606SMark Murray mul_add_c(a[2], b[5], c2, c3, c1); 4525c87c606SMark Murray mul_add_c(a[3], b[4], c2, c3, c1); 4535c87c606SMark Murray mul_add_c(a[4], b[3], c2, c3, c1); 4545c87c606SMark Murray mul_add_c(a[5], b[2], c2, c3, c1); 4555c87c606SMark Murray mul_add_c(a[6], b[1], c2, c3, c1); 4565c87c606SMark Murray mul_add_c(a[7], b[0], c2, c3, c1); 4575c87c606SMark Murray r[7] = c2; 4585c87c606SMark Murray c2 = 0; 4595c87c606SMark Murray mul_add_c(a[7], b[1], c3, c1, c2); 4605c87c606SMark Murray mul_add_c(a[6], b[2], c3, c1, c2); 4615c87c606SMark Murray mul_add_c(a[5], b[3], c3, c1, c2); 4625c87c606SMark Murray mul_add_c(a[4], b[4], c3, c1, c2); 4635c87c606SMark Murray mul_add_c(a[3], b[5], c3, c1, c2); 4645c87c606SMark Murray mul_add_c(a[2], b[6], c3, c1, c2); 4655c87c606SMark Murray mul_add_c(a[1], b[7], c3, c1, c2); 4665c87c606SMark Murray r[8] = c3; 4675c87c606SMark Murray c3 = 0; 4685c87c606SMark Murray mul_add_c(a[2], b[7], c1, c2, c3); 4695c87c606SMark Murray mul_add_c(a[3], b[6], c1, c2, c3); 4705c87c606SMark Murray mul_add_c(a[4], b[5], c1, c2, c3); 4715c87c606SMark Murray mul_add_c(a[5], b[4], c1, c2, c3); 4725c87c606SMark Murray mul_add_c(a[6], b[3], c1, c2, c3); 4735c87c606SMark Murray mul_add_c(a[7], b[2], c1, c2, c3); 4745c87c606SMark Murray r[9] = c1; 4755c87c606SMark Murray c1 = 0; 4765c87c606SMark Murray mul_add_c(a[7], b[3], c2, c3, c1); 4775c87c606SMark Murray mul_add_c(a[6], b[4], c2, c3, c1); 4785c87c606SMark Murray mul_add_c(a[5], b[5], c2, c3, c1); 4795c87c606SMark Murray mul_add_c(a[4], b[6], c2, c3, c1); 4805c87c606SMark Murray mul_add_c(a[3], b[7], c2, c3, c1); 4815c87c606SMark Murray r[10] = c2; 4825c87c606SMark Murray c2 = 0; 4835c87c606SMark Murray mul_add_c(a[4], b[7], c3, c1, c2); 4845c87c606SMark Murray mul_add_c(a[5], b[6], c3, c1, c2); 4855c87c606SMark Murray mul_add_c(a[6], b[5], c3, c1, c2); 4865c87c606SMark Murray mul_add_c(a[7], b[4], c3, c1, c2); 4875c87c606SMark Murray r[11] = c3; 4885c87c606SMark Murray c3 = 0; 4895c87c606SMark Murray mul_add_c(a[7], b[5], c1, c2, c3); 4905c87c606SMark Murray mul_add_c(a[6], b[6], c1, c2, c3); 4915c87c606SMark Murray mul_add_c(a[5], b[7], c1, c2, c3); 4925c87c606SMark Murray r[12] = c1; 4935c87c606SMark Murray c1 = 0; 4945c87c606SMark Murray mul_add_c(a[6], b[7], c2, c3, c1); 4955c87c606SMark Murray mul_add_c(a[7], b[6], c2, c3, c1); 4965c87c606SMark Murray r[13] = c2; 4975c87c606SMark Murray c2 = 0; 4985c87c606SMark Murray mul_add_c(a[7], b[7], c3, c1, c2); 4995c87c606SMark Murray r[14] = c3; 5005c87c606SMark Murray r[15] = c1; 5015c87c606SMark Murray } 5025c87c606SMark Murray 5035c87c606SMark Murray void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) 5045c87c606SMark Murray { 5055c87c606SMark Murray BN_ULONG c1, c2, c3; 5065c87c606SMark Murray 5075c87c606SMark Murray c1 = 0; 5085c87c606SMark Murray c2 = 0; 5095c87c606SMark Murray c3 = 0; 5105c87c606SMark Murray mul_add_c(a[0], b[0], c1, c2, c3); 5115c87c606SMark Murray r[0] = c1; 5125c87c606SMark Murray c1 = 0; 5135c87c606SMark Murray mul_add_c(a[0], b[1], c2, c3, c1); 5145c87c606SMark Murray mul_add_c(a[1], b[0], c2, c3, c1); 5155c87c606SMark Murray r[1] = c2; 5165c87c606SMark Murray c2 = 0; 5175c87c606SMark Murray mul_add_c(a[2], b[0], c3, c1, c2); 5185c87c606SMark Murray mul_add_c(a[1], b[1], c3, c1, c2); 5195c87c606SMark Murray mul_add_c(a[0], b[2], c3, c1, c2); 5205c87c606SMark Murray r[2] = c3; 5215c87c606SMark Murray c3 = 0; 5225c87c606SMark Murray mul_add_c(a[0], b[3], c1, c2, c3); 5235c87c606SMark Murray mul_add_c(a[1], b[2], c1, c2, c3); 5245c87c606SMark Murray mul_add_c(a[2], b[1], c1, c2, c3); 5255c87c606SMark Murray mul_add_c(a[3], b[0], c1, c2, c3); 5265c87c606SMark Murray r[3] = c1; 5275c87c606SMark Murray c1 = 0; 5285c87c606SMark Murray mul_add_c(a[3], b[1], c2, c3, c1); 5295c87c606SMark Murray mul_add_c(a[2], b[2], c2, c3, c1); 5305c87c606SMark Murray mul_add_c(a[1], b[3], c2, c3, c1); 5315c87c606SMark Murray r[4] = c2; 5325c87c606SMark Murray c2 = 0; 5335c87c606SMark Murray mul_add_c(a[2], b[3], c3, c1, c2); 5345c87c606SMark Murray mul_add_c(a[3], b[2], c3, c1, c2); 5355c87c606SMark Murray r[5] = c3; 5365c87c606SMark Murray c3 = 0; 5375c87c606SMark Murray mul_add_c(a[3], b[3], c1, c2, c3); 5385c87c606SMark Murray r[6] = c1; 5395c87c606SMark Murray r[7] = c2; 5405c87c606SMark Murray } 5415c87c606SMark Murray 5426a599222SSimon L. B. Nielsen void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) 5435c87c606SMark Murray { 5445c87c606SMark Murray BN_ULONG c1, c2, c3; 5455c87c606SMark Murray 5465c87c606SMark Murray c1 = 0; 5475c87c606SMark Murray c2 = 0; 5485c87c606SMark Murray c3 = 0; 5495c87c606SMark Murray sqr_add_c(a, 0, c1, c2, c3); 5505c87c606SMark Murray r[0] = c1; 5515c87c606SMark Murray c1 = 0; 5525c87c606SMark Murray sqr_add_c2(a, 1, 0, c2, c3, c1); 5535c87c606SMark Murray r[1] = c2; 5545c87c606SMark Murray c2 = 0; 5555c87c606SMark Murray sqr_add_c(a, 1, c3, c1, c2); 5565c87c606SMark Murray sqr_add_c2(a, 2, 0, c3, c1, c2); 5575c87c606SMark Murray r[2] = c3; 5585c87c606SMark Murray c3 = 0; 5595c87c606SMark Murray sqr_add_c2(a, 3, 0, c1, c2, c3); 5605c87c606SMark Murray sqr_add_c2(a, 2, 1, c1, c2, c3); 5615c87c606SMark Murray r[3] = c1; 5625c87c606SMark Murray c1 = 0; 5635c87c606SMark Murray sqr_add_c(a, 2, c2, c3, c1); 5645c87c606SMark Murray sqr_add_c2(a, 3, 1, c2, c3, c1); 5655c87c606SMark Murray sqr_add_c2(a, 4, 0, c2, c3, c1); 5665c87c606SMark Murray r[4] = c2; 5675c87c606SMark Murray c2 = 0; 5685c87c606SMark Murray sqr_add_c2(a, 5, 0, c3, c1, c2); 5695c87c606SMark Murray sqr_add_c2(a, 4, 1, c3, c1, c2); 5705c87c606SMark Murray sqr_add_c2(a, 3, 2, c3, c1, c2); 5715c87c606SMark Murray r[5] = c3; 5725c87c606SMark Murray c3 = 0; 5735c87c606SMark Murray sqr_add_c(a, 3, c1, c2, c3); 5745c87c606SMark Murray sqr_add_c2(a, 4, 2, c1, c2, c3); 5755c87c606SMark Murray sqr_add_c2(a, 5, 1, c1, c2, c3); 5765c87c606SMark Murray sqr_add_c2(a, 6, 0, c1, c2, c3); 5775c87c606SMark Murray r[6] = c1; 5785c87c606SMark Murray c1 = 0; 5795c87c606SMark Murray sqr_add_c2(a, 7, 0, c2, c3, c1); 5805c87c606SMark Murray sqr_add_c2(a, 6, 1, c2, c3, c1); 5815c87c606SMark Murray sqr_add_c2(a, 5, 2, c2, c3, c1); 5825c87c606SMark Murray sqr_add_c2(a, 4, 3, c2, c3, c1); 5835c87c606SMark Murray r[7] = c2; 5845c87c606SMark Murray c2 = 0; 5855c87c606SMark Murray sqr_add_c(a, 4, c3, c1, c2); 5865c87c606SMark Murray sqr_add_c2(a, 5, 3, c3, c1, c2); 5875c87c606SMark Murray sqr_add_c2(a, 6, 2, c3, c1, c2); 5885c87c606SMark Murray sqr_add_c2(a, 7, 1, c3, c1, c2); 5895c87c606SMark Murray r[8] = c3; 5905c87c606SMark Murray c3 = 0; 5915c87c606SMark Murray sqr_add_c2(a, 7, 2, c1, c2, c3); 5925c87c606SMark Murray sqr_add_c2(a, 6, 3, c1, c2, c3); 5935c87c606SMark Murray sqr_add_c2(a, 5, 4, c1, c2, c3); 5945c87c606SMark Murray r[9] = c1; 5955c87c606SMark Murray c1 = 0; 5965c87c606SMark Murray sqr_add_c(a, 5, c2, c3, c1); 5975c87c606SMark Murray sqr_add_c2(a, 6, 4, c2, c3, c1); 5985c87c606SMark Murray sqr_add_c2(a, 7, 3, c2, c3, c1); 5995c87c606SMark Murray r[10] = c2; 6005c87c606SMark Murray c2 = 0; 6015c87c606SMark Murray sqr_add_c2(a, 7, 4, c3, c1, c2); 6025c87c606SMark Murray sqr_add_c2(a, 6, 5, c3, c1, c2); 6035c87c606SMark Murray r[11] = c3; 6045c87c606SMark Murray c3 = 0; 6055c87c606SMark Murray sqr_add_c(a, 6, c1, c2, c3); 6065c87c606SMark Murray sqr_add_c2(a, 7, 5, c1, c2, c3); 6075c87c606SMark Murray r[12] = c1; 6085c87c606SMark Murray c1 = 0; 6095c87c606SMark Murray sqr_add_c2(a, 7, 6, c2, c3, c1); 6105c87c606SMark Murray r[13] = c2; 6115c87c606SMark Murray c2 = 0; 6125c87c606SMark Murray sqr_add_c(a, 7, c3, c1, c2); 6135c87c606SMark Murray r[14] = c3; 6145c87c606SMark Murray r[15] = c1; 6155c87c606SMark Murray } 6165c87c606SMark Murray 6176a599222SSimon L. B. Nielsen void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) 6185c87c606SMark Murray { 6195c87c606SMark Murray BN_ULONG c1, c2, c3; 6205c87c606SMark Murray 6215c87c606SMark Murray c1 = 0; 6225c87c606SMark Murray c2 = 0; 6235c87c606SMark Murray c3 = 0; 6245c87c606SMark Murray sqr_add_c(a, 0, c1, c2, c3); 6255c87c606SMark Murray r[0] = c1; 6265c87c606SMark Murray c1 = 0; 6275c87c606SMark Murray sqr_add_c2(a, 1, 0, c2, c3, c1); 6285c87c606SMark Murray r[1] = c2; 6295c87c606SMark Murray c2 = 0; 6305c87c606SMark Murray sqr_add_c(a, 1, c3, c1, c2); 6315c87c606SMark Murray sqr_add_c2(a, 2, 0, c3, c1, c2); 6325c87c606SMark Murray r[2] = c3; 6335c87c606SMark Murray c3 = 0; 6345c87c606SMark Murray sqr_add_c2(a, 3, 0, c1, c2, c3); 6355c87c606SMark Murray sqr_add_c2(a, 2, 1, c1, c2, c3); 6365c87c606SMark Murray r[3] = c1; 6375c87c606SMark Murray c1 = 0; 6385c87c606SMark Murray sqr_add_c(a, 2, c2, c3, c1); 6395c87c606SMark Murray sqr_add_c2(a, 3, 1, c2, c3, c1); 6405c87c606SMark Murray r[4] = c2; 6415c87c606SMark Murray c2 = 0; 6425c87c606SMark Murray sqr_add_c2(a, 3, 2, c3, c1, c2); 6435c87c606SMark Murray r[5] = c3; 6445c87c606SMark Murray c3 = 0; 6455c87c606SMark Murray sqr_add_c(a, 3, c1, c2, c3); 6465c87c606SMark Murray r[6] = c1; 6475c87c606SMark Murray r[7] = c2; 6485c87c606SMark Murray } 649ed5d4f9aSSimon L. B. Nielsen #endif 650