Implemented new style algorithm definitions (except ARM), removed Algo and Variant enums.

This commit is contained in:
XMRig 2019-06-13 22:08:52 +07:00
parent d7f42d54ad
commit 1f0e3e501c
30 changed files with 1223 additions and 1359 deletions

View file

@ -59,7 +59,8 @@ set(HEADERS_CRYPTO
src/crypto/cn/c_groestl.h src/crypto/cn/c_groestl.h
src/crypto/cn/c_jh.h src/crypto/cn/c_jh.h
src/crypto/cn/c_skein.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_monero.h
src/crypto/cn/CryptoNight_test.h src/crypto/cn/CryptoNight_test.h
src/crypto/cn/CryptoNight.h src/crypto/cn/CryptoNight.h
@ -102,10 +103,11 @@ set(SOURCES
) )
set(SOURCES_CRYPTO set(SOURCES_CRYPTO
src/crypto/cn/c_groestl.c
src/crypto/cn/c_blake256.c src/crypto/cn/c_blake256.c
src/crypto/cn/c_groestl.c
src/crypto/cn/c_jh.c src/crypto/cn/c_jh.c
src/crypto/cn/c_skein.c src/crypto/cn/c_skein.c
src/crypto/cn/CnHash.cpp
src/crypto/common/Algorithm.cpp src/crypto/common/Algorithm.cpp
) )

View file

@ -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}) 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(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) set_property(TARGET ${XMRIG_ASM_LIBRARY} PROPERTY LINKER_LANGUAGE C)
add_definitions(/DXMRIG_FEATURE_ASM)
else() else()
set(XMRIG_ASM_SOURCES "") set(XMRIG_ASM_SOURCES "")
set(XMRIG_ASM_LIBRARY "") set(XMRIG_ASM_LIBRARY "")
add_definitions(/DXMRIG_NO_ASM)
remove_definitions(/DXMRIG_FEATURE_ASM)
endif() endif()

View file

@ -27,7 +27,6 @@
#include <limits> #include <limits>
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/cn/CryptoNight.h" #include "crypto/cn/CryptoNight.h"
#include "crypto/common/portable/mm_malloc.h" #include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h" #include "crypto/common/VirtualMemory.h"
@ -38,12 +37,14 @@ bool Mem::m_enabled = true;
int Mem::m_flags = 0; 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; using namespace xmrig;
constexpr CnAlgo<Algorithm::CN_0> props;
MemInfo info; 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; constexpr const size_t align_size = 2 * 1024 * 1024;
info.size = ((info.size + align_size - 1) / align_size) * align_size; 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) { for (size_t i = 0; i < count; ++i) {
cryptonight_ctx *c = static_cast<cryptonight_ctx *>(_mm_malloc(sizeof(cryptonight_ctx), 4096)); cryptonight_ctx *c = static_cast<cryptonight_ctx *>(_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<cn_mainloop_fun_ms_abi>(xmrig::VirtualMemory::allocateExecutableMemory(0x4000)); c->generated_code = reinterpret_cast<cn_mainloop_fun_ms_abi>(VirtualMemory::allocateExecutableMemory(0x4000));
c->generated_code_data.variant = xmrig::VARIANT_MAX; c->generated_code_data.algo = Algorithm::INVALID;
c->generated_code_data.height = std::numeric_limits<uint64_t>::max(); c->generated_code_data.height = std::numeric_limits<uint64_t>::max();
ctx[i] = c; ctx[i] = c;

View file

@ -31,7 +31,7 @@
#include <stdint.h> #include <stdint.h>
#include "common/xmrig.h" #include "crypto/cn/CnAlgo.h"
struct cryptonight_ctx; struct cryptonight_ctx;
@ -56,7 +56,7 @@ public:
Lock = 4 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 init(bool enabled);
static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info); static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info);

View file

@ -34,7 +34,6 @@
#include "common/xmrig.h" #include "common/xmrig.h"
#include "crypto/common/portable/mm_malloc.h" #include "crypto/common/portable/mm_malloc.h"
#include "crypto/common/VirtualMemory.h" #include "crypto/common/VirtualMemory.h"
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/cn/CryptoNight.h" #include "crypto/cn/CryptoNight.h"
#include "Mem.h" #include "Mem.h"

View file

@ -39,7 +39,7 @@
#include "version.h" #include "version.h"
#ifndef XMRIG_NO_ASM #ifdef XMRIG_FEATURE_ASM
static const char *coloredAsmNames[] = { static const char *coloredAsmNames[] = {
RED_BOLD("none"), RED_BOLD("none"),
"auto", "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) { if (config->assembly() == xmrig::ASM_AUTO) {
const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly(); const xmrig::Assembly assembly = xmrig::Cpu::info()->assembly();

View file

@ -129,7 +129,7 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
{ {
cpu_brand_string(m_brand); cpu_brand_string(m_brand);
# ifndef XMRIG_NO_ASM # ifdef XMRIG_FEATURE_ASM
if (hasAES()) { if (hasAES()) {
char vendor[13] = { 0 }; char vendor[13] = { 0 };
int32_t data[4] = { 0 }; int32_t data[4] = { 0 };

View file

@ -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=1 For CPUs with hardware AES.
//--av=2 Lower power mode (double hash) of 1. //--av=2 Lower power mode (double hash) of 1.
//--av=3 Software AES implementation. //--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 { enum AlgoVerify {
VERIFY_HW_AES = 1, VERIFY_HW_AES = 1,
VERIFY_SOFT_AES = 2 VERIFY_SOFT_AES = 2

View file

@ -33,7 +33,6 @@
#include "common/cpu/Cpu.h" #include "common/cpu/Cpu.h"
#include "core/config/Config.h" #include "core/config/Config.h"
#include "crypto/cn/Asm.h" #include "crypto/cn/Asm.h"
#include "crypto/cn/CryptoNight_constants.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/filewritestream.h" #include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.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)); setPriority(reader.getInt("cpu-priority", -1));
setThreads(reader.getValue("threads")); setThreads(reader.getValue("threads"));
# ifndef XMRIG_NO_ASM # ifdef XMRIG_FEATURE_ASM
setAssembly(reader.getValue("asm")); setAssembly(reader.getValue("asm"));
# endif # endif
@ -93,7 +92,7 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
doc.AddMember("api", api, allocator); doc.AddMember("api", api, allocator);
doc.AddMember("http", m_http.toJSON(doc), 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); doc.AddMember("asm", Asm::toJSON(m_assembly), allocator);
# endif # endif
@ -144,37 +143,39 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
bool xmrig::Config::finalize() bool xmrig::Config::finalize()
{ {
// if (!m_threads.cpu.empty()) { // FIXME Algorithm algorithm(Algorithm::CN_0); // FIXME algo
// m_threads.mode = Advanced;
// const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::info()->hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT;
// for (size_t i = 0; i < m_threads.cpu.size(); ++i) { if (!m_threads.cpu.empty()) {
//// m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm.algo(), m_threads.cpu[i], m_priority, softAES)); 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(); return true;
// m_threads.mode = m_threads.count ? Simple : Automatic; }
//// 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) { const size_t size = CpuThread::multiway(av) * CnAlgo<>::memory(algorithm) / 1024;
// 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;
// }
// }
// for (size_t i = 0; i < m_threads.count; ++i) { if (!m_threads.count) {
// m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm.algo(), av, m_threads.mask, m_priority, m_assembly)); 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; return true;
} }
@ -276,7 +277,7 @@ xmrig::AlgoVariant xmrig::Config::getAlgoVariantLite() const
#endif #endif
#ifndef XMRIG_NO_ASM #ifdef XMRIG_FEATURE_ASM
void xmrig::Config::setAssembly(const rapidjson::Value &assembly) void xmrig::Config::setAssembly(const rapidjson::Value &assembly)
{ {
m_assembly = Asm::parse(assembly); m_assembly = Asm::parse(assembly);

View file

@ -94,7 +94,7 @@ private:
AlgoVariant getAlgoVariantLite() const; AlgoVariant getAlgoVariantLite() const;
# endif # endif
# ifndef XMRIG_NO_ASM # ifdef XMRIG_FEATURE_ASM
void setAssembly(const rapidjson::Value &assembly); void setAssembly(const rapidjson::Value &assembly);
# endif # endif

207
src/crypto/cn/CnAlgo.h Normal file
View file

@ -0,0 +1,207 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CN_ALGO_H
#define XMRIG_CN_ALGO_H
#include <stddef.h>
#include <stdint.h>
#include "crypto/common/Algorithm.h"
namespace xmrig
{
template<Algorithm::Id ALGO = Algorithm::INVALID>
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<Algorithm::CN_GPU>::mask() const { return 0x1FFFC0; }
#endif
#ifdef XMRIG_ALGO_CN_PICO
template<> constexpr inline uint32_t CnAlgo<Algorithm::CN_PICO_0>::mask() const { return 0x1FFF0; }
#endif
} /* namespace xmrig */
#endif /* XMRIG_CN_ALGO_H */

269
src/crypto/cn/CnHash.cpp Normal file
View file

@ -0,0 +1,269 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#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<algo, false>; \
m_map[algo][AV_SINGLE_SOFT][ASM_NONE] = cryptonight_single_hash<algo, true>; \
m_map[algo][AV_DOUBLE][ASM_NONE] = cryptonight_double_hash<algo, false>; \
m_map[algo][AV_DOUBLE_SOFT][ASM_NONE] = cryptonight_double_hash<algo, true>; \
m_map[algo][AV_TRIPLE][ASM_NONE] = cryptonight_triple_hash<algo, false>; \
m_map[algo][AV_TRIPLE_SOFT][ASM_NONE] = cryptonight_triple_hash<algo, true>; \
m_map[algo][AV_QUAD][ASM_NONE] = cryptonight_quad_hash<algo, false>; \
m_map[algo][AV_QUAD_SOFT][ASM_NONE] = cryptonight_quad_hash<algo, true>; \
m_map[algo][AV_PENTA][ASM_NONE] = cryptonight_penta_hash<algo, false>; \
m_map[algo][AV_PENTA_SOFT][ASM_NONE] = cryptonight_penta_hash<algo, true>;
#ifdef XMRIG_FEATURE_ASM
# define ADD_FN_ASM(algo) \
m_map[algo][AV_SINGLE][ASM_INTEL] = cryptonight_single_hash_asm<algo, ASM_INTEL>; \
m_map[algo][AV_SINGLE][ASM_RYZEN] = cryptonight_single_hash_asm<algo, ASM_RYZEN>; \
m_map[algo][AV_SINGLE][ASM_BULLDOZER] = cryptonight_single_hash_asm<algo, ASM_BULLDOZER>; \
m_map[algo][AV_DOUBLE][ASM_INTEL] = cryptonight_double_hash_asm<algo, ASM_INTEL>; \
m_map[algo][AV_DOUBLE][ASM_RYZEN] = cryptonight_double_hash_asm<algo, ASM_RYZEN>; \
m_map[algo][AV_DOUBLE][ASM_BULLDOZER] = cryptonight_double_hash_asm<algo, ASM_BULLDOZER>;
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<typename T, typename U>
static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t mask = CnAlgo<Algorithm::CN_HALF>().mask())
{
const uint8_t* p = reinterpret_cast<const uint8_t*>(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<uint8_t*>(dst);
for (size_t i = 0; i + sizeof(uint32_t) <= size; ++i) {
switch (*(uint32_t*)(patched_data + i)) {
case CnAlgo<Algorithm::CN_2>().iterations():
*(uint32_t*)(patched_data + i) = iterations;
break;
case CnAlgo<Algorithm::CN_2>().mask():
*(uint32_t*)(patched_data + i) = mask;
break;
}
}
}
static void patchAsmVariants()
{
const int allocation_size = 65536;
uint8_t *base = static_cast<uint8_t *>(VirtualMemory::allocateExecutableMemory(allocation_size));
cn_half_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x0000);
cn_half_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x1000);
cn_half_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x2000);
cn_half_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x3000);
# ifdef XMRIG_ALGO_CN_PICO
cn_trtl_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x4000);
cn_trtl_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x5000);
cn_trtl_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x6000);
cn_trtl_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x7000);
# endif
cn_zls_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x8000);
cn_zls_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x9000);
cn_zls_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xA000);
cn_zls_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xB000);
cn_double_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xC000);
cn_double_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xD000);
cn_double_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xE000);
cn_double_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xF000);
{
constexpr uint32_t ITER = CnAlgo<Algorithm::CN_HALF>().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<Algorithm::CN_PICO_0>().iterations();
constexpr uint32_t MASK = CnAlgo<Algorithm::CN_PICO_0>().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<Algorithm::CN_ZLS>().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<Algorithm::CN_DOUBLE>().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<Algorithm::CN_GPU, false>;
m_map[Algorithm::CN_GPU][AV_SINGLE_SOFT][ASM_NONE] = cryptonight_single_hash_gpu<Algorithm::CN_GPU, true>;
# 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];
}

63
src/crypto/cn/CnHash.h Normal file
View file

@ -0,0 +1,63 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CN_HASH_H
#define XMRIG_CN_HASH_H
#include <stddef.h>
#include <stdint.h>
#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 */

View file

@ -42,10 +42,10 @@ typedef void(*cn_mainloop_fun_ms_abi)(cryptonight_ctx**) ABI_ATTRIBUTE;
struct cryptonight_r_data { struct cryptonight_r_data {
int variant; int algo;
uint64_t height; 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); }
}; };

View file

@ -1,251 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2019 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018-2019 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2019 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CRYPTONIGHT_CONSTANTS_H
#define XMRIG_CRYPTONIGHT_CONSTANTS_H
#include <stddef.h>
#include <stdint.h>
#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<Algo ALGO> inline constexpr size_t cn_select_memory() { return 0; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT>() { return CRYPTONIGHT_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MEMORY; }
template<> inline constexpr size_t cn_select_memory<CRYPTONIGHT_PICO>() { 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<Algo ALGO> inline constexpr uint32_t cn_select_mask() { return 0; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT>() { return CRYPTONIGHT_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_LITE>() { return CRYPTONIGHT_LITE_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_HEAVY>() { return CRYPTONIGHT_HEAVY_MASK; }
template<> inline constexpr uint32_t cn_select_mask<CRYPTONIGHT_PICO>() { 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<Algo ALGO, Variant variant> inline constexpr uint32_t cn_select_iter() { return 0; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_0>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_1>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_2>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_WOW>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_4>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XTL>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_HALF>() { return CRYPTONIGHT_HALF_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_MSR>() { return CRYPTONIGHT_HALF_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_XAO>() { return CRYPTONIGHT_XAO_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_RTO>() { return CRYPTONIGHT_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_GPU>() { return CRYPTONIGHT_GPU_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_RWZ>() { return CRYPTONIGHT_WALTZ_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_ZLS>() { return CRYPTONIGHT_ZLS_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT, VARIANT_DOUBLE>() { return CRYPTONIGHT_DOUBLE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_0>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_LITE, VARIANT_1>() { return CRYPTONIGHT_LITE_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_0>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_XHV>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_HEAVY, VARIANT_TUBE>() { return CRYPTONIGHT_HEAVY_ITER; }
template<> inline constexpr uint32_t cn_select_iter<CRYPTONIGHT_PICO, VARIANT_TRTL>() { 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<Variant variant> inline constexpr Variant cn_base_variant() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_0>() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_1>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_TUBE>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_XTL>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_MSR>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_XHV>() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_XAO>() { return VARIANT_0; }
template<> inline constexpr Variant cn_base_variant<VARIANT_RTO>() { return VARIANT_1; }
template<> inline constexpr Variant cn_base_variant<VARIANT_2>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_HALF>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_TRTL>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_GPU>() { return VARIANT_GPU; }
template<> inline constexpr Variant cn_base_variant<VARIANT_WOW>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_4>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_RWZ>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_ZLS>() { return VARIANT_2; }
template<> inline constexpr Variant cn_base_variant<VARIANT_DOUBLE>() { 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<Variant variant> inline constexpr bool cn_is_cryptonight_r() { return false; }
template<> inline constexpr bool cn_is_cryptonight_r<VARIANT_WOW>() { return true; }
template<> inline constexpr bool cn_is_cryptonight_r<VARIANT_4>() { return true; }
} /* namespace xmrig */
#endif /* XMRIG_CRYPTONIGHT_CONSTANTS_H */

View file

@ -33,21 +33,21 @@
#ifndef XMRIG_ARM #ifndef XMRIG_ARM
# define VARIANT1_INIT(part) \ # define VARIANT1_INIT(part) \
uint64_t tweak1_2_##part = 0; \ uint64_t tweak1_2_##part = 0; \
if (BASE == xmrig::VARIANT_1) { \ if (BASE == Algorithm::CN_1) { \
tweak1_2_##part = (*reinterpret_cast<const uint64_t*>(input + 35 + part * size) ^ \ tweak1_2_##part = (*reinterpret_cast<const uint64_t*>(input + 35 + part * size) ^ \
*(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24)); \ *(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24)); \
} }
#else #else
# define VARIANT1_INIT(part) \ # define VARIANT1_INIT(part) \
uint64_t tweak1_2_##part = 0; \ 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); \ memcpy(&tweak1_2_##part, input + 35 + part * size, sizeof tweak1_2_##part); \
tweak1_2_##part ^= *(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24); \ tweak1_2_##part ^= *(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24); \
} }
#endif #endif
#define VARIANT1_1(p) \ #define VARIANT1_1(p) \
if (BASE == xmrig::VARIANT_1) { \ if (BASE == Algorithm::CN_1) { \
const uint8_t tmp = reinterpret_cast<const uint8_t*>(p)[11]; \ const uint8_t tmp = reinterpret_cast<const uint8_t*>(p)[11]; \
static const uint32_t table = 0x75310; \ static const uint32_t table = 0x75310; \
const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \
@ -55,20 +55,20 @@
} }
#define VARIANT1_2(p, part) \ #define VARIANT1_2(p, part) \
if (BASE == xmrig::VARIANT_1) { \ if (BASE == Algorithm::CN_1) { \
(p) ^= tweak1_2_##part; \ (p) ^= tweak1_2_##part; \
} }
#ifndef XMRIG_ARM #ifndef XMRIG_ARM
# define VARIANT2_INIT(part) \ # define VARIANT2_INIT(part) \
__m128i division_result_xmm_##part = _mm_cvtsi64_si128(h##part[12]); \ __m128i division_result_xmm_##part = _mm_cvtsi64_si128(static_cast<int64_t>(h##part[12])); \
__m128i sqrt_result_xmm_##part = _mm_cvtsi64_si128(h##part[13]); __m128i sqrt_result_xmm_##part = _mm_cvtsi64_si128(static_cast<int64_t>(h##part[13]));
#ifdef _MSC_VER #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 #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 #endif
# define VARIANT2_INTEGER_MATH(part, cl, cx) \ # 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) ^ 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) ^ 0x20)), _mm_add_epi64(chunk1, _b)); \
_mm_store_si128((__m128i *)((base_ptr) + ((offset) ^ 0x30)), _mm_add_epi64(chunk2, _a)); \ _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)); \ _c = _mm_xor_si128(_mm_xor_si128(_c, chunk3), _mm_xor_si128(chunk1, chunk2)); \
} \ } \
} while (0) } 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) ^ 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) ^ 0x20)), vaddq_u64(chunk1, vreinterpretq_u64_u8(_b))); \
vst1q_u64((uint64_t*)((base_ptr) + ((offset) ^ 0x30)), vaddq_u64(chunk2, vreinterpretq_u64_u8(_a))); \ 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)); \ _c = veorq_u64(veorq_u64(_c, chunk3), veorq_u64(chunk1, chunk2)); \
} \ } \
} while (0) } while (0)
@ -184,17 +184,17 @@
#define VARIANT4_RANDOM_MATH_INIT(part) \ #define VARIANT4_RANDOM_MATH_INIT(part) \
uint32_t r##part[9]; \ uint32_t r##part[9]; \
struct V4_Instruction code##part[256]; \ struct V4_Instruction code##part[256]; \
if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { \ if (props.isR()) { \
r##part[0] = (uint32_t)(h##part[12]); \ r##part[0] = static_cast<uint32_t>(h##part[12]); \
r##part[1] = (uint32_t)(h##part[12] >> 32); \ r##part[1] = static_cast<uint32_t>(h##part[12] >> 32); \
r##part[2] = (uint32_t)(h##part[13]); \ r##part[2] = static_cast<uint32_t>(h##part[13]); \
r##part[3] = (uint32_t)(h##part[13] >> 32); \ r##part[3] = static_cast<uint32_t>(h##part[13] >> 32); \
} \ } \
v4_random_math_init<VARIANT>(code##part, height); v4_random_math_init<ALGO>(code##part, height);
#define VARIANT4_RANDOM_MATH(part, al, ah, cl, bx0, bx1) \ #define VARIANT4_RANDOM_MATH(part, al, ah, cl, bx0, bx1) \
if ((VARIANT == xmrig::VARIANT_WOW) || (VARIANT == xmrig::VARIANT_4)) { \ if (props.isR()) { \
cl ^= (r##part[0] + r##part[1]) | ((uint64_t)(r##part[2] + r##part[3]) << 32); \ cl ^= (r##part[0] + r##part[1]) | (static_cast<uint64_t>(r##part[2] + r##part[3]) << 32); \
r##part[4] = static_cast<uint32_t>(al); \ r##part[4] = static_cast<uint32_t>(al); \
r##part[5] = static_cast<uint32_t>(ah); \ r##part[5] = static_cast<uint32_t>(ah); \
r##part[6] = static_cast<uint32_t>(_mm_cvtsi128_si32(bx0)); \ r##part[6] = static_cast<uint32_t>(_mm_cvtsi128_si32(bx0)); \

View file

@ -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" // "cn/half"
const static uint8_t test_output_half[160] = { const static uint8_t test_output_half[160] = {
0x5D, 0x4F, 0xBC, 0x35, 0x60, 0x97, 0xEA, 0x64, 0x40, 0xB0, 0x88, 0x8E, 0xDE, 0xB6, 0x35, 0xDD, 0x5D, 0x4F, 0xBC, 0x35, 0x60, 0x97, 0xEA, 0x64, 0x40, 0xB0, 0x88, 0x8E, 0xDE, 0xB6, 0x35, 0xDD,

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/cn/CnAlgo.h"
#ifdef __GNUC__ #ifdef __GNUC__
# include <x86intrin.h> # include <x86intrin.h>
@ -206,4 +208,4 @@ void cn_gpu_inner_avx(const uint8_t* spad, uint8_t* lpad)
} }
} }
template void cn_gpu_inner_avx<xmrig::CRYPTONIGHT_GPU_ITER, xmrig::CRYPTONIGHT_GPU_MASK>(const uint8_t* spad, uint8_t* lpad); template void cn_gpu_inner_avx<xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().iterations(), xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().mask()>(const uint8_t* spad, uint8_t* lpad);

View file

@ -22,7 +22,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "crypto/cn/CryptoNight_constants.h"
#include "crypto/cn/CnAlgo.h"
#ifdef __GNUC__ #ifdef __GNUC__
# include <x86intrin.h> # include <x86intrin.h>
@ -207,4 +209,4 @@ void cn_gpu_inner_ssse3(const uint8_t* spad, uint8_t* lpad)
} }
} }
template void cn_gpu_inner_ssse3<xmrig::CRYPTONIGHT_GPU_ITER, xmrig::CRYPTONIGHT_GPU_MASK>(const uint8_t* spad, uint8_t* lpad); template void cn_gpu_inner_ssse3<xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().iterations(), xmrig::CnAlgo<xmrig::Algorithm::CN_GPU>().mask()>(const uint8_t* spad, uint8_t* lpad);

View file

@ -1,6 +1,13 @@
#ifndef VARIANT4_RANDOM_MATH_H #ifndef VARIANT4_RANDOM_MATH_H
#define VARIANT4_RANDOM_MATH_H #define VARIANT4_RANDOM_MATH_H
#include <string.h>
#include "crypto/common/Algorithm.h"
extern "C" extern "C"
{ {
#include "crypto/cn/c_blake256.h" #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 // 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 // "code" array must have space for NUM_INSTRUCTIONS_MAX+1 instructions
template<xmrig::Variant VARIANT> template<xmrig::Algorithm::Id ALGO>
static int v4_random_math_init(struct V4_Instruction* code, const uint64_t height) 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 // 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)); memset(data, 0, sizeof(data));
uint64_t tmp = SWAP64LE(height); uint64_t tmp = SWAP64LE(height);
memcpy(data, &tmp, sizeof(uint64_t)); memcpy(data, &tmp, sizeof(uint64_t));
if (VARIANT == xmrig::VARIANT_4) if (ALGO == xmrig::Algorithm::CN_R) {
{
data[20] = -38; data[20] = -38;
} }
@ -249,7 +255,7 @@ static int v4_random_math_init(struct V4_Instruction* code, const uint64_t heigh
code_size = 0; code_size = 0;
int total_iterations = 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 // Generate random code to achieve minimal required latency for our abstract CPU
// Try to get this latency for all 4 registers // 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; int b = src_index;
// Don't do ADD/SUB/XOR with the same register // 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 // 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; src_index = b;
} }

View file

@ -56,12 +56,12 @@ struct AlgoName
static AlgoName const algorithm_names[] = { static AlgoName const algorithm_names[] = {
{ "cryptonight/0", "cn/0", Algorithm::CN_0 }, { "cryptonight/0", "cn/0", Algorithm::CN_0 },
{ "cryptonight", "cn", Algorithm::CN_0 }, { "cryptonight", "cn", Algorithm::CN_0 },
{ "cryptonight/1", "cn/1", Algorithm::CN_1 }, { "cryptonight/1", "cn/1", Algorithm::CN_1 },
{ "cryptonight-monerov7", nullptr, Algorithm::CN_1 }, { "cryptonight-monerov7", nullptr, Algorithm::CN_1 },
{ "cryptonight_v7", nullptr, Algorithm::CN_1 }, { "cryptonight_v7", nullptr, Algorithm::CN_1 },
{ "cryptonight/2", "cn/2", Algorithm::CN_2 }, { "cryptonight/2", "cn/2", Algorithm::CN_2 },
{ "cryptonight-monerov8", nullptr, Algorithm::CN_2 }, { "cryptonight-monerov8", nullptr, Algorithm::CN_2 },
{ "cryptonight_v8", nullptr, Algorithm::CN_2 }, { "cryptonight_v8", nullptr, Algorithm::CN_2 },
{ "cryptonight/r", "cn/r", Algorithm::CN_R }, { "cryptonight/r", "cn/r", Algorithm::CN_R },
@ -75,7 +75,7 @@ static AlgoName const algorithm_names[] = {
{ "cryptonight/rto", "cn/rto", Algorithm::CN_RTO }, { "cryptonight/rto", "cn/rto", Algorithm::CN_RTO },
{ "cryptonight/rwz", "cn/rwz", Algorithm::CN_RWZ }, { "cryptonight/rwz", "cn/rwz", Algorithm::CN_RWZ },
{ "cryptonight/zls", "cn/zls", Algorithm::CN_ZLS }, { "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 # ifdef XMRIG_ALGO_CN_GPU
{ "cryptonight/gpu", "cn/gpu", Algorithm::CN_GPU }, { "cryptonight/gpu", "cn/gpu", Algorithm::CN_GPU },
{ "cryptonight_gpu", nullptr, 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 }, { "cryptonight-bittube2", nullptr, Algorithm::CN_HEAVY_TUBE },
# endif # endif
# ifdef XMRIG_ALGO_CN_PICO # ifdef XMRIG_ALGO_CN_PICO
{ "cryptonight-pico", "cn-pico", Algorithm::CN_PICO }, { "cryptonight-pico", "cn-pico", Algorithm::CN_PICO_0 },
{ "cryptonight-pico/trtl", "cn-pico/trtl", Algorithm::CN_PICO }, { "cryptonight-pico/trtl", "cn-pico/trtl", Algorithm::CN_PICO_0 },
{ "cryptonight-turtle", "cn-trtl", Algorithm::CN_PICO }, { "cryptonight-turtle", "cn-trtl", Algorithm::CN_PICO_0 },
{ "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO }, { "cryptonight-ultralite", "cn-ultralite", Algorithm::CN_PICO_0 },
{ "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO }, { "cryptonight_turtle", "cn_turtle", Algorithm::CN_PICO_0 },
# endif # endif
}; };
@ -111,15 +111,48 @@ static AlgoName const algorithm_names[] = {
} /* namespace xmrig */ } /* 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++) { switch (id) {
if (algorithm_names[i].id == m_id) { case CN_0:
return shortName ? algorithm_names[i].shortName : algorithm_names[i].name; 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; 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";
}

View file

@ -63,24 +63,35 @@ public:
CN_HEAVY_XHV, // "cn-heavy/xhv" Modified CryptoNight-Heavy (Haven Protocol only) CN_HEAVY_XHV, // "cn-heavy/xhv" Modified CryptoNight-Heavy (Haven Protocol only)
# endif # endif
# ifdef XMRIG_ALGO_CN_PICO # ifdef XMRIG_ALGO_CN_PICO
CN_PICO, // "cn-pico" CryptoNight Turtle (TRTL) CN_PICO_0, // "cn-pico" CryptoNight Turtle (TRTL)
# endif # endif
MAX MAX
}; };
enum Family : int {
UNKNOWN,
CN,
CN_LITE,
CN_HEAVY,
CN_PICO
};
inline Algorithm() {} inline Algorithm() {}
inline Algorithm(const char *algo) : m_id(parse(algo)) {} inline Algorithm(const char *algo) : m_id(parse(algo)) {}
inline Algorithm(Id id) : m_id(id) {} inline Algorithm(Id id) : m_id(id) {}
inline bool isEqual(const Algorithm &other) const { return m_id == other.m_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 *name() const { return name(false); }
inline const char *shortName() const { return name(true); } inline const char *shortName() const { return name(true); }
inline Family family() const { return family(m_id); }
inline Id id() const { return 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 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); static Id parse(const char *name);
private: private:

View file

@ -27,7 +27,7 @@
#include <stdint.h> #include <stdint.h>
#include "common/xmrig.h" #include "crypto/common/Algorithm.h"
#include "rapidjson/fwd.h" #include "rapidjson/fwd.h"
@ -53,7 +53,7 @@ public:
virtual ~IThread() = default; virtual ~IThread() = default;
virtual Algo algorithm() const = 0; virtual Algorithm algorithm() const = 0;
virtual int priority() const = 0; virtual int priority() const = 0;
virtual int64_t affinity() const = 0; virtual int64_t affinity() const = 0;
virtual Multiway multiway() const = 0; virtual Multiway multiway() const = 0;

View file

@ -28,20 +28,20 @@
#include "base/io/log/Log.h" #include "base/io/log/Log.h"
#include "common/cpu/Cpu.h" #include "common/cpu/Cpu.h"
#include "crypto/cn/Asm.h" #include "crypto/cn/Asm.h"
#include "crypto/cn/CnHash.h"
#include "crypto/common/VirtualMemory.h" #include "crypto/common/VirtualMemory.h"
#include "Mem.h" #include "Mem.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "workers/CpuThread.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_algorithm(algorithm),
m_av(av), m_av(av),
m_assembly(assembly), m_assembly(assembly),
@ -55,119 +55,12 @@ xmrig::CpuThread::CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiw
} }
#ifndef XMRIG_NO_ASM xmrig::cn_hash_fun xmrig::CpuThread::fn(const Algorithm &algorithm) const
template<typename T, typename U>
static void patchCode(T dst, U src, const uint32_t iterations, const uint32_t mask)
{ {
const uint8_t* p = reinterpret_cast<const uint8_t*>(src); return cnHash.fn(algorithm, m_av, m_assembly);
// 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<uint8_t*>(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;
}
}
} }
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<uint8_t *>(VirtualMemory::allocateExecutableMemory(allocation_size));
cn_half_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x0000);
cn_half_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x1000);
cn_half_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x2000);
cn_half_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x3000);
cn_trtl_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x4000);
cn_trtl_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x5000);
cn_trtl_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x6000);
cn_trtl_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x7000);
cn_zls_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x8000);
cn_zls_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0x9000);
cn_zls_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xA000);
cn_zls_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xB000);
cn_double_mainloop_ivybridge_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xC000);
cn_double_mainloop_ryzen_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xD000);
cn_double_mainloop_bulldozer_asm = reinterpret_cast<cn_mainloop_fun> (base + 0xE000);
cn_double_double_mainloop_sandybridge_asm = reinterpret_cast<cn_mainloop_fun> (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) bool xmrig::CpuThread::isSoftAES(AlgoVariant av)
{ {
@ -175,418 +68,7 @@ bool xmrig::CpuThread::isSoftAES(AlgoVariant av)
} }
#ifndef XMRIG_NO_ASM xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, Assembly assembly)
template<xmrig::Algo algo, xmrig::Variant variant>
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<algo, variant, xmrig::ASM_INTEL>;
asm_func_map[algo][xmrig::AV_SINGLE][variant][xmrig::ASM_RYZEN] = cryptonight_single_hash_asm<algo, variant, xmrig::ASM_RYZEN>;
asm_func_map[algo][xmrig::AV_SINGLE][variant][xmrig::ASM_BULLDOZER] = cryptonight_single_hash_asm<algo, variant, xmrig::ASM_BULLDOZER>;
asm_func_map[algo][xmrig::AV_DOUBLE][variant][xmrig::ASM_INTEL] = cryptonight_double_hash_asm<algo, variant, xmrig::ASM_INTEL>;
asm_func_map[algo][xmrig::AV_DOUBLE][variant][xmrig::ASM_RYZEN] = cryptonight_double_hash_asm<algo, variant, xmrig::ASM_RYZEN>;
asm_func_map[algo][xmrig::AV_DOUBLE][variant][xmrig::ASM_BULLDOZER] = cryptonight_double_hash_asm<algo, variant, xmrig::ASM_BULLDOZER>;
}
#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<CRYPTONIGHT, VARIANT_2>(asm_func_map);
add_asm_func<CRYPTONIGHT, VARIANT_HALF>(asm_func_map);
add_asm_func<CRYPTONIGHT, VARIANT_WOW>(asm_func_map);
add_asm_func<CRYPTONIGHT, VARIANT_4>(asm_func_map);
# ifdef XMRIG_ALGO_CN_PICO
add_asm_func<CRYPTONIGHT_PICO, VARIANT_TRTL>(asm_func_map);
# endif
add_asm_func<CRYPTONIGHT, VARIANT_RWZ>(asm_func_map);
add_asm_func<CRYPTONIGHT, VARIANT_ZLS>(asm_func_map);
add_asm_func<CRYPTONIGHT, VARIANT_DOUBLE>(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, false, VARIANT_0>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_0>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_0>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_0>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_0>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_0>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_0>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_0>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_0>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_0>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_1>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_1>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_1>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_1>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_1>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_1>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_1>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_1>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_1>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_1>,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TUBE
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_XTL>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_XTL>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_XTL>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_XTL>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_XTL>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_XTL>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_XTL>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_XTL>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_XTL>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_XTL>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_MSR>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_MSR>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_MSR>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_MSR>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_MSR>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_MSR>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_MSR>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_MSR>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_MSR>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_MSR>,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_XHV
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_XAO>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_XAO>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_XAO>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_XAO>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_XAO>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_XAO>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_XAO>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_XAO>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_XAO>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_XAO>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_RTO>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_RTO>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_RTO>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_RTO>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_RTO>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_RTO>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_RTO>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_RTO>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_RTO>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_RTO>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_2>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_2>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_2>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_2>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_2>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_2>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_2>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_2>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_2>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_2>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_HALF>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_HALF>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_HALF>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_HALF>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_HALF>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_HALF>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_HALF>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_HALF>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_HALF>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_HALF>,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_TRTL
# ifdef XMRIG_ALGO_CN_GPU
cryptonight_single_hash_gpu<CRYPTONIGHT, false, VARIANT_GPU>,
nullptr,
cryptonight_single_hash_gpu<CRYPTONIGHT, true, VARIANT_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, false, VARIANT_WOW>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_WOW>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_WOW>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_WOW>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_WOW>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_WOW>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_WOW>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_WOW>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_WOW>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_WOW>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_4>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_4>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_4>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_4>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_4>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_4>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_4>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_4>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_4>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_4>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_RWZ>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_RWZ>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_RWZ>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_RWZ>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_RWZ>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_RWZ>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_RWZ>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_RWZ>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_RWZ>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_RWZ>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_ZLS>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_ZLS>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_ZLS>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_ZLS>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_ZLS>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_ZLS>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_ZLS>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_ZLS>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_ZLS>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_ZLS>,
cryptonight_single_hash<CRYPTONIGHT, false, VARIANT_DOUBLE>,
cryptonight_double_hash<CRYPTONIGHT, false, VARIANT_DOUBLE>,
cryptonight_single_hash<CRYPTONIGHT, true, VARIANT_DOUBLE>,
cryptonight_double_hash<CRYPTONIGHT, true, VARIANT_DOUBLE>,
cryptonight_triple_hash<CRYPTONIGHT, false, VARIANT_DOUBLE>,
cryptonight_quad_hash<CRYPTONIGHT, false, VARIANT_DOUBLE>,
cryptonight_penta_hash<CRYPTONIGHT, false, VARIANT_DOUBLE>,
cryptonight_triple_hash<CRYPTONIGHT, true, VARIANT_DOUBLE>,
cryptonight_quad_hash<CRYPTONIGHT, true, VARIANT_DOUBLE>,
cryptonight_penta_hash<CRYPTONIGHT, true, VARIANT_DOUBLE>,
# ifdef XMRIG_ALGO_CN_LITE
cryptonight_single_hash<CRYPTONIGHT_LITE, false, VARIANT_0>,
cryptonight_double_hash<CRYPTONIGHT_LITE, false, VARIANT_0>,
cryptonight_single_hash<CRYPTONIGHT_LITE, true, VARIANT_0>,
cryptonight_double_hash<CRYPTONIGHT_LITE, true, VARIANT_0>,
cryptonight_triple_hash<CRYPTONIGHT_LITE, false, VARIANT_0>,
cryptonight_quad_hash<CRYPTONIGHT_LITE, false, VARIANT_0>,
cryptonight_penta_hash<CRYPTONIGHT_LITE, false, VARIANT_0>,
cryptonight_triple_hash<CRYPTONIGHT_LITE, true, VARIANT_0>,
cryptonight_quad_hash<CRYPTONIGHT_LITE, true, VARIANT_0>,
cryptonight_penta_hash<CRYPTONIGHT_LITE, true, VARIANT_0>,
cryptonight_single_hash<CRYPTONIGHT_LITE, false, VARIANT_1>,
cryptonight_double_hash<CRYPTONIGHT_LITE, false, VARIANT_1>,
cryptonight_single_hash<CRYPTONIGHT_LITE, true, VARIANT_1>,
cryptonight_double_hash<CRYPTONIGHT_LITE, true, VARIANT_1>,
cryptonight_triple_hash<CRYPTONIGHT_LITE, false, VARIANT_1>,
cryptonight_quad_hash<CRYPTONIGHT_LITE, false, VARIANT_1>,
cryptonight_penta_hash<CRYPTONIGHT_LITE, false, VARIANT_1>,
cryptonight_triple_hash<CRYPTONIGHT_LITE, true, VARIANT_1>,
cryptonight_quad_hash<CRYPTONIGHT_LITE, true, VARIANT_1>,
cryptonight_penta_hash<CRYPTONIGHT_LITE, true, 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
# 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_HEAVY, false, VARIANT_0>,
cryptonight_double_hash<CRYPTONIGHT_HEAVY, false, VARIANT_0>,
cryptonight_single_hash<CRYPTONIGHT_HEAVY, true, VARIANT_0>,
cryptonight_double_hash<CRYPTONIGHT_HEAVY, true, VARIANT_0>,
cryptonight_triple_hash<CRYPTONIGHT_HEAVY, false, VARIANT_0>,
cryptonight_quad_hash<CRYPTONIGHT_HEAVY, false, VARIANT_0>,
cryptonight_penta_hash<CRYPTONIGHT_HEAVY, false, VARIANT_0>,
cryptonight_triple_hash<CRYPTONIGHT_HEAVY, true, VARIANT_0>,
cryptonight_quad_hash<CRYPTONIGHT_HEAVY, true, VARIANT_0>,
cryptonight_penta_hash<CRYPTONIGHT_HEAVY, true, VARIANT_0>,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, // VARIANT_1
cryptonight_single_hash<CRYPTONIGHT_HEAVY, false, VARIANT_TUBE>,
cryptonight_double_hash<CRYPTONIGHT_HEAVY, false, VARIANT_TUBE>,
cryptonight_single_hash<CRYPTONIGHT_HEAVY, true, VARIANT_TUBE>,
cryptonight_double_hash<CRYPTONIGHT_HEAVY, true, VARIANT_TUBE>,
cryptonight_triple_hash<CRYPTONIGHT_HEAVY, false, VARIANT_TUBE>,
cryptonight_quad_hash<CRYPTONIGHT_HEAVY, false, VARIANT_TUBE>,
cryptonight_penta_hash<CRYPTONIGHT_HEAVY, false, VARIANT_TUBE>,
cryptonight_triple_hash<CRYPTONIGHT_HEAVY, true, VARIANT_TUBE>,
cryptonight_quad_hash<CRYPTONIGHT_HEAVY, true, VARIANT_TUBE>,
cryptonight_penta_hash<CRYPTONIGHT_HEAVY, true, 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
cryptonight_single_hash<CRYPTONIGHT_HEAVY, false, VARIANT_XHV>,
cryptonight_double_hash<CRYPTONIGHT_HEAVY, false, VARIANT_XHV>,
cryptonight_single_hash<CRYPTONIGHT_HEAVY, true, VARIANT_XHV>,
cryptonight_double_hash<CRYPTONIGHT_HEAVY, true, VARIANT_XHV>,
cryptonight_triple_hash<CRYPTONIGHT_HEAVY, false, VARIANT_XHV>,
cryptonight_quad_hash<CRYPTONIGHT_HEAVY, false, VARIANT_XHV>,
cryptonight_penta_hash<CRYPTONIGHT_HEAVY, false, VARIANT_XHV>,
cryptonight_triple_hash<CRYPTONIGHT_HEAVY, true, VARIANT_XHV>,
cryptonight_quad_hash<CRYPTONIGHT_HEAVY, true, VARIANT_XHV>,
cryptonight_penta_hash<CRYPTONIGHT_HEAVY, true, 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_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_PICO, false, VARIANT_TRTL>,
cryptonight_double_hash<CRYPTONIGHT_PICO, false, VARIANT_TRTL>,
cryptonight_single_hash<CRYPTONIGHT_PICO, true, VARIANT_TRTL>,
cryptonight_double_hash<CRYPTONIGHT_PICO, true, VARIANT_TRTL>,
cryptonight_triple_hash<CRYPTONIGHT_PICO, false, VARIANT_TRTL>,
cryptonight_quad_hash<CRYPTONIGHT_PICO, false, VARIANT_TRTL>,
cryptonight_penta_hash<CRYPTONIGHT_PICO, false, VARIANT_TRTL>,
cryptonight_triple_hash<CRYPTONIGHT_PICO, true, VARIANT_TRTL>,
cryptonight_quad_hash<CRYPTONIGHT_PICO, true, VARIANT_TRTL>,
cryptonight_penta_hash<CRYPTONIGHT_PICO, true, 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
};
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)
{ {
assert(av > AV_AUTO && av < AV_MAX); 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; int av = AV_AUTO;
const Multiway multiway = data.multiway; const Multiway multiway = data.multiway;
@ -653,7 +135,7 @@ xmrig::CpuThread::Data xmrig::CpuThread::parse(const rapidjson::Value &object)
data.affinity = affinity.GetInt64(); data.affinity = affinity.GetInt64();
} }
# ifndef XMRIG_NO_ASM # ifdef XMRIG_FEATURE_ASM
data.assembly = Asm::parse(object["asm"]); data.assembly = Asm::parse(object["asm"]);
# endif # 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") ",", LOG_DEBUG(GREEN_BOLD("CPU thread: ") " index " WHITE_BOLD("%zu") ", multiway " WHITE_BOLD("%d") ", av " WHITE_BOLD("%d") ",",
index(), static_cast<int>(multiway()), static_cast<int>(m_av)); index(), static_cast<int>(multiway()), static_cast<int>(m_av));
# ifndef XMRIG_NO_ASM # ifdef XMRIG_FEATURE_ASM
LOG_DEBUG(" assembly: %s, affine_to_cpu: %" PRId64, Asm::toString(m_assembly), affinity()); LOG_DEBUG(" assembly: %s, affine_to_cpu: %" PRId64, Asm::toString(m_assembly), affinity());
# else # else
LOG_DEBUG(" affine_to_cpu: %" PRId64, affinity()); 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("low_power_mode", multiway(), allocator);
obj.AddMember("affine_to_cpu", affinity() == -1L ? Value(kFalseType) : Value(affinity()), 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); obj.AddMember("asm", Asm::toJSON(m_assembly), allocator);
# endif # endif

View file

@ -27,6 +27,7 @@
#include "common/xmrig.h" #include "common/xmrig.h"
#include "crypto/cn/CnHash.h"
#include "interfaces/IThread.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); cn_hash_fun fn(const Algorithm &algorithm) const;
typedef void (*cn_mainloop_fun)(cryptonight_ctx **ctx);
# ifndef XMRIG_NO_ASM
static void patchAsmVariants();
# endif
static bool isSoftAES(AlgoVariant av); static bool isSoftAES(AlgoVariant av);
static cn_hash_fun fn(Algo algorithm, AlgoVariant av, Variant variant, Assembly assembly); static CpuThread *createFromAV(size_t index, const Algorithm &algorithm, AlgoVariant av, int64_t affinity, int priority, 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, const Algorithm &algorithm, const CpuThread::Data &data, int priority, bool softAES);
static CpuThread *createFromData(size_t index, Algo algorithm, const CpuThread::Data &data, int priority, bool softAES);
static Data parse(const rapidjson::Value &object); static Data parse(const rapidjson::Value &object);
static Multiway multiway(AlgoVariant av); static Multiway multiway(AlgoVariant av);
inline bool isPrefetch() const { return m_prefetch; } inline bool isPrefetch() const { return m_prefetch; }
inline bool isSoftAES() const { return m_softAES; } 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 int priority() const override { return m_priority; }
inline int64_t affinity() const override { return m_affinity; } inline int64_t affinity() const override { return m_affinity; }
inline Multiway multiway() const override { return m_multiway; } inline Multiway multiway() const override { return m_multiway; }
@ -97,7 +91,7 @@ protected:
rapidjson::Value toConfig(rapidjson::Document &doc) const override; rapidjson::Value toConfig(rapidjson::Document &doc) const override;
private: private:
const Algo m_algorithm; const Algorithm m_algorithm;
const AlgoVariant m_av; const AlgoVariant m_av;
const Assembly m_assembly; const Assembly m_assembly;
const bool m_prefetch; const bool m_prefetch;

View file

@ -34,7 +34,7 @@
template<size_t N> template<size_t N>
MultiWorker<N>::MultiWorker(ThreadHandle *handle) xmrig::MultiWorker<N>::MultiWorker(ThreadHandle *handle)
: Worker(handle) : Worker(handle)
{ {
m_memory = Mem::create(m_ctx, m_thread->algorithm(), N); m_memory = Mem::create(m_ctx, m_thread->algorithm(), N);
@ -42,61 +42,58 @@ MultiWorker<N>::MultiWorker(ThreadHandle *handle)
template<size_t N> template<size_t N>
MultiWorker<N>::~MultiWorker() xmrig::MultiWorker<N>::~MultiWorker()
{ {
Mem::release(m_ctx, N, m_memory); Mem::release(m_ctx, N, m_memory);
} }
template<size_t N> template<size_t N>
bool MultiWorker<N>::selfTest() bool xmrig::MultiWorker<N>::selfTest()
{ {
using namespace xmrig; if (m_thread->algorithm().family() == Algorithm::CN) {
const bool rc = verify(Algorithm::CN_0, test_output_v0) &&
if (m_thread->algorithm() == CRYPTONIGHT) { verify(Algorithm::CN_1, test_output_v1) &&
const bool rc = verify(VARIANT_0, test_output_v0) && verify(Algorithm::CN_2, test_output_v2) &&
verify(VARIANT_1, test_output_v1) && verify(Algorithm::CN_FAST, test_output_msr) &&
verify(VARIANT_2, test_output_v2) && verify(Algorithm::CN_XAO, test_output_xao) &&
verify(VARIANT_XTL, test_output_xtl) && verify(Algorithm::CN_RTO, test_output_rto) &&
verify(VARIANT_MSR, test_output_msr) && verify(Algorithm::CN_HALF, test_output_half) &&
verify(VARIANT_XAO, test_output_xao) && verify2(Algorithm::CN_WOW, test_output_wow) &&
verify(VARIANT_RTO, test_output_rto) && verify2(Algorithm::CN_R, test_output_r) &&
verify(VARIANT_HALF, test_output_half) && verify(Algorithm::CN_RWZ, test_output_rwz) &&
verify2(VARIANT_WOW, test_output_wow) && verify(Algorithm::CN_ZLS, test_output_zls) &&
verify2(VARIANT_4, test_output_r) && verify(Algorithm::CN_DOUBLE, test_output_double);
verify(VARIANT_RWZ, test_output_rwz) &&
verify(VARIANT_ZLS, test_output_zls) &&
verify(VARIANT_DOUBLE, test_output_double);
# ifdef XMRIG_ALGO_CN_GPU # ifdef XMRIG_ALGO_CN_GPU
if (!rc || N > 1) { if (!rc || N > 1) {
return rc; return rc;
} }
return verify(VARIANT_GPU, test_output_gpu); return verify(Algorithm::CN_GPU, test_output_gpu);
# else # else
return rc; return rc;
# endif # endif
} }
# ifdef XMRIG_ALGO_CN_LITE # ifdef XMRIG_ALGO_CN_LITE
if (m_thread->algorithm() == CRYPTONIGHT_LITE) { if (m_thread->algorithm().family() == Algorithm::CN_LITE) {
return verify(VARIANT_0, test_output_v0_lite) && return verify(Algorithm::CN_LITE_0, test_output_v0_lite) &&
verify(VARIANT_1, test_output_v1_lite); verify(Algorithm::CN_LITE_1, test_output_v1_lite);
} }
# endif # endif
# ifdef XMRIG_ALGO_CN_HEAVY # ifdef XMRIG_ALGO_CN_HEAVY
if (m_thread->algorithm() == CRYPTONIGHT_HEAVY) { if (m_thread->algorithm().family() == Algorithm::CN_HEAVY) {
return verify(VARIANT_0, test_output_v0_heavy) && return verify(Algorithm::CN_HEAVY_0, test_output_v0_heavy) &&
verify(VARIANT_XHV, test_output_xhv_heavy) && verify(Algorithm::CN_HEAVY_XHV, test_output_xhv_heavy) &&
verify(VARIANT_TUBE, test_output_tube_heavy); verify(Algorithm::CN_HEAVY_TUBE, test_output_tube_heavy);
} }
# endif # endif
# ifdef XMRIG_ALGO_CN_PICO # ifdef XMRIG_ALGO_CN_PICO
if (m_thread->algorithm() == CRYPTONIGHT_PICO) { if (m_thread->algorithm().family() == Algorithm::CN_PICO) {
return verify(VARIANT_TRTL, test_output_pico_trtl); return verify(Algorithm::CN_PICO_0, test_output_pico_trtl);
} }
# endif # endif
@ -105,7 +102,7 @@ bool MultiWorker<N>::selfTest()
template<size_t N> template<size_t N>
void MultiWorker<N>::start() void xmrig::MultiWorker<N>::start()
{ {
while (Workers::sequence() > 0) { while (Workers::sequence() > 0) {
if (Workers::isPaused()) { if (Workers::isPaused()) {
@ -126,12 +123,11 @@ void MultiWorker<N>::start()
storeStats(); storeStats();
} }
// FIXME m_thread->fn(m_state.job.algorithm())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height());
// m_thread->fn(m_state.job.algorithm().variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx, m_state.job.height());
for (size_t i = 0; i < N; ++i) { for (size_t i = 0; i < N; ++i) {
if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < m_state.job.target()) { if (*reinterpret_cast<uint64_t*>(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; *nonce(i) += 1;
@ -148,7 +144,7 @@ void MultiWorker<N>::start()
template<size_t N> template<size_t N>
bool MultiWorker<N>::resume(const xmrig::Job &job) bool xmrig::MultiWorker<N>::resume(const xmrig::Job &job)
{ {
if (m_state.job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState.job.id()) { if (m_state.job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState.job.id()) {
m_state = m_pausedState; m_state = m_pausedState;
@ -160,10 +156,9 @@ bool MultiWorker<N>::resume(const xmrig::Job &job)
template<size_t N> template<size_t N>
bool MultiWorker<N>::verify(xmrig::Variant variant, const uint8_t *referenceValue) bool xmrig::MultiWorker<N>::verify(const Algorithm &algorithm, const uint8_t *referenceValue)
{ {
cn_hash_fun func = m_thread->fn(algorithm);
xmrig::CpuThread::cn_hash_fun func = m_thread->fn(variant);
if (!func) { if (!func) {
return false; return false;
} }
@ -174,9 +169,9 @@ bool MultiWorker<N>::verify(xmrig::Variant variant, const uint8_t *referenceValu
template<size_t N> template<size_t N>
bool MultiWorker<N>::verify2(xmrig::Variant variant, const uint8_t *referenceValue) bool xmrig::MultiWorker<N>::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) { if (!func) {
return false; return false;
} }
@ -201,9 +196,9 @@ bool MultiWorker<N>::verify2(xmrig::Variant variant, const uint8_t *referenceVal
template<> 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) { if (!func) {
return false; return false;
} }
@ -221,9 +216,9 @@ bool MultiWorker<1>::verify2(xmrig::Variant variant, const uint8_t *referenceVal
template<size_t N> template<size_t N>
void MultiWorker<N>::consumeJob() void xmrig::MultiWorker<N>::consumeJob()
{ {
xmrig::Job job = Workers::job(); Job job = Workers::job();
m_sequence = Workers::sequence(); m_sequence = Workers::sequence();
if (m_state.job == job) { if (m_state.job == job) {
return; return;
@ -258,7 +253,7 @@ void MultiWorker<N>::consumeJob()
template<size_t N> template<size_t N>
void MultiWorker<N>::save(const xmrig::Job &job) void xmrig::MultiWorker<N>::save(const Job &job)
{ {
if (job.poolId() == -1 && m_state.job.poolId() >= 0) { if (job.poolId() == -1 && m_state.job.poolId() >= 0) {
m_pausedState = m_state; m_pausedState = m_state;
@ -266,8 +261,13 @@ void MultiWorker<N>::save(const xmrig::Job &job)
} }
namespace xmrig {
template class MultiWorker<1>; template class MultiWorker<1>;
template class MultiWorker<2>; template class MultiWorker<2>;
template class MultiWorker<3>; template class MultiWorker<3>;
template class MultiWorker<4>; template class MultiWorker<4>;
template class MultiWorker<5>; template class MultiWorker<5>;
}

View file

@ -33,7 +33,7 @@
#include "workers/Worker.h" #include "workers/Worker.h"
class Handle; namespace xmrig {
template<size_t N> template<size_t N>
@ -48,11 +48,11 @@ protected:
void start() override; void start() override;
private: private:
bool resume(const xmrig::Job &job); bool resume(const Job &job);
bool verify(xmrig::Variant variant, const uint8_t *referenceValue); bool verify(const Algorithm &algorithm, const uint8_t *referenceValue);
bool verify2(xmrig::Variant variant, const uint8_t *referenceValue); bool verify2(const Algorithm &algorithm, const uint8_t *referenceValue);
void consumeJob(); void consumeJob();
void save(const xmrig::Job &job); void save(const Job &job);
inline uint32_t *nonce(size_t index) inline uint32_t *nonce(size_t index)
{ {
@ -61,8 +61,8 @@ private:
struct State struct State
{ {
alignas(16) uint8_t blob[xmrig::Job::kMaxBlobSize * N]; alignas(16) uint8_t blob[Job::kMaxBlobSize * N];
xmrig::Job job; Job job;
}; };
@ -73,4 +73,7 @@ private:
}; };
} // namespace xmrig
#endif /* XMRIG_MULTIWORKER_H */ #endif /* XMRIG_MULTIWORKER_H */

View file

@ -32,7 +32,6 @@
#include "base/tools/Handle.h" #include "base/tools/Handle.h"
#include "core/config/Config.h" #include "core/config/Config.h"
#include "core/Controller.h" #include "core/Controller.h"
#include "crypto/cn/CryptoNight_constants.h"
#include "interfaces/IJobResultListener.h" #include "interfaces/IJobResultListener.h"
#include "interfaces/IThread.h" #include "interfaces/IThread.h"
#include "Mem.h" #include "Mem.h"
@ -169,14 +168,10 @@ void Workers::start(xmrig::Controller *controller)
LOG_NOTICE("--------------------------------------------------------------------------"); LOG_NOTICE("--------------------------------------------------------------------------");
# endif # endif
# ifndef XMRIG_NO_ASM
xmrig::CpuThread::patchAsmVariants();
# endif
m_controller = controller; m_controller = controller;
const std::vector<xmrig::IThread *> &threads = controller->config()->threads(); const std::vector<xmrig::IThread *> &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(); m_status.threads = threads.size();
for (const xmrig::IThread *thread : threads) { for (const xmrig::IThread *thread : threads) {
@ -240,7 +235,7 @@ void Workers::threadsSummary(rapidjson::Document &doc)
{ {
uv_mutex_lock(&m_mutex); uv_mutex_lock(&m_mutex);
const uint64_t pages[2] = { m_status.hugePages, m_status.pages }; 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); uv_mutex_unlock(&m_mutex);
auto &allocator = doc.GetAllocator(); auto &allocator = doc.GetAllocator();
@ -263,23 +258,23 @@ void Workers::onReady(void *arg)
switch (handle->config()->multiway()) { switch (handle->config()->multiway()) {
case 1: case 1:
worker = new MultiWorker<1>(handle); worker = new xmrig::MultiWorker<1>(handle);
break; break;
case 2: case 2:
worker = new MultiWorker<2>(handle); worker = new xmrig::MultiWorker<2>(handle);
break; break;
case 3: case 3:
worker = new MultiWorker<3>(handle); worker = new xmrig::MultiWorker<3>(handle);
break; break;
case 4: case 4:
worker = new MultiWorker<4>(handle); worker = new xmrig::MultiWorker<4>(handle);
break; break;
case 5: case 5:
worker = new MultiWorker<5>(handle); worker = new xmrig::MultiWorker<5>(handle);
break; break;
default: default:
@ -344,7 +339,7 @@ void Workers::start(IWorker *worker)
if (m_status.started == m_status.threads) { if (m_status.started == m_status.threads) {
const double percent = (double) m_status.hugePages / m_status.pages * 100.0; 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") "", 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, m_status.threads, m_status.ways,

View file

@ -86,8 +86,7 @@ private:
pages(0), pages(0),
started(0), started(0),
threads(0), threads(0),
ways(0), ways(0)
algo(xmrig::CRYPTONIGHT)
{} {}
size_t hugePages; size_t hugePages;
@ -95,7 +94,7 @@ private:
size_t started; size_t started;
size_t threads; size_t threads;
size_t ways; size_t ways;
xmrig::Algo algo; xmrig::Algorithm algo;
}; };
static bool m_active; static bool m_active;