X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fsparcv9cap.c;h=c8c567536b33d78cedf4c650cebc64b84ee62b05;hp=1731ef65f1ec7b8dc0ed15c43bcad3b4eb20ff24;hb=939ef2ea114235f94124832c804161f735cec6c8;hpb=7aa0b022460e1a7bfdf5c70e8cd084d916bac012 diff --git a/crypto/sparcv9cap.c b/crypto/sparcv9cap.c index 1731ef65f1..c8c567536b 100644 --- a/crypto/sparcv9cap.c +++ b/crypto/sparcv9cap.c @@ -1,3 +1,12 @@ +/* + * Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + #include #include #include @@ -6,6 +15,7 @@ #include #include #include +#include "internal/cryptlib.h" #include "sparc_arch.h" @@ -60,9 +70,18 @@ int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, if ((OPENSSL_sparcv9cap_P[0] & SPARCV9_VIS3)) return bn_mul_mont_vis3(rp, ap, bp, np, n0, num); else if (num >= 8 && - (OPENSSL_sparcv9cap_P[0] & - (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) == - (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) + /* + * bn_mul_mont_fpu doesn't use FMADD, we just use the + * flag to detect when FPU path is preferable in cases + * when current heuristics is unreliable. [it works + * out because FMADD-capable processors where FPU + * code path is undesirable are also VIS3-capable and + * VIS3 code path takes precedence.] + */ + ( (OPENSSL_sparcv9cap_P[0] & SPARCV9_FMADD) || + (OPENSSL_sparcv9cap_P[0] & + (SPARCV9_PREFER_FPU | SPARCV9_VIS1)) == + (SPARCV9_PREFER_FPU | SPARCV9_VIS1) )) return bn_mul_mont_fpu(rp, ap, bp, np, n0, num); } return bn_mul_mont_int(rp, ap, bp, np, n0, num); @@ -75,11 +94,12 @@ void _sparcv9_vis2_probe(void); void _sparcv9_fmadd_probe(void); unsigned long _sparcv9_rdcfr(void); void _sparcv9_vis3_probe(void); +void _sparcv9_fjaesx_probe(void); unsigned long _sparcv9_random(void); size_t _sparcv9_vis1_instrument_bus(unsigned int *, size_t); size_t _sparcv9_vis1_instrument_bus2(unsigned int *, size_t, size_t); -unsigned long OPENSSL_rdtsc(void) +uint32_t OPENSSL_rdtsc(void) { if (OPENSSL_sparcv9cap_P[0] & SPARCV9_TICK_PRIVILEGED) #if defined(__sun) && defined(__SVR4) @@ -115,6 +135,17 @@ static void common_handler(int sig) siglongjmp(common_jmp, sig); } +#if defined(__sun) && defined(__SVR4) +# if defined(__GNUC__) && __GNUC__>=2 +extern unsigned int getisax(unsigned int vec[], unsigned int sz) __attribute__ ((weak)); +# elif defined(__SUNPRO_C) +#pragma weak getisax +extern unsigned int getisax(unsigned int vec[], unsigned int sz); +# else +static unsigned int (*getisax) (unsigned int vec[], unsigned int sz) = NULL; +# endif +#endif + void OPENSSL_cpuid_setup(void) { char *e; @@ -133,6 +164,50 @@ void OPENSSL_cpuid_setup(void) return; } +#if defined(__sun) && defined(__SVR4) + if (getisax != NULL) { + unsigned int vec[2] = { 0, 0 }; + + if (getisax (vec,2)) { + if (vec[0]&0x00020) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS1; + if (vec[0]&0x00040) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS2; + if (vec[0]&0x00080) OPENSSL_sparcv9cap_P[0] |= SPARCV9_BLK; + if (vec[0]&0x00100) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FMADD; + if (vec[0]&0x00400) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3; + if (vec[0]&0x01000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJHPCACE; + if (vec[0]&0x02000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJDESX; + if (vec[0]&0x08000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_IMA; + if (vec[0]&0x10000) OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX; + if (vec[1]&0x00008) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS4; + + /* reconstruct %cfr copy */ + OPENSSL_sparcv9cap_P[1] = (vec[0]>>17)&0x3ff; + OPENSSL_sparcv9cap_P[1] |= (OPENSSL_sparcv9cap_P[1]&CFR_MONTMUL)<<1; + if (vec[0]&0x20000000) OPENSSL_sparcv9cap_P[1] |= CFR_CRC32C; + if (vec[1]&0x00000020) OPENSSL_sparcv9cap_P[1] |= CFR_XMPMUL; + if (vec[1]&0x00000040) + OPENSSL_sparcv9cap_P[1] |= CFR_XMONTMUL|CFR_XMONTSQR; + + /* Some heuristics */ + /* all known VIS2-capable CPUs have unprivileged tick counter */ + if (OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS2) + OPENSSL_sparcv9cap_P[0] &= ~SPARCV9_TICK_PRIVILEGED; + + OPENSSL_sparcv9cap_P[0] |= SPARCV9_PREFER_FPU; + + /* detect UltraSPARC-Tx, see sparccpud.S for details... */ + if ((OPENSSL_sparcv9cap_P[0]&SPARCV9_VIS1) && + _sparcv9_vis1_instrument() >= 12) + OPENSSL_sparcv9cap_P[0] &= ~(SPARCV9_VIS1 | SPARCV9_PREFER_FPU); + } + + if (sizeof(size_t) == 8) + OPENSSL_sparcv9cap_P[0] |= SPARCV9_64BIT_STACK; + + return; + } +#endif + /* Initial value, fits UltraSPARC-I&II... */ OPENSSL_sparcv9cap_P[0] = SPARCV9_PREFER_FPU | SPARCV9_TICK_PRIVILEGED; @@ -186,6 +261,11 @@ void OPENSSL_cpuid_setup(void) OPENSSL_sparcv9cap_P[0] |= SPARCV9_VIS3; } + if (sigsetjmp(common_jmp, 1) == 0) { + _sparcv9_fjaesx_probe(); + OPENSSL_sparcv9cap_P[0] |= SPARCV9_FJAESX; + } + /* * In wait for better solution _sparcv9_rdcfr is masked by * VIS3 flag, because it goes to uninterruptable endless