|
@@ -0,0 +1,1024 @@
|
|
|
|
|
+#ifdef NDEBUG
|
|
|
|
|
+#undef NDEBUG
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+#include <cassert>
|
|
|
|
|
+#include <iomanip>
|
|
|
|
|
+#include "utility.hpp"
|
|
|
|
|
+#include "../bytecode_machine.hpp"
|
|
|
|
|
+#include "../dataset.hpp"
|
|
|
|
|
+#include "../blake2/endian.h"
|
|
|
|
|
+#include "../blake2/blake2.h"
|
|
|
|
|
+#include "../blake2_generator.hpp"
|
|
|
|
|
+#include "../superscalar.hpp"
|
|
|
|
|
+#include "../reciprocal.h"
|
|
|
|
|
+#include "../intrin_portable.h"
|
|
|
|
|
+#include "../jit_compiler.hpp"
|
|
|
|
|
+
|
|
|
|
|
+struct CacheKey {
|
|
|
|
|
+ void* key;
|
|
|
|
|
+ size_t size = 0;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+randomx_cache* cache;
|
|
|
|
|
+randomx_vm* vm = nullptr;
|
|
|
|
|
+CacheKey currentKey;
|
|
|
|
|
+
|
|
|
|
|
+template<size_t N>
|
|
|
|
|
+void initCache(const char (&key)[N]) {
|
|
|
|
|
+ assert(cache != nullptr);
|
|
|
|
|
+ if (N - 1 == currentKey.size && memcmp(currentKey.key, key, N - 1) == 0)
|
|
|
|
|
+ return;
|
|
|
|
|
+ //std::cout << "randomx_init_cache with key ";
|
|
|
|
|
+ //outputHex(std::cout, key, N - 1);
|
|
|
|
|
+ //std::cout << std::endl;
|
|
|
|
|
+ randomx_init_cache(cache, key, N - 1);
|
|
|
|
|
+ currentKey.key = (void*)key;
|
|
|
|
|
+ currentKey.size = N - 1;
|
|
|
|
|
+ if (vm != nullptr)
|
|
|
|
|
+ randomx_vm_set_cache(vm, cache);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<size_t K, size_t H>
|
|
|
|
|
+void calcStringHash(const char(&key)[K], const char(&input)[H], void* output) {
|
|
|
|
|
+ initCache(key);
|
|
|
|
|
+ assert(vm != nullptr);
|
|
|
|
|
+ randomx_calculate_hash(vm, input, H - 1, output);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<size_t K, size_t H>
|
|
|
|
|
+void calcHexHash(const char(&key)[K], const char(&hex)[H], void* output) {
|
|
|
|
|
+ initCache(key);
|
|
|
|
|
+ assert(vm != nullptr);
|
|
|
|
|
+ char input[H / 2];
|
|
|
|
|
+ hex2bin((char*)hex, H - 1, input);
|
|
|
|
|
+ randomx_calculate_hash(vm, input, sizeof(input), output);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int testNo = 0;
|
|
|
|
|
+int skipped = 0;
|
|
|
|
|
+
|
|
|
|
|
+template<typename FUNC>
|
|
|
|
|
+void runTest(const char* name, bool condition, FUNC f) {
|
|
|
|
|
+ std::cout << "[";
|
|
|
|
|
+ std::cout.width(2);
|
|
|
|
|
+ std::cout << std::right << ++testNo << "] ";
|
|
|
|
|
+ std::cout.width(40);
|
|
|
|
|
+ std::cout << std::left << name << " ... ";
|
|
|
|
|
+ std::cout.flush();
|
|
|
|
|
+ if (condition) {
|
|
|
|
|
+ f();
|
|
|
|
|
+ std::cout << "PASSED" << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ std::cout << "SKIPPED" << std::endl;
|
|
|
|
|
+ skipped++;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int main() {
|
|
|
|
|
+ char testHash[32];
|
|
|
|
|
+
|
|
|
|
|
+ //std::cout << "Allocating randomx_cache..." << std::endl;
|
|
|
|
|
+ cache = randomx_alloc_cache(RANDOMX_FLAG_DEFAULT);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Cache initialization", RANDOMX_ARGON_ITERATIONS == 3 && RANDOMX_ARGON_LANES == 1 && RANDOMX_ARGON_MEMORY == 262144 && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), []() {
|
|
|
|
|
+ initCache("test key 000");
|
|
|
|
|
+ uint64_t* cacheMemory = (uint64_t*)cache->memory;
|
|
|
|
|
+ assert(cacheMemory[0] == 0x191e0e1d23c02186);
|
|
|
|
|
+ assert(cacheMemory[1568413] == 0xf1b62fe6210bf8b1);
|
|
|
|
|
+ assert(cacheMemory[33554431] == 0x1f47f056d05cd99b);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("SuperscalarHash generator", RANDOMX_SUPERSCALAR_LATENCY == 170, []() {
|
|
|
|
|
+ char sprogHash[32];
|
|
|
|
|
+ randomx::SuperscalarProgram sprog;
|
|
|
|
|
+ const char key[] = "test key 000";
|
|
|
|
|
+ constexpr size_t keySize = sizeof(key) - 1;
|
|
|
|
|
+ randomx::Blake2Generator gen(key, keySize);
|
|
|
|
|
+
|
|
|
|
|
+ const char superscalarReferences[10][65] = {
|
|
|
|
|
+ "d3a4a6623738756f77e6104469102f082eff2a3e60be7ad696285ef7dfc72a61",
|
|
|
|
|
+ "f5e7e0bbc7e93c609003d6359208688070afb4a77165a552ff7be63b38dfbc86",
|
|
|
|
|
+ "85ed8b11734de5b3e9836641413a8f36e99e89694f419c8cd25c3f3f16c40c5a",
|
|
|
|
|
+ "5dd956292cf5d5704ad99e362d70098b2777b2a1730520be52f772ca48cd3bc0",
|
|
|
|
|
+ "6f14018ca7d519e9b48d91af094c0f2d7e12e93af0228782671a8640092af9e5",
|
|
|
|
|
+ "134be097c92e2c45a92f23208cacd89e4ce51f1009a0b900dbe83b38de11d791",
|
|
|
|
|
+ "268f9392c20c6e31371a5131f82bd7713d3910075f2f0468baafaa1abd2f3187",
|
|
|
|
|
+ "c668a05fd909714ed4a91e8d96d67b17e44329e88bc71e0672b529a3fc16be47",
|
|
|
|
|
+ "99739351315840963011e4c5d8e90ad0bfed3facdcb713fe8f7138fbf01c4c94",
|
|
|
|
|
+ "14ab53d61880471f66e80183968d97effd5492b406876060e595fcf9682f9295",
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < 10; ++i) {
|
|
|
|
|
+ randomx::generateSuperscalar(sprog, gen);
|
|
|
|
|
+ blake2b(sprogHash, sizeof(sprogHash), &sprog.programBuffer, sizeof(randomx::Instruction) * sprog.getSize(), nullptr, 0);
|
|
|
|
|
+ assert(equalsHex(sprogHash, superscalarReferences[i]));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Dataset initialization (interpreter)", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), []() {
|
|
|
|
|
+ initCache("test key 000");
|
|
|
|
|
+ uint64_t datasetItem[8];
|
|
|
|
|
+ randomx::initDatasetItem(cache, (uint8_t*)&datasetItem, 0);
|
|
|
|
|
+ assert(datasetItem[0] == 0x680588a85ae222db);
|
|
|
|
|
+ randomx::initDatasetItem(cache, (uint8_t*)&datasetItem, 10000000);
|
|
|
|
|
+ assert(datasetItem[0] == 0x7943a1f6186ffb72);
|
|
|
|
|
+ randomx::initDatasetItem(cache, (uint8_t*)&datasetItem, 20000000);
|
|
|
|
|
+ assert(datasetItem[0] == 0x9035244d718095e1);
|
|
|
|
|
+ randomx::initDatasetItem(cache, (uint8_t*)&datasetItem, 30000000);
|
|
|
|
|
+ assert(datasetItem[0] == 0x145a5091f7853099);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Dataset initialization (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), []() {
|
|
|
|
|
+ initCache("test key 000");
|
|
|
|
|
+ randomx::JitCompiler jit;
|
|
|
|
|
+ jit.generateSuperscalarHash(cache->programs, cache->reciprocalCache);
|
|
|
|
|
+ jit.generateDatasetInitCode();
|
|
|
|
|
+ uint64_t datasetItem[8];
|
|
|
|
|
+ jit.getDatasetInitFunc()(cache, (uint8_t*)&datasetItem, 0, 1);
|
|
|
|
|
+ assert(datasetItem[0] == 0x680588a85ae222db);
|
|
|
|
|
+ jit.getDatasetInitFunc()(cache, (uint8_t*)&datasetItem, 10000000, 10000001);
|
|
|
|
|
+ assert(datasetItem[0] == 0x7943a1f6186ffb72);
|
|
|
|
|
+ jit.getDatasetInitFunc()(cache, (uint8_t*)&datasetItem, 20000000, 20000001);
|
|
|
|
|
+ assert(datasetItem[0] == 0x9035244d718095e1);
|
|
|
|
|
+ jit.getDatasetInitFunc()(cache, (uint8_t*)&datasetItem, 30000000, 30000001);
|
|
|
|
|
+ assert(datasetItem[0] == 0x145a5091f7853099);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("randomx_reciprocal", true, []() {
|
|
|
|
|
+ assert(randomx_reciprocal(3) == 12297829382473034410U);
|
|
|
|
|
+ assert(randomx_reciprocal(13) == 11351842506898185609U);
|
|
|
|
|
+ assert(randomx_reciprocal(33) == 17887751829051686415U);
|
|
|
|
|
+ assert(randomx_reciprocal(65537) == 18446462603027742720U);
|
|
|
|
|
+ assert(randomx_reciprocal(15000001) == 10316166306300415204U);
|
|
|
|
|
+ assert(randomx_reciprocal(3845182035) == 10302264209224146340U);
|
|
|
|
|
+ assert(randomx_reciprocal(0xffffffff) == 9223372039002259456U);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("randomx_reciprocal_fast", RANDOMX_HAVE_FAST_RECIPROCAL, []() {
|
|
|
|
|
+ assert(randomx_reciprocal_fast(3) == 12297829382473034410U);
|
|
|
|
|
+ assert(randomx_reciprocal_fast(13) == 11351842506898185609U);
|
|
|
|
|
+ assert(randomx_reciprocal_fast(33) == 17887751829051686415U);
|
|
|
|
|
+ assert(randomx_reciprocal_fast(65537) == 18446462603027742720U);
|
|
|
|
|
+ assert(randomx_reciprocal_fast(15000001) == 10316166306300415204U);
|
|
|
|
|
+ assert(randomx_reciprocal_fast(3845182035) == 10302264209224146340U);
|
|
|
|
|
+ assert(randomx_reciprocal_fast(0xffffffff) == 9223372039002259456U);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ randomx::NativeRegisterFile reg;
|
|
|
|
|
+ randomx::BytecodeMachine decoder;
|
|
|
|
|
+ randomx::InstructionByteCode ibc;
|
|
|
|
|
+ alignas(16) randomx::ProgramConfiguration config;
|
|
|
|
|
+ constexpr int registerHigh = 192;
|
|
|
|
|
+ constexpr int registerDst = 0;
|
|
|
|
|
+ constexpr int registerSrc = 1;
|
|
|
|
|
+ int pc = 0;
|
|
|
|
|
+ constexpr uint32_t imm32 = 3234567890;
|
|
|
|
|
+ constexpr uint64_t imm64 = signExtend2sCompl(imm32);
|
|
|
|
|
+
|
|
|
|
|
+ decoder.beginCompilation(reg);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IADD_RS (decode)", RANDOMX_FREQ_IADD_RS > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IADD_RS - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.mod = UINT8_MAX;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IADD_RS);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.shift == 3);
|
|
|
|
|
+ assert(ibc.imm == 0);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IADD_RS (execute)", RANDOMX_FREQ_IADD_RS > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0x8000000000000000;
|
|
|
|
|
+ reg.r[registerSrc] = 0x1000000000000000;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 0);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IADD_RS with immediate (decode)", RANDOMX_FREQ_IADD_RS > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IADD_RS - 1;
|
|
|
|
|
+ instr.mod = 8;
|
|
|
|
|
+ instr.dst = registerHigh | randomx::RegisterNeedsDisplacement;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IADD_RS);
|
|
|
|
|
+ assert(ibc.idst == ®.r[randomx::RegisterNeedsDisplacement]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.shift == 2);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IADD_RS with immediate (decode)", RANDOMX_FREQ_IADD_RS > 0, [&] {
|
|
|
|
|
+ reg.r[randomx::RegisterNeedsDisplacement] = 0x8000000000000000;
|
|
|
|
|
+ reg.r[registerSrc] = 0x2000000000000000;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[randomx::RegisterNeedsDisplacement] == imm64);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IADD_M (decode)", RANDOMX_FREQ_IADD_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IADD_M - 1;
|
|
|
|
|
+ instr.mod = 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IADD_M);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL1Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISUB_R (decode)", RANDOMX_FREQ_ISUB_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISUB_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISUB_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISUB_R (execute)", RANDOMX_FREQ_ISUB_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 1;
|
|
|
|
|
+ reg.r[registerSrc] = 0xFFFFFFFF;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 0xFFFFFFFF00000002);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISUB_R with immediate (decode)", RANDOMX_FREQ_ISUB_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISUB_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISUB_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == &ibc.imm);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISUB_R with immediate (decode)", RANDOMX_FREQ_ISUB_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == (~imm64 + 1));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISUB_M (decode)", RANDOMX_FREQ_ISUB_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISUB_M - 1;
|
|
|
|
|
+ instr.mod = 0;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISUB_M);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL2Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMUL_R (decode)", RANDOMX_FREQ_IMUL_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMUL_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IMUL_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMUL_R (execute)", RANDOMX_FREQ_IMUL_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0xBC550E96BA88A72B;
|
|
|
|
|
+ reg.r[registerSrc] = 0xF5391FA9F18D6273;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 0x28723424A9108E51);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMUL_R with immediate (decode)", RANDOMX_FREQ_IMUL_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMUL_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IMUL_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == &ibc.imm);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMUL_R with immediate (execute)", RANDOMX_FREQ_IMUL_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 1;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == imm64);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMUL_M (decode)", RANDOMX_FREQ_IMUL_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMUL_M - 1;
|
|
|
|
|
+ instr.mod = 0;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IMUL_M);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(*ibc.isrc == 0);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL3Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMULH_R (decode)", RANDOMX_FREQ_IMULH_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMULH_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IMULH_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMULH_R (execute)", RANDOMX_FREQ_IMULH_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0xBC550E96BA88A72B;
|
|
|
|
|
+ reg.r[registerSrc] = 0xF5391FA9F18D6273;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 0xB4676D31D2B34883);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMULH_R squared (decode)", RANDOMX_FREQ_IMULH_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMULH_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IMULH_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerDst]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMULH_M (decode)", RANDOMX_FREQ_IMULH_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMULH_M - 1;
|
|
|
|
|
+ instr.mod = 0;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IMULH_M);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL2Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISMULH_R (decode)", RANDOMX_FREQ_ISMULH_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISMULH_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISMULH_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISMULH_R (execute)", RANDOMX_FREQ_ISMULH_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0xBC550E96BA88A72B;
|
|
|
|
|
+ reg.r[registerSrc] = 0xF5391FA9F18D6273;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 0x02D93EF1269D3EE5);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISMULH_R squared (decode)", RANDOMX_FREQ_ISMULH_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISMULH_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISMULH_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerDst]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISMULH_M (decode)", RANDOMX_FREQ_ISMULH_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISMULH_M - 1;
|
|
|
|
|
+ instr.mod = 3;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISMULH_M);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL1Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMUL_RCP (decode)", RANDOMX_FREQ_IMUL_RCP > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMUL_RCP - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IMUL_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == &ibc.imm);
|
|
|
|
|
+ assert(ibc.imm == randomx_reciprocal(imm32));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IMUL_RCP zero imm32 (decode)", RANDOMX_FREQ_IMUL_RCP > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IMUL_RCP - 1;
|
|
|
|
|
+ instr.setImm32(0);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::NOP);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("INEG_R (decode)", RANDOMX_FREQ_INEG_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_INEG_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::INEG_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("INEG_R (execute)", RANDOMX_FREQ_INEG_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0xFFFFFFFFFFFFFFFF;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 1);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IXOR_R (decode)", RANDOMX_FREQ_IXOR_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IXOR_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IXOR_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IXOR_R (execute)", RANDOMX_FREQ_IMUL_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0x8888888888888888;
|
|
|
|
|
+ reg.r[registerSrc] = 0xAAAAAAAAAAAAAAAA;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 0x2222222222222222);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IXOR_R with immediate (decode)", RANDOMX_FREQ_IXOR_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IXOR_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IXOR_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == &ibc.imm);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IXOR_R with immediate (execute)", RANDOMX_FREQ_IXOR_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0xFFFFFFFFFFFFFFFF;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == ~imm64);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IXOR_M (decode)", RANDOMX_FREQ_IXOR_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IXOR_M - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IXOR_M);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(*ibc.isrc == 0);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL3Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IROR_R (decode)", RANDOMX_FREQ_IROR_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IROR_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IROR_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IROR_R (execute)", RANDOMX_FREQ_IROR_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 953360005391419562;
|
|
|
|
|
+ reg.r[registerSrc] = 4569451684712230561;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 0xD835C455069D81EF);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IROL_R (decode)", RANDOMX_FREQ_IROL_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_IROL_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::IROL_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("IROL_R (execute)", RANDOMX_FREQ_IROL_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 953360005391419562;
|
|
|
|
|
+ reg.r[registerSrc] = 4569451684712230561;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 6978065200552740799);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISWAP_R (decode)", RANDOMX_FREQ_ISWAP_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISWAP_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISWAP_R);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISWAP_R (execute)", RANDOMX_FREQ_ISWAP_R > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 953360005391419562;
|
|
|
|
|
+ reg.r[registerSrc] = 4569451684712230561;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(reg.r[registerDst] == 4569451684712230561);
|
|
|
|
|
+ assert(reg.r[registerSrc] == 953360005391419562);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSWAP_R (decode)", RANDOMX_FREQ_FSWAP_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FSWAP_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FSWAP_R);
|
|
|
|
|
+ assert(ibc.fdst == ®.f[registerDst]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSWAP_R (execute)", RANDOMX_FREQ_FSWAP_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.f[registerDst] = rx_set_vec_f128(953360005391419562, 4569451684712230561);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.f[registerDst]);
|
|
|
|
|
+ assert(equalsHex((const char*)&vec, "aa886bb0df033b0da12e95e518f4693f"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FADD_R (decode)", RANDOMX_FREQ_FADD_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FADD_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FADD_R);
|
|
|
|
|
+ assert(ibc.fdst == ®.f[registerDst]);
|
|
|
|
|
+ assert(ibc.fsrc == ®.a[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FADD_R RoundToNearest (execute)", RANDOMX_FREQ_FADD_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.f[registerDst] = rx_set_vec_f128(0x3ffd2c97cc4ef015, 0xc1ce30b3c4223576);
|
|
|
|
|
+ reg.a[registerSrc] = rx_set_vec_f128(0x402a26a86a60c8fb, 0x40b8f684057a59e1);
|
|
|
|
|
+ rx_set_rounding_mode(RoundToNearest);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.f[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "b932e048a730cec1fea6ea633bcc2d40"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FADD_R RoundDown (execute)", RANDOMX_FREQ_FADD_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.f[registerDst] = rx_set_vec_f128(0x3ffd2c97cc4ef015, 0xc1ce30b3c4223576);
|
|
|
|
|
+ reg.a[registerSrc] = rx_set_vec_f128(0x402a26a86a60c8fb, 0x40b8f684057a59e1);
|
|
|
|
|
+ rx_set_rounding_mode(RoundDown);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.f[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "b932e048a730cec1fda6ea633bcc2d40"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FADD_R RoundUp (execute)", RANDOMX_FREQ_FADD_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.f[registerDst] = rx_set_vec_f128(0x3ffd2c97cc4ef015, 0xc1ce30b3c4223576);
|
|
|
|
|
+ reg.a[registerSrc] = rx_set_vec_f128(0x402a26a86a60c8fb, 0x40b8f684057a59e1);
|
|
|
|
|
+ rx_set_rounding_mode(RoundUp);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.f[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "b832e048a730cec1fea6ea633bcc2d40"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FADD_R RoundToZero (execute)", RANDOMX_FREQ_FADD_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.f[registerDst] = rx_set_vec_f128(0x3ffd2c97cc4ef015, 0xc1ce30b3c4223576);
|
|
|
|
|
+ reg.a[registerSrc] = rx_set_vec_f128(0x402a26a86a60c8fb, 0x40b8f684057a59e1);
|
|
|
|
|
+ rx_set_rounding_mode(RoundToZero);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.f[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "b832e048a730cec1fda6ea633bcc2d40"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FADD_M (decode)", RANDOMX_FREQ_FADD_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FADD_M - 1;
|
|
|
|
|
+ instr.mod = 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FADD_M);
|
|
|
|
|
+ assert(ibc.fdst == ®.f[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL1Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FADD_M (execute)", RANDOMX_FREQ_FADD_R > 0, [&] {
|
|
|
|
|
+ uint64_t mockScratchpad;
|
|
|
|
|
+ store64(&mockScratchpad, 0x1234567890abcdef);
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.f[registerDst] = rx_set_vec_f128(0, 0);
|
|
|
|
|
+ reg.r[registerSrc] = 0xFFFFFFFFFFFFE930;
|
|
|
|
|
+ rx_set_rounding_mode(RoundToNearest);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, (uint8_t*)&mockScratchpad, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.f[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "000040840cd5dbc1000000785634b241"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSUB_R (decode)", RANDOMX_FREQ_FSUB_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FSUB_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FSUB_R);
|
|
|
|
|
+ assert(ibc.fdst == ®.f[registerDst]);
|
|
|
|
|
+ assert(ibc.fsrc == ®.a[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSUB_M (decode)", RANDOMX_FREQ_FSUB_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FSUB_M - 1;
|
|
|
|
|
+ instr.mod = 2;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FSUB_M);
|
|
|
|
|
+ assert(ibc.fdst == ®.f[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL1Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSCAL_R (decode)", RANDOMX_FREQ_FSCAL_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FSCAL_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FSCAL_R);
|
|
|
|
|
+ assert(ibc.fdst == ®.f[registerDst]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSCAL_R (execute)", RANDOMX_FREQ_FSCAL_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.f[registerDst] = rx_set_vec_f128(0x41dbc35cef248783, 0x40fdfdabb6173d07);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.f[registerDst]);
|
|
|
|
|
+ assert(equalsHex((const char*)&vec, "073d17b6abfd0dc0838724ef5cc32bc1"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FMUL_R (decode)", RANDOMX_FREQ_FMUL_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FMUL_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FMUL_R);
|
|
|
|
|
+ assert(ibc.fdst == ®.e[registerDst]);
|
|
|
|
|
+ assert(ibc.fsrc == ®.a[registerSrc]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FMUL_R RoundToNearest (execute)", RANDOMX_FREQ_FMUL_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41dbc35cef248783, 0x40fdfdabb6173d07);
|
|
|
|
|
+ reg.a[registerSrc] = rx_set_vec_f128(0x40eba861aa31c7c0, 0x41c4561212ae2d50);
|
|
|
|
|
+ rx_set_rounding_mode(RoundToNearest);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "69697aff350fd3422f1589cdecfed742"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FMUL_R RoundDown/RoundToZero (execute)", RANDOMX_FREQ_FMUL_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41dbc35cef248783, 0x40fdfdabb6173d07);
|
|
|
|
|
+ reg.a[registerSrc] = rx_set_vec_f128(0x40eba861aa31c7c0, 0x41c4561212ae2d50);
|
|
|
|
|
+ rx_set_rounding_mode(RoundDown);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "69697aff350fd3422e1589cdecfed742"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FMUL_R RoundUp (execute)", RANDOMX_FREQ_FMUL_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41dbc35cef248783, 0x40fdfdabb6173d07);
|
|
|
|
|
+ reg.a[registerSrc] = rx_set_vec_f128(0x40eba861aa31c7c0, 0x41c4561212ae2d50);
|
|
|
|
|
+ rx_set_rounding_mode(RoundUp);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "6a697aff350fd3422f1589cdecfed742"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FDIV_M (decode)", RANDOMX_FREQ_FDIV_M > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FDIV_M - 1;
|
|
|
|
|
+ instr.mod = 3;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FDIV_M);
|
|
|
|
|
+ assert(ibc.fdst == ®.e[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL1Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FDIV_M RoundToNearest (execute)", RANDOMX_FREQ_FDIV_M > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ alignas(16) uint32_t mockScratchpad[2];
|
|
|
|
|
+ store32(&mockScratchpad[0], 0xd350a1b6);
|
|
|
|
|
+ store32(&mockScratchpad[1], 0x8b2460d9);
|
|
|
|
|
+ store64(&config.eMask[0], 0x3a0000000005d11a);
|
|
|
|
|
+ store64(&config.eMask[1], 0x39000000001ba31e);
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41937f76fede16ee, 0x411b414296ce93b6);
|
|
|
|
|
+ reg.r[registerSrc] = 0xFFFFFFFFFFFFE930;
|
|
|
|
|
+ rx_set_rounding_mode(RoundToNearest);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, (uint8_t*)&mockScratchpad, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "e7b269639484434632474a66635ba547"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FDIV_M RoundDown/RoundToZero (execute)", RANDOMX_FREQ_FDIV_M > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ alignas(16) uint32_t mockScratchpad[2];
|
|
|
|
|
+ store32(&mockScratchpad[0], 0xd350a1b6);
|
|
|
|
|
+ store32(&mockScratchpad[1], 0x8b2460d9);
|
|
|
|
|
+ store64(&config.eMask[0], 0x3a0000000005d11a);
|
|
|
|
|
+ store64(&config.eMask[1], 0x39000000001ba31e);
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41937f76fede16ee, 0x411b414296ce93b6);
|
|
|
|
|
+ reg.r[registerSrc] = 0xFFFFFFFFFFFFE930;
|
|
|
|
|
+ rx_set_rounding_mode(RoundDown);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, (uint8_t*)&mockScratchpad, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "e6b269639484434632474a66635ba547"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FDIV_M RoundUp (execute)", RANDOMX_FREQ_FDIV_M > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ alignas(16) uint32_t mockScratchpad[2];
|
|
|
|
|
+ store32(&mockScratchpad[0], 0xd350a1b6);
|
|
|
|
|
+ store32(&mockScratchpad[1], 0x8b2460d9);
|
|
|
|
|
+ store64(&config.eMask[0], 0x3a0000000005d11a);
|
|
|
|
|
+ store64(&config.eMask[1], 0x39000000001ba31e);
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41937f76fede16ee, 0x411b414296ce93b6);
|
|
|
|
|
+ reg.r[registerSrc] = 0xFFFFFFFFFFFFE930;
|
|
|
|
|
+ rx_set_rounding_mode(RoundUp);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, (uint8_t*)&mockScratchpad, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "e7b269639484434633474a66635ba547"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSQRT_R (decode)", RANDOMX_FREQ_FSQRT_R > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_FSQRT_R - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::FSQRT_R);
|
|
|
|
|
+ assert(ibc.fdst == ®.e[registerDst]);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSQRT_R RoundToNearest (execute)", RANDOMX_FREQ_FSQRT_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41b6b21c11affea7, 0x40526a7e778d9824);
|
|
|
|
|
+ rx_set_rounding_mode(RoundToNearest);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "e81f300b612a21408dbaa33f570ed340"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSQRT_R RoundDown/RoundToZero (execute)", RANDOMX_FREQ_FSQRT_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41b6b21c11affea7, 0x40526a7e778d9824);
|
|
|
|
|
+ rx_set_rounding_mode(RoundDown);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "e81f300b612a21408cbaa33f570ed340"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("FSQRT_R RoundUp (execute)", RANDOMX_FREQ_FSQRT_R > 0, [&] {
|
|
|
|
|
+ alignas(16) uint64_t vec[2];
|
|
|
|
|
+ reg.e[registerDst] = rx_set_vec_f128(0x41b6b21c11affea7, 0x40526a7e778d9824);
|
|
|
|
|
+ rx_set_rounding_mode(RoundUp);
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ rx_store_vec_f128((double*)&vec, reg.e[registerDst]);
|
|
|
|
|
+ assert(equalsHex(&vec, "e91f300b612a21408dbaa33f570ed340"));
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("CBRANCH (decode) 100", RANDOMX_FREQ_CBRANCH > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_CBRANCH - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ instr.mod = 48;
|
|
|
|
|
+ decoder.compileInstruction(instr, 100, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::CBRANCH);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.imm == 0xFFFFFFFFC0CB9AD2);
|
|
|
|
|
+ assert(ibc.memMask == 0x7F800);
|
|
|
|
|
+ assert(ibc.target == pc);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("CBRANCH (decode) 200", RANDOMX_FREQ_CBRANCH > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_CBRANCH - 1;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ instr.mod = 48;
|
|
|
|
|
+ decoder.compileInstruction(instr, pc = 200, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::CBRANCH);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.imm == 0xFFFFFFFFC0CB9AD2);
|
|
|
|
|
+ assert(ibc.memMask == 0x7F800);
|
|
|
|
|
+ assert(ibc.target == 100);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("CBRANCH not taken (execute)", RANDOMX_FREQ_CBRANCH > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(pc == 200);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("CBRANCH taken (execute)", RANDOMX_FREQ_CBRANCH > 0, [&] {
|
|
|
|
|
+ reg.r[registerDst] = 0xFFFFFFFFFFFC6800;
|
|
|
|
|
+ decoder.executeInstruction(ibc, pc, nullptr, config);
|
|
|
|
|
+ assert(pc == ibc.target);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("CFROUND (decode)", RANDOMX_FREQ_CFROUND > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_CFROUND - 1;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ decoder.compileInstruction(instr, 100, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::CFROUND);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == 18);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISTORE L1 (decode)", RANDOMX_FREQ_ISTORE > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISTORE - 1;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ instr.mod = 1;
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISTORE);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL1Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISTORE L2 (decode)", RANDOMX_FREQ_ISTORE > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISTORE - 1;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ instr.mod = 0;
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISTORE);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL2Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ runTest("ISTORE L3 (decode)", RANDOMX_FREQ_ISTORE > 0, [&] {
|
|
|
|
|
+ randomx::Instruction instr;
|
|
|
|
|
+ instr.opcode = randomx::ceil_ISTORE - 1;
|
|
|
|
|
+ instr.src = registerHigh | registerSrc;
|
|
|
|
|
+ instr.dst = registerHigh | registerDst;
|
|
|
|
|
+ instr.setImm32(imm32);
|
|
|
|
|
+ instr.mod = 224;
|
|
|
|
|
+ decoder.compileInstruction(instr, pc, ibc);
|
|
|
|
|
+ assert(ibc.type == randomx::InstructionType::ISTORE);
|
|
|
|
|
+ assert(ibc.idst == ®.r[registerDst]);
|
|
|
|
|
+ assert(ibc.isrc == ®.r[registerSrc]);
|
|
|
|
|
+ assert(ibc.imm == imm64);
|
|
|
|
|
+ assert(ibc.memMask == randomx::ScratchpadL3Mask);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ vm = randomx_create_vm(RANDOMX_FLAG_DEFAULT, cache, nullptr);
|
|
|
|
|
+
|
|
|
|
|
+ auto test_a = [&] {
|
|
|
|
|
+ char hash[RANDOMX_HASH_SIZE];
|
|
|
|
|
+ calcStringHash("test key 000", "This is a test", &hash);
|
|
|
|
|
+ assert(equalsHex(hash, "207d7cedf2a16590bd33d758e413ad129ce9888e05417984f46296252a7ba3d0"));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ auto test_b = [&] {
|
|
|
|
|
+ char hash[RANDOMX_HASH_SIZE];
|
|
|
|
|
+ calcStringHash("test key 000", "Lorem ipsum dolor sit amet", &hash);
|
|
|
|
|
+ assert(equalsHex(hash, "76dd2da840d56d38153e0beaca33e7f862c5ead91a052380d99f3a62bf84579b"));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ auto test_c = [&] {
|
|
|
|
|
+ char hash[RANDOMX_HASH_SIZE];
|
|
|
|
|
+ calcStringHash("test key 000", "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua", &hash);
|
|
|
|
|
+ assert(equalsHex(hash, "109f6a405efe09d302336dce4389127e33aa62d4c782aca7797a628e87839a61"));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ auto test_d = [&] {
|
|
|
|
|
+ char hash[RANDOMX_HASH_SIZE];
|
|
|
|
|
+ calcStringHash("test key 001", "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua", &hash);
|
|
|
|
|
+ assert(equalsHex(hash, "3cbb82edf9541ab80233cdc47384cea719c8567a8bbaca8f3ff038488ce9c16c"));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ auto test_e = [&] {
|
|
|
|
|
+ char hash[RANDOMX_HASH_SIZE];
|
|
|
|
|
+ calcHexHash("test key 001", "0b0b98bea7e805e0010a2126d287a2a0cc833d312cb786385a7c2f9de69d25537f584a9bc9977b00000000666fd8753bf61a8631f12984e3fd44f4014eca629276817b56f32e9b68bd82f416", &hash);
|
|
|
|
|
+
|
|
|
|
|
+ //outputHex(std::cout, (const char*)hash, sizeof(hash));
|
|
|
|
|
+ //std::cout << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+ assert(equalsHex(hash, "e003ef128b1f96d99d4a0490e03253ef11186002a8ec018cbd4e07b8ec8c82e8"));
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 1a (interpreter)", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_a);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 1b (interpreter)", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_b);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 1c (interpreter)", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_c);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 1d (interpreter)", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_d);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 1e (interpreter)", stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_e);
|
|
|
|
|
+
|
|
|
|
|
+ randomx_release_cache(cache);
|
|
|
|
|
+ cache = randomx_alloc_cache(RANDOMX_FLAG_JIT);
|
|
|
|
|
+ currentKey.size = 0;
|
|
|
|
|
+ randomx_destroy_vm(vm);
|
|
|
|
|
+ vm = randomx_create_vm(RANDOMX_FLAG_JIT, cache, nullptr);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 2a (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_a);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 2b (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_b);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 2c (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_c);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 2d (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_d);
|
|
|
|
|
+
|
|
|
|
|
+ runTest("Hash test 2e (compiler)", RANDOMX_HAVE_COMPILER && stringsEqual(RANDOMX_ARGON_SALT, "RandomX\x03"), test_e);
|
|
|
|
|
+
|
|
|
|
|
+ std::cout << std::endl << "All tests PASSED" << std::endl;
|
|
|
|
|
+
|
|
|
|
|
+ if (skipped) {
|
|
|
|
|
+ std::cout << skipped << " tests were SKIPPED due to incompatible configuration (see above)" << std::endl;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|