diff --git a/CMakeLists.txt b/CMakeLists.txt index f30e9ee6c..9aacdcba7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wno-pointer-to-int-cast") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2") +#set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-2") #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-generate") #set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fprofile-use -fprofile-correction") @@ -101,10 +101,11 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) set(CRYPTONIGHT64 algo/cryptonight/cryptonight_av1_aesni.c - algo/cryptonight/cryptonight_av2_aesni_wolf.c + algo/cryptonight/cryptonight_av3_aesni_alt.c algo/cryptonight/cryptonight_av4_softaes.c algo/cryptonight/cryptonight_av5_aesni_stak.c - algo/cryptonight/cryptonight_av6_aesni_experimental.c + algo/cryptonight/cryptonight_av6_aesni_stak_no_prefetch.c + algo/cryptonight/cryptonight_av7_aesni_experimental.c ) add_executable(xmrig ${HEADERS} ${HEADERS_CRYPTO} ${SOURCES} ${SOURCES_CRYPTO} ${HEADERS_UTILS} ${SOURCES_UTILS} ${HEADERS_COMPAT} ${SOURCES_COMPAT} ${SOURCES_OS} ${CRYPTONIGHT64}) diff --git a/algo/cryptonight/bmi2/CMakeLists.txt b/algo/cryptonight/bmi2/CMakeLists.txt index c9a3fd856..03c1e3f7f 100644 --- a/algo/cryptonight/bmi2/CMakeLists.txt +++ b/algo/cryptonight/bmi2/CMakeLists.txt @@ -1,2 +1,2 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbmi2") -add_library(cryptonight_av3_aesni_bmi2 STATIC ../cryptonight_av3_aesni_bmi2.c) +add_library(cryptonight_av3_aesni_bmi2 STATIC ../cryptonight_av2_aesni_bmi2.c) diff --git a/algo/cryptonight/cryptonight_av3_aesni_bmi2.c b/algo/cryptonight/cryptonight_av2_aesni_bmi2.c similarity index 99% rename from algo/cryptonight/cryptonight_av3_aesni_bmi2.c rename to algo/cryptonight/cryptonight_av2_aesni_bmi2.c index de94a62ef..15cf12c17 100644 --- a/algo/cryptonight/cryptonight_av3_aesni_bmi2.c +++ b/algo/cryptonight/cryptonight_av2_aesni_bmi2.c @@ -109,7 +109,7 @@ static inline void ExpandAESKey256(char *keybuf) } -void cryptonight_av3_aesni_bmi2(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) +void cryptonight_av2_aesni_bmi2(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) { uint64_t* state = ctx->state.hs.w; diff --git a/algo/cryptonight/cryptonight_av2_aesni_wolf.c b/algo/cryptonight/cryptonight_av3_aesni_alt.c similarity index 80% rename from algo/cryptonight/cryptonight_av2_aesni_wolf.c rename to algo/cryptonight/cryptonight_av3_aesni_alt.c index c13309110..d4d33ff4e 100644 --- a/algo/cryptonight/cryptonight_av2_aesni_wolf.c +++ b/algo/cryptonight/cryptonight_av3_aesni_alt.c @@ -22,6 +22,7 @@ */ #include +#include #include "cryptonight.h" #include "crypto/c_keccak.h" @@ -107,9 +108,9 @@ static inline void ExpandAESKey256(char *keybuf) keys[14] = tmp1; } -void cryptonight_av2_aesni_wolf(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) +void cryptonight_av3_aesni_alt(void *restrict output, const void *restrict input, const char *restrict memory, struct cryptonight_ctx *restrict ctx) { - keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200); + keccak((const uint8_t *)input, 76, (uint8_t *) &ctx->state.hs, 200); uint8_t ExpandedKey[256]; size_t i, j; @@ -118,7 +119,7 @@ void cryptonight_av2_aesni_wolf(void *restrict output, const void *restrict inpu ExpandAESKey256(ExpandedKey); __m128i *longoutput, *expkey, *xmminput; - longoutput = (__m128i *)memory; + longoutput = (__m128i *) memory; expkey = (__m128i *)ExpandedKey; xmminput = (__m128i *)ctx->text; @@ -151,63 +152,41 @@ void cryptonight_av2_aesni_wolf(void *restrict output, const void *restrict inpu ctx->b[i] = ((uint64_t *)ctx->state.k)[i+2] ^ ((uint64_t *)ctx->state.k)[i+6]; } - __m128i b_x = _mm_load_si128((__m128i *)ctx->b); - uint64_t a[2] __attribute((aligned(16))), b[2] __attribute((aligned(16))); - a[0] = ctx->a[0]; - a[1] = ctx->a[1]; + __m128i a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); + __m128i b_x = _mm_load_si128((__m128i *) ctx->b); - for(i = 0; __builtin_expect(i < 0x80000, 1); i++) - { - __m128i c_x = _mm_load_si128((__m128i *)&memory[a[0] & 0x1FFFF0]); - __m128i a_x = _mm_load_si128((__m128i *)a); - uint64_t c[2]; - c_x = _mm_aesenc_si128(c_x, a_x); + uint64_t c[2] __attribute((aligned(16))); + uint64_t d[2] __attribute((aligned(16))); - _mm_store_si128((__m128i *)c, c_x); - __builtin_prefetch(&memory[c[0] & 0x1FFFF0], 0, 1); + for (i = 0; __builtin_expect(i < 0x80000, 1); i++) { + __m128i c_x = _mm_aesenc_si128(a_x, _mm_load_si128((__m128i *) ctx->a)); + _mm_store_si128((__m128i *) c, c_x); - b_x = _mm_xor_si128(b_x, c_x); - _mm_store_si128((__m128i *)&memory[a[0] & 0x1FFFF0], b_x); + uint64_t *restrict d_ptr = (uint64_t *) &memory[c[0] & 0x1FFFF0]; + _mm_store_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0], _mm_xor_si128(b_x, c_x)); + b_x = c_x; - uint64_t *nextblock = (uint64_t *)&memory[c[0] & 0x1FFFF0]; - uint64_t b[2]; - b[0] = nextblock[0]; - b[1] = nextblock[1]; + d[0] = d_ptr[0]; + d[1] = d_ptr[1]; { - uint64_t hi, lo; - // hi,lo = 64bit x 64bit multiply of c[0] and b[0] + unsigned __int128 res = (unsigned __int128) c[0] * d[0]; - __asm__("mulq %3\n\t" - : "=d" (hi), - "=a" (lo) - : "%a" (c[0]), - "rm" (b[0]) - : "cc" ); - - a[0] += hi; - a[1] += lo; + d_ptr[0] = ctx->a[0] += res >> 64; + d_ptr[1] = ctx->a[1] += (uint64_t) res; } - uint64_t *dst = (uint64_t *) &memory[c[0] & 0x1FFFF0]; - dst[0] = a[0]; - dst[1] = a[1]; + ctx->a[0] ^= d[0]; + ctx->a[1] ^= d[1]; - a[0] ^= b[0]; - a[1] ^= b[1]; - b_x = c_x; - __builtin_prefetch(&memory[a[0] & 0x1FFFF0], 0, 3); + a_x = _mm_load_si128((__m128i *) &memory[ctx->a[0] & 0x1FFFF0]); } memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE); memcpy(ExpandedKey, &ctx->state.hs.b[32], AES_KEY_SIZE); ExpandAESKey256(ExpandedKey); - //for (i = 0; likely(i < MEMORY); i += INIT_SIZE_BYTE) - // aesni_parallel_xor(&ctx->text, ExpandedKey, &ctx->long_state[i]); - - for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) - { + for (i = 0; __builtin_expect(i < MEMORY, 1); i += INIT_SIZE_BYTE) { xmminput[0] = _mm_xor_si128(longoutput[(i >> 4)], xmminput[0]); xmminput[1] = _mm_xor_si128(longoutput[(i >> 4) + 1], xmminput[1]); xmminput[2] = _mm_xor_si128(longoutput[(i >> 4) + 2], xmminput[2]); diff --git a/algo/cryptonight/cryptonight_av6_aesni_stak_no_prefetch.c b/algo/cryptonight/cryptonight_av6_aesni_stak_no_prefetch.c new file mode 100644 index 000000000..f58031e06 --- /dev/null +++ b/algo/cryptonight/cryptonight_av6_aesni_stak_no_prefetch.c @@ -0,0 +1,269 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017 fireice-uk + * Copyright 2016-2017 XMRig + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "cryptonight.h" +#include "crypto/c_keccak.h" + + +#ifdef __GNUC__ +static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi) +{ + unsigned __int128 r = (unsigned __int128)a * (unsigned __int128)b; + *hi = r >> 64; + return (uint64_t)r; +} +#endif + +#define aes_genkey_sub(imm8) \ + __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, (imm8)); \ + xout1 = _mm_shuffle_epi32(xout1, 0xFF); \ + *xout0 = sl_xor(*xout0); \ + *xout0 = _mm_xor_si128(*xout0, xout1); \ + xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);\ + xout1 = _mm_shuffle_epi32(xout1, 0xAA); \ + *xout2 = sl_xor(*xout2); \ + *xout2 = _mm_xor_si128(*xout2, xout1); \ + + +// This will shift and xor tmp1 into itself as 4 32-bit vals such as +// sl_xor(a1 a2 a3 a4) = a1 (a2^a1) (a3^a2^a1) (a4^a3^a2^a1) +static inline __m128i sl_xor(__m128i tmp1) +{ + __m128i tmp4; + tmp4 = _mm_slli_si128(tmp1, 0x04); + tmp1 = _mm_xor_si128(tmp1, tmp4); + tmp4 = _mm_slli_si128(tmp4, 0x04); + tmp1 = _mm_xor_si128(tmp1, tmp4); + tmp4 = _mm_slli_si128(tmp4, 0x04); + tmp1 = _mm_xor_si128(tmp1, tmp4); + return tmp1; +} + + +static inline void aes_genkey_sub1(__m128i* xout0, __m128i* xout2) +{ + aes_genkey_sub(0x1) +} + + +static inline void aes_genkey_sub2(__m128i* xout0, __m128i* xout2) +{ + aes_genkey_sub(0x2) +} + + +static inline void aes_genkey_sub4(__m128i* xout0, __m128i* xout2) +{ + aes_genkey_sub(0x4) +} + + +static inline void aes_genkey_sub8(__m128i* xout0, __m128i* xout2) +{ + aes_genkey_sub(0x8) +} + + +static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9) +{ + __m128i xout0 = _mm_load_si128(memory); + __m128i xout2 = _mm_load_si128(memory + 1); + *k0 = xout0; + *k1 = xout2; + + aes_genkey_sub1(&xout0, &xout2); + *k2 = xout0; + *k3 = xout2; + + aes_genkey_sub2(&xout0, &xout2); + *k4 = xout0; + *k5 = xout2; + + aes_genkey_sub4(&xout0, &xout2); + *k6 = xout0; + *k7 = xout2; + + aes_genkey_sub8(&xout0, &xout2); + *k8 = xout0; + *k9 = xout2; +} + + +static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7) +{ + *x0 = _mm_aesenc_si128(*x0, key); + *x1 = _mm_aesenc_si128(*x1, key); + *x2 = _mm_aesenc_si128(*x2, key); + *x3 = _mm_aesenc_si128(*x3, key); + *x4 = _mm_aesenc_si128(*x4, key); + *x5 = _mm_aesenc_si128(*x5, key); + *x6 = _mm_aesenc_si128(*x6, key); + *x7 = _mm_aesenc_si128(*x7, key); +} + + +static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output) +{ + // This is more than we have registers, compiler will assign 2 keys on the stack + __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7; + __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; + + aes_genkey(input, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9); + + xin0 = _mm_load_si128(input + 4); + xin1 = _mm_load_si128(input + 5); + xin2 = _mm_load_si128(input + 6); + xin3 = _mm_load_si128(input + 7); + xin4 = _mm_load_si128(input + 8); + xin5 = _mm_load_si128(input + 9); + xin6 = _mm_load_si128(input + 10); + xin7 = _mm_load_si128(input + 11); + + for (size_t i = 0; i < MEMORY / sizeof(__m128i); i += 8) { + aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k3, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k4, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k5, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + aes_round(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); + + _mm_store_si128(output + i + 0, xin0); + _mm_store_si128(output + i + 1, xin1); + _mm_store_si128(output + i + 2, xin2); + _mm_store_si128(output + i + 3, xin3); + _mm_prefetch((const char*)output + i + 0, _MM_HINT_T2); + _mm_store_si128(output + i + 4, xin4); + _mm_store_si128(output + i + 5, xin5); + _mm_store_si128(output + i + 6, xin6); + _mm_store_si128(output + i + 7, xin7); + _mm_prefetch((const char*)output + i + 4, _MM_HINT_T2); + } +} + + +static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output) +{ + // This is more than we have registers, compiler will assign 2 keys on the stack + __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; + __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; + + aes_genkey(output + 2, &k0, &k1, &k2, &k3, &k4, &k5, &k6, &k7, &k8, &k9); + + xout0 = _mm_load_si128(output + 4); + xout1 = _mm_load_si128(output + 5); + xout2 = _mm_load_si128(output + 6); + xout3 = _mm_load_si128(output + 7); + xout4 = _mm_load_si128(output + 8); + xout5 = _mm_load_si128(output + 9); + xout6 = _mm_load_si128(output + 10); + xout7 = _mm_load_si128(output + 11); + + for (size_t i = 0; i < MEMORY / sizeof(__m128i); i += 8) + { + _mm_prefetch((const char*)input + i + 0, _MM_HINT_NTA); + xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0); + xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1); + xout2 = _mm_xor_si128(_mm_load_si128(input + i + 2), xout2); + xout3 = _mm_xor_si128(_mm_load_si128(input + i + 3), xout3); + _mm_prefetch((const char*)input + i + 4, _MM_HINT_NTA); + xout4 = _mm_xor_si128(_mm_load_si128(input + i + 4), xout4); + xout5 = _mm_xor_si128(_mm_load_si128(input + i + 5), xout5); + xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6); + xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7); + + aes_round(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k3, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k4, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k5, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); + } + + _mm_store_si128(output + 4, xout0); + _mm_store_si128(output + 5, xout1); + _mm_store_si128(output + 6, xout2); + _mm_store_si128(output + 7, xout3); + _mm_store_si128(output + 8, xout4); + _mm_store_si128(output + 9, xout5); + _mm_store_si128(output + 10, xout6); + _mm_store_si128(output + 11, xout7); +} + + +void cryptonight_av6_aesni_stak_no_prefetch(void *restrict output, const void *restrict input, char *restrict memory, struct cryptonight_ctx *restrict ctx) +{ + keccak((const uint8_t *) input, 76, (uint8_t *) &ctx->state.hs, 200); + + cn_explode_scratchpad((__m128i*) &ctx->state.hs, (__m128i*) memory); + + const uint8_t* l0 = memory; + uint64_t* h0 = (uint64_t*) &ctx->state.hs; + + uint64_t al0 = h0[0] ^ h0[4]; + uint64_t ah0 = h0[1] ^ h0[5]; + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + + uint64_t idx0 = h0[0] ^ h0[4]; + + for (size_t i = 0; __builtin_expect(i < 0x80000, 1); i++) { + __m128i cx; + cx = _mm_load_si128((__m128i *)&l0[idx0 & 0x1FFFF0]); + cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); + + _mm_store_si128((__m128i *)&l0[idx0 & 0x1FFFF0], _mm_xor_si128(bx0, cx)); + idx0 = _mm_cvtsi128_si64(cx); + bx0 = cx; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*)&l0[idx0 & 0x1FFFF0])[0]; + ch = ((uint64_t*)&l0[idx0 & 0x1FFFF0])[1]; + lo = _umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ((uint64_t*)&l0[idx0 & 0x1FFFF0])[0] = al0; + ((uint64_t*)&l0[idx0 & 0x1FFFF0])[1] = ah0; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + } + + cn_implode_scratchpad((__m128i*) memory, (__m128i*) &ctx->state.hs); + + keccakf((uint64_t*) &ctx->state.hs, 24); + extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output); +} diff --git a/algo/cryptonight/cryptonight_av6_aesni_experimental.c b/algo/cryptonight/cryptonight_av7_aesni_experimental.c similarity index 97% rename from algo/cryptonight/cryptonight_av6_aesni_experimental.c rename to algo/cryptonight/cryptonight_av7_aesni_experimental.c index 1ee79f06f..99eb3df05 100644 --- a/algo/cryptonight/cryptonight_av6_aesni_experimental.c +++ b/algo/cryptonight/cryptonight_av7_aesni_experimental.c @@ -29,15 +29,6 @@ #include "crypto/c_keccak.h" -#ifdef __GNUC__ -static inline uint64_t _umul128(uint64_t a, uint64_t b, uint64_t* hi) -{ - unsigned __int128 r = (unsigned __int128)a * (unsigned __int128)b; - *hi = r >> 64; - return (uint64_t)r; -} -#endif - #define aes_genkey_sub(imm8) \ __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, (imm8)); \ xout1 = _mm_shuffle_epi32(xout1, 0xFF); \ @@ -222,7 +213,7 @@ static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output) } -void cryptonight_av6_aesni_experimental(void *restrict output, const void *restrict input, char *restrict memory, struct cryptonight_ctx *restrict ctx) +void cryptonight_av7_aesni_experimental(void *restrict output, const void *restrict input, char *restrict memory, struct cryptonight_ctx *restrict ctx) { uint64_t* state = ctx->state.hs.w; diff --git a/algo/cryptonight/cryptonight_common.c b/algo/cryptonight/cryptonight_common.c index d63234f47..babe66d91 100644 --- a/algo/cryptonight/cryptonight_common.c +++ b/algo/cryptonight/cryptonight_common.c @@ -38,10 +38,11 @@ #if defined(__x86_64__) void cryptonight_av1_aesni(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); - void cryptonight_av2_aesni_wolf(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); - void cryptonight_av3_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); + void cryptonight_av2_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); + void cryptonight_av3_aesni_alt(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); void cryptonight_av5_aesni_stak(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); - void cryptonight_av6_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); + void cryptonight_av6_aesni_stak_no_prefetch(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); + void cryptonight_av7_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); #elif defined(__i386__) void cryptonight_av1_aesni32(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); #endif @@ -55,32 +56,37 @@ void cryptonight_init(int variant) { switch (variant) { #if defined(__x86_64__) - case XMR_VARIANT_AESNI: + case XMR_AV1_AESNI: cryptonight_hash_ctx = cryptonight_av1_aesni; break; - case XMR_VARIANT_AESNI_WOLF: - cryptonight_hash_ctx = cryptonight_av2_aesni_wolf; + case XMR_AV2_AESNI_BMI2: + cryptonight_hash_ctx = cryptonight_av2_aesni_bmi2; break; - case XMR_VARIANT_AESNI_BMI2: - cryptonight_hash_ctx = cryptonight_av3_aesni_bmi2; + case XMR_AV3_AESNI_ALT: + cryptonight_hash_ctx = cryptonight_av3_aesni_alt; break; - case XMR_VARIANT_STAK: + case XMR_AV5_STAK: cryptonight_hash_ctx = cryptonight_av5_aesni_stak; break; - case XMR_VARIANT_EXPERIMENTAL: - cryptonight_hash_ctx = cryptonight_av6_aesni_experimental; + case XMR_AV6_STAK_NO_PREFETCH: + cryptonight_hash_ctx = cryptonight_av6_aesni_stak_no_prefetch; break; + + case XMR_AV7_EXPERIMENTAL: + cryptonight_hash_ctx = cryptonight_av7_aesni_experimental; + break; + #elif defined(__i386__) case XMR_VARIANT_AESNI: cryptonight_hash_ctx = cryptonight_av1_aesni32; break; #endif - case XMR_VARIANT_LEGACY: + case XMR_AV4_SOFT_AES: cryptonight_hash_ctx = cryptonight_av4_softaes; break; diff --git a/options.c b/options.c index e4b6e799d..ed5aa857b 100644 --- a/options.c +++ b/options.c @@ -102,19 +102,15 @@ static struct option const options[] = { static int get_algo_variant(int variant) { - if (variant > XMR_VARIANT_AUTO && variant < XMR_VARIANT_MAX) { + if (variant > XMR_AV0_AUTO && variant < XMR_AV_MAX) { return variant; } if (cpu_info.flags & CPU_FLAG_AES) { - if (cpu_info.flags & CPU_FLAG_BMI2) { - return XMR_VARIANT_AESNI_BMI2; - } - - return XMR_VARIANT_AESNI; + return XMR_AV1_AESNI; } - return XMR_VARIANT_LEGACY; + return XMR_AV4_SOFT_AES; } @@ -237,7 +233,7 @@ static void parse_arg(int key, char *arg) { case 'v': /* --av */ v = atoi(arg); - if (v < 0 || v > XMR_VARIANT_MAX) { + if (v < 0 || v > XMR_AV_MAX) { show_usage_and_exit(1); } diff --git a/options.h b/options.h index f995a24eb..fe27cc2d7 100644 --- a/options.h +++ b/options.h @@ -33,14 +33,15 @@ enum xmr_algo_variant { - XMR_VARIANT_AUTO, - XMR_VARIANT_AESNI, - XMR_VARIANT_AESNI_WOLF, - XMR_VARIANT_AESNI_BMI2, - XMR_VARIANT_LEGACY, - XMR_VARIANT_STAK, - XMR_VARIANT_EXPERIMENTAL, - XMR_VARIANT_MAX + XMR_AV0_AUTO, + XMR_AV1_AESNI, + XMR_AV2_AESNI_BMI2, + XMR_AV3_AESNI_ALT, + XMR_AV4_SOFT_AES, + XMR_AV5_STAK, + XMR_AV6_STAK_NO_PREFETCH, + XMR_AV7_EXPERIMENTAL, + XMR_AV_MAX }; diff --git a/test/cryptonight/CMakeLists.txt b/test/cryptonight/CMakeLists.txt index a1e34482d..7cd314015 100644 --- a/test/cryptonight/CMakeLists.txt +++ b/test/cryptonight/CMakeLists.txt @@ -16,12 +16,13 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8) add_executable(cryptonight_app ${SOURCES} cryptonight.c ../../algo/cryptonight/cryptonight_av1_aesni.c - ../../algo/cryptonight/cryptonight_av2_aesni_wolf.c + ../../algo/cryptonight/cryptonight_av3_aesni_alt.c ../../algo/cryptonight/cryptonight_av5_aesni_stak.c - ../../algo/cryptonight/cryptonight_av6_aesni_experimental.c + ../../algo/cryptonight/cryptonight_av6_aesni_stak_no_prefetch.c + ../../algo/cryptonight/cryptonight_av7_aesni_experimental.c ) - target_link_libraries(cryptonight_app unity cryptonight_av3_aesni_bmi2) + target_link_libraries(cryptonight_app unity cryptonight_av2_aesni_bmi2) else() add_executable(cryptonight_app ${SOURCES} cryptonight32.c diff --git a/test/cryptonight/bmi2/CMakeLists.txt b/test/cryptonight/bmi2/CMakeLists.txt index 785709a9f..bfabb5564 100644 --- a/test/cryptonight/bmi2/CMakeLists.txt +++ b/test/cryptonight/bmi2/CMakeLists.txt @@ -1,3 +1,3 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -mbmi2") include_directories(../../..) -add_library(cryptonight_av3_aesni_bmi2 STATIC ../../../algo/cryptonight/cryptonight_av3_aesni_bmi2.c) +add_library(cryptonight_av2_aesni_bmi2 STATIC ../../../algo/cryptonight/cryptonight_av2_aesni_bmi2.c) diff --git a/test/cryptonight/cryptonight.c b/test/cryptonight/cryptonight.c index 6d246ea3e..eca192668 100644 --- a/test/cryptonight/cryptonight.c +++ b/test/cryptonight/cryptonight.c @@ -5,22 +5,30 @@ void cryptonight_av1_aesni(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); -void cryptonight_av2_aesni_wolf(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); -void cryptonight_av3_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); +void cryptonight_av2_aesni_bmi2(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); +void cryptonight_av3_aesni_alt(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); void cryptonight_av4_softaes(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); void cryptonight_av5_aesni_stak(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); -void cryptonight_av6_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); +void cryptonight_av6_aesni_stak_no_prefetch(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); +void cryptonight_av7_aesni_experimental(void* output, const void* input, const char *memory, struct cryptonight_ctx* ctx); + + +char hash[32]; +char data[76]; + +#define RESULT "1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100" char *bin2hex(const unsigned char *p, size_t len) { - int i; char *s = malloc((len * 2) + 1); - if (!s) + if (!s) { return NULL; + } - for (i = 0; i < len; i++) + for (int i = 0; i < len; i++) { sprintf(s + (i * 2), "%02x", (unsigned int) p[i]); + } return s; } @@ -52,87 +60,62 @@ bool hex2bin(unsigned char *p, const char *hexstr, size_t len) void test_cryptonight_av1_should_CalcHash(void) { - char hash[32]; - char data[76]; - - hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); - uint8_t *memory = (uint8_t *) malloc(MEMORY); - struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); + struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) malloc(sizeof(struct cryptonight_ctx)); cryptonight_av1_aesni(&hash, data, memory, ctx); free(memory); free(ctx); - TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); + TEST_ASSERT_EQUAL_STRING(RESULT, bin2hex(hash, 32)); } void test_cryptonight_av2_should_CalcHash(void) { - char hash[32]; - char data[76]; - - hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); - uint8_t *memory = (uint8_t *) malloc(MEMORY); struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); - cryptonight_av2_aesni_wolf(&hash, data, memory, ctx); + cryptonight_av2_aesni_bmi2(&hash, data, memory, ctx); free(memory); free(ctx); - TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); + TEST_ASSERT_EQUAL_STRING(RESULT, bin2hex(hash, 32)); } void test_cryptonight_av3_should_CalcHash(void) { - char hash[32]; - char data[76]; - - hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); - uint8_t *memory = (uint8_t *) malloc(MEMORY); - struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); + struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) malloc(sizeof(struct cryptonight_ctx)); - cryptonight_av3_aesni_bmi2(&hash, data, memory, ctx); + cryptonight_av3_aesni_alt(&hash, data, memory, ctx); free(memory); free(ctx); - TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); + TEST_ASSERT_EQUAL_STRING(RESULT, bin2hex(hash, 32)); } void test_cryptonight_av4_should_CalcHash(void) { - char hash[32]; - char data[76]; - - hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); - uint8_t *memory = (uint8_t *) malloc(MEMORY); - struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); + struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) malloc(sizeof(struct cryptonight_ctx)); cryptonight_av4_softaes(&hash, data, memory, ctx); free(memory); free(ctx); - TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); + TEST_ASSERT_EQUAL_STRING(RESULT, bin2hex(hash, 32)); } void test_cryptonight_av5_should_CalcHash(void) { - char hash[32]; - char data[76]; - - hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); - uint8_t *memory = (uint8_t *) malloc(MEMORY); struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); @@ -141,31 +124,42 @@ void test_cryptonight_av5_should_CalcHash(void) free(memory); free(ctx); - TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); + TEST_ASSERT_EQUAL_STRING(RESULT, bin2hex(hash, 32)); } void test_cryptonight_av6_should_CalcHash(void) { - char hash[32]; - char data[76]; - - hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); - uint8_t *memory = (uint8_t *) malloc(MEMORY); struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); - cryptonight_av6_aesni_experimental(&hash, data, memory, ctx); + cryptonight_av6_aesni_stak_no_prefetch(&hash, data, memory, ctx); free(memory); free(ctx); - TEST_ASSERT_EQUAL_STRING("1a3ffbee909b420d91f7be6e5fb56db71b3110d886011e877ee5786afd080100", bin2hex(hash, 32)); + TEST_ASSERT_EQUAL_STRING(RESULT, bin2hex(hash, 32)); +} + + +void test_cryptonight_av7_should_CalcHash(void) +{ + uint8_t *memory = (uint8_t *) malloc(MEMORY); + struct cryptonight_ctx *ctx = (struct cryptonight_ctx*)malloc(sizeof(struct cryptonight_ctx)); + + cryptonight_av7_aesni_experimental(&hash, data, memory, ctx); + + free(memory); + free(ctx); + + TEST_ASSERT_EQUAL_STRING(RESULT, bin2hex(hash, 32)); } int main(void) { + hex2bin((unsigned char *) &data, "0305a0dbd6bf05cf16e503f3a66f78007cbf34144332ecbfc22ed95c8700383b309ace1923a0964b00000008ba939a62724c0d7581fce5761e9d8a0e6a1c3f924fdd8493d1115649c05eb601", 76); + UNITY_BEGIN(); RUN_TEST(test_cryptonight_av1_should_CalcHash); @@ -174,6 +168,7 @@ int main(void) RUN_TEST(test_cryptonight_av4_should_CalcHash); RUN_TEST(test_cryptonight_av5_should_CalcHash); RUN_TEST(test_cryptonight_av6_should_CalcHash); + RUN_TEST(test_cryptonight_av7_should_CalcHash); return UNITY_END(); }