From 1f0e3e501cece285744e700d0da95ede52a37fc5 Mon Sep 17 00:00:00 2001 From: XMRig Date: Thu, 13 Jun 2019 22:08:52 +0700 Subject: [PATCH] Implemented new style algorithm definitions (except ARM), removed Algo and Variant enums. --- CMakeLists.txt | 6 +- cmake/asm.cmake | 5 +- src/Mem.cpp | 13 +- src/Mem.h | 4 +- src/Mem_win.cpp | 1 - src/Summary.cpp | 4 +- src/common/cpu/BasicCpuInfo.cpp | 2 +- src/common/xmrig.h | 33 -- src/core/config/Config.cpp | 57 +- src/core/config/Config.h | 2 +- src/crypto/cn/CnAlgo.h | 207 +++++++ src/crypto/cn/CnHash.cpp | 269 +++++++++ src/crypto/cn/CnHash.h | 63 ++ src/crypto/cn/CryptoNight.h | 4 +- src/crypto/cn/CryptoNight_constants.h | 251 -------- src/crypto/cn/CryptoNight_monero.h | 36 +- src/crypto/cn/CryptoNight_test.h | 15 - src/crypto/cn/CryptoNight_x86.h | 784 ++++++++++++++----------- src/crypto/cn/gpu/cn_gpu_avx.cpp | 6 +- src/crypto/cn/gpu/cn_gpu_ssse3.cpp | 6 +- src/crypto/cn/r/variant4_random_math.h | 19 +- src/crypto/common/Algorithm.cpp | 81 ++- src/crypto/common/Algorithm.h | 15 +- src/interfaces/IThread.h | 4 +- src/workers/CpuThread.cpp | 544 +---------------- src/workers/CpuThread.h | 20 +- src/workers/MultiWorker.cpp | 88 +-- src/workers/MultiWorker.h | 17 +- src/workers/Workers.cpp | 21 +- src/workers/Workers.h | 5 +- 30 files changed, 1223 insertions(+), 1359 deletions(-) create mode 100644 src/crypto/cn/CnAlgo.h create mode 100644 src/crypto/cn/CnHash.cpp create mode 100644 src/crypto/cn/CnHash.h delete mode 100644 src/crypto/cn/CryptoNight_constants.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 30625d28..9c70a673 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,8 @@ set(HEADERS_CRYPTO src/crypto/cn/c_groestl.h src/crypto/cn/c_jh.h src/crypto/cn/c_skein.h - src/crypto/cn/CryptoNight_constants.h + src/crypto/cn/CnAlgo.h + src/crypto/cn/CnHash.h src/crypto/cn/CryptoNight_monero.h src/crypto/cn/CryptoNight_test.h src/crypto/cn/CryptoNight.h @@ -102,10 +103,11 @@ set(SOURCES ) set(SOURCES_CRYPTO - src/crypto/cn/c_groestl.c src/crypto/cn/c_blake256.c + src/crypto/cn/c_groestl.c src/crypto/cn/c_jh.c src/crypto/cn/c_skein.c + src/crypto/cn/CnHash.cpp src/crypto/common/Algorithm.cpp ) diff --git a/cmake/asm.cmake b/cmake/asm.cmake index 25cccead..d3010e51 100644 --- a/cmake/asm.cmake +++ b/cmake/asm.cmake @@ -38,8 +38,11 @@ if (WITH_ASM AND NOT XMRIG_ARM AND CMAKE_SIZEOF_VOID_P EQUAL 8) add_library(${XMRIG_ASM_LIBRARY} STATIC ${XMRIG_ASM_FILES}) set(XMRIG_ASM_SOURCES src/crypto/cn/Asm.h src/crypto/cn/Asm.cpp src/crypto/cn/r/CryptonightR_gen.cpp) set_property(TARGET ${XMRIG_ASM_LIBRARY} PROPERTY LINKER_LANGUAGE C) + + add_definitions(/DXMRIG_FEATURE_ASM) else() set(XMRIG_ASM_SOURCES "") set(XMRIG_ASM_LIBRARY "") - add_definitions(/DXMRIG_NO_ASM) + + remove_definitions(/DXMRIG_FEATURE_ASM) endif() diff --git a/src/Mem.cpp b/src/Mem.cpp index b9e0fbf9..574c5ff2 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -27,7 +27,6 @@ #include -#include "crypto/cn/CryptoNight_constants.h" #include "crypto/cn/CryptoNight.h" #include "crypto/common/portable/mm_malloc.h" #include "crypto/common/VirtualMemory.h" @@ -38,12 +37,14 @@ bool Mem::m_enabled = true; int Mem::m_flags = 0; -MemInfo Mem::create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count) +MemInfo Mem::create(cryptonight_ctx **ctx, const xmrig::Algorithm &algorithm, size_t count) { using namespace xmrig; + constexpr CnAlgo props; + MemInfo info; - info.size = cn_select_memory(algorithm) * count; + info.size = props.memory(algorithm.id()) * count; constexpr const size_t align_size = 2 * 1024 * 1024; info.size = ((info.size + align_size - 1) / align_size) * align_size; @@ -53,10 +54,10 @@ MemInfo Mem::create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count) for (size_t i = 0; i < count; ++i) { cryptonight_ctx *c = static_cast(_mm_malloc(sizeof(cryptonight_ctx), 4096)); - c->memory = info.memory + (i * cn_select_memory(algorithm)); + c->memory = info.memory + (i * props.memory(algorithm.id())); - c->generated_code = reinterpret_cast(xmrig::VirtualMemory::allocateExecutableMemory(0x4000)); - c->generated_code_data.variant = xmrig::VARIANT_MAX; + c->generated_code = reinterpret_cast(VirtualMemory::allocateExecutableMemory(0x4000)); + c->generated_code_data.algo = Algorithm::INVALID; c->generated_code_data.height = std::numeric_limits::max(); ctx[i] = c; diff --git a/src/Mem.h b/src/Mem.h index bfb36b00..f43e005d 100644 --- a/src/Mem.h +++ b/src/Mem.h @@ -31,7 +31,7 @@ #include -#include "common/xmrig.h" +#include "crypto/cn/CnAlgo.h" struct cryptonight_ctx; @@ -56,7 +56,7 @@ public: Lock = 4 }; - static MemInfo create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count); + static MemInfo create(cryptonight_ctx **ctx, const xmrig::Algorithm &algorithm, size_t count); static void init(bool enabled); static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info); diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index 76cbf434..34460e9d 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -34,7 +34,6 @@ #include "common/xmrig.h" #include "crypto/common/portable/mm_malloc.h" #include "crypto/common/VirtualMemory.h" -#include "crypto/cn/CryptoNight_constants.h" #include "crypto/cn/CryptoNight.h" #include "Mem.h" diff --git a/src/Summary.cpp b/src/Summary.cpp index d780d64f..2ba0fd57 100644 --- a/src/Summary.cpp +++ b/src/Summary.cpp @@ -39,7 +39,7 @@ #include "version.h" -#ifndef XMRIG_NO_ASM +#ifdef XMRIG_FEATURE_ASM static const char *coloredAsmNames[] = { RED_BOLD("none"), "auto", @@ -108,7 +108,7 @@ static void print_threads(xmrig::Config *config) ); } -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM if (config->assembly() == xmrig::ASM_AUTO) { const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly(); diff --git a/src/common/cpu/BasicCpuInfo.cpp b/src/common/cpu/BasicCpuInfo.cpp index d7778bdd..c5b8ed0a 100644 --- a/src/common/cpu/BasicCpuInfo.cpp +++ b/src/common/cpu/BasicCpuInfo.cpp @@ -129,7 +129,7 @@ xmrig::BasicCpuInfo::BasicCpuInfo() : { cpu_brand_string(m_brand); -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM if (hasAES()) { char vendor[13] = { 0 }; int32_t data[4] = { 0 }; diff --git a/src/common/xmrig.h b/src/common/xmrig.h index e8ca8857..5dd41845 100644 --- a/src/common/xmrig.h +++ b/src/common/xmrig.h @@ -30,16 +30,6 @@ namespace xmrig { -enum Algo { - INVALID_ALGO = -1, - CRYPTONIGHT, /* CryptoNight (2 MB) */ - CRYPTONIGHT_LITE, /* CryptoNight (1 MB) */ - CRYPTONIGHT_HEAVY, /* CryptoNight (4 MB) */ - CRYPTONIGHT_PICO, /* CryptoNight (256 KB) */ - ALGO_MAX -}; - - //--av=1 For CPUs with hardware AES. //--av=2 Lower power mode (double hash) of 1. //--av=3 Software AES implementation. @@ -60,29 +50,6 @@ enum AlgoVariant { }; -enum Variant { - VARIANT_AUTO = -1, // Autodetect - VARIANT_0 = 0, // Original CryptoNight or CryptoNight-Heavy - VARIANT_1 = 1, // CryptoNight variant 1 also known as Monero7 and CryptoNightV7 - VARIANT_TUBE = 2, // Modified CryptoNight-Heavy (TUBE only) - VARIANT_XTL = 3, // Modified CryptoNight variant 1 (Stellite only) - VARIANT_MSR = 4, // Modified CryptoNight variant 1 (Masari only) - VARIANT_XHV = 5, // Modified CryptoNight-Heavy (Haven Protocol only) - VARIANT_XAO = 6, // Modified CryptoNight variant 0 (Alloy only) - VARIANT_RTO = 7, // Modified CryptoNight variant 1 (Arto only) - VARIANT_2 = 8, // CryptoNight variant 2 - VARIANT_HALF = 9, // CryptoNight variant 2 with half iterations (Masari/Stellite) - VARIANT_TRTL = 10, // CryptoNight Turtle (TRTL) - VARIANT_GPU = 11, // CryptoNight-GPU (Ryo) - VARIANT_WOW = 12, // CryptoNightR (Wownero) - VARIANT_4 = 13, // CryptoNightR (Monero's variant 4) - VARIANT_RWZ = 14, // CryptoNight variant 2 with 3/4 iterations and reversed shuffle operation (Graft) - VARIANT_ZLS = 15, // CryptoNight variant 2 with 3/4 iterations (Zelerius) - VARIANT_DOUBLE = 16, // CryptoNight variant 2 with double iterations (X-CASH) - VARIANT_MAX -}; - - enum AlgoVerify { VERIFY_HW_AES = 1, VERIFY_SOFT_AES = 2 diff --git a/src/core/config/Config.cpp b/src/core/config/Config.cpp index fbb12ffa..d82c3225 100644 --- a/src/core/config/Config.cpp +++ b/src/core/config/Config.cpp @@ -33,7 +33,6 @@ #include "common/cpu/Cpu.h" #include "core/config/Config.h" #include "crypto/cn/Asm.h" -#include "crypto/cn/CryptoNight_constants.h" #include "rapidjson/document.h" #include "rapidjson/filewritestream.h" #include "rapidjson/prettywriter.h" @@ -71,7 +70,7 @@ bool xmrig::Config::read(const IJsonReader &reader, const char *fileName) setPriority(reader.getInt("cpu-priority", -1)); setThreads(reader.getValue("threads")); -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM setAssembly(reader.getValue("asm")); # endif @@ -93,7 +92,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const doc.AddMember("api", api, allocator); doc.AddMember("http", m_http.toJSON(doc), allocator); -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM doc.AddMember("asm", Asm::toJSON(m_assembly), allocator); # endif @@ -144,37 +143,39 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const bool xmrig::Config::finalize() { -// if (!m_threads.cpu.empty()) { // FIXME -// m_threads.mode = Advanced; -// const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; + Algorithm algorithm(Algorithm::CN_0); // FIXME algo -// for (size_t i = 0; i < m_threads.cpu.size(); ++i) { -//// m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm.algo(), m_threads.cpu[i], m_priority, softAES)); -// } + if (!m_threads.cpu.empty()) { + m_threads.mode = Advanced; + const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT; -// return true; -// } + for (size_t i = 0; i < m_threads.cpu.size(); ++i) { + m_threads.list.push_back(CpuThread::createFromData(i, algorithm, m_threads.cpu[i], m_priority, softAES)); + } -// const AlgoVariant av = getAlgoVariant(); -// m_threads.mode = m_threads.count ? Simple : Automatic; + return true; + } -//// const size_t size = CpuThread::multiway(av) * cn_select_memory(m_algorithm.algo()) / 1024; + const AlgoVariant av = getAlgoVariant(); + m_threads.mode = m_threads.count ? Simple : Automatic; -// if (!m_threads.count) { -// m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage); -// } -// else if (m_safe) { -// const size_t count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage); -// if (m_threads.count > count) { -// m_threads.count = count; -// } -// } + const size_t size = CpuThread::multiway(av) * CnAlgo<>::memory(algorithm) / 1024; -// for (size_t i = 0; i < m_threads.count; ++i) { -// m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm.algo(), av, m_threads.mask, m_priority, m_assembly)); -// } + if (!m_threads.count) { + m_threads.count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage); + } + else if (m_safe) { + const size_t count = Cpu::info()->optimalThreadsCount(size, m_maxCpuUsage); + if (m_threads.count > count) { + m_threads.count = count; + } + } -// m_shouldSave = m_threads.mode == Automatic; + for (size_t i = 0; i < m_threads.count; ++i) { + m_threads.list.push_back(CpuThread::createFromAV(i, algorithm, av, m_threads.mask, m_priority, m_assembly)); + } + + m_shouldSave = m_threads.mode == Automatic; return true; } @@ -276,7 +277,7 @@ xmrig::AlgoVariant xmrig::Config::getAlgoVariantLite() const #endif -#ifndef XMRIG_NO_ASM +#ifdef XMRIG_FEATURE_ASM void xmrig::Config::setAssembly(const rapidjson::Value &assembly) { m_assembly = Asm::parse(assembly); diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 4bcb8bba..637f80df 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -94,7 +94,7 @@ private: AlgoVariant getAlgoVariantLite() const; # endif -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM void setAssembly(const rapidjson::Value &assembly); # endif diff --git a/src/crypto/cn/CnAlgo.h b/src/crypto/cn/CnAlgo.h new file mode 100644 index 00000000..74ade22b --- /dev/null +++ b/src/crypto/cn/CnAlgo.h @@ -0,0 +1,207 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2019 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 . + */ + +#ifndef XMRIG_CN_ALGO_H +#define XMRIG_CN_ALGO_H + + +#include +#include + + +#include "crypto/common/Algorithm.h" + + +namespace xmrig +{ + + +template +class CnAlgo +{ +public: + constexpr inline CnAlgo() + { + static_assert(ALGO != Algorithm::INVALID && m_memory[ALGO] > 0, "invalid CRYPTONIGHT algorithm"); + static_assert(sizeof(m_memory) / sizeof(m_memory)[0] == Algorithm::MAX, "memory table size mismatch"); + static_assert(sizeof(m_iterations) / sizeof(m_iterations)[0] == Algorithm::MAX, "iterations table size mismatch"); + static_assert(sizeof(m_base) / sizeof(m_base)[0] == Algorithm::MAX, "iterations table size mismatch"); + } + + constexpr inline Algorithm::Id base() const { return m_base[ALGO]; } + constexpr inline bool isHeavy() const { return memory() == CN_MEMORY * 2; } + constexpr inline bool isR() const { return ALGO == Algorithm::CN_R || ALGO == Algorithm::CN_WOW; } + constexpr inline size_t memory() const { return m_memory[ALGO]; } + constexpr inline uint32_t iterations() const { return m_iterations[ALGO]; } + constexpr inline uint32_t mask() const { return ((memory() - 1) / 16) * 16; } + + inline static size_t memory(Algorithm::Id algo) + { + switch (Algorithm::family(algo)) { + case Algorithm::CN: + return CN_MEMORY; + + case Algorithm::CN_LITE: + return CN_MEMORY / 2; + + case Algorithm::CN_HEAVY: + return CN_MEMORY * 2; + + case Algorithm::CN_PICO: + return CN_MEMORY / 8; + + default: + break; + } + + return 0; + } + + inline static uint32_t mask(Algorithm::Id algo) + { +# ifdef XMRIG_ALGO_CN_GPU + if (algo == Algorithm::CN_GPU) { + return 0x1FFFC0; + } +# endif + +# ifdef XMRIG_ALGO_CN_PICO + if (algo == Algorithm::CN_PICO_0) { + return 0x1FFF0; + } +# endif + + return ((memory(algo) - 1) / 16) * 16; + } + +private: + constexpr const static size_t CN_MEMORY = 0x200000; + constexpr const static uint32_t CN_ITER = 0x80000; + + constexpr const static size_t m_memory[] = { + CN_MEMORY, // CN_0 + CN_MEMORY, // CN_1 + CN_MEMORY, // CN_2 + CN_MEMORY, // CN_R + CN_MEMORY, // CN_WOW + CN_MEMORY, // CN_FAST + CN_MEMORY, // CN_HALF + CN_MEMORY, // CN_XAO + CN_MEMORY, // CN_RTO + CN_MEMORY, // CN_RWZ + CN_MEMORY, // CN_ZLS + CN_MEMORY, // CN_DOUBLE +# ifdef XMRIG_ALGO_CN_GPU + CN_MEMORY, // CN_GPU +# endif +# ifdef XMRIG_ALGO_CN_LITE + CN_MEMORY / 2, // CN_LITE_0 + CN_MEMORY / 2, // CN_LITE_1 +# endif +# ifdef XMRIG_ALGO_CN_HEAVY + CN_MEMORY * 2, // CN_HEAVY_0 + CN_MEMORY * 2, // CN_HEAVY_TUBE + CN_MEMORY * 2, // CN_HEAVY_XHV +# endif +# ifdef XMRIG_ALGO_CN_PICO + CN_MEMORY / 8, // CN_PICO_0 +# endif + }; + + constexpr const static uint32_t m_iterations[] = { + CN_ITER, // CN_0 + CN_ITER, // CN_1 + CN_ITER, // CN_2 + CN_ITER, // CN_R + CN_ITER, // CN_WOW + CN_ITER / 2, // CN_FAST + CN_ITER / 2, // CN_HALF + CN_ITER * 2, // CN_XAO + CN_ITER, // CN_RTO + 0x60000, // CN_RWZ + 0x60000, // CN_ZLS + CN_ITER * 2, // CN_DOUBLE +# ifdef XMRIG_ALGO_CN_GPU + 0xC000, // CN_GPU +# endif +# ifdef XMRIG_ALGO_CN_LITE + CN_ITER / 2, // CN_LITE_0 + CN_ITER / 2, // CN_LITE_1 +# endif +# ifdef XMRIG_ALGO_CN_HEAVY + CN_ITER / 2, // CN_HEAVY_0 + CN_ITER / 2, // CN_HEAVY_TUBE + CN_ITER / 2, // CN_HEAVY_XHV +# endif +# ifdef XMRIG_ALGO_CN_PICO + CN_ITER / 8, // CN_PICO_0 +# endif + }; + + constexpr const static Algorithm::Id m_base[] = { + Algorithm::CN_0, // CN_0 + Algorithm::CN_1, // CN_1 + Algorithm::CN_2, // CN_2 + Algorithm::CN_2, // CN_R + Algorithm::CN_2, // CN_WOW + Algorithm::CN_1, // CN_FAST + Algorithm::CN_2, // CN_HALF + Algorithm::CN_0, // CN_XAO + Algorithm::CN_1, // CN_RTO + Algorithm::CN_2, // CN_RWZ + Algorithm::CN_2, // CN_ZLS + Algorithm::CN_2, // CN_DOUBLE +# ifdef XMRIG_ALGO_CN_GPU + Algorithm::CN_GPU, // CN_GPU +# endif +# ifdef XMRIG_ALGO_CN_LITE + Algorithm::CN_0, // CN_LITE_0 + Algorithm::CN_1, // CN_LITE_1 +# endif +# ifdef XMRIG_ALGO_CN_HEAVY + Algorithm::CN_0, // CN_HEAVY_0 + Algorithm::CN_1, // CN_HEAVY_TUBE + Algorithm::CN_0, // CN_HEAVY_XHV +# endif +# ifdef XMRIG_ALGO_CN_PICO + Algorithm::CN_2, // CN_PICO_0 +# endif + }; +}; + + +#ifdef XMRIG_ALGO_CN_GPU +template<> constexpr inline uint32_t CnAlgo::mask() const { return 0x1FFFC0; } +#endif + +#ifdef XMRIG_ALGO_CN_PICO +template<> constexpr inline uint32_t CnAlgo::mask() const { return 0x1FFF0; } +#endif + + +} /* namespace xmrig */ + + +#endif /* XMRIG_CN_ALGO_H */ diff --git a/src/crypto/cn/CnHash.cpp b/src/crypto/cn/CnHash.cpp new file mode 100644 index 00000000..61d2ea69 --- /dev/null +++ b/src/crypto/cn/CnHash.cpp @@ -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-2019 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 "common/cpu/Cpu.h" +#include "crypto/cn/CnHash.h" +#include "crypto/common/VirtualMemory.h" + + +#if defined(XMRIG_ARM) +# include "crypto/cn/CryptoNight_arm.h" +#else +# include "crypto/cn/CryptoNight_x86.h" +#endif + + +#define ADD_FN(algo) \ + m_map[algo][AV_SINGLE][ASM_NONE] = cryptonight_single_hash; \ + m_map[algo][AV_SINGLE_SOFT][ASM_NONE] = cryptonight_single_hash; \ + m_map[algo][AV_DOUBLE][ASM_NONE] = cryptonight_double_hash; \ + m_map[algo][AV_DOUBLE_SOFT][ASM_NONE] = cryptonight_double_hash; \ + m_map[algo][AV_TRIPLE][ASM_NONE] = cryptonight_triple_hash; \ + m_map[algo][AV_TRIPLE_SOFT][ASM_NONE] = cryptonight_triple_hash; \ + m_map[algo][AV_QUAD][ASM_NONE] = cryptonight_quad_hash; \ + m_map[algo][AV_QUAD_SOFT][ASM_NONE] = cryptonight_quad_hash; \ + m_map[algo][AV_PENTA][ASM_NONE] = cryptonight_penta_hash; \ + m_map[algo][AV_PENTA_SOFT][ASM_NONE] = cryptonight_penta_hash; + + +#ifdef XMRIG_FEATURE_ASM +# define ADD_FN_ASM(algo) \ + m_map[algo][AV_SINGLE][ASM_INTEL] = cryptonight_single_hash_asm; \ + m_map[algo][AV_SINGLE][ASM_RYZEN] = cryptonight_single_hash_asm; \ + m_map[algo][AV_SINGLE][ASM_BULLDOZER] = cryptonight_single_hash_asm; \ + m_map[algo][AV_DOUBLE][ASM_INTEL] = cryptonight_double_hash_asm; \ + m_map[algo][AV_DOUBLE][ASM_RYZEN] = cryptonight_double_hash_asm; \ + m_map[algo][AV_DOUBLE][ASM_BULLDOZER] = cryptonight_double_hash_asm; + + +extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx **ctx); +extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx **ctx); + + +namespace xmrig { + + +cn_mainloop_fun cn_half_mainloop_ivybridge_asm = nullptr; +cn_mainloop_fun cn_half_mainloop_ryzen_asm = nullptr; +cn_mainloop_fun cn_half_mainloop_bulldozer_asm = nullptr; +cn_mainloop_fun cn_half_double_mainloop_sandybridge_asm = nullptr; + +cn_mainloop_fun cn_trtl_mainloop_ivybridge_asm = nullptr; +cn_mainloop_fun cn_trtl_mainloop_ryzen_asm = nullptr; +cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm = nullptr; +cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm = nullptr; + +cn_mainloop_fun cn_zls_mainloop_ivybridge_asm = nullptr; +cn_mainloop_fun cn_zls_mainloop_ryzen_asm = nullptr; +cn_mainloop_fun cn_zls_mainloop_bulldozer_asm = nullptr; +cn_mainloop_fun cn_zls_double_mainloop_sandybridge_asm = nullptr; + +cn_mainloop_fun cn_double_mainloop_ivybridge_asm = nullptr; +cn_mainloop_fun cn_double_mainloop_ryzen_asm = nullptr; +cn_mainloop_fun cn_double_mainloop_bulldozer_asm = nullptr; +cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm = nullptr; + + +template +static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t mask = CnAlgo().mask()) +{ + const uint8_t* p = reinterpret_cast(src); + + // Workaround for Visual Studio placing trampoline in debug builds. +# if defined(_MSC_VER) + if (p[0] == 0xE9) { + p += *(int32_t*)(p + 1) + 5; + } +# endif + + size_t size = 0; + while (*(uint32_t*)(p + size) != 0xDEADC0DE) { + ++size; + } + + size += sizeof(uint32_t); + + memcpy((void*) dst, (const void*) src, size); + + uint8_t* patched_data = reinterpret_cast(dst); + for (size_t i = 0; i + sizeof(uint32_t) <= size; ++i) { + switch (*(uint32_t*)(patched_data + i)) { + case CnAlgo().iterations(): + *(uint32_t*)(patched_data + i) = iterations; + break; + + case CnAlgo().mask(): + *(uint32_t*)(patched_data + i) = mask; + break; + } + } +} + + +static void patchAsmVariants() +{ + const int allocation_size = 65536; + uint8_t *base = static_cast(VirtualMemory::allocateExecutableMemory(allocation_size)); + + cn_half_mainloop_ivybridge_asm = reinterpret_cast (base + 0x0000); + cn_half_mainloop_ryzen_asm = reinterpret_cast (base + 0x1000); + cn_half_mainloop_bulldozer_asm = reinterpret_cast (base + 0x2000); + cn_half_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x3000); + +# ifdef XMRIG_ALGO_CN_PICO + cn_trtl_mainloop_ivybridge_asm = reinterpret_cast (base + 0x4000); + cn_trtl_mainloop_ryzen_asm = reinterpret_cast (base + 0x5000); + cn_trtl_mainloop_bulldozer_asm = reinterpret_cast (base + 0x6000); + cn_trtl_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x7000); +# endif + + cn_zls_mainloop_ivybridge_asm = reinterpret_cast (base + 0x8000); + cn_zls_mainloop_ryzen_asm = reinterpret_cast (base + 0x9000); + cn_zls_mainloop_bulldozer_asm = reinterpret_cast (base + 0xA000); + cn_zls_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xB000); + + cn_double_mainloop_ivybridge_asm = reinterpret_cast (base + 0xC000); + cn_double_mainloop_ryzen_asm = reinterpret_cast (base + 0xD000); + cn_double_mainloop_bulldozer_asm = reinterpret_cast (base + 0xE000); + cn_double_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xF000); + + { + constexpr uint32_t ITER = CnAlgo().iterations(); + + patchCode(cn_half_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER); + patchCode(cn_half_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER); + patchCode(cn_half_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER); + patchCode(cn_half_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER); + } + +# ifdef XMRIG_ALGO_CN_PICO + { + constexpr uint32_t ITER = CnAlgo().iterations(); + constexpr uint32_t MASK = CnAlgo().mask(); + + patchCode(cn_trtl_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER, MASK); + patchCode(cn_trtl_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER, MASK); + patchCode(cn_trtl_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER, MASK); + patchCode(cn_trtl_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER, MASK); + } +# endif + + { + constexpr uint32_t ITER = CnAlgo().iterations(); + + patchCode(cn_zls_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER); + patchCode(cn_zls_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER); + patchCode(cn_zls_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER); + patchCode(cn_zls_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER); + } + + { + constexpr uint32_t ITER = CnAlgo().iterations(); + + patchCode(cn_double_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, ITER); + patchCode(cn_double_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, ITER); + patchCode(cn_double_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, ITER); + patchCode(cn_double_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, ITER); + } + + VirtualMemory::protectExecutableMemory(base, allocation_size); + VirtualMemory::flushInstructionCache(base, allocation_size); +} +} // namespace xmrig +#else +# define ADD_FN_ASM(algo) +#endif + + +xmrig::CnHash::CnHash() +{ + ADD_FN(Algorithm::CN_0); + ADD_FN(Algorithm::CN_1); + ADD_FN(Algorithm::CN_2); + ADD_FN(Algorithm::CN_R); + ADD_FN(Algorithm::CN_WOW); + ADD_FN(Algorithm::CN_FAST); + ADD_FN(Algorithm::CN_HALF); + ADD_FN(Algorithm::CN_XAO); + ADD_FN(Algorithm::CN_RTO); + ADD_FN(Algorithm::CN_RWZ); + ADD_FN(Algorithm::CN_ZLS); + ADD_FN(Algorithm::CN_DOUBLE); + + ADD_FN_ASM(Algorithm::CN_2); + ADD_FN_ASM(Algorithm::CN_HALF); + ADD_FN_ASM(Algorithm::CN_R); + ADD_FN_ASM(Algorithm::CN_WOW); + ADD_FN_ASM(Algorithm::CN_RWZ); + ADD_FN_ASM(Algorithm::CN_ZLS); + ADD_FN_ASM(Algorithm::CN_DOUBLE); + +# ifdef XMRIG_ALGO_CN_GPU + m_map[Algorithm::CN_GPU][AV_SINGLE][ASM_NONE] = cryptonight_single_hash_gpu; + m_map[Algorithm::CN_GPU][AV_SINGLE_SOFT][ASM_NONE] = cryptonight_single_hash_gpu; +# endif + +# ifdef XMRIG_ALGO_CN_LITE + ADD_FN(Algorithm::CN_LITE_0); + ADD_FN(Algorithm::CN_LITE_1); +# endif + +# ifdef XMRIG_ALGO_CN_HEAVY + ADD_FN(Algorithm::CN_HEAVY_0); + ADD_FN(Algorithm::CN_HEAVY_TUBE); + ADD_FN(Algorithm::CN_HEAVY_XHV); +# endif + +# ifdef XMRIG_ALGO_CN_PICO + ADD_FN(Algorithm::CN_PICO_0); + ADD_FN_ASM(Algorithm::CN_PICO_0); +# endif + +# ifdef XMRIG_FEATURE_ASM + patchAsmVariants(); +# endif +} + + +xmrig::cn_hash_fun xmrig::CnHash::fn(const Algorithm &algorithm, AlgoVariant av, Assembly assembly) const +{ + if (!algorithm.isValid()) { + return nullptr; + } + +# ifdef XMRIG_FEATURE_ASM + cn_hash_fun fun = m_map[algorithm][av][assembly == ASM_AUTO ? Cpu::info()->assembly() : assembly]; + if (fun) { + return fun; + } +# endif + + return m_map[algorithm][av][ASM_NONE]; +} diff --git a/src/crypto/cn/CnHash.h b/src/crypto/cn/CnHash.h new file mode 100644 index 00000000..5fbf5c8a --- /dev/null +++ b/src/crypto/cn/CnHash.h @@ -0,0 +1,63 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2019 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2016-2019 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 . + */ + +#ifndef XMRIG_CN_HASH_H +#define XMRIG_CN_HASH_H + + +#include +#include + + +#include "common/xmrig.h" +#include "crypto/cn/CnAlgo.h" + + +struct cryptonight_ctx; + + +namespace xmrig +{ + +typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx, uint64_t height); +typedef void (*cn_mainloop_fun)(cryptonight_ctx **ctx); + + +class CnHash +{ +public: + CnHash(); + + cn_hash_fun fn(const Algorithm &algorithm, AlgoVariant av, Assembly assembly) const; + +private: + cn_hash_fun m_map[Algorithm::MAX][AV_MAX][ASM_MAX] = {}; +}; + + +} /* namespace xmrig */ + + +#endif /* XMRIG_CN_HASH_H */ diff --git a/src/crypto/cn/CryptoNight.h b/src/crypto/cn/CryptoNight.h index f50966ed..434c34f8 100644 --- a/src/crypto/cn/CryptoNight.h +++ b/src/crypto/cn/CryptoNight.h @@ -42,10 +42,10 @@ typedef void(*cn_mainloop_fun_ms_abi)(cryptonight_ctx**) ABI_ATTRIBUTE; struct cryptonight_r_data { - int variant; + int algo; uint64_t height; - bool match(const int v, const uint64_t h) const { return (v == variant) && (h == height); } + bool match(const int a, const uint64_t h) const { return (a == algo) && (h == height); } }; diff --git a/src/crypto/cn/CryptoNight_constants.h b/src/crypto/cn/CryptoNight_constants.h deleted file mode 100644 index 1bc06a3b..00000000 --- a/src/crypto/cn/CryptoNight_constants.h +++ /dev/null @@ -1,251 +0,0 @@ -/* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2019 XMR-Stak , - * Copyright 2018 Lee Clagett - * Copyright 2018-2019 SChernykh - * Copyright 2016-2019 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 . - */ - -#ifndef XMRIG_CRYPTONIGHT_CONSTANTS_H -#define XMRIG_CRYPTONIGHT_CONSTANTS_H - - -#include -#include - - -#include "common/xmrig.h" - - -namespace xmrig -{ - -constexpr const size_t CRYPTONIGHT_MEMORY = 2 * 1024 * 1024; -constexpr const uint32_t CRYPTONIGHT_MASK = 0x1FFFF0; -constexpr const uint32_t CRYPTONIGHT_ITER = 0x80000; -constexpr const uint32_t CRYPTONIGHT_HALF_ITER = 0x40000; -constexpr const uint32_t CRYPTONIGHT_XAO_ITER = 0x100000; -constexpr const uint32_t CRYPTONIGHT_DOUBLE_ITER = 0x100000; -constexpr const uint32_t CRYPTONIGHT_WALTZ_ITER = 0x60000; -constexpr const uint32_t CRYPTONIGHT_ZLS_ITER = 0x60000; - -constexpr const uint32_t CRYPTONIGHT_GPU_ITER = 0xC000; -constexpr const uint32_t CRYPTONIGHT_GPU_MASK = 0x1FFFC0; - -constexpr const size_t CRYPTONIGHT_LITE_MEMORY = 1 * 1024 * 1024; -constexpr const uint32_t CRYPTONIGHT_LITE_MASK = 0xFFFF0; -constexpr const uint32_t CRYPTONIGHT_LITE_ITER = 0x40000; - -constexpr const size_t CRYPTONIGHT_HEAVY_MEMORY = 4 * 1024 * 1024; -constexpr const uint32_t CRYPTONIGHT_HEAVY_MASK = 0x3FFFF0; -constexpr const uint32_t CRYPTONIGHT_HEAVY_ITER = 0x40000; - -constexpr const size_t CRYPTONIGHT_PICO_MEMORY = 256 * 1024; -constexpr const uint32_t CRYPTONIGHT_PICO_MASK = 0x1FFF0; -constexpr const uint32_t CRYPTONIGHT_PICO_ITER = 0x40000; -constexpr const uint32_t CRYPTONIGHT_TRTL_ITER = 0x10000; - - -template inline constexpr size_t cn_select_memory() { return 0; } -template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_MEMORY; } -template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_LITE_MEMORY; } -template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_HEAVY_MEMORY; } -template<> inline constexpr size_t cn_select_memory() { return CRYPTONIGHT_PICO_MEMORY; } - - -inline size_t cn_select_memory(Algo algorithm) -{ - switch(algorithm) - { - case CRYPTONIGHT: - return CRYPTONIGHT_MEMORY; - - case CRYPTONIGHT_LITE: - return CRYPTONIGHT_LITE_MEMORY; - - case CRYPTONIGHT_HEAVY: - return CRYPTONIGHT_HEAVY_MEMORY; - - case CRYPTONIGHT_PICO: - return CRYPTONIGHT_PICO_MEMORY; - - default: - break; - } - - return 0; -} - - -template inline constexpr uint32_t cn_select_mask() { return 0; } -template<> inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_MASK; } -template<> inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_LITE_MASK; } -template<> inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_HEAVY_MASK; } -template<> inline constexpr uint32_t cn_select_mask() { return CRYPTONIGHT_PICO_MASK; } - - -inline uint32_t cn_select_mask(Algo algorithm) -{ - switch(algorithm) - { - case CRYPTONIGHT: - return CRYPTONIGHT_MASK; - - case CRYPTONIGHT_LITE: - return CRYPTONIGHT_LITE_MASK; - - case CRYPTONIGHT_HEAVY: - return CRYPTONIGHT_HEAVY_MASK; - - case CRYPTONIGHT_PICO: - return CRYPTONIGHT_PICO_MASK; - - default: - break; - } - - return 0; -} - - -template inline constexpr uint32_t cn_select_iter() { return 0; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HALF_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HALF_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_XAO_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_GPU_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_WALTZ_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_ZLS_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_DOUBLE_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_LITE_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_LITE_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HEAVY_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HEAVY_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_HEAVY_ITER; } -template<> inline constexpr uint32_t cn_select_iter() { return CRYPTONIGHT_TRTL_ITER; } - - -inline uint32_t cn_select_iter(Algo algorithm, Variant variant) -{ - switch (variant) { - case VARIANT_MSR: - case VARIANT_HALF: - return CRYPTONIGHT_HALF_ITER; - - case VARIANT_GPU: - return CRYPTONIGHT_GPU_ITER; - - case VARIANT_RTO: - case VARIANT_DOUBLE: - return CRYPTONIGHT_XAO_ITER; - - case VARIANT_TRTL: - return CRYPTONIGHT_TRTL_ITER; - - case VARIANT_RWZ: - case VARIANT_ZLS: - return CRYPTONIGHT_WALTZ_ITER; - - default: - break; - } - - switch(algorithm) - { - case CRYPTONIGHT: - return CRYPTONIGHT_ITER; - - case CRYPTONIGHT_LITE: - return CRYPTONIGHT_LITE_ITER; - - case CRYPTONIGHT_HEAVY: - return CRYPTONIGHT_HEAVY_ITER; - - case CRYPTONIGHT_PICO: - return CRYPTONIGHT_TRTL_ITER; - - default: - break; - } - - return 0; -} - - -template inline constexpr Variant cn_base_variant() { return VARIANT_0; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_0; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_1; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_1; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_1; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_1; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_0; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_0; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_1; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_GPU; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } -template<> inline constexpr Variant cn_base_variant() { return VARIANT_2; } - - -inline Variant cn_base_variant(Variant variant) -{ - switch (variant) { - case VARIANT_0: - case VARIANT_XHV: - case VARIANT_XAO: - return VARIANT_0; - - case VARIANT_1: - case VARIANT_TUBE: - case VARIANT_XTL: - case VARIANT_MSR: - case VARIANT_RTO: - return VARIANT_1; - - case VARIANT_GPU: - return VARIANT_GPU; - - default: - break; - } - - return VARIANT_2; -} - - -template inline constexpr bool cn_is_cryptonight_r() { return false; } -template<> inline constexpr bool cn_is_cryptonight_r() { return true; } -template<> inline constexpr bool cn_is_cryptonight_r() { return true; } - -} /* namespace xmrig */ - - -#endif /* XMRIG_CRYPTONIGHT_CONSTANTS_H */ diff --git a/src/crypto/cn/CryptoNight_monero.h b/src/crypto/cn/CryptoNight_monero.h index 94a18c45..259cb3b6 100644 --- a/src/crypto/cn/CryptoNight_monero.h +++ b/src/crypto/cn/CryptoNight_monero.h @@ -33,21 +33,21 @@ #ifndef XMRIG_ARM # define VARIANT1_INIT(part) \ uint64_t tweak1_2_##part = 0; \ - if (BASE == xmrig::VARIANT_1) { \ + if (BASE == Algorithm::CN_1) { \ tweak1_2_##part = (*reinterpret_cast(input + 35 + part * size) ^ \ *(reinterpret_cast(ctx[part]->state) + 24)); \ } #else # define VARIANT1_INIT(part) \ uint64_t tweak1_2_##part = 0; \ - if (BASE == xmrig::VARIANT_1) { \ + if (BASE == Algorithm::CN_1) { \ memcpy(&tweak1_2_##part, input + 35 + part * size, sizeof tweak1_2_##part); \ tweak1_2_##part ^= *(reinterpret_cast(ctx[part]->state) + 24); \ } #endif #define VARIANT1_1(p) \ - if (BASE == xmrig::VARIANT_1) { \ + if (BASE == Algorithm::CN_1) { \ const uint8_t tmp = reinterpret_cast(p)[11]; \ static const uint32_t table = 0x75310; \ const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ @@ -55,20 +55,20 @@ } #define VARIANT1_2(p, part) \ - if (BASE == xmrig::VARIANT_1) { \ + if (BASE == Algorithm::CN_1) { \ (p) ^= tweak1_2_##part; \ } #ifndef XMRIG_ARM # define VARIANT2_INIT(part) \ - __m128i division_result_xmm_##part = _mm_cvtsi64_si128(h##part[12]); \ - __m128i sqrt_result_xmm_##part = _mm_cvtsi64_si128(h##part[13]); + __m128i division_result_xmm_##part = _mm_cvtsi64_si128(static_cast(h##part[12])); \ + __m128i sqrt_result_xmm_##part = _mm_cvtsi64_si128(static_cast(h##part[13])); #ifdef _MSC_VER -# define VARIANT2_SET_ROUNDING_MODE() if (BASE == xmrig::VARIANT_2) { _control87(RC_DOWN, MCW_RC); } +# define VARIANT2_SET_ROUNDING_MODE() if (BASE == Algorithm::CN_2) { _control87(RC_DOWN, MCW_RC); } #else -# define VARIANT2_SET_ROUNDING_MODE() if (BASE == xmrig::VARIANT_2) { fesetround(FE_DOWNWARD); } +# define VARIANT2_SET_ROUNDING_MODE() if (BASE == Algorithm::CN_2) { fesetround(FE_DOWNWARD); } #endif # define VARIANT2_INTEGER_MATH(part, cl, cx) \ @@ -91,7 +91,7 @@ _mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x10)), _mm_add_epi64(chunk3, _b1)); \ _mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x20)), _mm_add_epi64(chunk1, _b)); \ _mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30)), _mm_add_epi64(chunk2, _a)); \ - if (VARIANT == xmrig::VARIANT_4) { \ + if (ALGO == Algorithm::CN_R) { \ _c = _mm_xor_si128(_mm_xor_si128(_c, chunk3), _mm_xor_si128(chunk1, chunk2)); \ } \ } while (0) @@ -141,7 +141,7 @@ vst1q_u64((uint64_t*)((base_ptr) + ((offset) ^ 0x10)), vaddq_u64(chunk3, vreinterpretq_u64_u8(_b1))); \ vst1q_u64((uint64_t*)((base_ptr) + ((offset) ^ 0x20)), vaddq_u64(chunk1, vreinterpretq_u64_u8(_b))); \ vst1q_u64((uint64_t*)((base_ptr) + ((offset) ^ 0x30)), vaddq_u64(chunk2, vreinterpretq_u64_u8(_a))); \ - if (VARIANT == xmrig::VARIANT_4) { \ + if (ALGO == Algorithm::CN_4) { \ _c = veorq_u64(veorq_u64(_c, chunk3), veorq_u64(chunk1, chunk2)); \ } \ } while (0) @@ -184,17 +184,17 @@ #define VARIANT4_RANDOM_MATH_INIT(part) \ uint32_t r##part[9]; \ struct V4_Instruction code##part[256]; \ - if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { \ - r##part[0] = (uint32_t)(h##part[12]); \ - r##part[1] = (uint32_t)(h##part[12] >> 32); \ - r##part[2] = (uint32_t)(h##part[13]); \ - r##part[3] = (uint32_t)(h##part[13] >> 32); \ + if (props.isR()) { \ + r##part[0] = static_cast(h##part[12]); \ + r##part[1] = static_cast(h##part[12] >> 32); \ + r##part[2] = static_cast(h##part[13]); \ + r##part[3] = static_cast(h##part[13] >> 32); \ } \ - v4_random_math_init(code##part, height); + v4_random_math_init(code##part, height); #define VARIANT4_RANDOM_MATH(part, al, ah, cl, bx0, bx1) \ - if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { \ - cl ^= (r##part[0] + r##part[1]) | ((uint64_t)(r##part[2] + r##part[3]) << 32); \ + if (props.isR()) { \ + cl ^= (r##part[0] + r##part[1]) | (static_cast(r##part[2] + r##part[3]) << 32); \ r##part[4] = static_cast(al); \ r##part[5] = static_cast(ah); \ r##part[6] = static_cast(_mm_cvtsi128_si32(bx0)); \ diff --git a/src/crypto/cn/CryptoNight_test.h b/src/crypto/cn/CryptoNight_test.h index 2429fc17..77cbbb8e 100644 --- a/src/crypto/cn/CryptoNight_test.h +++ b/src/crypto/cn/CryptoNight_test.h @@ -156,21 +156,6 @@ const static uint8_t test_output_v2[160] = { }; -// "cn/xtl" Stellite (XTL) -const static uint8_t test_output_xtl[160] = { - 0x8F, 0xE5, 0xF0, 0x5F, 0x02, 0x2A, 0x61, 0x7D, 0xE5, 0x3F, 0x79, 0x36, 0x4B, 0x25, 0xCB, 0xC3, - 0xC0, 0x8E, 0x0E, 0x1F, 0xE3, 0xBE, 0x48, 0x57, 0x07, 0x03, 0xFE, 0xE1, 0xEC, 0x0E, 0xB0, 0xB1, - 0x21, 0x26, 0xFF, 0x98, 0xE6, 0x86, 0x08, 0x5B, 0xC9, 0x96, 0x44, 0xA3, 0xB8, 0x4E, 0x28, 0x90, - 0x76, 0xED, 0xAD, 0xB9, 0xAA, 0xAC, 0x01, 0x94, 0x1D, 0xBE, 0x3E, 0xEA, 0xAD, 0xEE, 0xB2, 0xCF, - 0xB0, 0x43, 0x4B, 0x88, 0xFC, 0xB2, 0xF3, 0x82, 0x9D, 0xD7, 0xDF, 0x51, 0x97, 0x2C, 0x5A, 0xE3, - 0xC7, 0x16, 0x0B, 0xC8, 0x7C, 0xB7, 0x2F, 0x1C, 0x55, 0x33, 0xCA, 0xE1, 0xEE, 0x08, 0xA4, 0x86, - 0x60, 0xED, 0x6E, 0x9D, 0x2D, 0x05, 0x0D, 0x7D, 0x02, 0x49, 0x23, 0x39, 0x7C, 0xC3, 0x6D, 0x3D, - 0x05, 0x51, 0x28, 0xF1, 0x9B, 0x3C, 0xDF, 0xC4, 0xEA, 0x8A, 0xA6, 0x6A, 0x3C, 0x8B, 0xE2, 0xAF, - 0x47, 0x00, 0xFC, 0x36, 0xED, 0x50, 0xBB, 0xD2, 0x2E, 0x63, 0x4B, 0x93, 0x11, 0x0C, 0xA7, 0xBA, - 0x32, 0x6E, 0x47, 0x4D, 0xCE, 0xCC, 0x82, 0x54, 0x1D, 0x06, 0xF8, 0x06, 0x86, 0xBD, 0x22, 0x48 -}; - - // "cn/half" const static uint8_t test_output_half[160] = { 0x5D, 0x4F, 0xBC, 0x35, 0x60, 0x97, 0xEA, 0x64, 0x40, 0xB0, 0x88, 0x8E, 0xDE, 0xB6, 0x35, 0xDD, diff --git a/src/crypto/cn/CryptoNight_x86.h b/src/crypto/cn/CryptoNight_x86.h index 8d6792d2..994ee116 100644 --- a/src/crypto/cn/CryptoNight_x86.h +++ b/src/crypto/cn/CryptoNight_x86.h @@ -37,9 +37,9 @@ #include "common/cpu/Cpu.h" #include "common/crypto/keccak.h" -#include "crypto/cn/CryptoNight.h" -#include "crypto/cn/CryptoNight_constants.h" +#include "crypto/cn/CnAlgo.h" #include "crypto/cn/CryptoNight_monero.h" +#include "crypto/cn/CryptoNight.h" #include "crypto/cn/soft_aes.h" @@ -303,9 +303,14 @@ inline void mix_and_propagate(__m128i& x0, __m128i& x1, __m128i& x2, __m128i& x3 } -template +namespace xmrig { + + +template static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) { + constexpr CnAlgo props; + __m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7; __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; @@ -320,7 +325,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) xin6 = _mm_load_si128(input + 10); xin7 = _mm_load_si128(input + 11); - if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + if (props.isHeavy()) { for (size_t i = 0; i < 16; i++) { aes_round(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); aes_round(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7); @@ -337,7 +342,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) } } - for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { + for (size_t i = 0; i < props.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); @@ -361,37 +366,17 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output) } -#ifdef XMRIG_ALGO_CN_GPU -template -void cn_explode_scratchpad_gpu(const uint8_t *input, uint8_t *output) -{ - constexpr size_t hash_size = 200; // 25x8 bytes - alignas(16) uint64_t hash[25]; - - for (uint64_t i = 0; i < MEM / 512; i++) - { - memcpy(hash, input, hash_size); - hash[0] ^= i; - - xmrig::keccakf(hash, 24); - memcpy(output, hash, 160); - output += 160; - - xmrig::keccakf(hash, 24); - memcpy(output, hash, 176); - output += 176; - - xmrig::keccakf(hash, 24); - memcpy(output, hash, 176); - output += 176; - } -} -#endif - - -template +template static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) { + constexpr CnAlgo props; + +# ifdef XMRIG_ALGO_CN_GPU + constexpr bool IS_HEAVY = props.isHeavy() || ALGO == Algorithm::CN_GPU; +# else + constexpr bool IS_HEAVY = props.isHeavy(); +# endif + __m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7; __m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9; @@ -406,8 +391,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) xout6 = _mm_load_si128(output + 10); xout7 = _mm_load_si128(output + 11); - for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) - { + for (size_t i = 0; i < props.memory() / sizeof(__m128i); i += 8) { 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); @@ -428,13 +412,13 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) aes_round(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); aes_round(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7); - if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { + if (IS_HEAVY) { mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7); } } - if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { - for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) { + if (IS_HEAVY) { + for (size_t i = 0; i < props.memory() / sizeof(__m128i); i += 8) { 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); @@ -485,6 +469,9 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) } +} /* namespace xmrig */ + + static inline __m128i aes_round_tweak_div(const __m128i &in, const __m128i &key) { alignas(16) uint32_t k[4]; @@ -527,12 +514,21 @@ static inline __m128i int_sqrt_v2(const uint64_t n0) } -template -static inline void cryptonight_monero_tweak(uint64_t* mem_out, const uint8_t* l, uint64_t idx, __m128i ax0, __m128i bx0, __m128i bx1, __m128i& cx) +void wow_soft_aes_compile_code(const V4_Instruction *code, int code_size, void *machine_code, xmrig::Assembly ASM); +void v4_soft_aes_compile_code(const V4_Instruction *code, int code_size, void *machine_code, xmrig::Assembly ASM); + + +namespace xmrig { + + +template +static inline void cryptonight_monero_tweak(uint64_t *mem_out, const uint8_t *l, uint64_t idx, __m128i ax0, __m128i bx0, __m128i bx1, __m128i& cx) { - if (BASE == xmrig::VARIANT_2) { - VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0)); - _mm_store_si128((__m128i *)mem_out, _mm_xor_si128(bx0, cx)); + constexpr CnAlgo props; + + if (props.base() == Algorithm::CN_2) { + VARIANT2_SHUFFLE(l, idx, ax0, bx0, bx1, cx, (ALGO == Algorithm::CN_RWZ ? 1 : 0)); + _mm_store_si128(reinterpret_cast<__m128i *>(mem_out), _mm_xor_si128(bx0, cx)); } else { __m128i tmp = _mm_xor_si128(bx0, cx); mem_out[0] = _mm_cvtsi128_si64(tmp); @@ -542,107 +538,105 @@ static inline void cryptonight_monero_tweak(uint64_t* mem_out, const uint8_t* l, uint8_t x = static_cast(vh >> 24); static const uint16_t table = 0x7531; - const uint8_t index = (((x >> (VARIANT == xmrig::VARIANT_XTL ? 4 : 3)) & 6) | (x & 1)) << 1; + const uint8_t index = (((x >> (3)) & 6) | (x & 1)) << 1; vh ^= ((table >> index) & 0x3) << 28; mem_out[1] = vh; } } -void wow_soft_aes_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); -void v4_soft_aes_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); -template +template inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) { - constexpr size_t MASK = xmrig::cn_select_mask(); - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); - constexpr size_t MEM = xmrig::cn_select_memory(); - constexpr xmrig::Variant BASE = xmrig::cn_base_variant(); + constexpr CnAlgo props; + constexpr size_t MASK = props.mask(); + constexpr Algorithm::Id BASE = props.base(); - static_assert(MASK > 0 && ITERATIONS > 0 && MEM > 0, "unsupported algorithm/variant"); +# ifdef XMRIG_ALGO_CN_HEAVY + constexpr bool IS_CN_HEAVY_TUBE = ALGO == Algorithm::CN_HEAVY_TUBE; +# else + constexpr bool IS_CN_HEAVY_TUBE = false; +# endif - if (BASE == xmrig::VARIANT_1 && size < 43) { + if (BASE == Algorithm::CN_1 && size < 43) { memset(output, 0, 32); return; } - xmrig::keccak(input, size, ctx[0]->state); + keccak(input, size, ctx[0]->state); + cn_explode_scratchpad(reinterpret_cast(ctx[0]->state), reinterpret_cast<__m128i *>(ctx[0]->memory)); - cn_explode_scratchpad((__m128i*) ctx[0]->state, (__m128i*) ctx[0]->memory); + uint64_t *h0 = reinterpret_cast(ctx[0]->state); + uint8_t *l0 = ctx[0]->memory; - uint64_t* h0 = reinterpret_cast(ctx[0]->state); - -#ifndef XMRIG_NO_ASM - if (SOFT_AES && xmrig::cn_is_cryptonight_r()) - { - if (!ctx[0]->generated_code_data.match(VARIANT, height)) { +# ifdef XMRIG_FEATURE_ASM + if (SOFT_AES && props.isR()) { + if (!ctx[0]->generated_code_data.match(ALGO, height)) { V4_Instruction code[256]; - const int code_size = v4_random_math_init(code, height); + const int code_size = v4_random_math_init(code, height); - if (VARIANT == xmrig::VARIANT_WOW) - wow_soft_aes_compile_code(code, code_size, reinterpret_cast(ctx[0]->generated_code), xmrig::ASM_NONE); - else if (VARIANT == xmrig::VARIANT_4) - v4_soft_aes_compile_code(code, code_size, reinterpret_cast(ctx[0]->generated_code), xmrig::ASM_NONE); + if (ALGO == Algorithm::CN_WOW) { + wow_soft_aes_compile_code(code, code_size, reinterpret_cast(ctx[0]->generated_code), ASM_NONE); + } + else if (ALGO == Algorithm::CN_R) { + v4_soft_aes_compile_code(code, code_size, reinterpret_cast(ctx[0]->generated_code), ASM_NONE); + } - ctx[0]->generated_code_data.variant = VARIANT; - ctx[0]->generated_code_data.height = height; + ctx[0]->generated_code_data = { ALGO, height }; } - ctx[0]->saes_table = (const uint32_t*)saes_table; + ctx[0]->saes_table = reinterpret_cast(saes_table); ctx[0]->generated_code(ctx); } else { -#endif - - const uint8_t* l0 = ctx[0]->memory; +# endif VARIANT1_INIT(0); VARIANT2_INIT(0); VARIANT2_SET_ROUNDING_MODE(); VARIANT4_RANDOM_MATH_INIT(0); - 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]); - __m128i bx1 = _mm_set_epi64x(h0[9] ^ h0[11], h0[8] ^ h0[10]); - + uint64_t al0 = h0[0] ^ h0[4]; + uint64_t ah0 = h0[1] ^ h0[5]; uint64_t idx0 = al0; + __m128i bx0 = _mm_set_epi64x(static_cast(h0[3] ^ h0[7]), static_cast(h0[2] ^ h0[6])); + __m128i bx1 = _mm_set_epi64x(static_cast(h0[9] ^ h0[11]), static_cast(h0[8] ^ h0[10])); - for (size_t i = 0; i < ITERATIONS; i++) { + for (size_t i = 0; i < props.iterations(); i++) { __m128i cx; - if (VARIANT == xmrig::VARIANT_TUBE || !SOFT_AES) { - cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + if (IS_CN_HEAVY_TUBE || !SOFT_AES) { + cx = _mm_load_si128(reinterpret_cast(&l0[idx0 & MASK])); } - const __m128i ax0 = _mm_set_epi64x(ah0, al0); - if (VARIANT == xmrig::VARIANT_TUBE) { + const __m128i ax0 = _mm_set_epi64x(static_cast(ah0), static_cast(al0)); + if (IS_CN_HEAVY_TUBE) { cx = aes_round_tweak_div(cx, ax0); } else if (SOFT_AES) { - cx = soft_aesenc((uint32_t*)&l0[idx0 & MASK], ax0, (const uint32_t*)saes_table); + cx = soft_aesenc(&l0[idx0 & MASK], ax0, reinterpret_cast(saes_table)); } else { cx = _mm_aesenc_si128(cx, ax0); } - if (BASE == xmrig::VARIANT_1 || BASE == xmrig::VARIANT_2) { - cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], l0, idx0 & MASK, ax0, bx0, bx1, cx); + if (BASE == Algorithm::CN_1 || BASE == Algorithm::CN_2) { + cryptonight_monero_tweak(reinterpret_cast(&l0[idx0 & MASK]), l0, idx0 & MASK, ax0, bx0, bx1, cx); } else { - _mm_store_si128((__m128i *)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + _mm_store_si128(reinterpret_cast<__m128i *>(&l0[idx0 & MASK]), _mm_xor_si128(bx0, cx)); } - idx0 = _mm_cvtsi128_si64(cx); + idx0 = static_cast(_mm_cvtsi128_si64(cx)); uint64_t hi, lo, cl, ch; - cl = ((uint64_t*) &l0[idx0 & MASK])[0]; - ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + cl = (reinterpret_cast(&l0[idx0 & MASK]))[0]; + ch = (reinterpret_cast(&l0[idx0 & MASK]))[1]; - if (BASE == xmrig::VARIANT_2) { - if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { + if (BASE == Algorithm::CN_2) { + if (props.isR()) { VARIANT4_RANDOM_MATH(0, al0, ah0, cl, bx0, bx1); - if (VARIANT == xmrig::VARIANT_4) { - al0 ^= r0[2] | ((uint64_t)(r0[3]) << 32); - ah0 ^= r0[0] | ((uint64_t)(r0[1]) << 32); + if (ALGO == Algorithm::CN_R) { + al0 ^= r0[2] | (static_cast(r0[3]) << 32); + ah0 ^= r0[0] | (static_cast(r0[1]) << 32); } } else { VARIANT2_INTEGER_MATH(0, cl, cx); @@ -651,63 +645,67 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si lo = __umul128(idx0, cl, &hi); - if (BASE == xmrig::VARIANT_2) { - if (VARIANT == xmrig::VARIANT_4) { + if (BASE == Algorithm::CN_2) { + if (ALGO == Algorithm::CN_R) { VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx0, bx1, cx, 0); } else { - VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0)); + VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx0, bx1, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0)); } } al0 += hi; ah0 += lo; - ((uint64_t*)&l0[idx0 & MASK])[0] = al0; + reinterpret_cast(&l0[idx0 & MASK])[0] = al0; - if (BASE == xmrig::VARIANT_1 && (VARIANT == xmrig::VARIANT_TUBE || VARIANT == xmrig::VARIANT_RTO)) { - ((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0; - } else if (BASE == xmrig::VARIANT_1) { - ((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0; + if (IS_CN_HEAVY_TUBE || ALGO == Algorithm::CN_RTO) { + reinterpret_cast(&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0; + } else if (BASE == Algorithm::CN_1) { + reinterpret_cast(&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0; } else { - ((uint64_t*)&l0[idx0 & MASK])[1] = ah0; + reinterpret_cast(&l0[idx0 & MASK])[1] = ah0; } al0 ^= cl; ah0 ^= ch; idx0 = al0; - if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { +# ifdef XMRIG_ALGO_CN_HEAVY + if (props.isHeavy()) { int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; int64_t q = n / (d | 0x5); ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; - if (VARIANT == xmrig::VARIANT_XHV) { + if (ALGO == Algorithm::CN_HEAVY_XHV) { d = ~d; } idx0 = d ^ q; } +# endif - if (BASE == xmrig::VARIANT_2) { + if (BASE == Algorithm::CN_2) { bx1 = bx0; } bx0 = cx; } -#ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM } -#endif - - cn_implode_scratchpad((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state); +# endif - xmrig::keccakf(h0, 24); + cn_implode_scratchpad(reinterpret_cast(ctx[0]->memory), reinterpret_cast<__m128i *>(ctx[0]->state)); + keccakf(h0, 24); extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); } +} /* namespace xmrig */ + + #ifdef XMRIG_ALGO_CN_GPU template void cn_gpu_inner_avx(const uint8_t *spad, uint8_t *lpad); @@ -717,17 +715,41 @@ template void cn_gpu_inner_ssse3(const uint8_t *spad, uint8_t *lpad); -template -inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) +namespace xmrig { + + +template +void cn_explode_scratchpad_gpu(const uint8_t *input, uint8_t *output) { - constexpr size_t MASK = xmrig::CRYPTONIGHT_GPU_MASK; - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); - constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr size_t hash_size = 200; // 25x8 bytes + alignas(16) uint64_t hash[25]; - static_assert(MASK > 0 && ITERATIONS > 0 && MEM > 0, "unsupported algorithm/variant"); + for (uint64_t i = 0; i < MEM / 512; i++) { + memcpy(hash, input, hash_size); + hash[0] ^= i; - xmrig::keccak(input, size, ctx[0]->state); - cn_explode_scratchpad_gpu(ctx[0]->state, ctx[0]->memory); + xmrig::keccakf(hash, 24); + memcpy(output, hash, 160); + output += 160; + + xmrig::keccakf(hash, 24); + memcpy(output, hash, 176); + output += 176; + + xmrig::keccakf(hash, 24); + memcpy(output, hash, 176); + output += 176; + } +} + + +template +inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t) +{ + constexpr CnAlgo props; + + keccak(input, size, ctx[0]->state); + cn_explode_scratchpad_gpu(ctx[0]->state, ctx[0]->memory); # ifdef _MSC_VER _control87(RC_NEAR, MCW_RC); @@ -736,20 +758,22 @@ inline void cryptonight_single_hash_gpu(const uint8_t *__restrict__ input, size_ # endif if (xmrig::Cpu::info()->hasAVX2()) { - cn_gpu_inner_avx(ctx[0]->state, ctx[0]->memory); + cn_gpu_inner_avx(ctx[0]->state, ctx[0]->memory); } else { - cn_gpu_inner_ssse3(ctx[0]->state, ctx[0]->memory); + cn_gpu_inner_ssse3(ctx[0]->state, ctx[0]->memory); } - cn_implode_scratchpad((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state); - - xmrig::keccakf((uint64_t*) ctx[0]->state, 24); + cn_implode_scratchpad(reinterpret_cast(ctx[0]->memory), reinterpret_cast<__m128i *>(ctx[0]->state)); + keccakf(reinterpret_cast(ctx[0]->state), 24); memcpy(output, ctx[0]->state, 32); } + + +} /* namespace xmrig */ #endif -#ifndef XMRIG_NO_ASM +#ifdef XMRIG_FEATURE_ASM extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx **ctx); extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx **ctx); extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx **ctx); @@ -757,212 +781,243 @@ extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx **ctx); extern "C" void cnv2_rwz_mainloop_asm(cryptonight_ctx **ctx); extern "C" void cnv2_rwz_double_mainloop_asm(cryptonight_ctx **ctx); -extern xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ivybridge_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ryzen_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_half_double_mainloop_sandybridge_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ivybridge_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ryzen_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm; +namespace xmrig { -extern xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ivybridge_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ryzen_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_zls_double_mainloop_sandybridge_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ivybridge_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ryzen_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_bulldozer_asm; -extern xmrig::CpuThread::cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm; +extern cn_mainloop_fun cn_half_mainloop_ivybridge_asm; +extern cn_mainloop_fun cn_half_mainloop_ryzen_asm; +extern cn_mainloop_fun cn_half_mainloop_bulldozer_asm; +extern cn_mainloop_fun cn_half_double_mainloop_sandybridge_asm; + +extern cn_mainloop_fun cn_trtl_mainloop_ivybridge_asm; +extern cn_mainloop_fun cn_trtl_mainloop_ryzen_asm; +extern cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm; +extern cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm; + +extern cn_mainloop_fun cn_zls_mainloop_ivybridge_asm; +extern cn_mainloop_fun cn_zls_mainloop_ryzen_asm; +extern cn_mainloop_fun cn_zls_mainloop_bulldozer_asm; +extern cn_mainloop_fun cn_zls_double_mainloop_sandybridge_asm; + +extern cn_mainloop_fun cn_double_mainloop_ivybridge_asm; +extern cn_mainloop_fun cn_double_mainloop_ryzen_asm; +extern cn_mainloop_fun cn_double_mainloop_bulldozer_asm; +extern cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm; + + +} // namespace xmrig + void wow_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); void v4_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); void wow_compile_code_double(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); void v4_compile_code_double(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM); -template + +template void cn_r_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM) { v4_compile_code(code, code_size, machine_code, ASM); } -template + +template void cn_r_compile_code_double(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM) { v4_compile_code_double(code, code_size, machine_code, ASM); } + template<> -void cn_r_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM) +void cn_r_compile_code(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM) { wow_compile_code(code, code_size, machine_code, ASM); } + template<> -void cn_r_compile_code_double(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM) +void cn_r_compile_code_double(const V4_Instruction* code, int code_size, void* machine_code, xmrig::Assembly ASM) { wow_compile_code_double(code, code_size, machine_code, ASM); } -template + +namespace xmrig { + + +template inline void cryptonight_single_hash_asm(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) { - constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr CnAlgo props; - if (xmrig::cn_is_cryptonight_r() && !ctx[0]->generated_code_data.match(VARIANT, height)) { + if (props.isR() && !ctx[0]->generated_code_data.match(ALGO, height)) { V4_Instruction code[256]; - const int code_size = v4_random_math_init(code, height); - cn_r_compile_code(code, code_size, reinterpret_cast(ctx[0]->generated_code), ASM); - ctx[0]->generated_code_data.variant = VARIANT; - ctx[0]->generated_code_data.height = height; + const int code_size = v4_random_math_init(code, height); + cn_r_compile_code(code, code_size, reinterpret_cast(ctx[0]->generated_code), ASM); + + ctx[0]->generated_code_data = { ALGO, height }; } - xmrig::keccak(input, size, ctx[0]->state); - cn_explode_scratchpad(reinterpret_cast<__m128i*>(ctx[0]->state), reinterpret_cast<__m128i*>(ctx[0]->memory)); + keccak(input, size, ctx[0]->state); + cn_explode_scratchpad(reinterpret_cast(ctx[0]->state), reinterpret_cast<__m128i*>(ctx[0]->memory)); - if (VARIANT == xmrig::VARIANT_2) { - if (ASM == xmrig::ASM_INTEL) { + if (ALGO == Algorithm::CN_2) { + if (ASM == ASM_INTEL) { cnv2_mainloop_ivybridge_asm(ctx); } - else if (ASM == xmrig::ASM_RYZEN) { + else if (ASM == ASM_RYZEN) { cnv2_mainloop_ryzen_asm(ctx); } else { cnv2_mainloop_bulldozer_asm(ctx); } } - else if (VARIANT == xmrig::VARIANT_HALF) { - if (ASM == xmrig::ASM_INTEL) { + else if (ALGO == Algorithm::CN_HALF) { + if (ASM == ASM_INTEL) { cn_half_mainloop_ivybridge_asm(ctx); } - else if (ASM == xmrig::ASM_RYZEN) { + else if (ASM == ASM_RYZEN) { cn_half_mainloop_ryzen_asm(ctx); } else { cn_half_mainloop_bulldozer_asm(ctx); } } - else if (VARIANT == xmrig::VARIANT_TRTL) { - if (ASM == xmrig::ASM_INTEL) { +# ifdef XMRIG_ALGO_CN_PICO + else if (ALGO == Algorithm::CN_PICO_0) { + if (ASM == ASM_INTEL) { cn_trtl_mainloop_ivybridge_asm(ctx); } - else if (ASM == xmrig::ASM_RYZEN) { + else if (ASM == ASM_RYZEN) { cn_trtl_mainloop_ryzen_asm(ctx); } else { cn_trtl_mainloop_bulldozer_asm(ctx); } } - else if (VARIANT == xmrig::VARIANT_RWZ) { +# endif + else if (ALGO == Algorithm::CN_RWZ) { cnv2_rwz_mainloop_asm(ctx); } - else if (VARIANT == xmrig::VARIANT_ZLS) { - if (ASM == xmrig::ASM_INTEL) { + else if (ALGO == Algorithm::CN_ZLS) { + if (ASM == ASM_INTEL) { cn_zls_mainloop_ivybridge_asm(ctx); } - else if (ASM == xmrig::ASM_RYZEN) { + else if (ASM == ASM_RYZEN) { cn_zls_mainloop_ryzen_asm(ctx); } else { cn_zls_mainloop_bulldozer_asm(ctx); } } - else if (VARIANT == xmrig::VARIANT_DOUBLE) { - if (ASM == xmrig::ASM_INTEL) { + else if (ALGO == Algorithm::CN_DOUBLE) { + if (ASM == ASM_INTEL) { cn_double_mainloop_ivybridge_asm(ctx); } - else if (ASM == xmrig::ASM_RYZEN) { + else if (ASM == ASM_RYZEN) { cn_double_mainloop_ryzen_asm(ctx); } else { cn_double_mainloop_bulldozer_asm(ctx); } } - else if (xmrig::cn_is_cryptonight_r()) { + else if (props.isR()) { ctx[0]->generated_code(ctx); } - cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[0]->memory), reinterpret_cast<__m128i*>(ctx[0]->state)); - xmrig::keccakf(reinterpret_cast(ctx[0]->state), 24); + cn_implode_scratchpad(reinterpret_cast(ctx[0]->memory), reinterpret_cast<__m128i*>(ctx[0]->state)); + keccakf(reinterpret_cast(ctx[0]->state), 24); extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); } -template +template inline void cryptonight_double_hash_asm(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) { - constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr CnAlgo props; - if (xmrig::cn_is_cryptonight_r() && !ctx[0]->generated_code_data.match(VARIANT, height)) { + if (props.isR() && !ctx[0]->generated_code_data.match(ALGO, height)) { V4_Instruction code[256]; - const int code_size = v4_random_math_init(code, height); - cn_r_compile_code_double(code, code_size, reinterpret_cast(ctx[0]->generated_code), ASM); - ctx[0]->generated_code_data.variant = VARIANT; - ctx[0]->generated_code_data.height = height; + const int code_size = v4_random_math_init(code, height); + cn_r_compile_code_double(code, code_size, reinterpret_cast(ctx[0]->generated_code), ASM); + + ctx[0]->generated_code_data = { ALGO, height }; } - xmrig::keccak(input, size, ctx[0]->state); - xmrig::keccak(input + size, size, ctx[1]->state); + keccak(input, size, ctx[0]->state); + keccak(input + size, size, ctx[1]->state); - cn_explode_scratchpad(reinterpret_cast<__m128i*>(ctx[0]->state), reinterpret_cast<__m128i*>(ctx[0]->memory)); - cn_explode_scratchpad(reinterpret_cast<__m128i*>(ctx[1]->state), reinterpret_cast<__m128i*>(ctx[1]->memory)); + cn_explode_scratchpad(reinterpret_cast(ctx[0]->state), reinterpret_cast<__m128i*>(ctx[0]->memory)); + cn_explode_scratchpad(reinterpret_cast(ctx[1]->state), reinterpret_cast<__m128i*>(ctx[1]->memory)); - if (VARIANT == xmrig::VARIANT_2) { + if (ALGO == Algorithm::CN_2) { cnv2_double_mainloop_sandybridge_asm(ctx); } - else if (VARIANT == xmrig::VARIANT_HALF) { + else if (ALGO == Algorithm::CN_HALF) { cn_half_double_mainloop_sandybridge_asm(ctx); } - else if (VARIANT == xmrig::VARIANT_TRTL) { +# ifdef XMRIG_ALGO_CN_PICO + else if (ALGO == Algorithm::CN_PICO_0) { cn_trtl_double_mainloop_sandybridge_asm(ctx); } - else if (VARIANT == xmrig::VARIANT_RWZ) { +# endif + else if (ALGO == Algorithm::CN_RWZ) { cnv2_rwz_double_mainloop_asm(ctx); } - else if (VARIANT == xmrig::VARIANT_ZLS) { + else if (ALGO == Algorithm::CN_ZLS) { cn_zls_double_mainloop_sandybridge_asm(ctx); } - else if (VARIANT == xmrig::VARIANT_DOUBLE) { + else if (ALGO == Algorithm::CN_DOUBLE) { cn_double_double_mainloop_sandybridge_asm(ctx); } - else if (xmrig::cn_is_cryptonight_r()) { + else if (props.isR()) { ctx[0]->generated_code(ctx); } - cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[0]->memory), reinterpret_cast<__m128i*>(ctx[0]->state)); - cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[1]->memory), reinterpret_cast<__m128i*>(ctx[1]->state)); + cn_implode_scratchpad(reinterpret_cast(ctx[0]->memory), reinterpret_cast<__m128i*>(ctx[0]->state)); + cn_implode_scratchpad(reinterpret_cast(ctx[1]->memory), reinterpret_cast<__m128i*>(ctx[1]->state)); - xmrig::keccakf(reinterpret_cast(ctx[0]->state), 24); - xmrig::keccakf(reinterpret_cast(ctx[1]->state), 24); + keccakf(reinterpret_cast(ctx[0]->state), 24); + keccakf(reinterpret_cast(ctx[1]->state), 24); extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32); } + + +} /* namespace xmrig */ #endif -template +namespace xmrig { + + +template inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) { - constexpr size_t MASK = xmrig::cn_select_mask(); - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); - constexpr size_t MEM = xmrig::cn_select_memory(); - constexpr xmrig::Variant BASE = xmrig::cn_base_variant(); + constexpr CnAlgo props; + constexpr size_t MASK = props.mask(); + constexpr Algorithm::Id BASE = props.base(); - if (BASE == xmrig::VARIANT_1 && size < 43) { +# ifdef XMRIG_ALGO_CN_HEAVY + constexpr bool IS_CN_HEAVY_TUBE = ALGO == Algorithm::CN_HEAVY_TUBE; +# else + constexpr bool IS_CN_HEAVY_TUBE = false; +# endif + + if (BASE == Algorithm::CN_1 && size < 43) { memset(output, 0, 64); return; } - xmrig::keccak(input, size, ctx[0]->state); - xmrig::keccak(input + size, size, ctx[1]->state); + keccak(input, size, ctx[0]->state); + keccak(input + size, size, ctx[1]->state); - const uint8_t* l0 = ctx[0]->memory; - const uint8_t* l1 = ctx[1]->memory; - uint64_t* h0 = reinterpret_cast(ctx[0]->state); - uint64_t* h1 = reinterpret_cast(ctx[1]->state); + uint8_t *l0 = ctx[0]->memory; + uint8_t *l1 = ctx[1]->memory; + uint64_t *h0 = reinterpret_cast(ctx[0]->state); + uint64_t *h1 = reinterpret_cast(ctx[1]->state); VARIANT1_INIT(0); VARIANT1_INIT(1); @@ -972,8 +1027,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si VARIANT4_RANDOM_MATH_INIT(0); VARIANT4_RANDOM_MATH_INIT(1); - cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); - cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad(reinterpret_cast(h0), reinterpret_cast<__m128i *>(l0)); + cn_explode_scratchpad(reinterpret_cast(h1), reinterpret_cast<__m128i *>(l1)); uint64_t al0 = h0[0] ^ h0[4]; uint64_t al1 = h1[0] ^ h1[4]; @@ -988,31 +1043,31 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si uint64_t idx0 = al0; uint64_t idx1 = al1; - for (size_t i = 0; i < ITERATIONS; i++) { + for (size_t i = 0; i < props.iterations(); i++) { __m128i cx0, cx1; - if (VARIANT == xmrig::VARIANT_TUBE || !SOFT_AES) { - cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); - cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + if (IS_CN_HEAVY_TUBE || !SOFT_AES) { + cx0 = _mm_load_si128(reinterpret_cast(&l0[idx0 & MASK])); + cx1 = _mm_load_si128(reinterpret_cast(&l1[idx1 & MASK])); } const __m128i ax0 = _mm_set_epi64x(ah0, al0); const __m128i ax1 = _mm_set_epi64x(ah1, al1); - if (VARIANT == xmrig::VARIANT_TUBE) { + if (IS_CN_HEAVY_TUBE) { cx0 = aes_round_tweak_div(cx0, ax0); cx1 = aes_round_tweak_div(cx1, ax1); } else if (SOFT_AES) { - cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], ax0, (const uint32_t*)saes_table); - cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], ax1, (const uint32_t*)saes_table); + cx0 = soft_aesenc(&l0[idx0 & MASK], ax0, reinterpret_cast(saes_table)); + cx1 = soft_aesenc(&l1[idx1 & MASK], ax1, reinterpret_cast(saes_table)); } else { cx0 = _mm_aesenc_si128(cx0, ax0); cx1 = _mm_aesenc_si128(cx1, ax1); } - if (BASE == xmrig::VARIANT_1 || (BASE == xmrig::VARIANT_2)) { - cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], l0, idx0 & MASK, ax0, bx00, bx01, cx0); - cryptonight_monero_tweak((uint64_t*)&l1[idx1 & MASK], l1, idx1 & MASK, ax1, bx10, bx11, cx1); + if (BASE == Algorithm::CN_1 || BASE == Algorithm::CN_2) { + cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], l0, idx0 & MASK, ax0, bx00, bx01, cx0); + cryptonight_monero_tweak((uint64_t*)&l1[idx1 & MASK], l1, idx1 & MASK, ax1, bx10, bx11, cx1); } else { _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx00, cx0)); _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx10, cx1)); @@ -1025,10 +1080,10 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si cl = ((uint64_t*) &l0[idx0 & MASK])[0]; ch = ((uint64_t*) &l0[idx0 & MASK])[1]; - if (BASE == xmrig::VARIANT_2) { - if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { + if (BASE == Algorithm::CN_2) { + if (props.isR()) { VARIANT4_RANDOM_MATH(0, al0, ah0, cl, bx00, bx01); - if (VARIANT == xmrig::VARIANT_4) { + if (ALGO == Algorithm::CN_R) { al0 ^= r0[2] | ((uint64_t)(r0[3]) << 32); ah0 ^= r0[0] | ((uint64_t)(r0[1]) << 32); } @@ -1039,11 +1094,11 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si lo = __umul128(idx0, cl, &hi); - if (BASE == xmrig::VARIANT_2) { - if (VARIANT == xmrig::VARIANT_4) { + if (BASE == Algorithm::CN_2) { + if (ALGO == Algorithm::CN_R) { VARIANT2_SHUFFLE(l0, idx0 & MASK, ax0, bx00, bx01, cx0, 0); } else { - VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0)); + VARIANT2_SHUFFLE2(l0, idx0 & MASK, ax0, bx00, bx01, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0)); } } @@ -1052,9 +1107,9 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l0[idx0 & MASK])[0] = al0; - if (BASE == xmrig::VARIANT_1 && (VARIANT == xmrig::VARIANT_TUBE || VARIANT == xmrig::VARIANT_RTO)) { + if (IS_CN_HEAVY_TUBE || ALGO == Algorithm::CN_RTO) { ((uint64_t*) &l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0; - } else if (BASE == xmrig::VARIANT_1) { + } else if (BASE == Algorithm::CN_1) { ((uint64_t*) &l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0; } else { ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; @@ -1064,27 +1119,29 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ah0 ^= ch; idx0 = al0; - if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { +# ifdef XMRIG_ALGO_CN_HEAVY + if (props.isHeavy()) { int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; int64_t q = n / (d | 0x5); ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; - if (VARIANT == xmrig::VARIANT_XHV) { + if (ALGO == Algorithm::CN_HEAVY_XHV) { d = ~d; } idx0 = d ^ q; } +# endif cl = ((uint64_t*) &l1[idx1 & MASK])[0]; ch = ((uint64_t*) &l1[idx1 & MASK])[1]; - if (BASE == xmrig::VARIANT_2) { - if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { + if (BASE == Algorithm::CN_2) { + if (props.isR()) { VARIANT4_RANDOM_MATH(1, al1, ah1, cl, bx10, bx11); - if (VARIANT == xmrig::VARIANT_4) { + if (ALGO == Algorithm::CN_R) { al1 ^= r1[2] | ((uint64_t)(r1[3]) << 32); ah1 ^= r1[0] | ((uint64_t)(r1[1]) << 32); } @@ -1095,11 +1152,11 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si lo = __umul128(idx1, cl, &hi); - if (BASE == xmrig::VARIANT_2) { - if (VARIANT == xmrig::VARIANT_4) { + if (BASE == Algorithm::CN_2) { + if (ALGO == Algorithm::CN_R) { VARIANT2_SHUFFLE(l1, idx1 & MASK, ax1, bx10, bx11, cx1, 0); } else { - VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0)); + VARIANT2_SHUFFLE2(l1, idx1 & MASK, ax1, bx10, bx11, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0)); } } @@ -1108,9 +1165,9 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l1[idx1 & MASK])[0] = al1; - if (BASE == xmrig::VARIANT_1 && (VARIANT == xmrig::VARIANT_TUBE || VARIANT == xmrig::VARIANT_RTO)) { + if (IS_CN_HEAVY_TUBE || ALGO == Algorithm::CN_RTO) { ((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1 ^ al1; - } else if (BASE == xmrig::VARIANT_1) { + } else if (BASE == Algorithm::CN_1) { ((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1; } else { ((uint64_t*)&l1[idx1 & MASK])[1] = ah1; @@ -1120,21 +1177,23 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ah1 ^= ch; idx1 = al1; - if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { +# ifdef XMRIG_ALGO_CN_HEAVY + if (props.isHeavy()) { int64_t n = ((int64_t*)&l1[idx1 & MASK])[0]; int32_t d = ((int32_t*)&l1[idx1 & MASK])[2]; int64_t q = n / (d | 0x5); ((int64_t*)&l1[idx1 & MASK])[0] = n ^ q; - if (VARIANT == xmrig::VARIANT_XHV) { + if (ALGO == Algorithm::CN_HEAVY_XHV) { d = ~d; } idx1 = d ^ q; } +# endif - if (BASE == xmrig::VARIANT_2) { + if (BASE == Algorithm::CN_2) { bx01 = bx00; bx11 = bx10; } @@ -1143,11 +1202,11 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si bx10 = cx1; } - cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); - cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad(reinterpret_cast(l0), reinterpret_cast<__m128i *>(h0)); + cn_implode_scratchpad(reinterpret_cast(l1), reinterpret_cast<__m128i *>(h1)); - xmrig::keccakf(h0, 24); - xmrig::keccakf(h1, 24); + keccakf(h0, 24); + keccakf(h1, 24); extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output); extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32); @@ -1159,20 +1218,20 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si c = _mm_load_si128(ptr); -#define CN_STEP2(a, b0, b1, c, l, ptr, idx) \ - if (VARIANT == xmrig::VARIANT_TUBE) { \ - c = aes_round_tweak_div(c, a); \ - } \ - else if (SOFT_AES) { \ - c = soft_aesenc(&c, a, (const uint32_t*)saes_table); \ - } else { \ - c = _mm_aesenc_si128(c, a); \ - } \ - \ - if (BASE == xmrig::VARIANT_1 || BASE == xmrig::VARIANT_2) { \ - cryptonight_monero_tweak((uint64_t*)ptr, l, idx & MASK, a, b0, b1, c); \ - } else { \ - _mm_store_si128(ptr, _mm_xor_si128(b0, c)); \ +#define CN_STEP2(a, b0, b1, c, l, ptr, idx) \ + if (IS_CN_HEAVY_TUBE) { \ + c = aes_round_tweak_div(c, a); \ + } \ + else if (SOFT_AES) { \ + c = soft_aesenc(&c, a, (const uint32_t*)saes_table); \ + } else { \ + c = _mm_aesenc_si128(c, a); \ + } \ + \ + if (BASE == Algorithm::CN_1 || BASE == Algorithm::CN_2) { \ + cryptonight_monero_tweak((uint64_t*)ptr, l, idx & MASK, a, b0, b1, c); \ + } else { \ + _mm_store_si128(ptr, _mm_xor_si128(b0, c)); \ } @@ -1183,62 +1242,60 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si uint64_t ch##part = ((uint64_t*)ptr)[1]; -#define CN_STEP4(part, a, b0, b1, c, l, mc, ptr, idx) \ - uint64_t al##part, ah##part; \ - if (BASE == xmrig::VARIANT_2) { \ - if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { \ - al##part = _mm_cvtsi128_si64(a); \ - ah##part = _mm_cvtsi128_si64(_mm_srli_si128(a, 8)); \ - VARIANT4_RANDOM_MATH(part, al##part, ah##part, cl##part, b0, b1); \ - if (VARIANT == xmrig::VARIANT_4) { \ - al##part ^= r##part[2] | ((uint64_t)(r##part[3]) << 32); \ - ah##part ^= r##part[0] | ((uint64_t)(r##part[1]) << 32); \ - } \ - } else { \ - VARIANT2_INTEGER_MATH(part, cl##part, c); \ - } \ - } \ - lo = __umul128(idx, cl##part, &hi); \ - if (BASE == xmrig::VARIANT_2) { \ - if (VARIANT == xmrig::VARIANT_4) { \ - VARIANT2_SHUFFLE(l, idx & MASK, a, b0, b1, c, 0); \ - } else { \ - VARIANT2_SHUFFLE2(l, idx & MASK, a, b0, b1, hi, lo, (VARIANT == xmrig::VARIANT_RWZ ? 1 : 0)); \ - } \ - } \ - if (VARIANT == xmrig::VARIANT_4) { \ - a = _mm_set_epi64x(ah##part, al##part); \ - } \ - a = _mm_add_epi64(a, _mm_set_epi64x(lo, hi)); \ - \ - if (BASE == xmrig::VARIANT_1) { \ - _mm_store_si128(ptr, _mm_xor_si128(a, mc)); \ - \ - if (VARIANT == xmrig::VARIANT_TUBE || \ - VARIANT == xmrig::VARIANT_RTO) { \ - ((uint64_t*)ptr)[1] ^= ((uint64_t*)ptr)[0]; \ - } \ - } else { \ - _mm_store_si128(ptr, a); \ - } \ - \ - a = _mm_xor_si128(a, _mm_set_epi64x(ch##part, cl##part)); \ - idx = _mm_cvtsi128_si64(a); \ - \ - if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { \ - int64_t n = ((int64_t*)&l[idx & MASK])[0]; \ - int32_t d = ((int32_t*)&l[idx & MASK])[2]; \ - int64_t q = n / (d | 0x5); \ - ((int64_t*)&l[idx & MASK])[0] = n ^ q; \ - if (VARIANT == xmrig::VARIANT_XHV) { \ - d = ~d; \ - } \ - \ - idx = d ^ q; \ - } \ - if (BASE == xmrig::VARIANT_2) { \ - b1 = b0; \ - } \ +#define CN_STEP4(part, a, b0, b1, c, l, mc, ptr, idx) \ + uint64_t al##part, ah##part; \ + if (BASE == Algorithm::CN_2) { \ + if (props.isR()) { \ + al##part = _mm_cvtsi128_si64(a); \ + ah##part = _mm_cvtsi128_si64(_mm_srli_si128(a, 8)); \ + VARIANT4_RANDOM_MATH(part, al##part, ah##part, cl##part, b0, b1); \ + if (ALGO == Algorithm::CN_R) { \ + al##part ^= r##part[2] | ((uint64_t)(r##part[3]) << 32); \ + ah##part ^= r##part[0] | ((uint64_t)(r##part[1]) << 32); \ + } \ + } else { \ + VARIANT2_INTEGER_MATH(part, cl##part, c); \ + } \ + } \ + lo = __umul128(idx, cl##part, &hi); \ + if (BASE == Algorithm::CN_2) { \ + if (ALGO == Algorithm::CN_R) { \ + VARIANT2_SHUFFLE(l, idx & MASK, a, b0, b1, c, 0); \ + } else { \ + VARIANT2_SHUFFLE2(l, idx & MASK, a, b0, b1, hi, lo, (ALGO == Algorithm::CN_RWZ ? 1 : 0)); \ + } \ + } \ + if (ALGO == Algorithm::CN_R) { \ + a = _mm_set_epi64x(ah##part, al##part); \ + } \ + a = _mm_add_epi64(a, _mm_set_epi64x(lo, hi)); \ + \ + if (BASE == Algorithm::CN_1) { \ + _mm_store_si128(ptr, _mm_xor_si128(a, mc)); \ + \ + if (IS_CN_HEAVY_TUBE || ALGO == Algorithm::CN_RTO) { \ + ((uint64_t*)ptr)[1] ^= ((uint64_t*)ptr)[0]; \ + } \ + } else { \ + _mm_store_si128(ptr, a); \ + } \ + \ + a = _mm_xor_si128(a, _mm_set_epi64x(ch##part, cl##part)); \ + idx = _mm_cvtsi128_si64(a); \ + if (props.isHeavy()) { \ + int64_t n = ((int64_t*)&l[idx & MASK])[0]; \ + int32_t d = ((int32_t*)&l[idx & MASK])[2]; \ + int64_t q = n / (d | 0x5); \ + ((int64_t*)&l[idx & MASK])[0] = n ^ q; \ + if (IS_CN_HEAVY_XHV) { \ + d = ~d; \ + } \ + \ + idx = d ^ q; \ + } \ + if (BASE == Algorithm::CN_2) { \ + b1 = b0; \ + } \ b0 = c; @@ -1246,11 +1303,11 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si __m128i mc##n; \ __m128i division_result_xmm_##n; \ __m128i sqrt_result_xmm_##n; \ - if (BASE == xmrig::VARIANT_1) { \ + if (BASE == Algorithm::CN_1) { \ mc##n = _mm_set_epi64x(*reinterpret_cast(input + n * size + 35) ^ \ *(reinterpret_cast((ctx)->state) + 24), 0); \ } \ - if (BASE == xmrig::VARIANT_2) { \ + if (BASE == Algorithm::CN_2) { \ division_result_xmm_##n = _mm_cvtsi64_si128(h##n[12]); \ sqrt_result_xmm_##n = _mm_cvtsi64_si128(h##n[13]); \ } \ @@ -1261,22 +1318,29 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si VARIANT4_RANDOM_MATH_INIT(n); -template +template inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) { - constexpr size_t MASK = xmrig::cn_select_mask(); - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); - constexpr size_t MEM = xmrig::cn_select_memory(); - constexpr xmrig::Variant BASE = xmrig::cn_base_variant(); + constexpr CnAlgo props; + constexpr size_t MASK = props.mask(); + constexpr Algorithm::Id BASE = props.base(); - if (BASE == xmrig::VARIANT_1 && size < 43) { +# ifdef XMRIG_ALGO_CN_HEAVY + constexpr bool IS_CN_HEAVY_TUBE = ALGO == Algorithm::CN_HEAVY_TUBE; + constexpr bool IS_CN_HEAVY_XHV = ALGO == Algorithm::CN_HEAVY_XHV; +# else + constexpr bool IS_CN_HEAVY_TUBE = false; + constexpr bool IS_CN_HEAVY_XHV = false; +# endif + + if (BASE == Algorithm::CN_1 && size < 43) { memset(output, 0, 32 * 3); return; } for (size_t i = 0; i < 3; i++) { - xmrig::keccak(input + size * i, size, ctx[i]->state); - cn_explode_scratchpad(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory)); + keccak(input + size * i, size, ctx[i]->state); + cn_explode_scratchpad(reinterpret_cast(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory)); } uint8_t* l0 = ctx[0]->memory; @@ -1296,7 +1360,7 @@ inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t si idx1 = _mm_cvtsi128_si64(ax1); idx2 = _mm_cvtsi128_si64(ax2); - for (size_t i = 0; i < ITERATIONS; i++) { + for (size_t i = 0; i < props.iterations(); i++) { uint64_t hi, lo; __m128i *ptr0, *ptr1, *ptr2; @@ -1318,29 +1382,36 @@ inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t si } for (size_t i = 0; i < 3; i++) { - cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state)); - xmrig::keccakf(reinterpret_cast(ctx[i]->state), 24); + cn_implode_scratchpad(reinterpret_cast(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state)); + keccakf(reinterpret_cast(ctx[i]->state), 24); extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i); } } -template +template inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) { - constexpr size_t MASK = xmrig::cn_select_mask(); - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); - constexpr size_t MEM = xmrig::cn_select_memory(); - constexpr xmrig::Variant BASE = xmrig::cn_base_variant(); + constexpr CnAlgo props; + constexpr size_t MASK = props.mask(); + constexpr Algorithm::Id BASE = props.base(); - if (BASE == xmrig::VARIANT_1 && size < 43) { +# ifdef XMRIG_ALGO_CN_HEAVY + constexpr bool IS_CN_HEAVY_TUBE = ALGO == Algorithm::CN_HEAVY_TUBE; + constexpr bool IS_CN_HEAVY_XHV = ALGO == Algorithm::CN_HEAVY_XHV; +# else + constexpr bool IS_CN_HEAVY_TUBE = false; + constexpr bool IS_CN_HEAVY_XHV = false; +# endif + + if (BASE == Algorithm::CN_1 && size < 43) { memset(output, 0, 32 * 4); return; } for (size_t i = 0; i < 4; i++) { - xmrig::keccak(input + size * i, size, ctx[i]->state); - cn_explode_scratchpad(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory)); + keccak(input + size * i, size, ctx[i]->state); + cn_explode_scratchpad(reinterpret_cast(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory)); } uint8_t* l0 = ctx[0]->memory; @@ -1364,8 +1435,7 @@ inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size idx2 = _mm_cvtsi128_si64(ax2); idx3 = _mm_cvtsi128_si64(ax3); - for (size_t i = 0; i < ITERATIONS; i++) - { + for (size_t i = 0; i < props.iterations(); i++) { uint64_t hi, lo; __m128i *ptr0, *ptr1, *ptr2, *ptr3; @@ -1391,29 +1461,36 @@ inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size } for (size_t i = 0; i < 4; i++) { - cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state)); - xmrig::keccakf(reinterpret_cast(ctx[i]->state), 24); + cn_implode_scratchpad(reinterpret_cast(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state)); + keccakf(reinterpret_cast(ctx[i]->state), 24); extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i); } } -template +template inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx, uint64_t height) { - constexpr size_t MASK = xmrig::cn_select_mask(); - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); - constexpr size_t MEM = xmrig::cn_select_memory(); - constexpr xmrig::Variant BASE = xmrig::cn_base_variant(); + constexpr CnAlgo props; + constexpr size_t MASK = props.mask(); + constexpr Algorithm::Id BASE = props.base(); - if (BASE == xmrig::VARIANT_1 && size < 43) { +# ifdef XMRIG_ALGO_CN_HEAVY + constexpr bool IS_CN_HEAVY_TUBE = ALGO == Algorithm::CN_HEAVY_TUBE; + constexpr bool IS_CN_HEAVY_XHV = ALGO == Algorithm::CN_HEAVY_XHV; +# else + constexpr bool IS_CN_HEAVY_TUBE = false; + constexpr bool IS_CN_HEAVY_XHV = false; +# endif + + if (BASE == Algorithm::CN_1 && size < 43) { memset(output, 0, 32 * 5); return; } for (size_t i = 0; i < 5; i++) { - xmrig::keccak(input + size * i, size, ctx[i]->state); - cn_explode_scratchpad(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory)); + keccak(input + size * i, size, ctx[i]->state); + cn_explode_scratchpad(reinterpret_cast(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory)); } uint8_t* l0 = ctx[0]->memory; @@ -1441,8 +1518,7 @@ inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t siz idx3 = _mm_cvtsi128_si64(ax3); idx4 = _mm_cvtsi128_si64(ax4); - for (size_t i = 0; i < ITERATIONS; i++) - { + for (size_t i = 0; i < props.iterations(); i++) { uint64_t hi, lo; __m128i *ptr0, *ptr1, *ptr2, *ptr3, *ptr4; @@ -1472,10 +1548,14 @@ inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t siz } for (size_t i = 0; i < 5; i++) { - cn_implode_scratchpad(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state)); - xmrig::keccakf(reinterpret_cast(ctx[i]->state), 24); + cn_implode_scratchpad(reinterpret_cast(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state)); + keccakf(reinterpret_cast(ctx[i]->state), 24); extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i); } } + +} /* namespace xmrig */ + + #endif /* XMRIG_CRYPTONIGHT_X86_H */ diff --git a/src/crypto/cn/gpu/cn_gpu_avx.cpp b/src/crypto/cn/gpu/cn_gpu_avx.cpp index 382be570..38da9714 100644 --- a/src/crypto/cn/gpu/cn_gpu_avx.cpp +++ b/src/crypto/cn/gpu/cn_gpu_avx.cpp @@ -22,7 +22,9 @@ * along with this program. If not, see . */ -#include "crypto/cn/CryptoNight_constants.h" + +#include "crypto/cn/CnAlgo.h" + #ifdef __GNUC__ # include @@ -206,4 +208,4 @@ void cn_gpu_inner_avx(const uint8_t* spad, uint8_t* lpad) } } -template void cn_gpu_inner_avx(const uint8_t* spad, uint8_t* lpad); +template void cn_gpu_inner_avx().iterations(), xmrig::CnAlgo().mask()>(const uint8_t* spad, uint8_t* lpad); diff --git a/src/crypto/cn/gpu/cn_gpu_ssse3.cpp b/src/crypto/cn/gpu/cn_gpu_ssse3.cpp index 42a11a1d..7cca096e 100644 --- a/src/crypto/cn/gpu/cn_gpu_ssse3.cpp +++ b/src/crypto/cn/gpu/cn_gpu_ssse3.cpp @@ -22,7 +22,9 @@ * along with this program. If not, see . */ -#include "crypto/cn/CryptoNight_constants.h" + +#include "crypto/cn/CnAlgo.h" + #ifdef __GNUC__ # include @@ -207,4 +209,4 @@ void cn_gpu_inner_ssse3(const uint8_t* spad, uint8_t* lpad) } } -template void cn_gpu_inner_ssse3(const uint8_t* spad, uint8_t* lpad); +template void cn_gpu_inner_ssse3().iterations(), xmrig::CnAlgo().mask()>(const uint8_t* spad, uint8_t* lpad); diff --git a/src/crypto/cn/r/variant4_random_math.h b/src/crypto/cn/r/variant4_random_math.h index c384df7a..48f0f6ce 100644 --- a/src/crypto/cn/r/variant4_random_math.h +++ b/src/crypto/cn/r/variant4_random_math.h @@ -1,6 +1,13 @@ #ifndef VARIANT4_RANDOM_MATH_H #define VARIANT4_RANDOM_MATH_H + +#include + + +#include "crypto/common/Algorithm.h" + + extern "C" { #include "crypto/cn/c_blake256.h" @@ -182,7 +189,7 @@ static FORCEINLINE void check_data(size_t* data_index, const size_t bytes_needed // Generates as many random math operations as possible with given latency and ALU restrictions // "code" array must have space for NUM_INSTRUCTIONS_MAX+1 instructions -template +template static int v4_random_math_init(struct V4_Instruction* code, const uint64_t height) { // MUL is 3 cycles, 3-way addition and rotations are 2 cycles, SUB/XOR are 1 cycle @@ -204,8 +211,7 @@ static int v4_random_math_init(struct V4_Instruction* code, const uint64_t heigh memset(data, 0, sizeof(data)); uint64_t tmp = SWAP64LE(height); memcpy(data, &tmp, sizeof(uint64_t)); - if (VARIANT == xmrig::VARIANT_4) - { + if (ALGO == xmrig::Algorithm::CN_R) { data[20] = -38; } @@ -249,7 +255,7 @@ static int v4_random_math_init(struct V4_Instruction* code, const uint64_t heigh code_size = 0; int total_iterations = 0; - r8_used = (VARIANT == xmrig::VARIANT_WOW); + r8_used = (ALGO == xmrig::Algorithm::CN_WOW); // Generate random code to achieve minimal required latency for our abstract CPU // Try to get this latency for all 4 registers @@ -291,10 +297,9 @@ static int v4_random_math_init(struct V4_Instruction* code, const uint64_t heigh int b = src_index; // Don't do ADD/SUB/XOR with the same register - if (((opcode == ADD) || (opcode == SUB) || (opcode == XOR)) && (a == b)) - { + if (((opcode == ADD) || (opcode == SUB) || (opcode == XOR)) && (a == b)) { // a is always < 4, so we don't need to check bounds here - b = (VARIANT == xmrig::VARIANT_WOW) ? (a + 4) : 8; + b = (ALGO == xmrig::Algorithm::CN_WOW) ? (a + 4) : 8; src_index = b; } diff --git a/src/crypto/common/Algorithm.cpp b/src/crypto/common/Algorithm.cpp index f85b0a6f..78272f79 100644 --- a/src/crypto/common/Algorithm.cpp +++ b/src/crypto/common/Algorithm.cpp @@ -56,12 +56,12 @@ struct AlgoName static AlgoName const algorithm_names[] = { - { "cryptonight/0", "cn/0", Algorithm::CN_0 }, - { "cryptonight", "cn", Algorithm::CN_0 }, - { "cryptonight/1", "cn/1", Algorithm::CN_1 }, - { "cryptonight-monerov7", nullptr, Algorithm::CN_1 }, - { "cryptonight_v7", nullptr, Algorithm::CN_1 }, - { "cryptonight/2", "cn/2", Algorithm::CN_2 }, + { "cryptonight/0", "cn/0", Algorithm::CN_0 }, + { "cryptonight", "cn", Algorithm::CN_0 }, + { "cryptonight/1", "cn/1", Algorithm::CN_1 }, + { "cryptonight-monerov7", nullptr, Algorithm::CN_1 }, + { "cryptonight_v7", nullptr, Algorithm::CN_1 }, + { "cryptonight/2", "cn/2", Algorithm::CN_2 }, { "cryptonight-monerov8", nullptr, Algorithm::CN_2 }, { "cryptonight_v8", nullptr, Algorithm::CN_2 }, { "cryptonight/r", "cn/r", Algorithm::CN_R }, @@ -75,7 +75,7 @@ static AlgoName const algorithm_names[] = { { "cryptonight/rto", "cn/rto", Algorithm::CN_RTO }, { "cryptonight/rwz", "cn/rwz", Algorithm::CN_RWZ }, { "cryptonight/zls", "cn/zls", Algorithm::CN_ZLS }, - { "cryptonight/double", "cn/double", Algorithm::CN_ZLS }, + { "cryptonight/double", "cn/double", Algorithm::CN_DOUBLE }, # ifdef XMRIG_ALGO_CN_GPU { "cryptonight/gpu", "cn/gpu", Algorithm::CN_GPU }, { "cryptonight_gpu", nullptr, Algorithm::CN_GPU }, @@ -99,11 +99,11 @@ static AlgoName const algorithm_names[] = { { "cryptonight-bittube2", nullptr, Algorithm::CN_HEAVY_TUBE }, # endif # ifdef XMRIG_ALGO_CN_PICO - { "cryptonight-pico", "cn-pico", Algorithm::CN_PICO }, - { "cryptonight-pico/trtl", "cn-pico/trtl", Algorithm::CN_PICO }, - { "cryptonight-turtle", "cn-trtl", Algorithm::CN_PICO }, - { "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO }, - { "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO }, + { "cryptonight-pico", "cn-pico", Algorithm::CN_PICO_0 }, + { "cryptonight-pico/trtl", "cn-pico/trtl", Algorithm::CN_PICO_0 }, + { "cryptonight-turtle", "cn-trtl", Algorithm::CN_PICO_0 }, + { "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO_0 }, + { "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 }, # endif }; @@ -111,15 +111,48 @@ static AlgoName const algorithm_names[] = { } /* namespace xmrig */ -const char *xmrig::Algorithm::name(bool shortName) const +xmrig::Algorithm::Family xmrig::Algorithm::family(Id id) { - for (size_t i = 0; i < ARRAY_SIZE(algorithm_names); i++) { - if (algorithm_names[i].id == m_id) { - return shortName ? algorithm_names[i].shortName : algorithm_names[i].name; - } + switch (id) { + case CN_0: + case CN_1: + case CN_2: + case CN_R: + case CN_WOW: + case CN_FAST: + case CN_HALF: + case CN_XAO: + case CN_RTO: + case CN_RWZ: + case CN_DOUBLE: +# ifdef XMRIG_ALGO_CN_GPU + case CN_GPU: +# endif + return CN; + +# ifdef XMRIG_ALGO_CN_LITE + case CN_LITE_0: + case CN_LITE_1: + return CN_LITE; +# endif + +# ifdef XMRIG_ALGO_CN_HEAVY + case CN_HEAVY_0: + case CN_HEAVY_TUBE: + case CN_HEAVY_XHV: + return CN_HEAVY; +# endif + +# ifdef XMRIG_ALGO_CN_PICO + case Algorithm::CN_PICO_0: + return CN_PICO; +# endif + + default: + break; } - return "invalid"; + return UNKNOWN; } @@ -137,3 +170,15 @@ xmrig::Algorithm::Id xmrig::Algorithm::parse(const char *name) return INVALID; } + + +const char *xmrig::Algorithm::name(bool shortName) const +{ + for (size_t i = 0; i < ARRAY_SIZE(algorithm_names); i++) { + if (algorithm_names[i].id == m_id) { + return shortName ? algorithm_names[i].shortName : algorithm_names[i].name; + } + } + + return "invalid"; +} diff --git a/src/crypto/common/Algorithm.h b/src/crypto/common/Algorithm.h index c70e0caa..c9388dee 100644 --- a/src/crypto/common/Algorithm.h +++ b/src/crypto/common/Algorithm.h @@ -63,24 +63,35 @@ public: CN_HEAVY_XHV, // "cn-heavy/xhv" Modified CryptoNight-Heavy (Haven Protocol only) # endif # ifdef XMRIG_ALGO_CN_PICO - CN_PICO, // "cn-pico" CryptoNight Turtle (TRTL) + CN_PICO_0, // "cn-pico" CryptoNight Turtle (TRTL) # endif MAX }; + enum Family : int { + UNKNOWN, + CN, + CN_LITE, + CN_HEAVY, + CN_PICO + }; + inline Algorithm() {} inline Algorithm(const char *algo) : m_id(parse(algo)) {} inline Algorithm(Id id) : m_id(id) {} inline bool isEqual(const Algorithm &other) const { return m_id == other.m_id; } + inline bool isValid() const { return m_id != INVALID; } inline const char *name() const { return name(false); } inline const char *shortName() const { return name(true); } + inline Family family() const { return family(m_id); } inline Id id() const { return m_id; } - inline bool isValid() const { return m_id != INVALID; } inline bool operator!=(const Algorithm &other) const { return !isEqual(other); } inline bool operator==(const Algorithm &other) const { return isEqual(other); } + inline operator Algorithm::Id() const { return m_id; } + static Family family(Id id); static Id parse(const char *name); private: diff --git a/src/interfaces/IThread.h b/src/interfaces/IThread.h index e74b5bca..3c0a7287 100644 --- a/src/interfaces/IThread.h +++ b/src/interfaces/IThread.h @@ -27,7 +27,7 @@ #include -#include "common/xmrig.h" +#include "crypto/common/Algorithm.h" #include "rapidjson/fwd.h" @@ -53,7 +53,7 @@ public: virtual ~IThread() = default; - virtual Algo algorithm() const = 0; + virtual Algorithm algorithm() const = 0; virtual int priority() const = 0; virtual int64_t affinity() const = 0; virtual Multiway multiway() const = 0; diff --git a/src/workers/CpuThread.cpp b/src/workers/CpuThread.cpp index 5c98a5b3..e26b8a0a 100644 --- a/src/workers/CpuThread.cpp +++ b/src/workers/CpuThread.cpp @@ -28,20 +28,20 @@ #include "base/io/log/Log.h" #include "common/cpu/Cpu.h" #include "crypto/cn/Asm.h" +#include "crypto/cn/CnHash.h" #include "crypto/common/VirtualMemory.h" #include "Mem.h" #include "rapidjson/document.h" #include "workers/CpuThread.h" -#if defined(XMRIG_ARM) -# include "crypto/cn/CryptoNight_arm.h" -#else -# include "crypto/cn/CryptoNight_x86.h" -#endif -xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly) : + +static const xmrig::CnHash cnHash; + + +xmrig::CpuThread::CpuThread(size_t index, Algorithm algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly) : m_algorithm(algorithm), m_av(av), m_assembly(assembly), @@ -55,119 +55,12 @@ xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiw } -#ifndef XMRIG_NO_ASM -template -static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t mask) +xmrig::cn_hash_fun xmrig::CpuThread::fn(const Algorithm &algorithm) const { - const uint8_t* p = reinterpret_cast(src); - - // Workaround for Visual Studio placing trampoline in debug builds. -# if defined(_MSC_VER) - if (p[0] == 0xE9) { - p += *(int32_t*)(p + 1) + 5; - } -# endif - - size_t size = 0; - while (*(uint32_t*)(p + size) != 0xDEADC0DE) { - ++size; - } - size += sizeof(uint32_t); - - memcpy((void*) dst, (const void*) src, size); - - uint8_t* patched_data = reinterpret_cast(dst); - for (size_t i = 0; i + sizeof(uint32_t) <= size; ++i) { - switch (*(uint32_t*)(patched_data + i)) { - case xmrig::CRYPTONIGHT_ITER: - *(uint32_t*)(patched_data + i) = iterations; - break; - - case xmrig::CRYPTONIGHT_MASK: - *(uint32_t*)(patched_data + i) = mask; - break; - } - } + return cnHash.fn(algorithm, m_av, m_assembly); } -extern "C" void cnv2_mainloop_ivybridge_asm(cryptonight_ctx **ctx); -extern "C" void cnv2_mainloop_ryzen_asm(cryptonight_ctx **ctx); -extern "C" void cnv2_mainloop_bulldozer_asm(cryptonight_ctx **ctx); -extern "C" void cnv2_double_mainloop_sandybridge_asm(cryptonight_ctx **ctx); - - -xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ivybridge_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_ryzen_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_half_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_half_double_mainloop_sandybridge_asm = nullptr; - -xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ivybridge_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_ryzen_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_trtl_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_trtl_double_mainloop_sandybridge_asm = nullptr; - -xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ivybridge_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_ryzen_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_zls_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_zls_double_mainloop_sandybridge_asm = nullptr; - -xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ivybridge_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_ryzen_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_double_mainloop_bulldozer_asm = nullptr; -xmrig::CpuThread::cn_mainloop_fun cn_double_double_mainloop_sandybridge_asm = nullptr; - - -void xmrig::CpuThread::patchAsmVariants() -{ - const int allocation_size = 65536; - uint8_t *base = static_cast(VirtualMemory::allocateExecutableMemory(allocation_size)); - - cn_half_mainloop_ivybridge_asm = reinterpret_cast (base + 0x0000); - cn_half_mainloop_ryzen_asm = reinterpret_cast (base + 0x1000); - cn_half_mainloop_bulldozer_asm = reinterpret_cast (base + 0x2000); - cn_half_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x3000); - - cn_trtl_mainloop_ivybridge_asm = reinterpret_cast (base + 0x4000); - cn_trtl_mainloop_ryzen_asm = reinterpret_cast (base + 0x5000); - cn_trtl_mainloop_bulldozer_asm = reinterpret_cast (base + 0x6000); - cn_trtl_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0x7000); - - cn_zls_mainloop_ivybridge_asm = reinterpret_cast (base + 0x8000); - cn_zls_mainloop_ryzen_asm = reinterpret_cast (base + 0x9000); - cn_zls_mainloop_bulldozer_asm = reinterpret_cast (base + 0xA000); - cn_zls_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xB000); - - cn_double_mainloop_ivybridge_asm = reinterpret_cast (base + 0xC000); - cn_double_mainloop_ryzen_asm = reinterpret_cast (base + 0xD000); - cn_double_mainloop_bulldozer_asm = reinterpret_cast (base + 0xE000); - cn_double_double_mainloop_sandybridge_asm = reinterpret_cast (base + 0xF000); - - patchCode(cn_half_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_half_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_half_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_half_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, xmrig::CRYPTONIGHT_HALF_ITER, xmrig::CRYPTONIGHT_MASK); - - patchCode(cn_trtl_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, xmrig::CRYPTONIGHT_TRTL_ITER, xmrig::CRYPTONIGHT_PICO_MASK); - patchCode(cn_trtl_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, xmrig::CRYPTONIGHT_TRTL_ITER, xmrig::CRYPTONIGHT_PICO_MASK); - patchCode(cn_trtl_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, xmrig::CRYPTONIGHT_TRTL_ITER, xmrig::CRYPTONIGHT_PICO_MASK); - patchCode(cn_trtl_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, xmrig::CRYPTONIGHT_TRTL_ITER, xmrig::CRYPTONIGHT_PICO_MASK); - - patchCode(cn_zls_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, xmrig::CRYPTONIGHT_ZLS_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_zls_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, xmrig::CRYPTONIGHT_ZLS_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_zls_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, xmrig::CRYPTONIGHT_ZLS_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_zls_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, xmrig::CRYPTONIGHT_ZLS_ITER, xmrig::CRYPTONIGHT_MASK); - - patchCode(cn_double_mainloop_ivybridge_asm, cnv2_mainloop_ivybridge_asm, xmrig::CRYPTONIGHT_DOUBLE_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_double_mainloop_ryzen_asm, cnv2_mainloop_ryzen_asm, xmrig::CRYPTONIGHT_DOUBLE_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_double_mainloop_bulldozer_asm, cnv2_mainloop_bulldozer_asm, xmrig::CRYPTONIGHT_DOUBLE_ITER, xmrig::CRYPTONIGHT_MASK); - patchCode(cn_double_double_mainloop_sandybridge_asm, cnv2_double_mainloop_sandybridge_asm, xmrig::CRYPTONIGHT_DOUBLE_ITER, xmrig::CRYPTONIGHT_MASK); - - VirtualMemory::protectExecutableMemory(base, allocation_size); - VirtualMemory::flushInstructionCache(base, allocation_size); -} -#endif - bool xmrig::CpuThread::isSoftAES(AlgoVariant av) { @@ -175,418 +68,7 @@ bool xmrig::CpuThread::isSoftAES(AlgoVariant av) } -#ifndef XMRIG_NO_ASM -template -static inline void add_asm_func(xmrig::CpuThread::cn_hash_fun(&asm_func_map)[xmrig::ALGO_MAX][xmrig::AV_MAX][xmrig::VARIANT_MAX][xmrig::ASM_MAX]) -{ - asm_func_map[algo][xmrig::AV_SINGLE][variant][xmrig::ASM_INTEL] = cryptonight_single_hash_asm; - asm_func_map[algo][xmrig::AV_SINGLE][variant][xmrig::ASM_RYZEN] = cryptonight_single_hash_asm; - asm_func_map[algo][xmrig::AV_SINGLE][variant][xmrig::ASM_BULLDOZER] = cryptonight_single_hash_asm; - - asm_func_map[algo][xmrig::AV_DOUBLE][variant][xmrig::ASM_INTEL] = cryptonight_double_hash_asm; - asm_func_map[algo][xmrig::AV_DOUBLE][variant][xmrig::ASM_RYZEN] = cryptonight_double_hash_asm; - asm_func_map[algo][xmrig::AV_DOUBLE][variant][xmrig::ASM_BULLDOZER] = cryptonight_double_hash_asm; -} -#endif - -xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant av, Variant variant, Assembly assembly) -{ - assert(variant >= VARIANT_0 && variant < VARIANT_MAX); - -# ifndef XMRIG_NO_ASM - if (assembly == ASM_AUTO) { - assembly = Cpu::info()->assembly(); - } - - static cn_hash_fun asm_func_map[ALGO_MAX][AV_MAX][VARIANT_MAX][ASM_MAX] = {}; - static bool asm_func_map_initialized = false; - - if (!asm_func_map_initialized) { - add_asm_func(asm_func_map); - add_asm_func(asm_func_map); - add_asm_func(asm_func_map); - add_asm_func(asm_func_map); - -# ifdef XMRIG_ALGO_CN_PICO - add_asm_func(asm_func_map); -# endif - - add_asm_func(asm_func_map); - add_asm_func(asm_func_map); - add_asm_func(asm_func_map); - - asm_func_map_initialized = true; - } - - cn_hash_fun fun = asm_func_map[algorithm][av][variant][assembly]; - if (fun) { - return fun; - } -# endif - - constexpr const size_t count = VARIANT_MAX * 10 * ALGO_MAX; - - static const cn_hash_fun func_table[] = { - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL - -# ifdef XMRIG_ALGO_CN_GPU - cryptonight_single_hash_gpu, - nullptr, - cryptonight_single_hash_gpu, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, -# else - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU -# endif - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - -# ifdef XMRIG_ALGO_CN_LITE - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE -# else - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE -# endif - -# ifdef XMRIG_ALGO_CN_HEAVY - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE -# else - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE -# endif - -# ifdef XMRIG_ALGO_CN_PICO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF - - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_single_hash, - cryptonight_double_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - cryptonight_triple_hash, - cryptonight_quad_hash, - cryptonight_penta_hash, - - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE -# else - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_0 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_MSR - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XAO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RTO - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_2 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_HALF - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_GPU - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_WOW - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_4 - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_RWZ - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_ZLS - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_DOUBLE -# endif - }; - - static_assert(count == sizeof(func_table) / sizeof(func_table[0]), "func_table size mismatch"); - - const size_t index = VARIANT_MAX * 10 * algorithm + 10 * variant + av - 1; - -# ifndef NDEBUG - cn_hash_fun func = func_table[index]; - - assert(index < sizeof(func_table) / sizeof(func_table[0])); - assert(func != nullptr); - - return func; -# else - return func_table[index]; -# endif -} - - -xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly) +xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly) { assert(av > AV_AUTO && av < AV_MAX); @@ -613,7 +95,7 @@ xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, A } -xmrig::CpuThread *xmrig::CpuThread::createFromData(size_t index, Algo algorithm, const CpuThread::Data &data, int priority, bool softAES) +xmrig::CpuThread *xmrig::CpuThread::createFromData(size_t index, const Algorithm &algorithm, const CpuThread::Data &data, int priority, bool softAES) { int av = AV_AUTO; const Multiway multiway = data.multiway; @@ -653,7 +135,7 @@ xmrig::CpuThread::Data xmrig::CpuThread::parse(const rapidjson::Value &object) data.affinity = affinity.GetInt64(); } -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM data.assembly = Asm::parse(object["asm"]); # endif @@ -698,7 +180,7 @@ void xmrig::CpuThread::print() const LOG_DEBUG(GREEN_BOLD("CPU thread: ") " index " WHITE_BOLD("%zu") ", multiway " WHITE_BOLD("%d") ", av " WHITE_BOLD("%d") ",", index(), static_cast(multiway()), static_cast(m_av)); -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM LOG_DEBUG(" assembly: %s, affine_to_cpu: %" PRId64, Asm::toString(m_assembly), affinity()); # else LOG_DEBUG(" affine_to_cpu: %" PRId64, affinity()); @@ -737,7 +219,7 @@ rapidjson::Value xmrig::CpuThread::toConfig(rapidjson::Document &doc) const obj.AddMember("low_power_mode", multiway(), allocator); obj.AddMember("affine_to_cpu", affinity() == -1L ? Value(kFalseType) : Value(affinity()), allocator); -# ifndef XMRIG_NO_ASM +# ifdef XMRIG_FEATURE_ASM obj.AddMember("asm", Asm::toJSON(m_assembly), allocator); # endif diff --git a/src/workers/CpuThread.h b/src/workers/CpuThread.h index 2af421be..08aa89cb 100644 --- a/src/workers/CpuThread.h +++ b/src/workers/CpuThread.h @@ -27,6 +27,7 @@ #include "common/xmrig.h" +#include "crypto/cn/CnHash.h" #include "interfaces/IThread.h" @@ -58,27 +59,20 @@ public: }; - CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly); + CpuThread(size_t index, Algorithm algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch, Assembly assembly); - typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx, uint64_t height); - typedef void (*cn_mainloop_fun)(cryptonight_ctx **ctx); - -# ifndef XMRIG_NO_ASM - static void patchAsmVariants(); -# endif + cn_hash_fun fn(const Algorithm &algorithm) const; static bool isSoftAES(AlgoVariant av); - static cn_hash_fun fn(Algo algorithm, AlgoVariant av, Variant variant, Assembly assembly); - static CpuThread *createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly); - static CpuThread *createFromData(size_t index, Algo algorithm, const CpuThread::Data &data, int priority, bool softAES); + static CpuThread *createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly); + static CpuThread *createFromData(size_t index, const Algorithm &algorithm, const CpuThread::Data &data, int priority, bool softAES); static Data parse(const rapidjson::Value &object); static Multiway multiway(AlgoVariant av); inline bool isPrefetch() const { return m_prefetch; } inline bool isSoftAES() const { return m_softAES; } - inline cn_hash_fun fn(Variant variant) const { return fn(m_algorithm, m_av, variant, m_assembly); } - inline Algo algorithm() const override { return m_algorithm; } + inline Algorithm algorithm() const override { return m_algorithm; } inline int priority() const override { return m_priority; } inline int64_t affinity() const override { return m_affinity; } inline Multiway multiway() const override { return m_multiway; } @@ -97,7 +91,7 @@ protected: rapidjson::Value toConfig(rapidjson::Document &doc) const override; private: - const Algo m_algorithm; + const Algorithm m_algorithm; const AlgoVariant m_av; const Assembly m_assembly; const bool m_prefetch; diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index 30c43000..f209ca76 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -34,7 +34,7 @@ template -MultiWorker::MultiWorker(ThreadHandle *handle) +xmrig::MultiWorker::MultiWorker(ThreadHandle *handle) : Worker(handle) { m_memory = Mem::create(m_ctx, m_thread->algorithm(), N); @@ -42,61 +42,58 @@ MultiWorker::MultiWorker(ThreadHandle *handle) template -MultiWorker::~MultiWorker() +xmrig::MultiWorker::~MultiWorker() { Mem::release(m_ctx, N, m_memory); } template -bool MultiWorker::selfTest() +bool xmrig::MultiWorker::selfTest() { - using namespace xmrig; - - if (m_thread->algorithm() == CRYPTONIGHT) { - const bool rc = verify(VARIANT_0, test_output_v0) && - verify(VARIANT_1, test_output_v1) && - verify(VARIANT_2, test_output_v2) && - verify(VARIANT_XTL, test_output_xtl) && - verify(VARIANT_MSR, test_output_msr) && - verify(VARIANT_XAO, test_output_xao) && - verify(VARIANT_RTO, test_output_rto) && - verify(VARIANT_HALF, test_output_half) && - verify2(VARIANT_WOW, test_output_wow) && - verify2(VARIANT_4, test_output_r) && - verify(VARIANT_RWZ, test_output_rwz) && - verify(VARIANT_ZLS, test_output_zls) && - verify(VARIANT_DOUBLE, test_output_double); + if (m_thread->algorithm().family() == Algorithm::CN) { + const bool rc = verify(Algorithm::CN_0, test_output_v0) && + verify(Algorithm::CN_1, test_output_v1) && + verify(Algorithm::CN_2, test_output_v2) && + verify(Algorithm::CN_FAST, test_output_msr) && + verify(Algorithm::CN_XAO, test_output_xao) && + verify(Algorithm::CN_RTO, test_output_rto) && + verify(Algorithm::CN_HALF, test_output_half) && + verify2(Algorithm::CN_WOW, test_output_wow) && + verify2(Algorithm::CN_R, test_output_r) && + verify(Algorithm::CN_RWZ, test_output_rwz) && + verify(Algorithm::CN_ZLS, test_output_zls) && + verify(Algorithm::CN_DOUBLE, test_output_double); # ifdef XMRIG_ALGO_CN_GPU if (!rc || N > 1) { return rc; } - return verify(VARIANT_GPU, test_output_gpu); + return verify(Algorithm::CN_GPU, test_output_gpu); # else return rc; # endif } # ifdef XMRIG_ALGO_CN_LITE - if (m_thread->algorithm() == CRYPTONIGHT_LITE) { - return verify(VARIANT_0, test_output_v0_lite) && - verify(VARIANT_1, test_output_v1_lite); + if (m_thread->algorithm().family() == Algorithm::CN_LITE) { + return verify(Algorithm::CN_LITE_0, test_output_v0_lite) && + verify(Algorithm::CN_LITE_1, test_output_v1_lite); } # endif # ifdef XMRIG_ALGO_CN_HEAVY - if (m_thread->algorithm() == CRYPTONIGHT_HEAVY) { - return verify(VARIANT_0, test_output_v0_heavy) && - verify(VARIANT_XHV, test_output_xhv_heavy) && - verify(VARIANT_TUBE, test_output_tube_heavy); + if (m_thread->algorithm().family() == Algorithm::CN_HEAVY) { + return verify(Algorithm::CN_HEAVY_0, test_output_v0_heavy) && + verify(Algorithm::CN_HEAVY_XHV, test_output_xhv_heavy) && + verify(Algorithm::CN_HEAVY_TUBE, test_output_tube_heavy); } # endif # ifdef XMRIG_ALGO_CN_PICO - if (m_thread->algorithm() == CRYPTONIGHT_PICO) { - return verify(VARIANT_TRTL, test_output_pico_trtl); + if (m_thread->algorithm().family() == Algorithm::CN_PICO) { + return verify(Algorithm::CN_PICO_0, test_output_pico_trtl); } # endif @@ -105,7 +102,7 @@ bool MultiWorker::selfTest() template -void MultiWorker::start() +void xmrig::MultiWorker::start() { while (Workers::sequence() > 0) { if (Workers::isPaused()) { @@ -126,12 +123,11 @@ void MultiWorker::start() storeStats(); } - // FIXME -// m_thread->fn(m_state.job.algorithm().variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); + m_thread->fn(m_state.job.algorithm())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height()); for (size_t i = 0; i < N; ++i) { if (*reinterpret_cast(m_hash + (i * 32) + 24) < m_state.job.target()) { - Workers::submit(xmrig::JobResult(m_state.job.poolId(), m_state.job.id(), m_state.job.clientId(), *nonce(i), m_hash + (i * 32), m_state.job.diff(), m_state.job.algorithm())); + Workers::submit(JobResult(m_state.job.poolId(), m_state.job.id(), m_state.job.clientId(), *nonce(i), m_hash + (i * 32), m_state.job.diff(), m_state.job.algorithm())); } *nonce(i) += 1; @@ -148,7 +144,7 @@ void MultiWorker::start() template -bool MultiWorker::resume(const xmrig::Job &job) +bool xmrig::MultiWorker::resume(const xmrig::Job &job) { if (m_state.job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState.job.id()) { m_state = m_pausedState; @@ -160,10 +156,9 @@ bool MultiWorker::resume(const xmrig::Job &job) template -bool MultiWorker::verify(xmrig::Variant variant, const uint8_t *referenceValue) +bool xmrig::MultiWorker::verify(const Algorithm &algorithm, const uint8_t *referenceValue) { - - xmrig::CpuThread::cn_hash_fun func = m_thread->fn(variant); + cn_hash_fun func = m_thread->fn(algorithm); if (!func) { return false; } @@ -174,9 +169,9 @@ bool MultiWorker::verify(xmrig::Variant variant, const uint8_t *referenceValu template -bool MultiWorker::verify2(xmrig::Variant variant, const uint8_t *referenceValue) +bool xmrig::MultiWorker::verify2(const Algorithm &algorithm, const uint8_t *referenceValue) { - xmrig::CpuThread::cn_hash_fun func = m_thread->fn(variant); + cn_hash_fun func = m_thread->fn(algorithm); if (!func) { return false; } @@ -201,9 +196,9 @@ bool MultiWorker::verify2(xmrig::Variant variant, const uint8_t *referenceVal template<> -bool MultiWorker<1>::verify2(xmrig::Variant variant, const uint8_t *referenceValue) +bool xmrig::MultiWorker<1>::verify2(const Algorithm &algorithm, const uint8_t *referenceValue) { - xmrig::CpuThread::cn_hash_fun func = m_thread->fn(variant); + cn_hash_fun func = m_thread->fn(algorithm); if (!func) { return false; } @@ -221,9 +216,9 @@ bool MultiWorker<1>::verify2(xmrig::Variant variant, const uint8_t *referenceVal template -void MultiWorker::consumeJob() +void xmrig::MultiWorker::consumeJob() { - xmrig::Job job = Workers::job(); + Job job = Workers::job(); m_sequence = Workers::sequence(); if (m_state.job == job) { return; @@ -258,7 +253,7 @@ void MultiWorker::consumeJob() template -void MultiWorker::save(const xmrig::Job &job) +void xmrig::MultiWorker::save(const Job &job) { if (job.poolId() == -1 && m_state.job.poolId() >= 0) { m_pausedState = m_state; @@ -266,8 +261,13 @@ void MultiWorker::save(const xmrig::Job &job) } +namespace xmrig { + template class MultiWorker<1>; template class MultiWorker<2>; template class MultiWorker<3>; template class MultiWorker<4>; template class MultiWorker<5>; + +} + diff --git a/src/workers/MultiWorker.h b/src/workers/MultiWorker.h index 99d37e44..82898e1e 100644 --- a/src/workers/MultiWorker.h +++ b/src/workers/MultiWorker.h @@ -33,7 +33,7 @@ #include "workers/Worker.h" -class Handle; +namespace xmrig { template @@ -48,11 +48,11 @@ protected: void start() override; private: - bool resume(const xmrig::Job &job); - bool verify(xmrig::Variant variant, const uint8_t *referenceValue); - bool verify2(xmrig::Variant variant, const uint8_t *referenceValue); + bool resume(const Job &job); + bool verify(const Algorithm &algorithm, const uint8_t *referenceValue); + bool verify2(const Algorithm &algorithm, const uint8_t *referenceValue); void consumeJob(); - void save(const xmrig::Job &job); + void save(const Job &job); inline uint32_t *nonce(size_t index) { @@ -61,8 +61,8 @@ private: struct State { - alignas(16) uint8_t blob[xmrig::Job::kMaxBlobSize * N]; - xmrig::Job job; + alignas(16) uint8_t blob[Job::kMaxBlobSize * N]; + Job job; }; @@ -73,4 +73,7 @@ private: }; +} // namespace xmrig + + #endif /* XMRIG_MULTIWORKER_H */ diff --git a/src/workers/Workers.cpp b/src/workers/Workers.cpp index 62cbd1cf..1955677b 100644 --- a/src/workers/Workers.cpp +++ b/src/workers/Workers.cpp @@ -32,7 +32,6 @@ #include "base/tools/Handle.h" #include "core/config/Config.h" #include "core/Controller.h" -#include "crypto/cn/CryptoNight_constants.h" #include "interfaces/IJobResultListener.h" #include "interfaces/IThread.h" #include "Mem.h" @@ -169,14 +168,10 @@ void Workers::start(xmrig::Controller *controller) LOG_NOTICE("--------------------------------------------------------------------------"); # endif -# ifndef XMRIG_NO_ASM - xmrig::CpuThread::patchAsmVariants(); -# endif - m_controller = controller; const std::vector &threads = controller->config()->threads(); -// m_status.algo = controller->config()->algorithm().algo(); // FIXME + m_status.algo = xmrig::Algorithm::CN_0; // FIXME algo m_status.threads = threads.size(); for (const xmrig::IThread *thread : threads) { @@ -240,7 +235,7 @@ void Workers::threadsSummary(rapidjson::Document &doc) { uv_mutex_lock(&m_mutex); const uint64_t pages[2] = { m_status.hugePages, m_status.pages }; - const uint64_t memory = m_status.ways * xmrig::cn_select_memory(m_status.algo); + const uint64_t memory = m_status.ways * xmrig::CnAlgo<>::memory(m_status.algo); uv_mutex_unlock(&m_mutex); auto &allocator = doc.GetAllocator(); @@ -263,23 +258,23 @@ void Workers::onReady(void *arg) switch (handle->config()->multiway()) { case 1: - worker = new MultiWorker<1>(handle); + worker = new xmrig::MultiWorker<1>(handle); break; case 2: - worker = new MultiWorker<2>(handle); + worker = new xmrig::MultiWorker<2>(handle); break; case 3: - worker = new MultiWorker<3>(handle); + worker = new xmrig::MultiWorker<3>(handle); break; case 4: - worker = new MultiWorker<4>(handle); + worker = new xmrig::MultiWorker<4>(handle); break; case 5: - worker = new MultiWorker<5>(handle); + worker = new xmrig::MultiWorker<5>(handle); break; default: @@ -344,7 +339,7 @@ void Workers::start(IWorker *worker) if (m_status.started == m_status.threads) { const double percent = (double) m_status.hugePages / m_status.pages * 100.0; - const size_t memory = m_status.ways * xmrig::cn_select_memory(m_status.algo) / 1024; + const size_t memory = m_status.ways * xmrig::CnAlgo<>::memory(m_status.algo) / 1024; LOG_INFO(GREEN_BOLD("READY (CPU)") " threads " CYAN_BOLD("%zu(%zu)") " huge pages %s%zu/%zu %1.0f%%\x1B[0m memory " CYAN_BOLD("%zu KB") "", m_status.threads, m_status.ways, diff --git a/src/workers/Workers.h b/src/workers/Workers.h index 5b084fc2..24480517 100644 --- a/src/workers/Workers.h +++ b/src/workers/Workers.h @@ -86,8 +86,7 @@ private: pages(0), started(0), threads(0), - ways(0), - algo(xmrig::CRYPTONIGHT) + ways(0) {} size_t hugePages; @@ -95,7 +94,7 @@ private: size_t started; size_t threads; size_t ways; - xmrig::Algo algo; + xmrig::Algorithm algo; }; static bool m_active;