mirror of
https://github.com/xmrig/xmrig.git
synced 2026-04-17 13:02:57 -04:00
Compare commits
49 Commits
eb49237aaa
...
v6.26.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2ca72480c | ||
|
|
92705f2dae | ||
|
|
4f58a7afff | ||
|
|
806cfc3f4d | ||
|
|
84352c71ca | ||
|
|
27d535d00f | ||
|
|
9d296c7f02 | ||
|
|
3b4e38ba18 | ||
|
|
8b33d2494b | ||
|
|
c534c669cb | ||
|
|
d7f7094c45 | ||
|
|
14dcd36296 | ||
|
|
a935641274 | ||
|
|
976a08efb4 | ||
|
|
17aa97e543 | ||
|
|
48b29fd68b | ||
|
|
6454a0abf2 | ||
|
|
8464d474d4 | ||
|
|
26ee1cd291 | ||
|
|
d9b39e8c32 | ||
|
|
05dd6dcc40 | ||
|
|
316a3673bc | ||
|
|
42c943c03f | ||
|
|
c2c8080783 | ||
|
|
d82d7f3f20 | ||
|
|
a189d84fcd | ||
|
|
cb6001945e | ||
|
|
f16a06eb67 | ||
|
|
9d71358f46 | ||
|
|
5a80c65d31 | ||
|
|
67cc6cfd1c | ||
|
|
db24bf5154 | ||
|
|
0d9a372e49 | ||
|
|
c1e3d386fe | ||
|
|
5ca4828255 | ||
|
|
1a04bf2904 | ||
|
|
5feb764b27 | ||
|
|
cb7511507f | ||
|
|
6e6eab1763 | ||
|
|
f35f9d7241 | ||
|
|
45d0a15c98 | ||
|
|
f4845cbd68 | ||
|
|
ed80a8a828 | ||
|
|
9e5492eecc | ||
|
|
e41b28ef78 | ||
|
|
1bd59129c4 | ||
|
|
8ccf7de304 | ||
|
|
30ffb9cb27 | ||
|
|
d3a84c4b52 |
3
.codespellrc
Normal file
3
.codespellrc
Normal file
@@ -0,0 +1,3 @@
|
||||
[codespell]
|
||||
skip = ./src/3rdparty,./src/crypto/ghostrider,./src/crypto/randomx/blake2,./src/crypto/cn/sse2neon.h,./src/backend/opencl/cl/cn/groestl256.cl,./src/backend/opencl/cl/cn/jh.cl
|
||||
ignore-words-list = Carmel,vor
|
||||
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,3 +1,17 @@
|
||||
# v6.26.0
|
||||
- [#3769](https://github.com/xmrig/xmrig/pull/3769), [#3772](https://github.com/xmrig/xmrig/pull/3772), [#3774](https://github.com/xmrig/xmrig/pull/3774), [#3775](https://github.com/xmrig/xmrig/pull/3775), [#3776](https://github.com/xmrig/xmrig/pull/3776), [#3782](https://github.com/xmrig/xmrig/pull/3782), [#3783](https://github.com/xmrig/xmrig/pull/3783) **Added support for RandomX v2.**
|
||||
- [#3746](https://github.com/xmrig/xmrig/pull/3746) RISC-V: vectorized RandomX main loop.
|
||||
- [#3748](https://github.com/xmrig/xmrig/pull/3748) RISC-V: auto-detect and use vector code for all RandomX AES functions.
|
||||
- [#3749](https://github.com/xmrig/xmrig/pull/3749) RISC-V: detect and use hardware AES.
|
||||
- [#3750](https://github.com/xmrig/xmrig/pull/3750) RISC-V: use vector hardware AES instead of scalar.
|
||||
- [#3757](https://github.com/xmrig/xmrig/pull/3757) RISC-V: Fixed scratchpad prefetch, removed an unnecessary instruction.
|
||||
- [#3758](https://github.com/xmrig/xmrig/pull/3758) RandomX: added VAES-512 support for Zen5.
|
||||
- [#3759](https://github.com/xmrig/xmrig/pull/3759) RandomX: Optimized VAES code.
|
||||
- [#3762](https://github.com/xmrig/xmrig/pull/3762) Fixed keepalive timer logic.
|
||||
- [#3778](https://github.com/xmrig/xmrig/pull/3778) RandomX: ARM64 fixes.
|
||||
- [#3784](https://github.com/xmrig/xmrig/pull/3784) Fixed OpenCL address-space mismatch in `keccak_f800_round`.
|
||||
- [#3785](https://github.com/xmrig/xmrig/pull/3785) Don't reset nonce during donation rounds.
|
||||
|
||||
# v6.25.0
|
||||
- [#3680](https://github.com/xmrig/xmrig/pull/3680) Added `armv8l` to the list of 32-bit ARM targets.
|
||||
- [#3708](https://github.com/xmrig/xmrig/pull/3708) Minor Aarch64 JIT changes (better instruction selection, don't emit instructions that add 0, etc).
|
||||
@@ -160,7 +174,7 @@
|
||||
# v6.16.2
|
||||
- [#2751](https://github.com/xmrig/xmrig/pull/2751) Fixed crash on CPUs supporting VAES and running GCC-compiled xmrig.
|
||||
- [#2761](https://github.com/xmrig/xmrig/pull/2761) Fixed broken auto-tuning in GCC Windows build.
|
||||
- [#2771](https://github.com/xmrig/xmrig/issues/2771) Fixed environment variables support for GhostRider and KawPow.
|
||||
- [#2771](https://github.com/xmrig/xmrig/issues/2771) Fixed environment variables support for GhostRider and KawPow.
|
||||
- [#2769](https://github.com/xmrig/xmrig/pull/2769) Performance fixes:
|
||||
- Fixed several performance bottlenecks introduced in v6.16.1.
|
||||
- Fixed overall GCC-compiled build performance, it's the same speed as MSVC build now.
|
||||
@@ -468,7 +482,7 @@
|
||||
- Compiler for Windows gcc builds updated to v10.1.
|
||||
|
||||
# v5.11.1
|
||||
- [#1652](https://github.com/xmrig/xmrig/pull/1652) Up to 1% RandomX perfomance improvement on recent AMD CPUs.
|
||||
- [#1652](https://github.com/xmrig/xmrig/pull/1652) Up to 1% RandomX performance improvement on recent AMD CPUs.
|
||||
- [#1306](https://github.com/xmrig/xmrig/issues/1306) Fixed possible double connection to a pool.
|
||||
- [#1654](https://github.com/xmrig/xmrig/issues/1654) Fixed build with LibreSSL.
|
||||
|
||||
@@ -574,9 +588,9 @@
|
||||
- Added automatic huge pages configuration on Linux if use the miner with root privileges.
|
||||
- **Added [automatic Intel prefetchers configuration](https://xmrig.com/docs/miner/randomx-optimization-guide#intel-specific-optimizations) on Linux.**
|
||||
- Added new option `wrmsr` in `randomx` object with command line equivalent `--randomx-wrmsr=6`.
|
||||
- [#1396](https://github.com/xmrig/xmrig/pull/1396) [#1401](https://github.com/xmrig/xmrig/pull/1401) New performance optimizations for Ryzen CPUs.
|
||||
- [#1385](https://github.com/xmrig/xmrig/issues/1385) Added `max-threads-hint` option support for RandomX dataset initialization threads.
|
||||
- [#1386](https://github.com/xmrig/xmrig/issues/1386) Added `priority` option support for RandomX dataset initialization threads.
|
||||
- [#1396](https://github.com/xmrig/xmrig/pull/1396) [#1401](https://github.com/xmrig/xmrig/pull/1401) New performance optimizations for Ryzen CPUs.
|
||||
- [#1385](https://github.com/xmrig/xmrig/issues/1385) Added `max-threads-hint` option support for RandomX dataset initialization threads.
|
||||
- [#1386](https://github.com/xmrig/xmrig/issues/1386) Added `priority` option support for RandomX dataset initialization threads.
|
||||
- For official builds all dependencies (libuv, hwloc, openssl) updated to recent versions.
|
||||
- Windows `msvc` builds now use Visual Studio 2019 instead of 2017.
|
||||
|
||||
@@ -622,7 +636,7 @@ This release based on 4.x.x series and include all features from v4.6.2-beta, ch
|
||||
- Removed command line option `--http-enabled`, HTTP API enabled automatically if any other `--http-*` option provided.
|
||||
- [#1172](https://github.com/xmrig/xmrig/issues/1172) **Added OpenCL mining backend.**
|
||||
- [#268](https://github.com/xmrig/xmrig-amd/pull/268) [#270](https://github.com/xmrig/xmrig-amd/pull/270) [#271](https://github.com/xmrig/xmrig-amd/pull/271) [#273](https://github.com/xmrig/xmrig-amd/pull/273) [#274](https://github.com/xmrig/xmrig-amd/pull/274) [#1171](https://github.com/xmrig/xmrig/pull/1171) Added RandomX support for OpenCL, thanks [@SChernykh](https://github.com/SChernykh).
|
||||
- Algorithm `cn/wow` removed, as no longer alive.
|
||||
- Algorithm `cn/wow` removed, as no longer alive.
|
||||
|
||||
# Previous versions
|
||||
[doc/CHANGELOG_OLD.md](doc/CHANGELOG_OLD.md)
|
||||
|
||||
@@ -105,6 +105,32 @@ if (XMRIG_RISCV)
|
||||
set(RVARCH_ZBB OFF)
|
||||
endif()
|
||||
|
||||
try_run(RANDOMX_ZVKB_RUN_FAIL
|
||||
RANDOMX_ZVKB_COMPILE_OK
|
||||
${CMAKE_CURRENT_BINARY_DIR}/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/randomx/tests/riscv64_zvkb.s
|
||||
COMPILE_DEFINITIONS "-march=rv64gcv_zvkb")
|
||||
|
||||
if (RANDOMX_ZVKB_COMPILE_OK AND NOT RANDOMX_ZVKB_RUN_FAIL)
|
||||
set(RVARCH_ZVKB ON)
|
||||
message(STATUS "RISC-V zvkb extension detected")
|
||||
else()
|
||||
set(RVARCH_ZVKB OFF)
|
||||
endif()
|
||||
|
||||
try_run(RANDOMX_ZVKNED_RUN_FAIL
|
||||
RANDOMX_ZVKNED_COMPILE_OK
|
||||
${CMAKE_CURRENT_BINARY_DIR}/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/crypto/randomx/tests/riscv64_zvkned.s
|
||||
COMPILE_DEFINITIONS "-march=rv64gcv_zvkned")
|
||||
|
||||
if (RANDOMX_ZVKNED_COMPILE_OK AND NOT RANDOMX_ZVKNED_RUN_FAIL)
|
||||
set(RVARCH_ZVKNED ON)
|
||||
message(STATUS "RISC-V zvkned extension detected")
|
||||
else()
|
||||
set(RVARCH_ZVKNED OFF)
|
||||
endif()
|
||||
|
||||
# for native builds, enable Zba and Zbb if supported by the CPU
|
||||
if (ARCH STREQUAL "native")
|
||||
if (RVARCH_V)
|
||||
@@ -119,6 +145,12 @@ if (XMRIG_RISCV)
|
||||
if (RVARCH_ZBB)
|
||||
set(RVARCH "${RVARCH}_zbb")
|
||||
endif()
|
||||
if (RVARCH_ZVKB)
|
||||
set(RVARCH "${RVARCH}_zvkb")
|
||||
endif()
|
||||
if (RVARCH_ZVKNED)
|
||||
set(RVARCH "${RVARCH}_zvkned")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Using -march=${RVARCH}")
|
||||
|
||||
@@ -86,6 +86,8 @@ if (WITH_RANDOMX)
|
||||
src/crypto/randomx/jit_compiler_rv64_vector_static.S
|
||||
src/crypto/randomx/jit_compiler_rv64.cpp
|
||||
src/crypto/randomx/jit_compiler_rv64_vector.cpp
|
||||
src/crypto/randomx/aes_hash_rv64_vector.cpp
|
||||
src/crypto/randomx/aes_hash_rv64_zvkned.cpp
|
||||
)
|
||||
# cheat because cmake and ccache hate each other
|
||||
set_property(SOURCE src/crypto/randomx/jit_compiler_rv64_static.S PROPERTY LANGUAGE C)
|
||||
@@ -103,9 +105,14 @@ if (WITH_RANDOMX)
|
||||
if (RVARCH_ZBB)
|
||||
set(RV64_VECTOR_FILE_ARCH "${RV64_VECTOR_FILE_ARCH}_zbb")
|
||||
endif()
|
||||
if (RVARCH_ZVKB)
|
||||
set(RV64_VECTOR_FILE_ARCH "${RV64_VECTOR_FILE_ARCH}_zvkb")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_source_files_properties(src/crypto/randomx/jit_compiler_rv64_vector_static.S PROPERTIES COMPILE_FLAGS "-march=${RV64_VECTOR_FILE_ARCH}")
|
||||
set_source_files_properties(src/crypto/randomx/jit_compiler_rv64_vector_static.S PROPERTIES COMPILE_FLAGS "-march=${RV64_VECTOR_FILE_ARCH}_zvkned")
|
||||
set_source_files_properties(src/crypto/randomx/aes_hash_rv64_vector.cpp PROPERTIES COMPILE_FLAGS "-O3 -march=${RV64_VECTOR_FILE_ARCH}")
|
||||
set_source_files_properties(src/crypto/randomx/aes_hash_rv64_zvkned.cpp PROPERTIES COMPILE_FLAGS "-O3 -march=${RV64_VECTOR_FILE_ARCH}_zvkned")
|
||||
else()
|
||||
list(APPEND SOURCES_CRYPTO
|
||||
src/crypto/randomx/jit_compiler_fallback.cpp
|
||||
@@ -183,6 +190,15 @@ if (WITH_RANDOMX)
|
||||
list(APPEND HEADERS_CRYPTO src/crypto/rx/Profiler.h)
|
||||
list(APPEND SOURCES_CRYPTO src/crypto/rx/Profiler.cpp)
|
||||
endif()
|
||||
|
||||
if (WITH_VAES)
|
||||
set(SOURCES_CRYPTO "${SOURCES_CRYPTO}" src/crypto/randomx/aes_hash_vaes512.cpp)
|
||||
if (CMAKE_C_COMPILER_ID MATCHES MSVC)
|
||||
set_source_files_properties(src/crypto/randomx/aes_hash_vaes512.cpp PROPERTIES COMPILE_FLAGS "/arch:AVX512")
|
||||
elseif (CMAKE_C_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
|
||||
set_source_files_properties(src/crypto/randomx/aes_hash_vaes512.cpp PROPERTIES COMPILE_FLAGS "-mavx512f -mvaes")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
remove_definitions(/DXMRIG_ALGO_RANDOMX)
|
||||
endif()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# HTTP API
|
||||
|
||||
If you want use HTTP API you need enable it (`"enabled": true,`) then choice `port` and optionaly `host`. API not available if miner built without HTTP support (`-DWITH_HTTP=OFF`).
|
||||
If you want use HTTP API you need enable it (`"enabled": true,`) then choice `port` and optionally `host`. API not available if miner built without HTTP support (`-DWITH_HTTP=OFF`).
|
||||
|
||||
Offical HTTP client for API: http://workers.xmrig.info/
|
||||
Official HTTP client for API: http://workers.xmrig.info/
|
||||
|
||||
Example configuration:
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Double check that you see `Huge pages 100%` both for dataset and for all threads
|
||||
|
||||
### Benchmark with custom config
|
||||
|
||||
You can run benchmark with any configuration you want. Just start without command line parameteres, use regular config.json and add `"benchmark":"1M",` on the next line after pool url.
|
||||
You can run benchmark with any configuration you want. Just start without command line parameters, use regular config.json and add `"benchmark":"1M",` on the next line after pool url.
|
||||
|
||||
# Stress test
|
||||
|
||||
@@ -26,4 +26,4 @@ You can also run continuous stress-test that is as close to the real RandomX min
|
||||
xmrig --stress
|
||||
xmrig --stress -a rx/wow
|
||||
```
|
||||
This will require Internet connection and will run indefinitely.
|
||||
This will require Internet connection and will run indefinitely.
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
# v4.0.0-beta
|
||||
- [#1172](https://github.com/xmrig/xmrig/issues/1172) **Added OpenCL mining backend.**
|
||||
- [#268](https://github.com/xmrig/xmrig-amd/pull/268) [#270](https://github.com/xmrig/xmrig-amd/pull/270) [#271](https://github.com/xmrig/xmrig-amd/pull/271) [#273](https://github.com/xmrig/xmrig-amd/pull/273) [#274](https://github.com/xmrig/xmrig-amd/pull/274) [#1171](https://github.com/xmrig/xmrig/pull/1171) Added RandomX support for OpenCL, thanks [@SChernykh](https://github.com/SChernykh).
|
||||
- Algorithm `cn/wow` removed, as no longer alive.
|
||||
- Algorithm `cn/wow` removed, as no longer alive.
|
||||
|
||||
# v3.2.0
|
||||
- Added per pool option `coin` with single possible value `monero` for pools without algorithm negotiation, for upcoming Monero fork.
|
||||
@@ -103,7 +103,7 @@
|
||||
- [#1105](https://github.com/xmrig/xmrig/issues/1105) Improved auto configuration for `cn-pico` algorithm.
|
||||
- Added commands `pause` and `resume` via JSON RPC 2.0 API (`POST /json_rpc`).
|
||||
- Added command line option `--export-topology` for export hwloc topology to a XML file.
|
||||
- Breaked backward compatibility with previous configs and command line, `variant` option replaced to `algo`, global option `algo` removed, all CPU related settings moved to `cpu` object.
|
||||
- Broken backward compatibility with previous configs and command line, `variant` option replaced to `algo`, global option `algo` removed, all CPU related settings moved to `cpu` object.
|
||||
- Options `av`, `safe` and `max-cpu-usage` removed.
|
||||
- Algorithm `cn/msr` renamed to `cn/fast`.
|
||||
- Algorithm `cn/xtl` removed.
|
||||
@@ -122,7 +122,7 @@
|
||||
- [#1092](https://github.com/xmrig/xmrig/issues/1092) Fixed crash if wrong CPU affinity used.
|
||||
- [#1103](https://github.com/xmrig/xmrig/issues/1103) Improved auto configuration for RandomX for CPUs where L2 cache is limiting factor.
|
||||
- [#1105](https://github.com/xmrig/xmrig/issues/1105) Improved auto configuration for `cn-pico` algorithm.
|
||||
- [#1106](https://github.com/xmrig/xmrig/issues/1106) Fixed `hugepages` field in summary API.
|
||||
- [#1106](https://github.com/xmrig/xmrig/issues/1106) Fixed `hugepages` field in summary API.
|
||||
- Added alternative short format for CPU threads.
|
||||
- Changed format for CPU threads with intensity above 1.
|
||||
- Name for reference RandomX configuration changed to `rx/test` to avoid potential conflicts in future.
|
||||
@@ -150,7 +150,7 @@
|
||||
- [#1050](https://github.com/xmrig/xmrig/pull/1050) Added RandomXL algorithm for [Loki](https://loki.network/), algorithm name used by miner is `randomx/loki` or `rx/loki`.
|
||||
- Added [flexible](https://github.com/xmrig/xmrig/blob/evo/doc/CPU.md) multi algorithm configuration.
|
||||
- Added unlimited switching between incompatible algorithms, all mining options can be changed in runtime.
|
||||
- Breaked backward compatibility with previous configs and command line, `variant` option replaced to `algo`, global option `algo` removed, all CPU related settings moved to `cpu` object.
|
||||
- Broken backward compatibility with previous configs and command line, `variant` option replaced to `algo`, global option `algo` removed, all CPU related settings moved to `cpu` object.
|
||||
- Options `av`, `safe` and `max-cpu-usage` removed.
|
||||
- Algorithm `cn/msr` renamed to `cn/fast`.
|
||||
- Algorithm `cn/xtl` removed.
|
||||
@@ -183,7 +183,7 @@
|
||||
- [#314](https://github.com/xmrig/xmrig-proxy/issues/314) Added donate over proxy feature.
|
||||
- Added new option `donate-over-proxy`.
|
||||
- Added real graceful exit.
|
||||
|
||||
|
||||
# v2.14.4
|
||||
- [#992](https://github.com/xmrig/xmrig/pull/992) Fixed compilation with Clang 3.5.
|
||||
- [#1012](https://github.com/xmrig/xmrig/pull/1012) Fixed compilation with Clang 9.0.
|
||||
@@ -250,7 +250,7 @@
|
||||
# v2.8.1
|
||||
- [#768](https://github.com/xmrig/xmrig/issues/768) Fixed build with Visual Studio 2015.
|
||||
- [#769](https://github.com/xmrig/xmrig/issues/769) Fixed regression, some ANSI escape sequences was in log with disabled colors.
|
||||
- [#777](https://github.com/xmrig/xmrig/issues/777) Better report about pool connection issues.
|
||||
- [#777](https://github.com/xmrig/xmrig/issues/777) Better report about pool connection issues.
|
||||
- Simplified checks for ASM auto detection, only AES support necessary.
|
||||
- Added missing options to `--help` output.
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
- Added global and per thread option `"asm"` and command line equivalent.
|
||||
- **[#758](https://github.com/xmrig/xmrig/issues/758) Added SSL/TLS support for secure connections to pools.**
|
||||
- Added per pool options `"tls"` and `"tls-fingerprint"` and command line equivalents.
|
||||
- [#767](https://github.com/xmrig/xmrig/issues/767) Added config autosave feature, same with GPU miners.
|
||||
- [#767](https://github.com/xmrig/xmrig/issues/767) Added config autosave feature, same with GPU miners.
|
||||
- [#245](https://github.com/xmrig/xmrig-proxy/issues/245) Fixed API ID collision when run multiple miners on same machine.
|
||||
- [#757](https://github.com/xmrig/xmrig/issues/757) Fixed send buffer overflow.
|
||||
|
||||
@@ -346,7 +346,7 @@
|
||||
|
||||
# v2.4.4
|
||||
- Added libmicrohttpd version to --version output.
|
||||
- Fixed bug in singal handler, in some cases miner wasn't shutdown properly.
|
||||
- Fixed bug in signal handler, in some cases miner wasn't shutdown properly.
|
||||
- Fixed recent MSVC 2017 version detection.
|
||||
- [#279](https://github.com/xmrig/xmrig/pull/279) Fixed build on some macOS versions.
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
# v2.4.2
|
||||
- [#60](https://github.com/xmrig/xmrig/issues/60) Added FreeBSD support, thanks [vcambur](https://github.com/vcambur).
|
||||
- [#153](https://github.com/xmrig/xmrig/issues/153) Fixed issues with dwarfpool.com.
|
||||
|
||||
|
||||
# v2.4.1
|
||||
- [#147](https://github.com/xmrig/xmrig/issues/147) Fixed comparability with monero-stratum.
|
||||
|
||||
@@ -371,7 +371,7 @@
|
||||
- [#101](https://github.com/xmrig/xmrig/issues/101) Fixed MSVC 2017 (15.3) compile time version detection.
|
||||
- [#108](https://github.com/xmrig/xmrig/issues/108) Silently ignore invalid values for `donate-level` option.
|
||||
- [#111](https://github.com/xmrig/xmrig/issues/111) Fixed build without AEON support.
|
||||
|
||||
|
||||
# v2.3.1
|
||||
- [#68](https://github.com/xmrig/xmrig/issues/68) Fixed compatibility with Docker containers, was nothing print on console.
|
||||
|
||||
@@ -398,7 +398,7 @@
|
||||
# v2.1.0
|
||||
- [#40](https://github.com/xmrig/xmrig/issues/40)
|
||||
Improved miner shutdown, fixed crash on exit for Linux and OS X.
|
||||
- Fixed, login request was contain malformed JSON if username or password has some special characters for example `\`.
|
||||
- Fixed, login request was contain malformed JSON if username or password has some special characters for example `\`.
|
||||
- [#220](https://github.com/fireice-uk/xmr-stak-cpu/pull/220) Better support for Round Robin DNS, IP address now always chosen randomly instead of stuck on first one.
|
||||
- Changed donation address, new [xmrig-proxy](https://github.com/xmrig/xmrig-proxy) is coming soon.
|
||||
|
||||
@@ -418,16 +418,16 @@ Improved miner shutdown, fixed crash on exit for Linux and OS X.
|
||||
- Fixed Windows XP support.
|
||||
- Fixed regression, option `--no-color` was not fully disable colored output.
|
||||
- Show resolved pool IP address in miner output.
|
||||
|
||||
|
||||
# v1.0.1
|
||||
- Fix broken software AES implementation, app has crashed if CPU not support AES-NI, only version 1.0.0 affected.
|
||||
|
||||
# v1.0.0
|
||||
- Miner complete rewritten in C++ with libuv.
|
||||
- This version should be fully compatible (except config file) with previos versions, many new nice features will come in next versions.
|
||||
- This is still beta. If you found regression, stability or perfomance issues or have an idea for new feature please fell free to open new [issue](https://github.com/xmrig/xmrig/issues/new).
|
||||
- This version should be fully compatible (except config file) with previous versions, many new nice features will come in next versions.
|
||||
- This is still beta. If you found regression, stability or performance issues or have an idea for new feature please fell free to open new [issue](https://github.com/xmrig/xmrig/issues/new).
|
||||
- Added new option `--print-time=N`, print hashrate report every N seconds.
|
||||
- New hashrate reports, by default every 60 secons.
|
||||
- New hashrate reports, by default every 60 seconds.
|
||||
- Added Microsoft Visual C++ 2015 and 2017 support.
|
||||
- Removed dependency on libcurl.
|
||||
- To compile this version from source please switch to [dev](https://github.com/xmrig/xmrig/tree/dev) branch.
|
||||
@@ -440,7 +440,7 @@ Improved miner shutdown, fixed crash on exit for Linux and OS X.
|
||||
- Fixed gcc 7.1 support.
|
||||
|
||||
# v0.8.1
|
||||
- Added nicehash support, detects automaticaly by pool URL, for example `cryptonight.eu.nicehash.com:3355` or manually via option `--nicehash`.
|
||||
- Added nicehash support, detects automatically by pool URL, for example `cryptonight.eu.nicehash.com:3355` or manually via option `--nicehash`.
|
||||
|
||||
# v0.8.0
|
||||
- Added double hash mode, also known as lower power mode. `--av=2` and `--av=4`.
|
||||
|
||||
@@ -124,7 +124,7 @@ Force enable (`true`) or disable (`false`) hardware AES support. Default value `
|
||||
Mining threads priority, value from `1` (lowest priority) to `5` (highest possible priority). Default value `null` means miner don't change threads priority at all. Setting priority higher than 2 can make your PC unresponsive.
|
||||
|
||||
#### `memory-pool` (since v4.3.0)
|
||||
Use continuous, persistent memory block for mining threads, useful for preserve huge pages allocation while algorithm switching. Possible values `false` (feature disabled, by default) or `true` or specific count of 2 MB huge pages. It helps to avoid loosing huge pages for scratchpads when RandomX dataset is updated and mining threads restart after a 2-3 days of mining.
|
||||
Use continuous, persistent memory block for mining threads, useful for preserve huge pages allocation while algorithm switching. Possible values `false` (feature disabled, by default) or `true` or specific count of 2 MB huge pages. It helps to avoid losing huge pages for scratchpads when RandomX dataset is updated and mining threads restart after a 2-3 days of mining.
|
||||
|
||||
#### `yield` (since v5.1.1)
|
||||
Prefer system better system response/stability `true` (default value) or maximum hashrate `false`.
|
||||
@@ -133,7 +133,7 @@ Prefer system better system response/stability `true` (default value) or maximum
|
||||
Enable/configure or disable ASM optimizations. Possible values: `true`, `false`, `"intel"`, `"ryzen"`, `"bulldozer"`.
|
||||
|
||||
#### `argon2-impl` (since v3.1.0)
|
||||
Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. This is used in RandomX dataset initialization and also in some other mining algorithms. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards - if your CPU doesn't support required instuctions, miner will crash.
|
||||
Allow override automatically detected Argon2 implementation, this option added mostly for debug purposes, default value `null` means autodetect. This is used in RandomX dataset initialization and also in some other mining algorithms. Other possible values: `"x86_64"`, `"SSE2"`, `"SSSE3"`, `"XOP"`, `"AVX2"`, `"AVX-512F"`. Manual selection has no safe guards - if your CPU doesn't support required instructions, miner will crash.
|
||||
|
||||
#### `astrobwt-max-size`
|
||||
AstroBWT algorithm: skip hashes with large stage 2 size, default: `550`, min: `400`, max: `1200`. Optimal value depends on your CPU/GPU
|
||||
|
||||
@@ -48,6 +48,24 @@ static const std::map<int, std::map<uint32_t, uint64_t> > hashCheck = {
|
||||
{ 9000000U, 0x323935102AB6B45CULL },
|
||||
{ 10000000U, 0xB5231262E2792B26ULL }
|
||||
}},
|
||||
{ Algorithm::RX_V2, {
|
||||
# ifndef NDEBUG
|
||||
{ 10000U, 0x57d2051d099613a4ULL },
|
||||
{ 20000U, 0x0bae0155cc797f01ULL },
|
||||
# endif
|
||||
{ 250000U, 0x18cf741a71484072ULL },
|
||||
{ 500000U, 0xcd8c3e6ec31b2faeULL },
|
||||
{ 1000000U, 0x88d6b8fb70cd479dULL },
|
||||
{ 2000000U, 0x0e16828d236a1a63ULL },
|
||||
{ 3000000U, 0x2739bdd0f25b83a6ULL },
|
||||
{ 4000000U, 0x32f42d9006d2d34bULL },
|
||||
{ 5000000U, 0x16d9c6286cb82251ULL },
|
||||
{ 6000000U, 0x1f916ae19d6bcf07ULL },
|
||||
{ 7000000U, 0x1f474f99a873948fULL },
|
||||
{ 8000000U, 0x8d67e0ddf05476bbULL },
|
||||
{ 9000000U, 0x3ebf37dcd5c4a215ULL },
|
||||
{ 10000000U, 0x7efbddff3f30fb74ULL }
|
||||
}},
|
||||
{ Algorithm::RX_WOW, {
|
||||
# ifndef NDEBUG
|
||||
{ 10000U, 0x6B0918757100B338ULL },
|
||||
@@ -88,6 +106,24 @@ static const std::map<int, std::map<uint32_t, uint64_t> > hashCheck1T = {
|
||||
{ 9000000U, 0xC6D39EF59213A07CULL },
|
||||
{ 10000000U, 0x95E6BAE68DD779CDULL }
|
||||
}},
|
||||
{ Algorithm::RX_V2, {
|
||||
# ifndef NDEBUG
|
||||
{ 10000, 0x90eb7c07cd9e0d90ULL },
|
||||
{ 20000, 0x6523a3658d7d9930ULL },
|
||||
# endif
|
||||
{ 250000, 0xf83b6d9d355ee5b1ULL },
|
||||
{ 500000, 0xbea3c1bf1465e9abULL },
|
||||
{ 1000000, 0x9e16f7cb56b366e1ULL },
|
||||
{ 2000000, 0x3b5e671f47e15e55ULL },
|
||||
{ 3000000, 0xec5819c180df03e2ULL },
|
||||
{ 4000000, 0x19d31b498f86aad4ULL },
|
||||
{ 5000000, 0x2487626c75cd12ccULL },
|
||||
{ 6000000, 0xa323a25a5286c39aULL },
|
||||
{ 7000000, 0xa123b100f3104dfcULL },
|
||||
{ 8000000, 0x602db9d83bfa0ddcULL },
|
||||
{ 9000000, 0x98da909e579765ddULL },
|
||||
{ 10000000, 0x3a45b7247cec9895ULL }
|
||||
}},
|
||||
{ Algorithm::RX_WOW, {
|
||||
# ifndef NDEBUG
|
||||
{ 10000U, 0x9EC1B9B8C8C7F082ULL },
|
||||
|
||||
@@ -256,7 +256,10 @@ void xmrig::CpuWorker<N>::start()
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
bool first = true;
|
||||
alignas(16) uint64_t tempHash[8] = {};
|
||||
alignas(64) uint64_t tempHash[8] = {};
|
||||
|
||||
size_t prev_job_size = 0;
|
||||
alignas(64) uint8_t prev_job[Job::kMaxBlobSize] = {};
|
||||
# endif
|
||||
|
||||
while (!Nonce::isOutdated(Nonce::CPU, m_job.sequence())) {
|
||||
@@ -297,6 +300,11 @@ void xmrig::CpuWorker<N>::start()
|
||||
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
|
||||
}
|
||||
randomx_calculate_hash_first(m_vm, tempHash, m_job.blob(), job.size());
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_COMMITMENT) {
|
||||
prev_job_size = job.size();
|
||||
memcpy(prev_job, m_job.blob(), prev_job_size);
|
||||
}
|
||||
}
|
||||
|
||||
if (!nextRound()) {
|
||||
@@ -307,7 +315,15 @@ void xmrig::CpuWorker<N>::start()
|
||||
memcpy(miner_signature_saved, miner_signature_ptr, sizeof(miner_signature_saved));
|
||||
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
|
||||
}
|
||||
|
||||
randomx_calculate_hash_next(m_vm, tempHash, m_job.blob(), job.size(), m_hash);
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_COMMITMENT) {
|
||||
memcpy(m_commitment, m_hash, RANDOMX_HASH_SIZE);
|
||||
randomx_calculate_commitment(prev_job, prev_job_size, m_hash, m_hash);
|
||||
prev_job_size = job.size();
|
||||
memcpy(prev_job, m_job.blob(), prev_job_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
# endif
|
||||
@@ -347,8 +363,20 @@ void xmrig::CpuWorker<N>::start()
|
||||
}
|
||||
else
|
||||
# endif
|
||||
|
||||
if (value < job.target()) {
|
||||
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32), job.hasMinerSignature() ? miner_signature_saved : nullptr);
|
||||
uint8_t* extra_data = nullptr;
|
||||
|
||||
if (job.algorithm().family() == Algorithm::RANDOM_X) {
|
||||
if (RandomX_CurrentConfig.Tweak_V2_COMMITMENT) {
|
||||
extra_data = m_commitment;
|
||||
}
|
||||
else if (job.hasMinerSignature()) {
|
||||
extra_data = miner_signature_saved;
|
||||
}
|
||||
}
|
||||
|
||||
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32), extra_data);
|
||||
}
|
||||
}
|
||||
m_count += N;
|
||||
|
||||
@@ -83,6 +83,7 @@ private:
|
||||
void allocateCnCtx();
|
||||
void consumeJob();
|
||||
|
||||
alignas(8) uint8_t m_commitment[N * 32]{ 0 };
|
||||
alignas(8) uint8_t m_hash[N * 32]{ 0 };
|
||||
const Algorithm m_algorithm;
|
||||
const Assembly m_assembly;
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace xmrig {
|
||||
|
||||
extern String cpu_name_riscv();
|
||||
extern bool has_riscv_vector();
|
||||
extern bool has_riscv_crypto();
|
||||
extern bool has_riscv_aes();
|
||||
|
||||
|
||||
} // namespace xmrig
|
||||
@@ -58,8 +58,8 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
|
||||
// Check for vector extensions
|
||||
m_flags.set(FLAG_RISCV_VECTOR, has_riscv_vector());
|
||||
|
||||
// Check for crypto extensions (Zknd/Zkne/Zknh - AES and SHA)
|
||||
m_flags.set(FLAG_AES, has_riscv_crypto());
|
||||
// Check for AES extensions (Zknd/Zkne)
|
||||
m_flags.set(FLAG_AES, has_riscv_aes());
|
||||
|
||||
// RISC-V typically supports 1GB huge pages
|
||||
m_flags.set(FLAG_PDPE1GB, std::ifstream("/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages").good());
|
||||
|
||||
@@ -32,7 +32,7 @@ struct riscv_cpu_desc
|
||||
String isa;
|
||||
String uarch;
|
||||
bool has_vector = false;
|
||||
bool has_crypto = false;
|
||||
bool has_aes = false;
|
||||
|
||||
inline bool isReady() const { return !isa.isNull(); }
|
||||
};
|
||||
@@ -81,16 +81,26 @@ static bool read_riscv_cpuinfo(riscv_cpu_desc *desc)
|
||||
lookup_riscv(buf, "model name", desc->model);
|
||||
|
||||
if (lookup_riscv(buf, "isa", desc->isa)) {
|
||||
// Check for vector extensions
|
||||
if (strstr(buf, "zve64d") || strstr(buf, "v_")) {
|
||||
desc->has_vector = true;
|
||||
}
|
||||
// Check for crypto extensions (AES, SHA, etc.)
|
||||
// zkn* = NIST crypto suite, zks* = SM crypto suite
|
||||
// Note: zba/zbb/zbc/zbs are bit-manipulation, NOT crypto
|
||||
if (strstr(buf, "zknd") || strstr(buf, "zkne") || strstr(buf, "zknh") ||
|
||||
strstr(buf, "zksed") || strstr(buf, "zksh")) {
|
||||
desc->has_crypto = true;
|
||||
desc->isa.toLower();
|
||||
|
||||
for (const String& s : desc->isa.split('_')) {
|
||||
const char* p = s.data();
|
||||
const size_t n = s.size();
|
||||
|
||||
if ((s.size() > 4) && (memcmp(p, "rv64", 4) == 0)) {
|
||||
for (size_t i = 4; i < n; ++i) {
|
||||
if (p[i] == 'v') {
|
||||
desc->has_vector = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (s == "zve64d") {
|
||||
desc->has_vector = true;
|
||||
}
|
||||
else if ((s == "zvkn") || (s == "zvknc") || (s == "zvkned") || (s == "zvkng")){
|
||||
desc->has_aes = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,11 +138,11 @@ bool has_riscv_vector()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_riscv_crypto()
|
||||
bool has_riscv_aes()
|
||||
{
|
||||
riscv_cpu_desc desc;
|
||||
if (read_riscv_cpuinfo(&desc)) {
|
||||
return desc.has_crypto;
|
||||
return desc.has_aes;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define ALGO_CN_PICO_TLO 0x63120274
|
||||
#define ALGO_CN_UPX2 0x63110200
|
||||
#define ALGO_RX_0 0x72151200
|
||||
#define ALGO_RX_V2 0x72151202
|
||||
#define ALGO_RX_WOW 0x72141177
|
||||
#define ALGO_RX_ARQMA 0x72121061
|
||||
#define ALGO_RX_SFX 0x72151273
|
||||
|
||||
@@ -706,7 +706,7 @@ __kernel void cn2(__global uint4 *Scratchpad, __global ulong *states, __global u
|
||||
}
|
||||
|
||||
# if (ALGO_FAMILY == FAMILY_CN_HEAVY)
|
||||
/* Also left over threads performe this loop.
|
||||
/* Also left over threads perform this loop.
|
||||
* The left over thread results will be ignored
|
||||
*/
|
||||
#pragma unroll 16
|
||||
@@ -1005,7 +1005,7 @@ __kernel void Groestl(__global ulong *states, __global uint *BranchBuf, __global
|
||||
ulong State[8] = { 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0x0001000000000000UL };
|
||||
ulong H[8], M[8];
|
||||
|
||||
// BUG: AMD driver 19.7.X crashs if this is written as loop
|
||||
// BUG: AMD driver 19.7.X crashes if this is written as loop
|
||||
// Thx AMD for so bad software
|
||||
{
|
||||
((ulong8 *)M)[0] = vload8(0, states);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,7 +10,7 @@
|
||||
#else
|
||||
# define STATIC
|
||||
/* taken from https://www.khronos.org/registry/OpenCL/extensions/amd/cl_amd_media_ops.txt
|
||||
* Build-in Function
|
||||
* Built-in Function
|
||||
* uintn amd_bitalign (uintn src0, uintn src1, uintn src2)
|
||||
* Description
|
||||
* dst.s0 = (uint) (((((long)src0.s0) << 32) | (long)src1.s0) >> (src2.s0 & 31))
|
||||
|
||||
@@ -74,10 +74,10 @@ void keccak_f800_round(uint32_t st[25], const int r)
|
||||
// Keccak - implemented as a variant of SHAKE
|
||||
// The width is 800, with a bitrate of 576, a capacity of 224, and no padding
|
||||
// Only need 64 bits of output for mining
|
||||
void keccak_f800(uint32_t* st)
|
||||
void keccak_f800(uint32_t st[25])
|
||||
{
|
||||
// Complete all 22 rounds as a separate impl to
|
||||
// evaluate only first 8 words is wasteful of regsters
|
||||
// evaluate only first 8 words is wasteful of registers
|
||||
for (int r = 0; r < 22; r++) {
|
||||
keccak_f800_round(st, r);
|
||||
}
|
||||
@@ -181,7 +181,7 @@ __kernel void progpow_search(__global dag_t const* g_dag, __global uint* job_blo
|
||||
for (int i = 10; i < 25; i++)
|
||||
state[i] = ravencoin_rndc[i-10];
|
||||
|
||||
// Run intial keccak round
|
||||
// Run initial keccak round
|
||||
keccak_f800(state);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
static const char kawpow_cl[5944] = {
|
||||
static const char kawpow_cl[5947] = {
|
||||
0x23,0x69,0x66,0x64,0x65,0x66,0x20,0x63,0x6c,0x5f,0x63,0x6c,0x61,0x6e,0x67,0x5f,0x73,0x74,0x6f,0x72,0x61,0x67,0x65,0x5f,0x63,0x6c,0x61,0x73,0x73,0x5f,0x73,0x70,
|
||||
0x65,0x63,0x69,0x66,0x69,0x65,0x72,0x73,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,0x20,0x45,0x58,0x54,0x45,0x4e,0x53,0x49,0x4f,
|
||||
0x4e,0x20,0x63,0x6c,0x5f,0x63,0x6c,0x61,0x6e,0x67,0x5f,0x73,0x74,0x6f,0x72,0x61,0x67,0x65,0x5f,0x63,0x6c,0x61,0x73,0x73,0x5f,0x73,0x70,0x65,0x63,0x69,0x66,0x69,
|
||||
@@ -77,118 +77,118 @@ static const char kawpow_cl[5944] = {
|
||||
0x29,0x0a,0x73,0x74,0x5b,0x6a,0x2b,0x69,0x5d,0x20,0x5e,0x3d,0x20,0x28,0x7e,0x62,0x63,0x5b,0x28,0x69,0x2b,0x31,0x29,0x20,0x25,0x20,0x35,0x5d,0x29,0x26,0x62,0x63,
|
||||
0x5b,0x28,0x69,0x2b,0x32,0x29,0x20,0x25,0x20,0x35,0x5d,0x3b,0x0a,0x7d,0x0a,0x73,0x74,0x5b,0x30,0x5d,0x20,0x5e,0x3d,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x66,0x5f,
|
||||
0x72,0x6e,0x64,0x63,0x5b,0x72,0x5d,0x3b,0x0a,0x7d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,0x75,0x69,0x6e,0x74,
|
||||
0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x72,0x3d,0x30,0x3b,0x20,0x72,0x3c,0x32,0x32,0x3b,0x20,
|
||||
0x72,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x73,0x74,0x2c,0x72,0x29,0x3b,0x0a,
|
||||
0x7d,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x66,0x6e,0x76,0x31,0x61,0x28,0x68,0x2c,0x20,0x64,0x29,0x20,0x28,0x68,0x20,0x3d,0x20,0x28,0x68,0x20,
|
||||
0x5e,0x20,0x64,0x29,0x20,0x2a,0x20,0x46,0x4e,0x56,0x5f,0x50,0x52,0x49,0x4d,0x45,0x29,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,
|
||||
0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x7a,0x2c,0x77,0x2c,0x6a,0x73,0x72,0x2c,0x6a,0x63,0x6f,0x6e,0x67,0x3b,0x0a,0x7d,0x20,0x6b,0x69,0x73,
|
||||
0x73,0x39,0x39,0x5f,0x74,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6b,0x69,0x73,0x73,0x39,0x39,0x28,0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74,0x2a,
|
||||
0x20,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x73,0x74,0x2d,0x3e,0x7a,0x3d,0x33,0x36,0x39,0x36,0x39,0x2a,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x26,0x36,0x35,0x35,0x33,0x35,0x29,
|
||||
0x2b,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x77,0x3d,0x31,0x38,0x30,0x30,0x30,0x2a,0x28,0x73,0x74,0x2d,0x3e,0x77,
|
||||
0x26,0x36,0x35,0x35,0x33,0x35,0x29,0x2b,0x28,0x73,0x74,0x2d,0x3e,0x77,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x4d,0x57,
|
||||
0x43,0x3d,0x28,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3c,0x3c,0x31,0x36,0x29,0x2b,0x73,0x74,0x2d,0x3e,0x77,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,
|
||||
0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3c,0x3c,0x31,0x37,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,
|
||||
0x3e,0x6a,0x73,0x72,0x3e,0x3e,0x31,0x33,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3c,0x3c,
|
||||
0x35,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x36,0x39,0x30,0x36,0x39,0x2a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x2b,0x31,0x32,
|
||||
0x33,0x34,0x35,0x36,0x37,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x28,0x4d,0x57,0x43,0x5e,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x29,0x2b,0x73,
|
||||
0x74,0x2d,0x3e,0x6a,0x73,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,
|
||||
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x65,0x65,0x64,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x2c,0x75,
|
||||
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6d,0x69,0x78,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,
|
||||
0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74,0x20,0x73,0x74,0x3b,
|
||||
0x0a,0x73,0x74,0x2e,0x7a,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x30,0x5d,0x29,0x3b,0x0a,0x73,
|
||||
0x74,0x2e,0x77,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x31,0x5d,0x29,0x3b,0x0a,0x73,0x74,0x2e,
|
||||
0x6a,0x73,0x72,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x3b,0x0a,0x73,0x74,0x2e,
|
||||
0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x3b,0x0a,0x23,
|
||||
0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,
|
||||
0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x6d,0x69,0x78,0x5b,0x69,0x5d,0x3d,0x6b,0x69,0x73,0x73,0x39,0x39,0x28,0x26,
|
||||
0x73,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
|
||||
0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x5d,0x3b,0x0a,0x7d,0x20,0x73,0x68,0x75,0x66,0x66,
|
||||
0x6c,0x65,0x5f,0x74,0x3b,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
|
||||
0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x33,0x32,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x5d,0x3b,0x0a,0x7d,0x20,
|
||||
0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x3b,0x0a,0x23,0x69,0x66,0x20,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x20,0x21,0x3d,0x20,0x4f,0x50,0x45,0x4e,0x43,0x4c,
|
||||
0x5f,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x5f,0x4e,0x56,0x49,0x44,0x49,0x41,0x20,0x0a,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x5f,0x5f,0x28,
|
||||
0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,
|
||||
0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,0x70,0x72,0x6f,
|
||||
0x67,0x70,0x6f,0x77,0x5f,0x73,0x65,0x61,0x72,0x63,0x68,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x64,0x61,0x67,0x5f,0x74,0x20,0x63,0x6f,0x6e,0x73,0x74,
|
||||
0x2a,0x20,0x67,0x5f,0x64,0x61,0x67,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x6a,0x6f,0x62,0x5f,0x62,0x6c,0x6f,0x62,0x2c,
|
||||
0x75,0x6c,0x6f,0x6e,0x67,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2c,0x75,0x69,0x6e,0x74,0x20,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x2c,0x76,0x6f,0x6c,
|
||||
0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x2c,0x76,0x6f,0x6c,
|
||||
0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x73,0x74,0x6f,0x70,0x29,0x0a,0x7b,0x0a,0x63,0x6f,0x6e,
|
||||
0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,
|
||||
0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,
|
||||
0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x73,0x74,0x6f,0x70,0x5b,0x30,0x5d,0x29,0x20,0x7b,0x0a,0x69,0x66,0x28,0x6c,0x69,0x64,0x3d,0x3d,0x30,0x29,0x20,0x7b,
|
||||
0x0a,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x73,0x74,0x6f,0x70,0x2b,0x31,0x29,0x3b,0x0a,0x7d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,
|
||||
0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x68,0x75,0x66,0x66,0x6c,0x65,0x5f,0x74,0x20,0x73,0x68,0x61,0x72,0x65,0x5b,0x48,0x41,0x53,0x48,0x45,0x53,0x5f,
|
||||
0x50,0x45,0x52,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x63,0x5f,0x64,
|
||||
0x61,0x67,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,
|
||||
0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x6c,0x69,0x64,0x26,0x28,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,
|
||||
0x45,0x53,0x2d,0x31,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x3d,0x6c,
|
||||
0x69,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
|
||||
0x77,0x6f,0x72,0x64,0x3d,0x6c,0x69,0x64,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20,0x77,0x6f,0x72,0x64,
|
||||
0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x3b,0x20,0x77,0x6f,0x72,0x64,0x2b,0x3d,0x47,0x52,0x4f,0x55,
|
||||
0x50,0x5f,0x53,0x49,0x5a,0x45,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x29,0x0a,0x7b,0x0a,0x64,0x61,0x67,0x5f,
|
||||
0x74,0x20,0x6c,0x6f,0x61,0x64,0x3d,0x67,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,
|
||||
0x41,0x44,0x53,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,
|
||||
0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x63,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2b,0x69,0x5d,0x3d,0x6c,0x6f,0x61,0x64,
|
||||
0x2e,0x73,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x61,0x73,0x68,0x5f,0x73,0x65,0x65,0x64,0x5b,0x32,0x5d,0x3b,0x20,
|
||||
0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x3b,0x20,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,
|
||||
0x65,0x32,0x5b,0x38,0x5d,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,0x65,0x5b,0x32,0x35,0x5d,0x3b,0x20,0x0a,0x66,0x6f,
|
||||
0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x31,0x30,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,
|
||||
0x6a,0x6f,0x62,0x5f,0x62,0x6c,0x6f,0x62,0x5b,0x69,0x5d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x38,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,
|
||||
0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x30,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x72,0x61,
|
||||
0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f,0x72,0x6e,0x64,0x63,0x5b,0x69,0x2d,0x31,0x30,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,
|
||||
0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,
|
||||
0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,
|
||||
0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x3d,0x30,0x3b,0x20,0x68,0x3c,0x50,0x52,0x4f,0x47,
|
||||
0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x68,0x2b,0x2b,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6d,0x69,0x78,0x5b,0x50,
|
||||
0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x68,0x29,0x20,0x7b,0x0a,0x73,
|
||||
0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,
|
||||
0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x31,0x5d,0x3d,
|
||||
0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,
|
||||
0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,
|
||||
0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x2c,0x6d,0x69,0x78,0x29,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,
|
||||
0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x32,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x6f,0x6f,0x70,0x3d,0x30,0x3b,
|
||||
0x20,0x6c,0x6f,0x6f,0x70,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x4e,0x54,0x5f,0x44,0x41,0x47,0x3b,0x20,0x2b,0x2b,0x6c,0x6f,0x6f,0x70,0x29,0x0a,0x7b,
|
||||
0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x28,0x6c,0x6f,0x6f,0x70,0x20,0x25,0x20,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,
|
||||
0x45,0x53,0x29,0x29,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x30,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x3d,
|
||||
0x6d,0x69,0x78,0x5b,0x30,0x5d,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,
|
||||
0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x73,0x68,0x61,0x72,0x65,0x5b,0x30,0x5d,0x2e,0x75,
|
||||
0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x25,0x3d,0x20,0x50,0x52,0x4f,0x47,
|
||||
0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x45,0x4c,0x45,0x4d,0x45,0x4e,0x54,0x53,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x6f,0x66,0x66,0x73,0x65,0x74,0x2a,
|
||||
0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x2b,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x5e,0x6c,0x6f,0x6f,0x70,0x29,0x20,0x25,0x20,0x50,
|
||||
0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x64,0x61,0x67,0x5f,0x74,0x20,0x64,0x61,0x74,0x61,0x5f,0x64,0x61,0x67,0x3d,0x67,0x5f,0x64,
|
||||
0x61,0x67,0x5b,0x6f,0x66,0x66,0x73,0x65,0x74,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62,0x61,0x72,0x72,0x69,
|
||||
0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,
|
||||
0x74,0x20,0x64,0x61,0x74,0x61,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,0x43,0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x41,
|
||||
0x4e,0x44,0x4f,0x4d,0x5f,0x4d,0x41,0x54,0x48,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62,0x61,0x72,0x72,0x69,0x65,0x72,
|
||||
0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,0x43,
|
||||
0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x54,0x41,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,
|
||||
0x5f,0x74,0x20,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x23,0x70,
|
||||
0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,
|
||||
0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66,0x6e,0x76,0x31,0x61,0x28,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6d,
|
||||
0x69,0x78,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x3b,0x0a,0x66,0x6f,
|
||||
0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,
|
||||
0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x73,
|
||||
0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x5d,0x3d,
|
||||
0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,
|
||||
0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,
|
||||
0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66,0x6e,0x76,0x31,0x61,
|
||||
0x28,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x20,0x25,0x20,0x38,0x5d,0x2c,0x73,0x68,0x61,0x72,
|
||||
0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x69,0x66,0x28,0x68,0x3d,0x3d,0x6c,
|
||||
0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74,0x3d,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x3b,0x0a,0x7d,0x0a,0x75,0x69,
|
||||
0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,0x65,0x5b,
|
||||
0x32,0x35,0x5d,0x3d,0x7b,0x30,0x78,0x30,0x7d,0x3b,0x20,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,
|
||||
0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,
|
||||
0x20,0x69,0x3d,0x38,0x3b,0x20,0x69,0x3c,0x31,0x36,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x64,0x69,0x67,0x65,0x73,0x74,
|
||||
0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x2d,0x38,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x36,0x3b,0x20,0x69,0x3c,
|
||||
0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x72,0x61,0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f,0x72,0x6e,0x64,0x63,
|
||||
0x5b,0x69,0x2d,0x31,0x36,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,
|
||||
0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x3d,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x73,0x74,0x61,0x74,0x65,0x5b,0x31,0x5d,0x3c,0x3c,0x33,0x32,0x7c,
|
||||
0x73,0x74,0x61,0x74,0x65,0x5b,0x30,0x5d,0x3b,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x28,0x61,0x73,0x5f,0x75,0x63,0x68,
|
||||
0x61,0x72,0x38,0x28,0x72,0x65,0x73,0x29,0x2e,0x73,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x72,0x65,0x73,0x75,0x6c,0x74,
|
||||
0x3c,0x3d,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x0a,0x7b,0x0a,0x2a,0x73,0x74,0x6f,0x70,0x3d,0x31,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x20,
|
||||
0x6b,0x3d,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x29,0x2b,0x31,0x3b,0x0a,0x69,0x66,0x28,0x6b,0x3c,0x3d,0x31,
|
||||
0x35,0x29,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x6b,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x00
|
||||
0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x5b,0x32,0x35,0x5d,0x29,0x0a,0x7b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x72,0x3d,0x30,0x3b,0x20,0x72,0x3c,0x32,
|
||||
0x32,0x3b,0x20,0x72,0x2b,0x2b,0x29,0x20,0x7b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x5f,0x72,0x6f,0x75,0x6e,0x64,0x28,0x73,0x74,0x2c,0x72,
|
||||
0x29,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x23,0x64,0x65,0x66,0x69,0x6e,0x65,0x20,0x66,0x6e,0x76,0x31,0x61,0x28,0x68,0x2c,0x20,0x64,0x29,0x20,0x28,0x68,0x20,0x3d,0x20,
|
||||
0x28,0x68,0x20,0x5e,0x20,0x64,0x29,0x20,0x2a,0x20,0x46,0x4e,0x56,0x5f,0x50,0x52,0x49,0x4d,0x45,0x29,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,
|
||||
0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x7a,0x2c,0x77,0x2c,0x6a,0x73,0x72,0x2c,0x6a,0x63,0x6f,0x6e,0x67,0x3b,0x0a,0x7d,0x20,
|
||||
0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6b,0x69,0x73,0x73,0x39,0x39,0x28,0x6b,0x69,0x73,0x73,0x39,0x39,
|
||||
0x5f,0x74,0x2a,0x20,0x73,0x74,0x29,0x0a,0x7b,0x0a,0x73,0x74,0x2d,0x3e,0x7a,0x3d,0x33,0x36,0x39,0x36,0x39,0x2a,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x26,0x36,0x35,0x35,
|
||||
0x33,0x35,0x29,0x2b,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x77,0x3d,0x31,0x38,0x30,0x30,0x30,0x2a,0x28,0x73,0x74,
|
||||
0x2d,0x3e,0x77,0x26,0x36,0x35,0x35,0x33,0x35,0x29,0x2b,0x28,0x73,0x74,0x2d,0x3e,0x77,0x3e,0x3e,0x31,0x36,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,
|
||||
0x20,0x4d,0x57,0x43,0x3d,0x28,0x28,0x73,0x74,0x2d,0x3e,0x7a,0x3c,0x3c,0x31,0x36,0x29,0x2b,0x73,0x74,0x2d,0x3e,0x77,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,
|
||||
0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3c,0x3c,0x31,0x37,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,
|
||||
0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x3e,0x3e,0x31,0x33,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x20,0x5e,0x3d,0x20,0x28,0x73,0x74,0x2d,0x3e,0x6a,0x73,
|
||||
0x72,0x3c,0x3c,0x35,0x29,0x3b,0x0a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x36,0x39,0x30,0x36,0x39,0x2a,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,
|
||||
0x2b,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x3b,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x28,0x4d,0x57,0x43,0x5e,0x73,0x74,0x2d,0x3e,0x6a,0x63,0x6f,0x6e,0x67,
|
||||
0x29,0x2b,0x73,0x74,0x2d,0x3e,0x6a,0x73,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x76,0x6f,0x69,0x64,0x20,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x6c,0x6f,0x63,0x61,
|
||||
0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x73,0x65,0x65,0x64,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f,0x69,
|
||||
0x64,0x2c,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x2a,0x20,0x6d,0x69,0x78,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x66,0x6e,0x76,0x5f,
|
||||
0x68,0x61,0x73,0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,0x0a,0x6b,0x69,0x73,0x73,0x39,0x39,0x5f,0x74,0x20,
|
||||
0x73,0x74,0x3b,0x0a,0x73,0x74,0x2e,0x7a,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x30,0x5d,0x29,
|
||||
0x3b,0x0a,0x73,0x74,0x2e,0x77,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x73,0x65,0x65,0x64,0x5b,0x31,0x5d,0x29,0x3b,0x0a,
|
||||
0x73,0x74,0x2e,0x6a,0x73,0x72,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x3b,0x0a,
|
||||
0x73,0x74,0x2e,0x6a,0x63,0x6f,0x6e,0x67,0x3d,0x66,0x6e,0x76,0x31,0x61,0x28,0x66,0x6e,0x76,0x5f,0x68,0x61,0x73,0x68,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,
|
||||
0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,
|
||||
0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x6d,0x69,0x78,0x5b,0x69,0x5d,0x3d,0x6b,0x69,0x73,0x73,0x39,
|
||||
0x39,0x28,0x26,0x73,0x74,0x29,0x3b,0x0a,0x7d,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,
|
||||
0x32,0x5f,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x5d,0x3b,0x0a,0x7d,0x20,0x73,0x68,
|
||||
0x75,0x66,0x66,0x6c,0x65,0x5f,0x74,0x3b,0x0a,0x74,0x79,0x70,0x65,0x64,0x65,0x66,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,
|
||||
0x5f,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x33,0x32,0x2f,0x73,0x69,0x7a,0x65,0x6f,0x66,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x29,0x5d,0x3b,
|
||||
0x0a,0x7d,0x20,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x3b,0x0a,0x23,0x69,0x66,0x20,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x20,0x21,0x3d,0x20,0x4f,0x50,0x45,
|
||||
0x4e,0x43,0x4c,0x5f,0x50,0x4c,0x41,0x54,0x46,0x4f,0x52,0x4d,0x5f,0x4e,0x56,0x49,0x44,0x49,0x41,0x20,0x0a,0x5f,0x5f,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,
|
||||
0x5f,0x5f,0x28,0x28,0x72,0x65,0x71,0x64,0x5f,0x77,0x6f,0x72,0x6b,0x5f,0x67,0x72,0x6f,0x75,0x70,0x5f,0x73,0x69,0x7a,0x65,0x28,0x47,0x52,0x4f,0x55,0x50,0x5f,0x53,
|
||||
0x49,0x5a,0x45,0x2c,0x31,0x2c,0x31,0x29,0x29,0x29,0x0a,0x23,0x65,0x6e,0x64,0x69,0x66,0x0a,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f,0x69,0x64,0x20,
|
||||
0x70,0x72,0x6f,0x67,0x70,0x6f,0x77,0x5f,0x73,0x65,0x61,0x72,0x63,0x68,0x28,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x64,0x61,0x67,0x5f,0x74,0x20,0x63,0x6f,
|
||||
0x6e,0x73,0x74,0x2a,0x20,0x67,0x5f,0x64,0x61,0x67,0x2c,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x6a,0x6f,0x62,0x5f,0x62,0x6c,
|
||||
0x6f,0x62,0x2c,0x75,0x6c,0x6f,0x6e,0x67,0x20,0x74,0x61,0x72,0x67,0x65,0x74,0x2c,0x75,0x69,0x6e,0x74,0x20,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x2c,
|
||||
0x76,0x6f,0x6c,0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x2c,
|
||||
0x76,0x6f,0x6c,0x61,0x74,0x69,0x6c,0x65,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x2a,0x20,0x73,0x74,0x6f,0x70,0x29,0x0a,0x7b,0x0a,
|
||||
0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x69,0x64,0x28,
|
||||
0x30,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x69,0x64,0x3d,0x67,0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,
|
||||
0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b,0x0a,0x69,0x66,0x28,0x73,0x74,0x6f,0x70,0x5b,0x30,0x5d,0x29,0x20,0x7b,0x0a,0x69,0x66,0x28,0x6c,0x69,0x64,0x3d,0x3d,0x30,
|
||||
0x29,0x20,0x7b,0x0a,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x73,0x74,0x6f,0x70,0x2b,0x31,0x29,0x3b,0x0a,0x7d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,
|
||||
0x3b,0x0a,0x7d,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x68,0x75,0x66,0x66,0x6c,0x65,0x5f,0x74,0x20,0x73,0x68,0x61,0x72,0x65,0x5b,0x48,0x41,0x53,0x48,
|
||||
0x45,0x53,0x5f,0x50,0x45,0x52,0x5f,0x47,0x52,0x4f,0x55,0x50,0x5d,0x3b,0x0a,0x5f,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,
|
||||
0x63,0x5f,0x64,0x61,0x67,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x5d,0x3b,0x0a,0x63,0x6f,0x6e,0x73,
|
||||
0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x6c,0x69,0x64,0x26,0x28,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,
|
||||
0x4c,0x41,0x4e,0x45,0x53,0x2d,0x31,0x29,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,
|
||||
0x64,0x3d,0x6c,0x69,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,
|
||||
0x5f,0x74,0x20,0x77,0x6f,0x72,0x64,0x3d,0x6c,0x69,0x64,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20,0x77,
|
||||
0x6f,0x72,0x64,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x41,0x43,0x48,0x45,0x5f,0x57,0x4f,0x52,0x44,0x53,0x3b,0x20,0x77,0x6f,0x72,0x64,0x2b,0x3d,0x47,
|
||||
0x52,0x4f,0x55,0x50,0x5f,0x53,0x49,0x5a,0x45,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x29,0x0a,0x7b,0x0a,0x64,
|
||||
0x61,0x67,0x5f,0x74,0x20,0x6c,0x6f,0x61,0x64,0x3d,0x67,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,
|
||||
0x5f,0x4c,0x4f,0x41,0x44,0x53,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,
|
||||
0x5f,0x44,0x41,0x47,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x63,0x5f,0x64,0x61,0x67,0x5b,0x77,0x6f,0x72,0x64,0x2b,0x69,0x5d,0x3d,0x6c,
|
||||
0x6f,0x61,0x64,0x2e,0x73,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x61,0x73,0x68,0x5f,0x73,0x65,0x65,0x64,0x5b,0x32,
|
||||
0x5d,0x3b,0x20,0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x3b,0x20,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,
|
||||
0x74,0x61,0x74,0x65,0x32,0x5b,0x38,0x5d,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,0x74,0x65,0x5b,0x32,0x35,0x5d,0x3b,0x20,
|
||||
0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x31,0x30,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,
|
||||
0x69,0x5d,0x3d,0x6a,0x6f,0x62,0x5f,0x62,0x6c,0x6f,0x62,0x5b,0x69,0x5d,0x3b,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x38,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x66,0x6f,
|
||||
0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x30,0x3b,0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,
|
||||
0x3d,0x72,0x61,0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f,0x72,0x6e,0x64,0x63,0x5b,0x69,0x2d,0x31,0x30,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,
|
||||
0x30,0x30,0x28,0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,0x2b,
|
||||
0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3b,0x0a,0x7d,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,
|
||||
0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x31,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x68,0x3d,0x30,0x3b,0x20,0x68,0x3c,0x50,
|
||||
0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x68,0x2b,0x2b,0x29,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6d,0x69,
|
||||
0x78,0x5b,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x68,0x29,0x20,
|
||||
0x7b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x30,0x5d,0x3d,0x73,0x74,0x61,
|
||||
0x74,0x65,0x32,0x5b,0x30,0x5d,0x3b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,
|
||||
0x31,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x31,0x5d,0x3b,0x0a,0x7d,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,
|
||||
0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x66,0x69,0x6c,0x6c,0x5f,0x6d,0x69,0x78,0x28,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,
|
||||
0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x2c,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x2c,0x6d,0x69,0x78,0x29,0x3b,0x0a,0x23,0x70,0x72,
|
||||
0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x20,0x32,0x0a,0x66,0x6f,0x72,0x20,0x28,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6c,0x6f,0x6f,0x70,
|
||||
0x3d,0x30,0x3b,0x20,0x6c,0x6f,0x6f,0x70,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x43,0x4e,0x54,0x5f,0x44,0x41,0x47,0x3b,0x20,0x2b,0x2b,0x6c,0x6f,0x6f,0x70,
|
||||
0x29,0x0a,0x7b,0x0a,0x69,0x66,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x3d,0x3d,0x28,0x6c,0x6f,0x6f,0x70,0x20,0x25,0x20,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,
|
||||
0x4c,0x41,0x4e,0x45,0x53,0x29,0x29,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x30,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,
|
||||
0x64,0x5d,0x3d,0x6d,0x69,0x78,0x5b,0x30,0x5d,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,
|
||||
0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x73,0x68,0x61,0x72,0x65,0x5b,0x30,
|
||||
0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x25,0x3d,0x20,0x50,
|
||||
0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x47,0x5f,0x45,0x4c,0x45,0x4d,0x45,0x4e,0x54,0x53,0x3b,0x0a,0x6f,0x66,0x66,0x73,0x65,0x74,0x3d,0x6f,0x66,0x66,0x73,
|
||||
0x65,0x74,0x2a,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x2b,0x28,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x5e,0x6c,0x6f,0x6f,0x70,0x29,0x20,
|
||||
0x25,0x20,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x0a,0x64,0x61,0x67,0x5f,0x74,0x20,0x64,0x61,0x74,0x61,0x5f,0x64,0x61,0x67,0x3d,
|
||||
0x67,0x5f,0x64,0x61,0x67,0x5b,0x6f,0x66,0x66,0x73,0x65,0x74,0x5d,0x3b,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62,0x61,
|
||||
0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x75,0x69,0x6e,0x74,
|
||||
0x33,0x32,0x5f,0x74,0x20,0x64,0x61,0x74,0x61,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,0x49,0x4e,0x43,0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,
|
||||
0x5f,0x52,0x41,0x4e,0x44,0x4f,0x4d,0x5f,0x4d,0x41,0x54,0x48,0x0a,0x69,0x66,0x28,0x68,0x61,0x63,0x6b,0x5f,0x66,0x61,0x6c,0x73,0x65,0x29,0x20,0x62,0x61,0x72,0x72,
|
||||
0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x58,0x4d,0x52,0x49,0x47,0x5f,
|
||||
0x49,0x4e,0x43,0x4c,0x55,0x44,0x45,0x5f,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x44,0x41,0x54,0x41,0x5f,0x4c,0x4f,0x41,0x44,0x53,0x0a,0x7d,0x0a,0x75,0x69,0x6e,
|
||||
0x74,0x33,0x32,0x5f,0x74,0x20,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,0x3b,
|
||||
0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,
|
||||
0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x52,0x45,0x47,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66,0x6e,0x76,0x31,0x61,0x28,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,
|
||||
0x68,0x2c,0x6d,0x69,0x78,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x68,0x61,0x73,0x68,0x33,0x32,0x5f,0x74,0x20,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x3b,
|
||||
0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,
|
||||
0x74,0x65,0x6d,0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x3d,0x46,0x4e,0x56,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x5f,0x42,0x41,0x53,0x49,0x53,
|
||||
0x3b,0x0a,0x73,0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x6c,0x61,0x6e,0x65,0x5f,0x69,
|
||||
0x64,0x5d,0x3d,0x6d,0x69,0x78,0x5f,0x68,0x61,0x73,0x68,0x3b,0x0a,0x62,0x61,0x72,0x72,0x69,0x65,0x72,0x28,0x43,0x4c,0x4b,0x5f,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x4d,
|
||||
0x45,0x4d,0x5f,0x46,0x45,0x4e,0x43,0x45,0x29,0x3b,0x0a,0x23,0x70,0x72,0x61,0x67,0x6d,0x61,0x20,0x75,0x6e,0x72,0x6f,0x6c,0x6c,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,
|
||||
0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x50,0x52,0x4f,0x47,0x50,0x4f,0x57,0x5f,0x4c,0x41,0x4e,0x45,0x53,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x66,0x6e,
|
||||
0x76,0x31,0x61,0x28,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x20,0x25,0x20,0x38,0x5d,0x2c,0x73,
|
||||
0x68,0x61,0x72,0x65,0x5b,0x67,0x72,0x6f,0x75,0x70,0x5f,0x69,0x64,0x5d,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x5d,0x29,0x3b,0x0a,0x69,0x66,0x28,0x68,
|
||||
0x3d,0x3d,0x6c,0x61,0x6e,0x65,0x5f,0x69,0x64,0x29,0x0a,0x64,0x69,0x67,0x65,0x73,0x74,0x3d,0x64,0x69,0x67,0x65,0x73,0x74,0x5f,0x74,0x65,0x6d,0x70,0x3b,0x0a,0x7d,
|
||||
0x0a,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x3b,0x0a,0x7b,0x0a,0x75,0x69,0x6e,0x74,0x33,0x32,0x5f,0x74,0x20,0x73,0x74,0x61,
|
||||
0x74,0x65,0x5b,0x32,0x35,0x5d,0x3d,0x7b,0x30,0x78,0x30,0x7d,0x3b,0x20,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x30,0x3b,0x20,0x69,0x3c,0x38,
|
||||
0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x73,0x74,0x61,0x74,0x65,0x32,0x5b,0x69,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,
|
||||
0x69,0x6e,0x74,0x20,0x69,0x3d,0x38,0x3b,0x20,0x69,0x3c,0x31,0x36,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x64,0x69,0x67,
|
||||
0x65,0x73,0x74,0x2e,0x75,0x69,0x6e,0x74,0x33,0x32,0x73,0x5b,0x69,0x2d,0x38,0x5d,0x3b,0x0a,0x66,0x6f,0x72,0x20,0x28,0x69,0x6e,0x74,0x20,0x69,0x3d,0x31,0x36,0x3b,
|
||||
0x20,0x69,0x3c,0x32,0x35,0x3b,0x20,0x69,0x2b,0x2b,0x29,0x0a,0x73,0x74,0x61,0x74,0x65,0x5b,0x69,0x5d,0x3d,0x72,0x61,0x76,0x65,0x6e,0x63,0x6f,0x69,0x6e,0x5f,0x72,
|
||||
0x6e,0x64,0x63,0x5b,0x69,0x2d,0x31,0x36,0x5d,0x3b,0x0a,0x6b,0x65,0x63,0x63,0x61,0x6b,0x5f,0x66,0x38,0x30,0x30,0x28,0x73,0x74,0x61,0x74,0x65,0x29,0x3b,0x0a,0x75,
|
||||
0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x20,0x72,0x65,0x73,0x3d,0x28,0x75,0x69,0x6e,0x74,0x36,0x34,0x5f,0x74,0x29,0x73,0x74,0x61,0x74,0x65,0x5b,0x31,0x5d,0x3c,0x3c,
|
||||
0x33,0x32,0x7c,0x73,0x74,0x61,0x74,0x65,0x5b,0x30,0x5d,0x3b,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x3d,0x61,0x73,0x5f,0x75,0x6c,0x6f,0x6e,0x67,0x28,0x61,0x73,0x5f,
|
||||
0x75,0x63,0x68,0x61,0x72,0x38,0x28,0x72,0x65,0x73,0x29,0x2e,0x73,0x37,0x36,0x35,0x34,0x33,0x32,0x31,0x30,0x29,0x3b,0x0a,0x7d,0x0a,0x69,0x66,0x28,0x72,0x65,0x73,
|
||||
0x75,0x6c,0x74,0x3c,0x3d,0x74,0x61,0x72,0x67,0x65,0x74,0x29,0x0a,0x7b,0x0a,0x2a,0x73,0x74,0x6f,0x70,0x3d,0x31,0x3b,0x0a,0x63,0x6f,0x6e,0x73,0x74,0x20,0x75,0x69,
|
||||
0x6e,0x74,0x20,0x6b,0x3d,0x61,0x74,0x6f,0x6d,0x69,0x63,0x5f,0x69,0x6e,0x63,0x28,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x29,0x2b,0x31,0x3b,0x0a,0x69,0x66,0x28,0x6b,
|
||||
0x3c,0x3d,0x31,0x35,0x29,0x0a,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x6b,0x5d,0x3d,0x67,0x69,0x64,0x3b,0x0a,0x7d,0x0a,0x7d,0x0a,0x00
|
||||
};
|
||||
|
||||
} // namespace xmrig
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -77,6 +77,7 @@ const char *Algorithm::kCN_UPX2 = "cn/upx2";
|
||||
#ifdef XMRIG_ALGO_RANDOMX
|
||||
const char *Algorithm::kRX = "rx";
|
||||
const char *Algorithm::kRX_0 = "rx/0";
|
||||
const char *Algorithm::kRX_V2 = "rx/2";
|
||||
const char *Algorithm::kRX_WOW = "rx/wow";
|
||||
const char *Algorithm::kRX_ARQ = "rx/arq";
|
||||
const char *Algorithm::kRX_GRAFT = "rx/graft";
|
||||
@@ -143,6 +144,7 @@ static const std::map<uint32_t, const char *> kAlgorithmNames = {
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
ALGO_NAME(RX_0),
|
||||
ALGO_NAME(RX_V2),
|
||||
ALGO_NAME(RX_WOW),
|
||||
ALGO_NAME(RX_ARQ),
|
||||
ALGO_NAME(RX_GRAFT),
|
||||
@@ -253,6 +255,8 @@ static const std::map<const char *, Algorithm::Id, aliasCompare> kAlgorithmAlias
|
||||
ALGO_ALIAS(RX_0, "rx/test"),
|
||||
ALGO_ALIAS(RX_0, "randomx"),
|
||||
ALGO_ALIAS(RX_0, "rx"),
|
||||
ALGO_ALIAS_AUTO(RX_V2), ALGO_ALIAS(RX_V2, "randomx/v2"),
|
||||
ALGO_ALIAS(RX_V2, "rx/v2"),
|
||||
ALGO_ALIAS_AUTO(RX_WOW), ALGO_ALIAS(RX_WOW, "randomx/wow"),
|
||||
ALGO_ALIAS(RX_WOW, "randomwow"),
|
||||
ALGO_ALIAS_AUTO(RX_ARQ), ALGO_ALIAS(RX_ARQ, "randomx/arq"),
|
||||
@@ -350,7 +354,7 @@ std::vector<xmrig::Algorithm> xmrig::Algorithm::all(const std::function<bool(con
|
||||
CN_HEAVY_0, CN_HEAVY_TUBE, CN_HEAVY_XHV,
|
||||
CN_PICO_0, CN_PICO_TLO,
|
||||
CN_UPX2,
|
||||
RX_0, RX_WOW, RX_ARQ, RX_GRAFT, RX_SFX, RX_YADA,
|
||||
RX_0, RX_V2, RX_WOW, RX_ARQ, RX_GRAFT, RX_SFX, RX_YADA,
|
||||
AR2_CHUKWA, AR2_CHUKWA_V2, AR2_WRKZ,
|
||||
KAWPOW_RVN,
|
||||
GHOSTRIDER_RTM
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
CN_GR_5 = 0x63120105, // "cn/turtle-lite" GhostRider
|
||||
GHOSTRIDER_RTM = 0x6c150000, // "ghostrider" GhostRider
|
||||
RX_0 = 0x72151200, // "rx/0" RandomX (reference configuration).
|
||||
RX_V2 = 0x72151202, // "rx/2" RandomX (Monero v2).
|
||||
RX_WOW = 0x72141177, // "rx/wow" RandomWOW (Wownero).
|
||||
RX_ARQ = 0x72121061, // "rx/arq" RandomARQ (Arqma).
|
||||
RX_GRAFT = 0x72151267, // "rx/graft" RandomGRAFT (Graft).
|
||||
@@ -139,6 +140,7 @@ public:
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
static const char *kRX;
|
||||
static const char *kRX_0;
|
||||
static const char* kRX_V2;
|
||||
static const char *kRX_WOW;
|
||||
static const char *kRX_ARQ;
|
||||
static const char *kRX_GRAFT;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#define KECCAK_ROUNDS 24
|
||||
|
||||
|
||||
/* *************************** Public Inteface ************************ */
|
||||
/* *************************** Public Interface ************************ */
|
||||
|
||||
/* For Init or Reset call these: */
|
||||
sha3_return_t
|
||||
|
||||
@@ -81,7 +81,7 @@ xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||
BaseClient(id, listener),
|
||||
m_agent(agent),
|
||||
m_sendBuf(1024),
|
||||
m_tempBuf(256)
|
||||
m_tempBuf(320)
|
||||
{
|
||||
m_reader.setListener(this);
|
||||
m_key = m_storage.add(this);
|
||||
@@ -199,6 +199,7 @@ int64_t xmrig::Client::submit(const JobResult &result)
|
||||
char *nonce = m_tempBuf.data();
|
||||
char *data = m_tempBuf.data() + 16;
|
||||
char *signature = m_tempBuf.data() + 88;
|
||||
char *commitment = m_tempBuf.data() + 224;
|
||||
|
||||
Cvt::toHex(nonce, sizeof(uint32_t) * 2 + 1, reinterpret_cast<const uint8_t *>(&result.nonce), sizeof(uint32_t));
|
||||
Cvt::toHex(data, 65, result.result(), 32);
|
||||
@@ -206,6 +207,10 @@ int64_t xmrig::Client::submit(const JobResult &result)
|
||||
if (result.minerSignature()) {
|
||||
Cvt::toHex(signature, 129, result.minerSignature(), 64);
|
||||
}
|
||||
|
||||
if (result.commitment()) {
|
||||
Cvt::toHex(commitment, 65, result.commitment(), 32);
|
||||
}
|
||||
# endif
|
||||
|
||||
Document doc(kObjectType);
|
||||
@@ -227,6 +232,16 @@ int64_t xmrig::Client::submit(const JobResult &result)
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifndef XMRIG_PROXY_PROJECT
|
||||
if (result.commitment()) {
|
||||
params.AddMember("commitment", StringRef(commitment), allocator);
|
||||
}
|
||||
# else
|
||||
if (result.commitment) {
|
||||
params.AddMember("commitment", StringRef(result.commitment), allocator);
|
||||
}
|
||||
# endif
|
||||
|
||||
if (has<EXT_ALGO>() && result.algorithm.isValid()) {
|
||||
params.AddMember("algo", StringRef(result.algorithm.name()), allocator);
|
||||
}
|
||||
@@ -554,6 +569,7 @@ int64_t xmrig::Client::send(size_t size)
|
||||
}
|
||||
|
||||
m_expire = Chrono::steadyMSecs() + kResponseTimeout;
|
||||
startTimeout();
|
||||
return m_sequence++;
|
||||
}
|
||||
|
||||
@@ -661,8 +677,6 @@ void xmrig::Client::onClose()
|
||||
|
||||
void xmrig::Client::parse(char *line, size_t len)
|
||||
{
|
||||
startTimeout();
|
||||
|
||||
LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast<int>(len), line);
|
||||
|
||||
if (len < 22 || line[0] != '{') {
|
||||
@@ -857,8 +871,6 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
|
||||
void xmrig::Client::ping()
|
||||
{
|
||||
send(snprintf(m_sendBuf.data(), m_sendBuf.size(), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data()));
|
||||
|
||||
m_keepAlive = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -410,6 +410,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||
m_blocktemplate.offset(BlockTemplate::TX_EXTRA_NONCE_OFFSET) - k,
|
||||
m_blocktemplate.txExtraNonce().size(),
|
||||
m_blocktemplate.minerTxMerkleTreeBranch(),
|
||||
m_blocktemplate.minerTxMerkleTreePath(),
|
||||
m_blocktemplate.outputType() == 3
|
||||
);
|
||||
# endif
|
||||
|
||||
@@ -269,6 +269,7 @@ void xmrig::Job::copy(const Job &other)
|
||||
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
|
||||
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
|
||||
m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch;
|
||||
m_minerTxMerkleTreePath = other.m_minerTxMerkleTreePath;
|
||||
m_hasViewTag = other.m_hasViewTag;
|
||||
# else
|
||||
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
|
||||
@@ -325,6 +326,7 @@ void xmrig::Job::move(Job &&other)
|
||||
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
|
||||
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
|
||||
m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch);
|
||||
m_minerTxMerkleTreePath = other.m_minerTxMerkleTreePath;
|
||||
m_hasViewTag = other.m_hasViewTag;
|
||||
# else
|
||||
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
|
||||
@@ -349,7 +351,7 @@ void xmrig::Job::setSpendSecretKey(const uint8_t *key)
|
||||
}
|
||||
|
||||
|
||||
void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer &minerTxMerkleTreeBranch, bool hasViewTag)
|
||||
void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer &minerTxMerkleTreeBranch, uint32_t minerTxMerkleTreePath, bool hasViewTag)
|
||||
{
|
||||
m_minerTxPrefix.assign(begin, end);
|
||||
m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset;
|
||||
@@ -357,6 +359,7 @@ void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t min
|
||||
m_minerTxExtraNonceOffset = minerTxExtraNonceOffset;
|
||||
m_minerTxExtraNonceSize = minerTxExtraNonceSize;
|
||||
m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch;
|
||||
m_minerTxMerkleTreePath = minerTxMerkleTreePath;
|
||||
m_hasViewTag = hasViewTag;
|
||||
}
|
||||
|
||||
@@ -401,7 +404,7 @@ void xmrig::Job::generateHashingBlob(String &blob) const
|
||||
{
|
||||
uint8_t root_hash[32];
|
||||
const uint8_t* p = m_minerTxPrefix.data();
|
||||
BlockTemplate::calculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash);
|
||||
BlockTemplate::calculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, m_minerTxMerkleTreePath, root_hash);
|
||||
|
||||
uint64_t root_hash_offset = nonceOffset() + nonceSize();
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
inline bool hasViewTag() const { return m_hasViewTag; }
|
||||
|
||||
void setSpendSecretKey(const uint8_t* key);
|
||||
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer& minerTxMerkleTreeBranch, bool hasViewTag);
|
||||
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer& minerTxMerkleTreeBranch, uint32_t minerTxMerkleTreePath, bool hasViewTag);
|
||||
void setViewTagInMinerTx(uint8_t view_tag);
|
||||
void setExtraNonceInMinerTx(uint32_t extra_nonce);
|
||||
void generateSignatureData(String& signatureData, uint8_t& view_tag) const;
|
||||
@@ -179,6 +179,7 @@ private:
|
||||
size_t m_minerTxExtraNonceOffset = 0;
|
||||
size_t m_minerTxExtraNonceSize = 0;
|
||||
Buffer m_minerTxMerkleTreeBranch;
|
||||
uint32_t m_minerTxMerkleTreePath = 0;
|
||||
bool m_hasViewTag = false;
|
||||
# else
|
||||
// Miner signatures
|
||||
|
||||
@@ -48,69 +48,98 @@ void xmrig::BlockTemplate::calculateMinerTxHash(const uint8_t *prefix_begin, con
|
||||
}
|
||||
|
||||
|
||||
void xmrig::BlockTemplate::calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint8_t *root_hash)
|
||||
void xmrig::BlockTemplate::calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint32_t miner_tx_merkle_tree_path, uint8_t *root_hash)
|
||||
{
|
||||
calculateMinerTxHash(prefix_begin, prefix_end, root_hash);
|
||||
|
||||
for (size_t i = 0; i < miner_tx_merkle_tree_branch.size(); i += kHashSize) {
|
||||
const size_t depth = miner_tx_merkle_tree_branch.size() / kHashSize;
|
||||
|
||||
for (size_t d = 0; d < depth; ++d) {
|
||||
uint8_t h[kHashSize * 2];
|
||||
|
||||
memcpy(h, root_hash, kHashSize);
|
||||
memcpy(h + kHashSize, miner_tx_merkle_tree_branch.data() + i, kHashSize);
|
||||
const uint32_t t = (miner_tx_merkle_tree_path >> (depth - d - 1)) & 1;
|
||||
|
||||
memcpy(h + kHashSize * t, root_hash, kHashSize);
|
||||
memcpy(h + kHashSize * (t ^ 1), miner_tx_merkle_tree_branch.data() + d * kHashSize, kHashSize);
|
||||
|
||||
keccak(h, kHashSize * 2, root_hash, kHashSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void xmrig::BlockTemplate::calculateMerkleTreeHash()
|
||||
void xmrig::BlockTemplate::calculateMerkleTreeHash(uint32_t index)
|
||||
{
|
||||
m_minerTxMerkleTreeBranch.clear();
|
||||
m_minerTxMerkleTreePath = 0;
|
||||
|
||||
const uint64_t count = m_numHashes + 1;
|
||||
const size_t count = m_hashes.size() / kHashSize;
|
||||
const uint8_t *h = m_hashes.data();
|
||||
|
||||
if (count == 1) {
|
||||
if (count == 1) {
|
||||
memcpy(m_rootHash, h, kHashSize);
|
||||
}
|
||||
else if (count == 2) {
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize, h + kHashSize * 2);
|
||||
}
|
||||
else if (count == 2) {
|
||||
keccak(h, kHashSize * 2, m_rootHash, kHashSize);
|
||||
}
|
||||
else {
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
size_t cnt = 0;
|
||||
|
||||
for (i = 0, cnt = 1; cnt <= count; ++i, cnt <<= 1) {}
|
||||
m_minerTxMerkleTreeBranch.reserve(1);
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize * (index ^ 1), h + kHashSize * ((index ^ 1) + 1));
|
||||
m_minerTxMerkleTreePath = static_cast<uint32_t>(index);
|
||||
}
|
||||
else {
|
||||
uint8_t h2[kHashSize];
|
||||
memcpy(h2, h + kHashSize * index, kHashSize);
|
||||
|
||||
cnt >>= 1;
|
||||
size_t cnt = 1, proof_max_size = 0;
|
||||
do {
|
||||
cnt <<= 1;
|
||||
++proof_max_size;
|
||||
} while (cnt <= count);
|
||||
cnt >>= 1;
|
||||
|
||||
m_minerTxMerkleTreeBranch.reserve(kHashSize * (i - 1));
|
||||
m_minerTxMerkleTreeBranch.reserve(proof_max_size);
|
||||
|
||||
Buffer ints(cnt * kHashSize);
|
||||
memcpy(ints.data(), h, (cnt * 2 - count) * kHashSize);
|
||||
|
||||
for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) {
|
||||
if (i == 0) {
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize, h + kHashSize * 2);
|
||||
}
|
||||
keccak(h + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
|
||||
}
|
||||
const size_t k = cnt * 2 - count;
|
||||
memcpy(ints.data(), h, k * kHashSize);
|
||||
|
||||
while (cnt > 2) {
|
||||
cnt >>= 1;
|
||||
for (i = 0, j = 0; j < cnt; i += 2, ++j) {
|
||||
if (i == 0) {
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize, ints.data() + kHashSize * 2);
|
||||
}
|
||||
keccak(ints.data() + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
|
||||
}
|
||||
}
|
||||
for (size_t i = k, j = k; j < cnt; i += 2, ++j) {
|
||||
keccak(h + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
|
||||
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize, ints.data() + kHashSize * 2);
|
||||
keccak(ints.data(), kHashSize * 2, m_rootHash, kHashSize);
|
||||
}
|
||||
if (memcmp(h + i * kHashSize, h2, kHashSize) == 0) {
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize * (i + 1), h + kHashSize * (i + 2));
|
||||
memcpy(h2, ints.data() + j * kHashSize, kHashSize);
|
||||
}
|
||||
else if (memcmp(h + (i + 1) * kHashSize, h2, kHashSize) == 0) {
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize * i, h + kHashSize * (i + 1));
|
||||
memcpy(h2, ints.data() + j * kHashSize, kHashSize);
|
||||
m_minerTxMerkleTreePath = 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (cnt >= 2) {
|
||||
cnt >>= 1;
|
||||
for (size_t i = 0, j = 0; j < cnt; i += 2, ++j) {
|
||||
uint8_t tmp[kHashSize];
|
||||
keccak(ints.data() + i * kHashSize, kHashSize * 2, tmp, kHashSize);
|
||||
|
||||
if (memcmp(ints.data() + i * kHashSize, h2, kHashSize) == 0) {
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize * (i + 1), ints.data() + kHashSize * (i + 2));
|
||||
memcpy(h2, tmp, kHashSize);
|
||||
m_minerTxMerkleTreePath <<= 1;
|
||||
}
|
||||
else if (memcmp(ints.data() + (i + 1) * kHashSize, h2, kHashSize) == 0) {
|
||||
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize * i, ints.data() + kHashSize * (i + 1));
|
||||
memcpy(h2, tmp, kHashSize);
|
||||
m_minerTxMerkleTreePath = (m_minerTxMerkleTreePath << 1) | 1;
|
||||
}
|
||||
|
||||
memcpy(ints.data() + j * kHashSize, tmp, kHashSize);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(m_rootHash, ints.data(), kHashSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -375,16 +404,42 @@ bool xmrig::BlockTemplate::parse(bool hashes)
|
||||
ar(m_numHashes);
|
||||
|
||||
if (hashes) {
|
||||
m_hashes.resize((m_numHashes + 1) * kHashSize);
|
||||
calculateMinerTxHash(blob(MINER_TX_PREFIX_OFFSET), blob(MINER_TX_PREFIX_END_OFFSET), m_hashes.data());
|
||||
// FCMP++ layout:
|
||||
//
|
||||
// index 0 fcmp_pp_n_tree_layers + 31 zero bytes
|
||||
// index 1 fcmp_pp_tree_root
|
||||
// index 2 coinbase transaction hash
|
||||
// index 3+ other transaction hashes
|
||||
//
|
||||
// pre-FCMP++ layout:
|
||||
//
|
||||
// index 0 coinbase transaction hash
|
||||
// index 1+ other transaction hashes
|
||||
//
|
||||
const uint32_t coinbase_tx_index = is_fcmp_pp ? 2 : 0;
|
||||
|
||||
m_hashes.clear();
|
||||
m_hashes.resize((coinbase_tx_index + m_numHashes + 1) * kHashSize);
|
||||
|
||||
uint8_t* data = m_hashes.data() + coinbase_tx_index * kHashSize;
|
||||
|
||||
calculateMinerTxHash(blob(MINER_TX_PREFIX_OFFSET), blob(MINER_TX_PREFIX_END_OFFSET), data);
|
||||
|
||||
for (uint64_t i = 1; i <= m_numHashes; ++i) {
|
||||
Span h;
|
||||
ar(h, kHashSize);
|
||||
memcpy(m_hashes.data() + i * kHashSize, h.data(), kHashSize);
|
||||
memcpy(data + i * kHashSize, h.data(), kHashSize);
|
||||
}
|
||||
|
||||
calculateMerkleTreeHash();
|
||||
if (is_fcmp_pp) {
|
||||
ar(m_FCMPTreeLayers);
|
||||
ar(m_FCMPTreeRoot);
|
||||
|
||||
m_hashes[0] = m_FCMPTreeLayers;
|
||||
memcpy(m_hashes.data() + kHashSize, m_FCMPTreeRoot, kHashSize);
|
||||
}
|
||||
|
||||
calculateMerkleTreeHash(coinbase_tx_index);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
inline uint64_t numHashes() const { return m_numHashes; }
|
||||
inline const Buffer &hashes() const { return m_hashes; }
|
||||
inline const Buffer &minerTxMerkleTreeBranch() const { return m_minerTxMerkleTreeBranch; }
|
||||
inline uint32_t minerTxMerkleTreePath() const { return m_minerTxMerkleTreePath; }
|
||||
inline const uint8_t *rootHash() const { return m_rootHash; }
|
||||
|
||||
inline Buffer generateHashingBlob() const
|
||||
@@ -104,13 +105,13 @@ public:
|
||||
}
|
||||
|
||||
static void calculateMinerTxHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, uint8_t *hash);
|
||||
static void calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint8_t *root_hash);
|
||||
static void calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint32_t miner_tx_merkle_tree_path, uint8_t *root_hash);
|
||||
|
||||
bool parse(const Buffer &blocktemplate, const Coin &coin, bool hashes = kCalcHashes);
|
||||
bool parse(const char *blocktemplate, size_t size, const Coin &coin, bool hashes);
|
||||
bool parse(const rapidjson::Value &blocktemplate, const Coin &coin, bool hashes = kCalcHashes);
|
||||
bool parse(const String &blocktemplate, const Coin &coin, bool hashes = kCalcHashes);
|
||||
void calculateMerkleTreeHash();
|
||||
void calculateMerkleTreeHash(uint32_t index);
|
||||
void generateHashingBlob(Buffer &out) const;
|
||||
|
||||
private:
|
||||
@@ -147,9 +148,12 @@ private:
|
||||
uint64_t m_numHashes = 0;
|
||||
Buffer m_hashes;
|
||||
Buffer m_minerTxMerkleTreeBranch;
|
||||
uint32_t m_minerTxMerkleTreePath = 0;
|
||||
uint8_t m_rootHash[kHashSize]{};
|
||||
uint8_t m_carrotViewTag[3]{};
|
||||
uint8_t m_janusAnchor[16]{};
|
||||
uint8_t m_FCMPTreeLayers = 0;
|
||||
uint8_t m_FCMPTreeRoot[kHashSize]{};
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
# include "crypto/rx/Profiler.h"
|
||||
# include "crypto/rx/Rx.h"
|
||||
# include "crypto/rx/RxConfig.h"
|
||||
# include "crypto/rx/RxAlgo.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -556,11 +557,12 @@ void xmrig::Miner::setJob(const Job &job, bool donate)
|
||||
}
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (job.algorithm().family() == Algorithm::RANDOM_X && !Rx::isReady(job)) {
|
||||
if (job.algorithm().family() == Algorithm::RANDOM_X) {
|
||||
if (d_ptr->algorithm != job.algorithm()) {
|
||||
stop();
|
||||
RxAlgo::apply(job.algorithm());
|
||||
}
|
||||
else {
|
||||
else if (!Rx::isReady(job)) {
|
||||
Nonce::pause(true);
|
||||
Nonce::touch();
|
||||
}
|
||||
@@ -572,6 +574,7 @@ void xmrig::Miner::setJob(const Job &job, bool donate)
|
||||
mutex.lock();
|
||||
|
||||
const uint8_t index = donate ? 1 : 0;
|
||||
const bool same_job_index = d_ptr->job.index() == index;
|
||||
|
||||
d_ptr->reset = !(d_ptr->job.index() == 1 && index == 0 && d_ptr->userJobId == job.id());
|
||||
|
||||
@@ -591,7 +594,8 @@ void xmrig::Miner::setJob(const Job &job, bool donate)
|
||||
const bool ready = d_ptr->initRX();
|
||||
|
||||
// Always reset nonce on RandomX dataset change
|
||||
if (!ready) {
|
||||
// Except for switching to/from donation
|
||||
if (!ready && same_job_index) {
|
||||
d_ptr->reset = true;
|
||||
}
|
||||
# else
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
/* XMRig
|
||||
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
* Copyright (c) 2018-2026 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2026 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/>.
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
@@ -31,7 +20,7 @@
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
static const char short_options[] = "a:c:kBp:Px:r:R:s:t:T:o:u:O:v:l:Sx:46";
|
||||
static const char short_options[] = "a:c:kBp:x:r:R:s:t:T:o:u:O:v:l:S46";
|
||||
|
||||
|
||||
static const option options[] = {
|
||||
|
||||
@@ -235,7 +235,7 @@ static HashReturn Init(hashState *state, int hashbitlen)
|
||||
/*initialize the initial hash value of JH*/
|
||||
state->hashbitlen = hashbitlen;
|
||||
|
||||
/*load the intital hash value into state*/
|
||||
/*load the initial hash value into state*/
|
||||
switch (hashbitlen)
|
||||
{
|
||||
case 224: memcpy(state->x,JH224_H0,128); break;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
multiple of size / 8)
|
||||
|
||||
ptr_cast(x,size) casts a pointer to a pointer to a
|
||||
varaiable of length 'size' bits
|
||||
variable of length 'size' bits
|
||||
*/
|
||||
|
||||
#define ui_type(size) uint##size##_t
|
||||
|
||||
@@ -38,9 +38,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "crypto/randomx/common.hpp"
|
||||
#include "crypto/rx/Profiler.h"
|
||||
|
||||
#ifdef XMRIG_RISCV
|
||||
#include "backend/cpu/Cpu.h"
|
||||
|
||||
#ifdef XMRIG_RISCV
|
||||
#include "crypto/randomx/aes_hash_rv64_vector.hpp"
|
||||
#include "crypto/randomx/aes_hash_rv64_zvkned.hpp"
|
||||
#endif
|
||||
|
||||
#define AES_HASH_1R_STATE0 0xd7983aad, 0xcc82db47, 0x9fa856de, 0x92b52c0d
|
||||
@@ -67,8 +69,13 @@ template<int softAes>
|
||||
void hashAes1Rx4(const void *input, size_t inputSize, void *hash)
|
||||
{
|
||||
#ifdef XMRIG_RISCV
|
||||
if (xmrig::Cpu::info()->hasAES()) {
|
||||
hashAes1Rx4_zvkned(input, inputSize, hash);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmrig::Cpu::info()->hasRISCV_Vector()) {
|
||||
hashAes1Rx4_RVV<softAes>(input, inputSize, hash);
|
||||
hashAes1Rx4_RVV(input, inputSize, hash);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -79,7 +86,7 @@ void hashAes1Rx4(const void *input, size_t inputSize, void *hash)
|
||||
rx_vec_i128 state0, state1, state2, state3;
|
||||
rx_vec_i128 in0, in1, in2, in3;
|
||||
|
||||
//intial state
|
||||
//initial state
|
||||
state0 = rx_set_int_vec_i128(AES_HASH_1R_STATE0);
|
||||
state1 = rx_set_int_vec_i128(AES_HASH_1R_STATE1);
|
||||
state2 = rx_set_int_vec_i128(AES_HASH_1R_STATE2);
|
||||
@@ -143,8 +150,13 @@ template<int softAes>
|
||||
void fillAes1Rx4(void *state, size_t outputSize, void *buffer)
|
||||
{
|
||||
#ifdef XMRIG_RISCV
|
||||
if (xmrig::Cpu::info()->hasAES()) {
|
||||
fillAes1Rx4_zvkned(state, outputSize, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmrig::Cpu::info()->hasRISCV_Vector()) {
|
||||
fillAes1Rx4_RVV<softAes>(state, outputSize, buffer);
|
||||
fillAes1Rx4_RVV(state, outputSize, buffer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -195,8 +207,13 @@ template<int softAes>
|
||||
void fillAes4Rx4(void *state, size_t outputSize, void *buffer)
|
||||
{
|
||||
#ifdef XMRIG_RISCV
|
||||
if (xmrig::Cpu::info()->hasAES()) {
|
||||
fillAes4Rx4_zvkned(state, outputSize, buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmrig::Cpu::info()->hasRISCV_Vector()) {
|
||||
fillAes4Rx4_RVV<softAes>(state, outputSize, buffer);
|
||||
fillAes4Rx4_RVV(state, outputSize, buffer);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -264,14 +281,30 @@ void fillAes4Rx4(void *state, size_t outputSize, void *buffer)
|
||||
template void fillAes4Rx4<true>(void *state, size_t outputSize, void *buffer);
|
||||
template void fillAes4Rx4<false>(void *state, size_t outputSize, void *buffer);
|
||||
|
||||
#ifdef XMRIG_VAES
|
||||
void hashAndFillAes1Rx4_VAES512(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
|
||||
#endif
|
||||
|
||||
template<int softAes, int unroll>
|
||||
void hashAndFillAes1Rx4(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state)
|
||||
{
|
||||
PROFILE_SCOPE(RandomX_AES);
|
||||
|
||||
#ifdef XMRIG_RISCV
|
||||
if (xmrig::Cpu::info()->hasAES()) {
|
||||
hashAndFillAes1Rx4_zvkned(scratchpad, scratchpadSize, hash, fill_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmrig::Cpu::info()->hasRISCV_Vector()) {
|
||||
hashAndFillAes1Rx4_RVV<softAes, unroll>(scratchpad, scratchpadSize, hash, fill_state);
|
||||
hashAndFillAes1Rx4_RVV(scratchpad, scratchpadSize, hash, fill_state);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XMRIG_VAES
|
||||
if (xmrig::Cpu::info()->arch() == xmrig::ICpuInfo::ARCH_ZEN5) {
|
||||
hashAndFillAes1Rx4_VAES512(scratchpad, scratchpadSize, hash, fill_state);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,16 @@ static constexpr uint32_t AES_HASH_1R_XKEY11[8] = { 0x61b263d1, 0x51f4e03c, 0xee
|
||||
static constexpr uint32_t AES_HASH_STRIDE_X2[8] = { 0, 4, 8, 12, 32, 36, 40, 44 };
|
||||
static constexpr uint32_t AES_HASH_STRIDE_X4[8] = { 0, 4, 8, 12, 64, 68, 72, 76 };
|
||||
|
||||
template<int softAes>
|
||||
#define lutEnc0 lutEnc[0]
|
||||
#define lutEnc1 lutEnc[1]
|
||||
#define lutEnc2 lutEnc[2]
|
||||
#define lutEnc3 lutEnc[3]
|
||||
|
||||
#define lutDec0 lutDec[0]
|
||||
#define lutDec1 lutDec[1]
|
||||
#define lutDec2 lutDec[2]
|
||||
#define lutDec3 lutDec[3]
|
||||
|
||||
void hashAes1Rx4_RVV(const void *input, size_t inputSize, void *hash) {
|
||||
const uint8_t* inptr = (const uint8_t*)input;
|
||||
const uint8_t* inputEnd = inptr + inputSize;
|
||||
@@ -113,10 +122,6 @@ void hashAes1Rx4_RVV(const void *input, size_t inputSize, void *hash) {
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)hash + 4, stride, state13, 8);
|
||||
}
|
||||
|
||||
template void hashAes1Rx4_RVV<false>(const void *input, size_t inputSize, void *hash);
|
||||
template void hashAes1Rx4_RVV<true>(const void *input, size_t inputSize, void *hash);
|
||||
|
||||
template<int softAes>
|
||||
void fillAes1Rx4_RVV(void *state, size_t outputSize, void *buffer) {
|
||||
const uint8_t* outptr = (uint8_t*)buffer;
|
||||
const uint8_t* outputEnd = outptr + outputSize;
|
||||
@@ -153,10 +158,6 @@ void fillAes1Rx4_RVV(void *state, size_t outputSize, void *buffer) {
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)state + 4, stride, state13, 8);
|
||||
}
|
||||
|
||||
template void fillAes1Rx4_RVV<false>(void *state, size_t outputSize, void *buffer);
|
||||
template void fillAes1Rx4_RVV<true>(void *state, size_t outputSize, void *buffer);
|
||||
|
||||
template<int softAes>
|
||||
void fillAes4Rx4_RVV(void *state, size_t outputSize, void *buffer) {
|
||||
const uint8_t* outptr = (uint8_t*)buffer;
|
||||
const uint8_t* outputEnd = outptr + outputSize;
|
||||
@@ -203,10 +204,6 @@ void fillAes4Rx4_RVV(void *state, size_t outputSize, void *buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
template void fillAes4Rx4_RVV<false>(void *state, size_t outputSize, void *buffer);
|
||||
template void fillAes4Rx4_RVV<true>(void *state, size_t outputSize, void *buffer);
|
||||
|
||||
template<int softAes, int unroll>
|
||||
void hashAndFillAes1Rx4_RVV(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state) {
|
||||
uint8_t* scratchpadPtr = (uint8_t*)scratchpad;
|
||||
const uint8_t* scratchpadEnd = scratchpadPtr + scratchpadSize;
|
||||
@@ -244,54 +241,13 @@ void hashAndFillAes1Rx4_RVV(void *scratchpad, size_t scratchpadSize, void *hash,
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)scratchpadPtr + k * 16 + 0, stride, fill_state02, 8); \
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)scratchpadPtr + k * 16 + 4, stride, fill_state13, 8);
|
||||
|
||||
switch (softAes) {
|
||||
case 0:
|
||||
HASH_STATE(0);
|
||||
HASH_STATE(1);
|
||||
HASH_STATE(0);
|
||||
HASH_STATE(1);
|
||||
|
||||
FILL_STATE(0);
|
||||
FILL_STATE(1);
|
||||
FILL_STATE(0);
|
||||
FILL_STATE(1);
|
||||
|
||||
scratchpadPtr += 128;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch (unroll) {
|
||||
case 4:
|
||||
HASH_STATE(0);
|
||||
FILL_STATE(0);
|
||||
|
||||
HASH_STATE(1);
|
||||
FILL_STATE(1);
|
||||
|
||||
HASH_STATE(2);
|
||||
FILL_STATE(2);
|
||||
|
||||
HASH_STATE(3);
|
||||
FILL_STATE(3);
|
||||
|
||||
scratchpadPtr += 64 * 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
HASH_STATE(0);
|
||||
FILL_STATE(0);
|
||||
|
||||
HASH_STATE(1);
|
||||
FILL_STATE(1);
|
||||
|
||||
scratchpadPtr += 64 * 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
HASH_STATE(0);
|
||||
FILL_STATE(0);
|
||||
|
||||
scratchpadPtr += 64;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
scratchpadPtr += 128;
|
||||
}
|
||||
|
||||
#undef HASH_STATE
|
||||
@@ -314,9 +270,3 @@ void hashAndFillAes1Rx4_RVV(void *scratchpad, size_t scratchpadSize, void *hash,
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)hash + 0, stride, hash_state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)hash + 4, stride, hash_state13, 8);
|
||||
}
|
||||
|
||||
template void hashAndFillAes1Rx4_RVV<0,2>(void* scratchpad, size_t scratchpadSize, void* hash, void* fill_state);
|
||||
template void hashAndFillAes1Rx4_RVV<1,1>(void* scratchpad, size_t scratchpadSize, void* hash, void* fill_state);
|
||||
template void hashAndFillAes1Rx4_RVV<2,1>(void* scratchpad, size_t scratchpadSize, void* hash, void* fill_state);
|
||||
template void hashAndFillAes1Rx4_RVV<2,2>(void* scratchpad, size_t scratchpadSize, void* hash, void* fill_state);
|
||||
template void hashAndFillAes1Rx4_RVV<2,4>(void* scratchpad, size_t scratchpadSize, void* hash, void* fill_state);
|
||||
|
||||
@@ -29,14 +29,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
template<int softAes>
|
||||
void hashAes1Rx4_RVV(const void *input, size_t inputSize, void *hash);
|
||||
|
||||
template<int softAes>
|
||||
void fillAes1Rx4_RVV(void *state, size_t outputSize, void *buffer);
|
||||
|
||||
template<int softAes>
|
||||
void fillAes4Rx4_RVV(void *state, size_t outputSize, void *buffer);
|
||||
|
||||
template<int softAes, int unroll>
|
||||
void hashAndFillAes1Rx4_RVV(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
|
||||
|
||||
199
src/crypto/randomx/aes_hash_rv64_zvkned.cpp
Normal file
199
src/crypto/randomx/aes_hash_rv64_zvkned.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright (c) 2025 SChernykh <https://github.com/SChernykh>
|
||||
Copyright (c) 2025 XMRig <support@xmrig.com>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "crypto/randomx/aes_hash.hpp"
|
||||
#include "crypto/randomx/randomx.h"
|
||||
#include "crypto/rx/Profiler.h"
|
||||
|
||||
#include <riscv_vector.h>
|
||||
|
||||
static FORCE_INLINE vuint32m1_t aesenc_zvkned(vuint32m1_t a, vuint32m1_t b) { return __riscv_vaesem_vv_u32m1(a, b, 8); }
|
||||
static FORCE_INLINE vuint32m1_t aesdec_zvkned(vuint32m1_t a, vuint32m1_t b, vuint32m1_t zero) { return __riscv_vxor_vv_u32m1(__riscv_vaesdm_vv_u32m1(a, zero, 8), b, 8); }
|
||||
|
||||
static constexpr uint32_t AES_HASH_1R_STATE02[8] = { 0x92b52c0d, 0x9fa856de, 0xcc82db47, 0xd7983aad, 0x6a770017, 0xae62c7d0, 0x5079506b, 0xe8a07ce4 };
|
||||
static constexpr uint32_t AES_HASH_1R_STATE13[8] = { 0x338d996e, 0x15c7b798, 0xf59e125a, 0xace78057, 0x630a240c, 0x07ad828d, 0x79a10005, 0x7e994948 };
|
||||
|
||||
static constexpr uint32_t AES_GEN_1R_KEY02[8] = { 0x6daca553, 0x62716609, 0xdbb5552b, 0xb4f44917, 0x3f1262f1, 0x9f947ec6, 0xf4c0794f, 0x3e20e345 };
|
||||
static constexpr uint32_t AES_GEN_1R_KEY13[8] = { 0x6d7caf07, 0x846a710d, 0x1725d378, 0x0da1dc4e, 0x6aef8135, 0xb1ba317c, 0x16314c88, 0x49169154 };
|
||||
|
||||
static constexpr uint32_t AES_HASH_1R_XKEY00[8] = { 0xf6fa8389, 0x8b24949f, 0x90dc56bf, 0x06890201, 0xf6fa8389, 0x8b24949f, 0x90dc56bf, 0x06890201 };
|
||||
static constexpr uint32_t AES_HASH_1R_XKEY11[8] = { 0x61b263d1, 0x51f4e03c, 0xee1043c6, 0xed18f99b, 0x61b263d1, 0x51f4e03c, 0xee1043c6, 0xed18f99b };
|
||||
|
||||
static constexpr uint32_t AES_HASH_STRIDE_X2[8] = { 0, 4, 8, 12, 32, 36, 40, 44 };
|
||||
static constexpr uint32_t AES_HASH_STRIDE_X4[8] = { 0, 4, 8, 12, 64, 68, 72, 76 };
|
||||
|
||||
void hashAes1Rx4_zvkned(const void *input, size_t inputSize, void *hash)
|
||||
{
|
||||
const uint8_t* inptr = (const uint8_t*)input;
|
||||
const uint8_t* inputEnd = inptr + inputSize;
|
||||
|
||||
//intial state
|
||||
vuint32m1_t state02 = __riscv_vle32_v_u32m1(AES_HASH_1R_STATE02, 8);
|
||||
vuint32m1_t state13 = __riscv_vle32_v_u32m1(AES_HASH_1R_STATE13, 8);
|
||||
|
||||
const vuint32m1_t stride = __riscv_vle32_v_u32m1(AES_HASH_STRIDE_X2, 8);
|
||||
const vuint32m1_t zero = {};
|
||||
|
||||
//process 64 bytes at a time in 4 lanes
|
||||
while (inptr < inputEnd) {
|
||||
state02 = aesenc_zvkned(state02, __riscv_vluxei32_v_u32m1((uint32_t*)inptr + 0, stride, 8));
|
||||
state13 = aesdec_zvkned(state13, __riscv_vluxei32_v_u32m1((uint32_t*)inptr + 4, stride, 8), zero);
|
||||
|
||||
inptr += 64;
|
||||
}
|
||||
|
||||
//two extra rounds to achieve full diffusion
|
||||
const vuint32m1_t xkey00 = __riscv_vle32_v_u32m1(AES_HASH_1R_XKEY00, 8);
|
||||
const vuint32m1_t xkey11 = __riscv_vle32_v_u32m1(AES_HASH_1R_XKEY11, 8);
|
||||
|
||||
state02 = aesenc_zvkned(state02, xkey00);
|
||||
state13 = aesdec_zvkned(state13, xkey00, zero);
|
||||
|
||||
state02 = aesenc_zvkned(state02, xkey11);
|
||||
state13 = aesdec_zvkned(state13, xkey11, zero);
|
||||
|
||||
//output hash
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)hash + 0, stride, state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)hash + 4, stride, state13, 8);
|
||||
}
|
||||
|
||||
void fillAes1Rx4_zvkned(void *state, size_t outputSize, void *buffer)
|
||||
{
|
||||
const uint8_t* outptr = (uint8_t*)buffer;
|
||||
const uint8_t* outputEnd = outptr + outputSize;
|
||||
|
||||
const vuint32m1_t key02 = __riscv_vle32_v_u32m1(AES_GEN_1R_KEY02, 8);
|
||||
const vuint32m1_t key13 = __riscv_vle32_v_u32m1(AES_GEN_1R_KEY13, 8);
|
||||
|
||||
const vuint32m1_t stride = __riscv_vle32_v_u32m1(AES_HASH_STRIDE_X2, 8);
|
||||
const vuint32m1_t zero = {};
|
||||
|
||||
vuint32m1_t state02 = __riscv_vluxei32_v_u32m1((uint32_t*)state + 0, stride, 8);
|
||||
vuint32m1_t state13 = __riscv_vluxei32_v_u32m1((uint32_t*)state + 4, stride, 8);
|
||||
|
||||
while (outptr < outputEnd) {
|
||||
state02 = aesdec_zvkned(state02, key02, zero);
|
||||
state13 = aesenc_zvkned(state13, key13);
|
||||
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)outptr + 0, stride, state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)outptr + 4, stride, state13, 8);
|
||||
|
||||
outptr += 64;
|
||||
}
|
||||
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)state + 0, stride, state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)state + 4, stride, state13, 8);
|
||||
}
|
||||
|
||||
void fillAes4Rx4_zvkned(void *state, size_t outputSize, void *buffer)
|
||||
{
|
||||
const uint8_t* outptr = (uint8_t*)buffer;
|
||||
const uint8_t* outputEnd = outptr + outputSize;
|
||||
|
||||
const vuint32m1_t stride4 = __riscv_vle32_v_u32m1(AES_HASH_STRIDE_X4, 8);
|
||||
|
||||
const vuint32m1_t key04 = __riscv_vluxei32_v_u32m1((uint32_t*)(RandomX_CurrentConfig.fillAes4Rx4_Key + 0), stride4, 8);
|
||||
const vuint32m1_t key15 = __riscv_vluxei32_v_u32m1((uint32_t*)(RandomX_CurrentConfig.fillAes4Rx4_Key + 1), stride4, 8);
|
||||
const vuint32m1_t key26 = __riscv_vluxei32_v_u32m1((uint32_t*)(RandomX_CurrentConfig.fillAes4Rx4_Key + 2), stride4, 8);
|
||||
const vuint32m1_t key37 = __riscv_vluxei32_v_u32m1((uint32_t*)(RandomX_CurrentConfig.fillAes4Rx4_Key + 3), stride4, 8);
|
||||
|
||||
const vuint32m1_t stride = __riscv_vle32_v_u32m1(AES_HASH_STRIDE_X2, 8);
|
||||
const vuint32m1_t zero = {};
|
||||
|
||||
vuint32m1_t state02 = __riscv_vluxei32_v_u32m1((uint32_t*)state + 0, stride, 8);
|
||||
vuint32m1_t state13 = __riscv_vluxei32_v_u32m1((uint32_t*)state + 4, stride, 8);
|
||||
|
||||
while (outptr < outputEnd) {
|
||||
state02 = aesdec_zvkned(state02, key04, zero);
|
||||
state13 = aesenc_zvkned(state13, key04);
|
||||
|
||||
state02 = aesdec_zvkned(state02, key15, zero);
|
||||
state13 = aesenc_zvkned(state13, key15);
|
||||
|
||||
state02 = aesdec_zvkned(state02, key26, zero);
|
||||
state13 = aesenc_zvkned(state13, key26);
|
||||
|
||||
state02 = aesdec_zvkned(state02, key37, zero);
|
||||
state13 = aesenc_zvkned(state13, key37);
|
||||
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)outptr + 0, stride, state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)outptr + 4, stride, state13, 8);
|
||||
|
||||
outptr += 64;
|
||||
}
|
||||
}
|
||||
|
||||
void hashAndFillAes1Rx4_zvkned(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state)
|
||||
{
|
||||
uint8_t* scratchpadPtr = (uint8_t*)scratchpad;
|
||||
const uint8_t* scratchpadEnd = scratchpadPtr + scratchpadSize;
|
||||
|
||||
vuint32m1_t hash_state02 = __riscv_vle32_v_u32m1(AES_HASH_1R_STATE02, 8);
|
||||
vuint32m1_t hash_state13 = __riscv_vle32_v_u32m1(AES_HASH_1R_STATE13, 8);
|
||||
|
||||
const vuint32m1_t key02 = __riscv_vle32_v_u32m1(AES_GEN_1R_KEY02, 8);
|
||||
const vuint32m1_t key13 = __riscv_vle32_v_u32m1(AES_GEN_1R_KEY13, 8);
|
||||
|
||||
const vuint32m1_t stride = __riscv_vle32_v_u32m1(AES_HASH_STRIDE_X2, 8);
|
||||
const vuint32m1_t zero = {};
|
||||
|
||||
vuint32m1_t fill_state02 = __riscv_vluxei32_v_u32m1((uint32_t*)fill_state + 0, stride, 8);
|
||||
vuint32m1_t fill_state13 = __riscv_vluxei32_v_u32m1((uint32_t*)fill_state + 4, stride, 8);
|
||||
|
||||
//process 64 bytes at a time in 4 lanes
|
||||
while (scratchpadPtr < scratchpadEnd) {
|
||||
hash_state02 = aesenc_zvkned(hash_state02, __riscv_vluxei32_v_u32m1((uint32_t*)scratchpadPtr + 0, stride, 8));
|
||||
hash_state13 = aesdec_zvkned(hash_state13, __riscv_vluxei32_v_u32m1((uint32_t*)scratchpadPtr + 4, stride, 8), zero);
|
||||
|
||||
fill_state02 = aesdec_zvkned(fill_state02, key02, zero);
|
||||
fill_state13 = aesenc_zvkned(fill_state13, key13);
|
||||
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)scratchpadPtr + 0, stride, fill_state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)scratchpadPtr + 4, stride, fill_state13, 8);
|
||||
|
||||
scratchpadPtr += 64;
|
||||
}
|
||||
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)fill_state + 0, stride, fill_state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)fill_state + 4, stride, fill_state13, 8);
|
||||
|
||||
//two extra rounds to achieve full diffusion
|
||||
const vuint32m1_t xkey00 = __riscv_vle32_v_u32m1(AES_HASH_1R_XKEY00, 8);
|
||||
const vuint32m1_t xkey11 = __riscv_vle32_v_u32m1(AES_HASH_1R_XKEY11, 8);
|
||||
|
||||
hash_state02 = aesenc_zvkned(hash_state02, xkey00);
|
||||
hash_state13 = aesdec_zvkned(hash_state13, xkey00, zero);
|
||||
|
||||
hash_state02 = aesenc_zvkned(hash_state02, xkey11);
|
||||
hash_state13 = aesdec_zvkned(hash_state13, xkey11, zero);
|
||||
|
||||
//output hash
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)hash + 0, stride, hash_state02, 8);
|
||||
__riscv_vsuxei32_v_u32m1((uint32_t*)hash + 4, stride, hash_state13, 8);
|
||||
}
|
||||
35
src/crypto/randomx/aes_hash_rv64_zvkned.hpp
Normal file
35
src/crypto/randomx/aes_hash_rv64_zvkned.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright (c) 2025 SChernykh <https://github.com/SChernykh>
|
||||
Copyright (c) 2025 XMRig <support@xmrig.com>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void hashAes1Rx4_zvkned(const void *input, size_t inputSize, void *hash);
|
||||
void fillAes1Rx4_zvkned(void *state, size_t outputSize, void *buffer);
|
||||
void fillAes4Rx4_zvkned(void *state, size_t outputSize, void *buffer);
|
||||
void hashAndFillAes1Rx4_zvkned(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state);
|
||||
148
src/crypto/randomx/aes_hash_vaes512.cpp
Normal file
148
src/crypto/randomx/aes_hash_vaes512.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright (c) 2018-2019, tevador <tevador@gmail.com>
|
||||
Copyright (c) 2026 XMRig <support@xmrig.com>
|
||||
Copyright (c) 2026 SChernykh <https://github.com/SChernykh>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <immintrin.h>
|
||||
|
||||
#define REVERSE_4(A, B, C, D) D, C, B, A
|
||||
|
||||
alignas(64) static const uint32_t AES_HASH_1R_STATE[] = {
|
||||
REVERSE_4(0xd7983aad, 0xcc82db47, 0x9fa856de, 0x92b52c0d),
|
||||
REVERSE_4(0xace78057, 0xf59e125a, 0x15c7b798, 0x338d996e),
|
||||
REVERSE_4(0xe8a07ce4, 0x5079506b, 0xae62c7d0, 0x6a770017),
|
||||
REVERSE_4(0x7e994948, 0x79a10005, 0x07ad828d, 0x630a240c)
|
||||
};
|
||||
|
||||
alignas(64) static const uint32_t AES_GEN_1R_KEY[] = {
|
||||
REVERSE_4(0xb4f44917, 0xdbb5552b, 0x62716609, 0x6daca553),
|
||||
REVERSE_4(0x0da1dc4e, 0x1725d378, 0x846a710d, 0x6d7caf07),
|
||||
REVERSE_4(0x3e20e345, 0xf4c0794f, 0x9f947ec6, 0x3f1262f1),
|
||||
REVERSE_4(0x49169154, 0x16314c88, 0xb1ba317c, 0x6aef8135)
|
||||
};
|
||||
|
||||
alignas(64) static const uint32_t AES_HASH_1R_XKEY0[] = {
|
||||
REVERSE_4(0x06890201, 0x90dc56bf, 0x8b24949f, 0xf6fa8389),
|
||||
REVERSE_4(0x06890201, 0x90dc56bf, 0x8b24949f, 0xf6fa8389),
|
||||
REVERSE_4(0x06890201, 0x90dc56bf, 0x8b24949f, 0xf6fa8389),
|
||||
REVERSE_4(0x06890201, 0x90dc56bf, 0x8b24949f, 0xf6fa8389)
|
||||
};
|
||||
|
||||
alignas(64) static const uint32_t AES_HASH_1R_XKEY1[] = {
|
||||
REVERSE_4(0xed18f99b, 0xee1043c6, 0x51f4e03c, 0x61b263d1),
|
||||
REVERSE_4(0xed18f99b, 0xee1043c6, 0x51f4e03c, 0x61b263d1),
|
||||
REVERSE_4(0xed18f99b, 0xee1043c6, 0x51f4e03c, 0x61b263d1),
|
||||
REVERSE_4(0xed18f99b, 0xee1043c6, 0x51f4e03c, 0x61b263d1)
|
||||
};
|
||||
|
||||
void hashAndFillAes1Rx4_VAES512(void *scratchpad, size_t scratchpadSize, void *hash, void* fill_state)
|
||||
{
|
||||
uint8_t* scratchpadPtr = (uint8_t*)scratchpad;
|
||||
const uint8_t* scratchpadEnd = scratchpadPtr + scratchpadSize;
|
||||
|
||||
const __m512i fill_key = _mm512_load_si512(AES_GEN_1R_KEY);
|
||||
|
||||
const __m512i initial_hash_state = _mm512_load_si512(AES_HASH_1R_STATE);
|
||||
const __m512i initial_fill_state = _mm512_load_si512(fill_state);
|
||||
|
||||
constexpr uint8_t mask = 0b11001100;
|
||||
|
||||
// enc_data[0] = hash_state[0]
|
||||
// enc_data[1] = fill_state[1]
|
||||
// enc_data[2] = hash_state[2]
|
||||
// enc_data[3] = fill_state[3]
|
||||
__m512i enc_data = _mm512_mask_blend_epi64(mask, initial_hash_state, initial_fill_state);
|
||||
|
||||
// dec_data[0] = fill_state[0]
|
||||
// dec_data[1] = hash_state[1]
|
||||
// dec_data[2] = fill_state[2]
|
||||
// dec_data[3] = hash_state[3]
|
||||
__m512i dec_data = _mm512_mask_blend_epi64(mask, initial_fill_state, initial_hash_state);
|
||||
|
||||
constexpr int PREFETCH_DISTANCE = 7168;
|
||||
|
||||
const uint8_t* prefetchPtr = scratchpadPtr + PREFETCH_DISTANCE;
|
||||
scratchpadEnd -= PREFETCH_DISTANCE;
|
||||
|
||||
for (const uint8_t* p = scratchpadPtr; p < prefetchPtr; p += 256) {
|
||||
_mm_prefetch((const char*)(p + 0), _MM_HINT_T0);
|
||||
_mm_prefetch((const char*)(p + 64), _MM_HINT_T0);
|
||||
_mm_prefetch((const char*)(p + 128), _MM_HINT_T0);
|
||||
_mm_prefetch((const char*)(p + 192), _MM_HINT_T0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
while (scratchpadPtr < scratchpadEnd) {
|
||||
const __m512i scratchpad_data = _mm512_load_si512(scratchpadPtr);
|
||||
|
||||
// enc_key[0] = scratchpad_data[0]
|
||||
// enc_key[1] = fill_key[1]
|
||||
// enc_key[2] = scratchpad_data[2]
|
||||
// enc_key[3] = fill_key[3]
|
||||
enc_data = _mm512_aesenc_epi128(enc_data, _mm512_mask_blend_epi64(mask, scratchpad_data, fill_key));
|
||||
|
||||
// dec_key[0] = fill_key[0]
|
||||
// dec_key[1] = scratchpad_data[1]
|
||||
// dec_key[2] = fill_key[2]
|
||||
// dec_key[3] = scratchpad_data[3]
|
||||
dec_data = _mm512_aesdec_epi128(dec_data, _mm512_mask_blend_epi64(mask, fill_key, scratchpad_data));
|
||||
|
||||
// fill_state[0] = dec_data[0]
|
||||
// fill_state[1] = enc_data[1]
|
||||
// fill_state[2] = dec_data[2]
|
||||
// fill_state[3] = enc_data[3]
|
||||
_mm512_store_si512(scratchpadPtr, _mm512_mask_blend_epi64(mask, dec_data, enc_data));
|
||||
|
||||
_mm_prefetch((const char*)prefetchPtr, _MM_HINT_T0);
|
||||
|
||||
scratchpadPtr += 64;
|
||||
prefetchPtr += 64;
|
||||
}
|
||||
prefetchPtr = (const uint8_t*) scratchpad;
|
||||
scratchpadEnd += PREFETCH_DISTANCE;
|
||||
}
|
||||
|
||||
_mm512_store_si512(fill_state, _mm512_mask_blend_epi64(mask, dec_data, enc_data));
|
||||
|
||||
//two extra rounds to achieve full diffusion
|
||||
const __m512i xkey0 = _mm512_load_si512(AES_HASH_1R_XKEY0);
|
||||
const __m512i xkey1 = _mm512_load_si512(AES_HASH_1R_XKEY1);
|
||||
|
||||
enc_data = _mm512_aesenc_epi128(enc_data, xkey0);
|
||||
dec_data = _mm512_aesdec_epi128(dec_data, xkey0);
|
||||
enc_data = _mm512_aesenc_epi128(enc_data, xkey1);
|
||||
dec_data = _mm512_aesdec_epi128(dec_data, xkey1);
|
||||
|
||||
//output hash
|
||||
_mm512_store_si512(hash, _mm512_mask_blend_epi64(mask, enc_data, dec_data));
|
||||
|
||||
// Just in case
|
||||
_mm256_zeroupper();
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
;# save VM register values
|
||||
add rsp, 40
|
||||
add rsp, 248
|
||||
pop rcx
|
||||
mov qword ptr [rcx+0], r8
|
||||
mov qword ptr [rcx+8], r9
|
||||
|
||||
30
src/crypto/randomx/asm/program_loop_store_hard_aes.inc
Normal file
30
src/crypto/randomx/asm/program_loop_store_hard_aes.inc
Normal file
@@ -0,0 +1,30 @@
|
||||
mov rcx, [rsp+24]
|
||||
mov qword ptr [rcx+0], r8
|
||||
mov qword ptr [rcx+8], r9
|
||||
mov qword ptr [rcx+16], r10
|
||||
mov qword ptr [rcx+24], r11
|
||||
mov qword ptr [rcx+32], r12
|
||||
mov qword ptr [rcx+40], r13
|
||||
mov qword ptr [rcx+48], r14
|
||||
mov qword ptr [rcx+56], r15
|
||||
mov rcx, [rsp+16]
|
||||
aesenc xmm0, xmm4
|
||||
aesdec xmm1, xmm4
|
||||
aesenc xmm2, xmm4
|
||||
aesdec xmm3, xmm4
|
||||
aesenc xmm0, xmm5
|
||||
aesdec xmm1, xmm5
|
||||
aesenc xmm2, xmm5
|
||||
aesdec xmm3, xmm5
|
||||
aesenc xmm0, xmm6
|
||||
aesdec xmm1, xmm6
|
||||
aesenc xmm2, xmm6
|
||||
aesdec xmm3, xmm6
|
||||
aesenc xmm0, xmm7
|
||||
aesdec xmm1, xmm7
|
||||
aesenc xmm2, xmm7
|
||||
aesdec xmm3, xmm7
|
||||
movapd xmmword ptr [rcx+0], xmm0
|
||||
movapd xmmword ptr [rcx+16], xmm1
|
||||
movapd xmmword ptr [rcx+32], xmm2
|
||||
movapd xmmword ptr [rcx+48], xmm3
|
||||
196
src/crypto/randomx/asm/program_loop_store_soft_aes.inc
Normal file
196
src/crypto/randomx/asm/program_loop_store_soft_aes.inc
Normal file
@@ -0,0 +1,196 @@
|
||||
mov rcx, [rsp+24]
|
||||
mov qword ptr [rcx+0], r8
|
||||
mov qword ptr [rcx+8], r9
|
||||
mov qword ptr [rcx+16], r10
|
||||
mov qword ptr [rcx+24], r11
|
||||
mov qword ptr [rcx+32], r12
|
||||
mov qword ptr [rcx+40], r13
|
||||
mov qword ptr [rcx+48], r14
|
||||
mov qword ptr [rcx+56], r15
|
||||
|
||||
movapd xmmword ptr [rsp+40], xmm0
|
||||
movapd xmmword ptr [rsp+56], xmm1
|
||||
movapd xmmword ptr [rsp+72], xmm2
|
||||
movapd xmmword ptr [rsp+88], xmm3
|
||||
movapd xmmword ptr [rsp+104], xmm4
|
||||
movapd xmmword ptr [rsp+120], xmm5
|
||||
movapd xmmword ptr [rsp+136], xmm6
|
||||
movapd xmmword ptr [rsp+152], xmm7
|
||||
|
||||
mov [rsp+168], rax
|
||||
mov [rsp+176], rbx
|
||||
mov [rsp+184], rdx
|
||||
mov [rsp+192], rsi
|
||||
mov [rsp+200], rdi
|
||||
mov [rsp+208], rbp
|
||||
mov [rsp+216], r8
|
||||
mov [rsp+224], r9
|
||||
|
||||
mov r8, [rsp+232] ;# aes_lut_enc
|
||||
mov r9, [rsp+240] ;# aes_lut_dec
|
||||
|
||||
movapd xmm12, xmmword ptr [rsp-8] ;# "call" will overwrite IMUL_RCP's data on stack, so save it
|
||||
|
||||
lea rsi, [rsp+104]
|
||||
lea rdi, [rsp+40]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+56]
|
||||
call soft_aes_dec
|
||||
lea rdi, [rsp+72]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+88]
|
||||
call soft_aes_dec
|
||||
|
||||
lea rsi, [rsp+120]
|
||||
lea rdi, [rsp+40]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+56]
|
||||
call soft_aes_dec
|
||||
lea rdi, [rsp+72]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+88]
|
||||
call soft_aes_dec
|
||||
|
||||
lea rsi, [rsp+136]
|
||||
lea rdi, [rsp+40]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+56]
|
||||
call soft_aes_dec
|
||||
lea rdi, [rsp+72]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+88]
|
||||
call soft_aes_dec
|
||||
|
||||
lea rsi, [rsp+152]
|
||||
lea rdi, [rsp+40]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+56]
|
||||
call soft_aes_dec
|
||||
lea rdi, [rsp+72]
|
||||
call soft_aes_enc
|
||||
lea rdi, [rsp+88]
|
||||
call soft_aes_dec
|
||||
|
||||
movapd xmmword ptr [rsp-8], xmm12
|
||||
|
||||
jmp soft_aes_end
|
||||
|
||||
soft_aes_enc:
|
||||
mov eax, dword ptr [rsi+0]
|
||||
mov ebx, dword ptr [rsi+4]
|
||||
mov ecx, dword ptr [rsi+8]
|
||||
mov edx, dword ptr [rsi+12]
|
||||
|
||||
movzx ebp, byte ptr [rdi+0]
|
||||
xor eax, dword ptr [r8+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+1]
|
||||
xor edx, dword ptr [r8+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+2]
|
||||
xor ecx, dword ptr [r8+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+3]
|
||||
xor ebx, dword ptr [r8+rbp*4+3072]
|
||||
|
||||
movzx ebp, byte ptr [rdi+4]
|
||||
xor ebx, dword ptr [r8+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+5]
|
||||
xor eax, dword ptr [r8+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+6]
|
||||
xor edx, dword ptr [r8+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+7]
|
||||
xor ecx, dword ptr [r8+rbp*4+3072]
|
||||
|
||||
movzx ebp, byte ptr [rdi+8]
|
||||
xor ecx, dword ptr [r8+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+9]
|
||||
xor ebx, dword ptr [r8+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+10]
|
||||
xor eax, dword ptr [r8+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+11]
|
||||
xor edx, dword ptr [r8+rbp*4+3072]
|
||||
|
||||
movzx ebp, byte ptr [rdi+12]
|
||||
xor edx, dword ptr [r8+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+13]
|
||||
xor ecx, dword ptr [r8+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+14]
|
||||
xor ebx, dword ptr [r8+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+15]
|
||||
xor eax, dword ptr [r8+rbp*4+3072]
|
||||
|
||||
mov dword ptr [rdi+0], eax
|
||||
mov dword ptr [rdi+4], ebx
|
||||
mov dword ptr [rdi+8], ecx
|
||||
mov dword ptr [rdi+12], edx
|
||||
|
||||
ret
|
||||
|
||||
soft_aes_dec:
|
||||
mov eax, dword ptr [rsi+0]
|
||||
mov ebx, dword ptr [rsi+4]
|
||||
mov ecx, dword ptr [rsi+8]
|
||||
mov edx, dword ptr [rsi+12]
|
||||
|
||||
movzx ebp, byte ptr [rdi+0]
|
||||
xor eax, dword ptr [r9+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+1]
|
||||
xor ebx, dword ptr [r9+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+2]
|
||||
xor ecx, dword ptr [r9+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+3]
|
||||
xor edx, dword ptr [r9+rbp*4+3072]
|
||||
|
||||
movzx ebp, byte ptr [rdi+4]
|
||||
xor ebx, dword ptr [r9+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+5]
|
||||
xor ecx, dword ptr [r9+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+6]
|
||||
xor edx, dword ptr [r9+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+7]
|
||||
xor eax, dword ptr [r9+rbp*4+3072]
|
||||
|
||||
movzx ebp, byte ptr [rdi+8]
|
||||
xor ecx, dword ptr [r9+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+9]
|
||||
xor edx, dword ptr [r9+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+10]
|
||||
xor eax, dword ptr [r9+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+11]
|
||||
xor ebx, dword ptr [r9+rbp*4+3072]
|
||||
|
||||
movzx ebp, byte ptr [rdi+12]
|
||||
xor edx, dword ptr [r9+rbp*4]
|
||||
movzx ebp, byte ptr [rdi+13]
|
||||
xor eax, dword ptr [r9+rbp*4+1024]
|
||||
movzx ebp, byte ptr [rdi+14]
|
||||
xor ebx, dword ptr [r9+rbp*4+2048]
|
||||
movzx ebp, byte ptr [rdi+15]
|
||||
xor ecx, dword ptr [r9+rbp*4+3072]
|
||||
|
||||
mov dword ptr [rdi+0], eax
|
||||
mov dword ptr [rdi+4], ebx
|
||||
mov dword ptr [rdi+8], ecx
|
||||
mov dword ptr [rdi+12], edx
|
||||
|
||||
ret
|
||||
|
||||
soft_aes_end:
|
||||
|
||||
mov rax, [rsp+168]
|
||||
mov rbx, [rsp+176]
|
||||
mov rcx, [rsp+16]
|
||||
mov rdx, [rsp+184]
|
||||
mov rsi, [rsp+192]
|
||||
mov rdi, [rsp+200]
|
||||
mov rbp, [rsp+208]
|
||||
mov r8, [rsp+216]
|
||||
mov r9, [rsp+224]
|
||||
|
||||
movapd xmm0, xmmword ptr [rsp+40]
|
||||
movapd xmm1, xmmword ptr [rsp+56]
|
||||
movapd xmm2, xmmword ptr [rsp+72]
|
||||
movapd xmm3, xmmword ptr [rsp+88]
|
||||
|
||||
movapd xmmword ptr [rcx+0], xmm0
|
||||
movapd xmmword ptr [rcx+16], xmm1
|
||||
movapd xmmword ptr [rcx+32], xmm2
|
||||
movapd xmmword ptr [rcx+48], xmm3
|
||||
@@ -13,12 +13,6 @@
|
||||
mov rbp, qword ptr [rsi] ;# "mx", "ma"
|
||||
mov rdi, qword ptr [rsi+8] ;# uint8_t* dataset
|
||||
|
||||
;# dataset prefetch for the first iteration of the main loop
|
||||
mov rax, rbp
|
||||
shr rax, 32
|
||||
and eax, RANDOMX_DATASET_BASE_MASK
|
||||
prefetchnta byte ptr [rdi+rax]
|
||||
|
||||
mov rsi, rdx ;# uint8_t* scratchpad
|
||||
|
||||
mov rax, rbp
|
||||
|
||||
@@ -25,12 +25,6 @@
|
||||
mov rbp, qword ptr [rdx] ;# "mx", "ma"
|
||||
mov rdi, qword ptr [rdx+8] ;# uint8_t* dataset
|
||||
|
||||
;# dataset prefetch for the first iteration of the main loop
|
||||
mov rax, rbp
|
||||
shr rax, 32
|
||||
and eax, RANDOMX_DATASET_BASE_MASK
|
||||
prefetchnta byte ptr [rdi+rax]
|
||||
|
||||
mov rsi, r8 ;# uint8_t* scratchpad
|
||||
mov rbx, r9 ;# loop counter
|
||||
|
||||
|
||||
16
src/crypto/randomx/asm/program_read_dataset_v2.inc
Normal file
16
src/crypto/randomx/asm/program_read_dataset_v2.inc
Normal file
@@ -0,0 +1,16 @@
|
||||
mov ecx, ebp ;# ecx = ma
|
||||
and ecx, RANDOMX_DATASET_BASE_MASK
|
||||
xor r8, qword ptr [rdi+rcx]
|
||||
xor rbp, rax ;# modify "ma"
|
||||
mov edx, ebp ;# edx = "ma"
|
||||
ror rbp, 32 ;# swap "ma" and "mx"
|
||||
and edx, RANDOMX_DATASET_BASE_MASK
|
||||
prefetchnta byte ptr [rdi+rdx]
|
||||
xor r9, qword ptr [rdi+rcx+8]
|
||||
xor r10, qword ptr [rdi+rcx+16]
|
||||
xor r11, qword ptr [rdi+rcx+24]
|
||||
xor r12, qword ptr [rdi+rcx+32]
|
||||
xor r13, qword ptr [rdi+rcx+40]
|
||||
xor r14, qword ptr [rdi+rcx+48]
|
||||
xor r15, qword ptr [rdi+rcx+56]
|
||||
|
||||
@@ -225,7 +225,10 @@ namespace randomx {
|
||||
}
|
||||
|
||||
static void exe_CFROUND(RANDOMX_EXE_ARGS) {
|
||||
rx_set_rounding_mode(rotr64(*ibc.isrc, static_cast<uint32_t>(ibc.imm)) % 4);
|
||||
uint64_t isrc = rotr64(*ibc.isrc, ibc.imm);
|
||||
if (!RandomX_CurrentConfig.Tweak_V2_CFROUND || ((isrc & 60) == 0)) {
|
||||
rx_set_rounding_mode(isrc % 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void exe_ISTORE(RANDOMX_EXE_ARGS) {
|
||||
|
||||
@@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define RANDOMX_DATASET_MAX_SIZE 2181038080
|
||||
|
||||
// Increase it if some configs use larger programs
|
||||
#define RANDOMX_PROGRAM_MAX_SIZE 280
|
||||
#define RANDOMX_PROGRAM_MAX_SIZE 384
|
||||
|
||||
// Increase it if some configs use larger scratchpad
|
||||
#define RANDOMX_SCRATCHPAD_L3_MAX_SIZE 2097152
|
||||
|
||||
@@ -174,7 +174,7 @@ FORCE_INLINE void rx_set_rounding_mode(uint32_t mode) {
|
||||
_mm_setcsr(rx_mxcsr_default | (mode << 13));
|
||||
}
|
||||
|
||||
#elif defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) //sadly only POWER7 and newer will be able to use SIMD acceleration. Earlier processors cant use doubles or 64 bit integers with SIMD
|
||||
#elif defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__) //sadly only POWER7 and newer will be able to use SIMD acceleration. Earlier processors can't use doubles or 64 bit integers with SIMD
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
@@ -420,7 +420,7 @@ inline void* rx_aligned_alloc(size_t size, size_t align) {
|
||||
# define rx_aligned_free(a) free(a)
|
||||
#endif
|
||||
|
||||
inline void rx_prefetch_nta(void* ptr) {
|
||||
inline void rx_prefetch_nta(const void* ptr) {
|
||||
asm volatile ("prfm pldl1strm, [%0]\n" : : "r" (ptr));
|
||||
}
|
||||
|
||||
@@ -577,8 +577,13 @@ inline void* rx_aligned_alloc(size_t size, size_t align) {
|
||||
# define rx_aligned_free(a) free(a)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (!defined(__clang__) || __has_builtin(__builtin_prefetch))
|
||||
#define rx_prefetch_nta(x) __builtin_prefetch((x), 0, 0)
|
||||
#define rx_prefetch_t0(x) __builtin_prefetch((x), 0, 3)
|
||||
#else
|
||||
#define rx_prefetch_nta(x)
|
||||
#define rx_prefetch_t0(x)
|
||||
#endif
|
||||
|
||||
FORCE_INLINE rx_vec_f128 rx_load_vec_f128(const double* pd) {
|
||||
rx_vec_f128 x;
|
||||
|
||||
@@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "crypto/randomx/reciprocal.h"
|
||||
#include "crypto/randomx/superscalar.hpp"
|
||||
#include "crypto/randomx/virtual_memory.hpp"
|
||||
#include "crypto/randomx/soft_aes.h"
|
||||
|
||||
static bool hugePagesJIT = false;
|
||||
static int optimizedDatasetInit = -1;
|
||||
@@ -114,7 +115,7 @@ JitCompilerA64::~JitCompilerA64()
|
||||
freePagedMemory(code, allocatedSize);
|
||||
}
|
||||
|
||||
void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& config, uint32_t)
|
||||
void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& config, uint32_t flags)
|
||||
{
|
||||
if (!allocatedSize) {
|
||||
allocate(CodeSize);
|
||||
@@ -125,6 +126,8 @@ void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& con
|
||||
}
|
||||
#endif
|
||||
|
||||
vm_flags = flags;
|
||||
|
||||
uint32_t codePos = MainLoopBegin + 4;
|
||||
|
||||
uint32_t mask = ((RandomX_CurrentConfig.Log2_ScratchpadL3 - 7) << 10);
|
||||
@@ -156,9 +159,9 @@ void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& con
|
||||
emit32(ARMV8A::B | (offset / 4), code, codePos);
|
||||
|
||||
mask = ((RandomX_CurrentConfig.Log2_DatasetBaseSize - 7) << 10);
|
||||
// and w20, w9, CacheLineAlignMask
|
||||
// and w20, w20, CacheLineAlignMask
|
||||
codePos = (((uint8_t*)randomx_program_aarch64_cacheline_align_mask1) - ((uint8_t*)randomx_program_aarch64));
|
||||
emit32(0x121A0000 | 20 | (9 << 5) | mask, code, codePos);
|
||||
emit32(0x121A0000 | 20 | (20 << 5) | mask, code, codePos);
|
||||
|
||||
// and w10, w10, CacheLineAlignMask
|
||||
codePos = (((uint8_t*)randomx_program_aarch64_cacheline_align_mask2) - ((uint8_t*)randomx_program_aarch64));
|
||||
@@ -169,6 +172,43 @@ void JitCompilerA64::generateProgram(Program& program, ProgramConfiguration& con
|
||||
codePos = ((uint8_t*)randomx_program_aarch64_update_spMix1) - ((uint8_t*)randomx_program_aarch64);
|
||||
emit32(ARMV8A::EOR | 10 | (IntRegMap[config.readReg0] << 5) | (IntRegMap[config.readReg1] << 16), code, codePos);
|
||||
|
||||
codePos = ((uint8_t*)randomx_program_aarch64_v2_FE_mix) - ((uint8_t*)randomx_program_aarch64);
|
||||
|
||||
// Enable RandomX v2 AES tweak
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES) {
|
||||
if (flags & RANDOMX_FLAG_HARD_AES) {
|
||||
// Disable the jump to RandomX v1 FE mix code by writing "movi v28.4s, 0" instruction
|
||||
emit32(0x4F00041C, code, codePos);
|
||||
}
|
||||
else {
|
||||
// Jump to RandomX v2 FE mix soft AES code by writing "b randomx_program_aarch64_v2_FE_mix_soft_aes" instruction
|
||||
uint32_t offset = (uint8_t*)randomx_program_aarch64_v2_FE_mix_soft_aes - (uint8_t*)randomx_program_aarch64_v2_FE_mix;
|
||||
emit32(ARMV8A::B | (offset / 4), code, codePos);
|
||||
|
||||
offset = (uint8_t*)randomx_program_aarch64_aes_lut_pointers - (uint8_t*)randomx_program_aarch64;
|
||||
|
||||
*(uint64_t*)(code + offset + 0) = (uint64_t) &lutEnc[0][0];
|
||||
*(uint64_t*)(code + offset + 8) = (uint64_t) &lutDec[0][0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Restore the jump to RandomX v1 FE mix code
|
||||
const uint32_t offset = (uint8_t*)randomx_program_aarch64_v1_FE_mix - (uint8_t*)randomx_program_aarch64_v2_FE_mix;
|
||||
emit32(ARMV8A::B | (offset / 4), code, codePos);
|
||||
}
|
||||
|
||||
// Apply v2 prefetch tweak
|
||||
if (RandomX_CurrentConfig.Tweak_V2_PREFETCH) {
|
||||
uint32_t dst = (((uint8_t*)randomx_program_aarch64_vm_instructions_end) - ((uint8_t*)randomx_program_aarch64));
|
||||
uint32_t src = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_v2) - ((uint8_t*)randomx_program_aarch64));
|
||||
memcpy(code + dst, code + src, 16);
|
||||
}
|
||||
else {
|
||||
uint32_t dst = (((uint8_t*)randomx_program_aarch64_vm_instructions_end) - ((uint8_t*)randomx_program_aarch64));
|
||||
uint32_t src = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_v1) - ((uint8_t*)randomx_program_aarch64));
|
||||
memcpy(code + dst, code + src, 16);
|
||||
}
|
||||
|
||||
# ifndef XMRIG_OS_APPLE
|
||||
xmrig::VirtualMemory::flushInstructionCache(reinterpret_cast<char*>(code + MainLoopBegin), codePos - MainLoopBegin);
|
||||
# endif
|
||||
@@ -210,19 +250,56 @@ void JitCompilerA64::generateProgramLight(Program& program, ProgramConfiguration
|
||||
// eor w20, config.readReg2, config.readReg3
|
||||
emit32(ARMV8A::EOR32 | 20 | (IntRegMap[config.readReg2] << 5) | (IntRegMap[config.readReg3] << 16), code, codePos);
|
||||
|
||||
// Apply v2 prefetch tweak
|
||||
if (RandomX_CurrentConfig.Tweak_V2_PREFETCH) {
|
||||
uint32_t dst = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_light_tweak) - ((uint8_t*)randomx_program_aarch64));
|
||||
uint32_t src = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_light_v2) - ((uint8_t*)randomx_program_aarch64));
|
||||
memcpy(code + dst, code + src, 8);
|
||||
}
|
||||
else {
|
||||
uint32_t dst = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_light_tweak) - ((uint8_t*)randomx_program_aarch64));
|
||||
uint32_t src = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_light_v1) - ((uint8_t*)randomx_program_aarch64));
|
||||
memcpy(code + dst, code + src, 8);
|
||||
}
|
||||
|
||||
// Jump back to the main loop
|
||||
const uint32_t offset = (((uint8_t*)randomx_program_aarch64_vm_instructions_end_light) - ((uint8_t*)randomx_program_aarch64)) - codePos;
|
||||
emit32(ARMV8A::B | (offset / 4), code, codePos);
|
||||
|
||||
// and w2, w9, CacheLineAlignMask
|
||||
// and w2, w2, CacheLineAlignMask
|
||||
codePos = (((uint8_t*)randomx_program_aarch64_light_cacheline_align_mask) - ((uint8_t*)randomx_program_aarch64));
|
||||
emit32(0x121A0000 | 2 | (9 << 5) | ((RandomX_CurrentConfig.Log2_DatasetBaseSize - 7) << 10), code, codePos);
|
||||
emit32(0x121A0000 | 2 | (2 << 5) | ((RandomX_CurrentConfig.Log2_DatasetBaseSize - 7) << 10), code, codePos);
|
||||
|
||||
// Update spMix1
|
||||
// eor x10, config.readReg0, config.readReg1
|
||||
codePos = ((uint8_t*)randomx_program_aarch64_update_spMix1) - ((uint8_t*)randomx_program_aarch64);
|
||||
emit32(ARMV8A::EOR | 10 | (IntRegMap[config.readReg0] << 5) | (IntRegMap[config.readReg1] << 16), code, codePos);
|
||||
|
||||
codePos = ((uint8_t*)randomx_program_aarch64_v2_FE_mix) - ((uint8_t*)randomx_program_aarch64);
|
||||
|
||||
// Enable RandomX v2 AES tweak
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES) {
|
||||
if (vm_flags & RANDOMX_FLAG_HARD_AES) {
|
||||
// Disable the jump to RandomX v1 FE mix code by writing "movi v28.4s, 0" instruction
|
||||
emit32(0x4F00041C, code, codePos);
|
||||
}
|
||||
else {
|
||||
// Jump to RandomX v2 FE mix soft AES code by writing "b randomx_program_aarch64_v2_FE_mix_soft_aes" instruction
|
||||
uint32_t offset = (uint8_t*)randomx_program_aarch64_v2_FE_mix_soft_aes - (uint8_t*)randomx_program_aarch64_v2_FE_mix;
|
||||
emit32(ARMV8A::B | (offset / 4), code, codePos);
|
||||
|
||||
offset = (uint8_t*)randomx_program_aarch64_aes_lut_pointers - (uint8_t*)randomx_program_aarch64;
|
||||
|
||||
*(uint64_t*)(code + offset + 0) = (uint64_t) &lutEnc[0][0];
|
||||
*(uint64_t*)(code + offset + 8) = (uint64_t) &lutDec[0][0];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Restore the jump to RandomX v1 FE mix code
|
||||
const uint32_t offset = (uint8_t*)randomx_program_aarch64_v1_FE_mix - (uint8_t*)randomx_program_aarch64_v2_FE_mix;
|
||||
emit32(ARMV8A::B | (offset / 4), code, codePos);
|
||||
}
|
||||
|
||||
// Apply dataset offset
|
||||
codePos = ((uint8_t*)randomx_program_aarch64_light_dataset_offset) - ((uint8_t*)randomx_program_aarch64);
|
||||
|
||||
@@ -1035,20 +1112,20 @@ void JitCompilerA64::h_CFROUND(Instruction& instr, uint32_t& codePos)
|
||||
constexpr uint32_t tmp_reg = 20;
|
||||
constexpr uint32_t fpcr_tmp_reg = 8;
|
||||
|
||||
if (instr.getImm32() & 63)
|
||||
{
|
||||
// ror tmp_reg, src, imm
|
||||
emit32(ARMV8A::ROR_IMM | tmp_reg | (src << 5) | ((instr.getImm32() & 63) << 10) | (src << 16), code, k);
|
||||
// ror tmp_reg, src, imm
|
||||
emit32(ARMV8A::ROR_IMM | tmp_reg | (src << 5) | ((instr.getImm32() & 63) << 10) | (src << 16), code, k);
|
||||
|
||||
// bfi fpcr_tmp_reg, tmp_reg, 40, 2
|
||||
emit32(0xB3580400 | fpcr_tmp_reg | (tmp_reg << 5), code, k);
|
||||
}
|
||||
else // no rotation
|
||||
{
|
||||
// bfi fpcr_tmp_reg, src, 40, 2
|
||||
emit32(0xB3580400 | fpcr_tmp_reg | (src << 5), code, k);
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
// tst tmp_reg, 60
|
||||
emit32(0xF27E0E9F, code, k);
|
||||
|
||||
// bne next
|
||||
emit32(0x54000081, code, k);
|
||||
}
|
||||
|
||||
// bfi fpcr_tmp_reg, tmp_reg, 40, 2
|
||||
emit32(0xB3580400 | fpcr_tmp_reg | (tmp_reg << 5), code, k);
|
||||
|
||||
// rbit tmp_reg, fpcr_tmp_reg
|
||||
emit32(0xDAC00000 | tmp_reg | (fpcr_tmp_reg << 5), code, k);
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ namespace randomx {
|
||||
uint32_t literalPos;
|
||||
uint32_t num32bitLiterals = 0;
|
||||
size_t allocatedSize = 0;
|
||||
uint32_t vm_flags = 0;
|
||||
|
||||
void allocate(size_t size);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#define DECL(x) x
|
||||
#endif
|
||||
|
||||
.arch armv8-a
|
||||
.arch armv8-a+crypto
|
||||
.text
|
||||
.global DECL(randomx_program_aarch64)
|
||||
.global DECL(randomx_program_aarch64_main_loop)
|
||||
@@ -41,9 +41,18 @@
|
||||
.global DECL(randomx_program_aarch64_cacheline_align_mask1)
|
||||
.global DECL(randomx_program_aarch64_cacheline_align_mask2)
|
||||
.global DECL(randomx_program_aarch64_update_spMix1)
|
||||
.global DECL(randomx_program_aarch64_v2_FE_mix)
|
||||
.global DECL(randomx_program_aarch64_v1_FE_mix)
|
||||
.global DECL(randomx_program_aarch64_v2_FE_mix_soft_aes)
|
||||
.global DECL(randomx_program_aarch64_aes_lut_pointers)
|
||||
.global DECL(randomx_program_aarch64_vm_instructions_end_light)
|
||||
.global DECL(randomx_program_aarch64_vm_instructions_end_light_tweak)
|
||||
.global DECL(randomx_program_aarch64_light_cacheline_align_mask)
|
||||
.global DECL(randomx_program_aarch64_light_dataset_offset)
|
||||
.global DECL(randomx_program_aarch64_vm_instructions_end_v1)
|
||||
.global DECL(randomx_program_aarch64_vm_instructions_end_v2)
|
||||
.global DECL(randomx_program_aarch64_vm_instructions_end_light_v1)
|
||||
.global DECL(randomx_program_aarch64_vm_instructions_end_light_v2)
|
||||
.global DECL(randomx_init_dataset_aarch64)
|
||||
.global DECL(randomx_init_dataset_aarch64_end)
|
||||
.global DECL(randomx_calc_dataset_item_aarch64)
|
||||
@@ -242,8 +251,8 @@ DECL(randomx_program_aarch64_main_loop):
|
||||
# Execute VM instructions
|
||||
DECL(randomx_program_aarch64_vm_instructions):
|
||||
|
||||
# 16 KB buffer for generated instructions
|
||||
.fill 4096,4,0
|
||||
# 24 KB buffer for generated instructions
|
||||
.fill 6144,4,0
|
||||
|
||||
literal_x0: .fill 1,8,0
|
||||
literal_x11: .fill 1,8,0
|
||||
@@ -285,17 +294,19 @@ DECL(randomx_program_aarch64_vm_instructions_end):
|
||||
eor x9, x9, x20
|
||||
|
||||
# Calculate dataset pointer for dataset prefetch
|
||||
mov w20, w9
|
||||
|
||||
# mx <-> ma
|
||||
ror x9, x9, 32
|
||||
|
||||
DECL(randomx_program_aarch64_cacheline_align_mask1):
|
||||
# Actual mask will be inserted by JIT compiler
|
||||
and x20, x9, 1
|
||||
and x20, x20, 1
|
||||
add x20, x20, x1
|
||||
|
||||
# Prefetch dataset data
|
||||
prfm pldl2strm, [x20]
|
||||
|
||||
# mx <-> ma
|
||||
ror x9, x9, 32
|
||||
|
||||
DECL(randomx_program_aarch64_cacheline_align_mask2):
|
||||
# Actual mask will be inserted by JIT compiler
|
||||
and x10, x10, 1
|
||||
@@ -326,12 +337,93 @@ DECL(randomx_program_aarch64_update_spMix1):
|
||||
stp x12, x13, [x17, 32]
|
||||
stp x14, x15, [x17, 48]
|
||||
|
||||
# xor group F and group E registers
|
||||
# RandomX v2 AES tweak (mix group F and group E registers using AES)
|
||||
DECL(randomx_program_aarch64_v2_FE_mix):
|
||||
|
||||
# Jump to v1 FE mix code if we're running RandomX v1
|
||||
# JIT compiler will write a "movi v28.4s, 0" (set v28 to all 0) here if we're running RandomX v2
|
||||
# Or, JIT compiler will write a "b randomx_program_aarch64_v2_FE_mix_soft_aes" if we're running RandomX v2 with soft AES
|
||||
b DECL(randomx_program_aarch64_v1_FE_mix)
|
||||
|
||||
# f0 = aesenc(f0, e0), f1 = aesdec(f1, e0), f2 = aesenc(f2, e0), f3 = aesdec(f3, e0)
|
||||
|
||||
aese v16.16b, v28.16b
|
||||
aesd v17.16b, v28.16b
|
||||
aese v18.16b, v28.16b
|
||||
aesd v19.16b, v28.16b
|
||||
|
||||
aesmc v16.16b, v16.16b
|
||||
aesimc v17.16b, v17.16b
|
||||
aesmc v18.16b, v18.16b
|
||||
aesimc v19.16b, v19.16b
|
||||
|
||||
eor v16.16b, v16.16b, v20.16b
|
||||
eor v17.16b, v17.16b, v20.16b
|
||||
eor v18.16b, v18.16b, v20.16b
|
||||
eor v19.16b, v19.16b, v20.16b
|
||||
|
||||
# f0 = aesenc(f0, e1), f1 = aesdec(f1, e1), f2 = aesenc(f2, e1), f3 = aesdec(f3, e1)
|
||||
|
||||
aese v16.16b, v28.16b
|
||||
aesd v17.16b, v28.16b
|
||||
aese v18.16b, v28.16b
|
||||
aesd v19.16b, v28.16b
|
||||
|
||||
aesmc v16.16b, v16.16b
|
||||
aesimc v17.16b, v17.16b
|
||||
aesmc v18.16b, v18.16b
|
||||
aesimc v19.16b, v19.16b
|
||||
|
||||
eor v16.16b, v16.16b, v21.16b
|
||||
eor v17.16b, v17.16b, v21.16b
|
||||
eor v18.16b, v18.16b, v21.16b
|
||||
eor v19.16b, v19.16b, v21.16b
|
||||
|
||||
# f0 = aesenc(f0, e2), f1 = aesdec(f1, e2), f2 = aesenc(f2, e2), f3 = aesdec(f3, e2)
|
||||
|
||||
aese v16.16b, v28.16b
|
||||
aesd v17.16b, v28.16b
|
||||
aese v18.16b, v28.16b
|
||||
aesd v19.16b, v28.16b
|
||||
|
||||
aesmc v16.16b, v16.16b
|
||||
aesimc v17.16b, v17.16b
|
||||
aesmc v18.16b, v18.16b
|
||||
aesimc v19.16b, v19.16b
|
||||
|
||||
eor v16.16b, v16.16b, v22.16b
|
||||
eor v17.16b, v17.16b, v22.16b
|
||||
eor v18.16b, v18.16b, v22.16b
|
||||
eor v19.16b, v19.16b, v22.16b
|
||||
|
||||
# f0 = aesenc(f0, e3), f1 = aesdec(f1, e3), f2 = aesenc(f2, e3), f3 = aesdec(f3, e3)
|
||||
|
||||
aese v16.16b, v28.16b
|
||||
aesd v17.16b, v28.16b
|
||||
aese v18.16b, v28.16b
|
||||
aesd v19.16b, v28.16b
|
||||
|
||||
aesmc v16.16b, v16.16b
|
||||
aesimc v17.16b, v17.16b
|
||||
aesmc v18.16b, v18.16b
|
||||
aesimc v19.16b, v19.16b
|
||||
|
||||
eor v16.16b, v16.16b, v23.16b
|
||||
eor v17.16b, v17.16b, v23.16b
|
||||
eor v18.16b, v18.16b, v23.16b
|
||||
eor v19.16b, v19.16b, v23.16b
|
||||
|
||||
# Skip v1 FE mix code because we already did v2 FE mix
|
||||
b randomx_program_aarch64_FE_store
|
||||
|
||||
DECL(randomx_program_aarch64_v1_FE_mix):
|
||||
eor v16.16b, v16.16b, v20.16b
|
||||
eor v17.16b, v17.16b, v21.16b
|
||||
eor v18.16b, v18.16b, v22.16b
|
||||
eor v19.16b, v19.16b, v23.16b
|
||||
|
||||
randomx_program_aarch64_FE_store:
|
||||
|
||||
# Store FP registers to scratchpad (spAddr0)
|
||||
stp q16, q17, [x16, 0]
|
||||
stp q18, q19, [x16, 32]
|
||||
@@ -376,6 +468,13 @@ DECL(randomx_program_aarch64_vm_instructions_end_light):
|
||||
stp x0, x1, [sp, 64]
|
||||
stp x2, x30, [sp, 80]
|
||||
|
||||
lsr x2, x9, 32
|
||||
|
||||
DECL(randomx_program_aarch64_light_cacheline_align_mask):
|
||||
# Actual mask will be inserted by JIT compiler
|
||||
and w2, w2, 1
|
||||
|
||||
DECL(randomx_program_aarch64_vm_instructions_end_light_tweak):
|
||||
# mx ^= r[readReg2] ^ r[readReg3];
|
||||
eor x9, x9, x20
|
||||
|
||||
@@ -388,10 +487,6 @@ DECL(randomx_program_aarch64_vm_instructions_end_light):
|
||||
# x1 -> pointer to output
|
||||
mov x1, sp
|
||||
|
||||
DECL(randomx_program_aarch64_light_cacheline_align_mask):
|
||||
# Actual mask will be inserted by JIT compiler
|
||||
and w2, w9, 1
|
||||
|
||||
# x2 -> item number
|
||||
lsr x2, x2, 6
|
||||
|
||||
@@ -409,6 +504,237 @@ DECL(randomx_program_aarch64_light_dataset_offset):
|
||||
|
||||
b DECL(randomx_program_aarch64_xor_with_dataset_line)
|
||||
|
||||
DECL(randomx_program_aarch64_vm_instructions_end_v1):
|
||||
lsr x10, x9, 32
|
||||
eor x9, x9, x20
|
||||
mov w20, w9
|
||||
ror x9, x9, 32
|
||||
|
||||
DECL(randomx_program_aarch64_vm_instructions_end_v2):
|
||||
lsr x10, x9, 32
|
||||
ror x9, x9, 32
|
||||
eor x9, x9, x20
|
||||
mov w20, w9
|
||||
|
||||
DECL(randomx_program_aarch64_vm_instructions_end_light_v1):
|
||||
eor x9, x9, x20
|
||||
ror x9, x9, 32
|
||||
|
||||
DECL(randomx_program_aarch64_vm_instructions_end_light_v2):
|
||||
ror x9, x9, 32
|
||||
eor x9, x9, x20
|
||||
|
||||
DECL(randomx_program_aarch64_v2_FE_mix_soft_aes):
|
||||
sub sp, sp, 176
|
||||
|
||||
stp x0, x1, [sp]
|
||||
stp x2, x3, [sp, 16]
|
||||
stp x4, x5, [sp, 32]
|
||||
stp x6, x7, [sp, 48]
|
||||
stp x8, x9, [sp, 64]
|
||||
stp x10, x11, [sp, 80]
|
||||
stp x12, x13, [sp, 96]
|
||||
stp x14, x15, [sp, 112]
|
||||
stp x16, x30, [sp, 128]
|
||||
stp q0, q1, [sp, 144]
|
||||
|
||||
adr x19, DECL(randomx_program_aarch64_aes_lut_pointers)
|
||||
ldp x19, x20, [x19]
|
||||
|
||||
# f0 = aesenc(f0, e0), f0 = aesenc(f0, e1), f0 = aesenc(f0, e2), f0 = aesenc(f0, e3)
|
||||
mov v0.16b, v16.16b
|
||||
mov v1.16b, v20.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v1.16b, v21.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v1.16b, v22.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v1.16b, v23.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v16.16b, v0.16b
|
||||
|
||||
# f1 = aesdec(f1, e0), f1 = aesdec(f1, e1), f1 = aesdec(f1, e2), f1 = aesdec(f1, e3)
|
||||
mov v0.16b, v17.16b
|
||||
mov v1.16b, v20.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v1.16b, v21.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v1.16b, v22.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v1.16b, v23.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v17.16b, v0.16b
|
||||
|
||||
# f2 = aesenc(f2, e0), f2 = aesenc(f2, e1), f2 = aesenc(f2, e2), f2 = aesenc(f2, e3)
|
||||
mov v0.16b, v18.16b
|
||||
mov v1.16b, v20.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v1.16b, v21.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v1.16b, v22.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v1.16b, v23.16b
|
||||
bl randomx_soft_aesenc
|
||||
mov v18.16b, v0.16b
|
||||
|
||||
# f3 = aesdec(f3, e0), f3 = aesdec(f3, e1), f3 = aesdec(f3, e2), f3 = aesdec(f3, e3)
|
||||
mov v0.16b, v19.16b
|
||||
mov v1.16b, v20.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v1.16b, v21.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v1.16b, v22.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v1.16b, v23.16b
|
||||
bl randomx_soft_aesdec
|
||||
mov v19.16b, v0.16b
|
||||
|
||||
ldp x0, x1, [sp]
|
||||
ldp x2, x3, [sp, 16]
|
||||
ldp x4, x5, [sp, 32]
|
||||
ldp x6, x7, [sp, 48]
|
||||
ldp x8, x9, [sp, 64]
|
||||
ldp x10, x11, [sp, 80]
|
||||
ldp x12, x13, [sp, 96]
|
||||
ldp x14, x15, [sp, 112]
|
||||
ldp x16, x30, [sp, 128]
|
||||
ldp q0, q1, [sp, 144]
|
||||
|
||||
add sp, sp, 176
|
||||
|
||||
b randomx_program_aarch64_FE_store
|
||||
|
||||
|
||||
randomx_soft_aesenc:
|
||||
umov w4, v0.b[5]
|
||||
umov w1, v0.b[10]
|
||||
umov w12, v0.b[15]
|
||||
umov w9, v0.b[9]
|
||||
umov w2, v0.b[14]
|
||||
umov w11, v0.b[3]
|
||||
umov w5, v0.b[0]
|
||||
umov w16, v0.b[4]
|
||||
add x4, x4, 256
|
||||
add x1, x1, 512
|
||||
add x12, x12, 768
|
||||
umov w3, v0.b[13]
|
||||
umov w8, v0.b[2]
|
||||
umov w7, v0.b[7]
|
||||
add x9, x9, 256
|
||||
add x2, x2, 512
|
||||
add x11, x11, 768
|
||||
ldr w10, [x19, x4, lsl 2]
|
||||
ldr w15, [x19, x5, lsl 2]
|
||||
umov w13, v0.b[8]
|
||||
ldr w14, [x19, x12, lsl 2]
|
||||
umov w6, v0.b[1]
|
||||
ldr w1, [x19, x1, lsl 2]
|
||||
eor w10, w10, w15
|
||||
ldr w2, [x19, x2, lsl 2]
|
||||
umov w5, v0.b[6]
|
||||
ldr w9, [x19, x9, lsl 2]
|
||||
umov w4, v0.b[11]
|
||||
ldr w12, [x19, x16, lsl 2]
|
||||
eor w1, w1, w14
|
||||
ldr w11, [x19, x11, lsl 2]
|
||||
eor w1, w1, w10
|
||||
add x8, x8, 512
|
||||
add x3, x3, 256
|
||||
add x7, x7, 768
|
||||
eor w9, w9, w12
|
||||
fmov s28, w1
|
||||
eor w1, w2, w11
|
||||
umov w10, v0.b[12]
|
||||
eor w1, w1, w9
|
||||
ldr w3, [x19, x3, lsl 2]
|
||||
add x6, x6, 256
|
||||
ldr w9, [x19, x13, lsl 2]
|
||||
ins v28.s[1], w1
|
||||
ldr w2, [x19, x8, lsl 2]
|
||||
add x5, x5, 512
|
||||
ldr w7, [x19, x7, lsl 2]
|
||||
add x4, x4, 768
|
||||
eor w1, w3, w9
|
||||
ldr w3, [x19, x6, lsl 2]
|
||||
eor w2, w2, w7
|
||||
ldr w6, [x19, x10, lsl 2]
|
||||
eor w2, w2, w1
|
||||
ldr w1, [x19, x5, lsl 2]
|
||||
ldr w0, [x19, x4, lsl 2]
|
||||
eor w3, w3, w6
|
||||
ins v28.s[2], w2
|
||||
eor w0, w1, w0
|
||||
eor w0, w0, w3
|
||||
ins v28.s[3], w0
|
||||
eor v0.16b, v1.16b, v28.16b
|
||||
ret
|
||||
|
||||
randomx_soft_aesdec:
|
||||
umov w1, v0.b[10]
|
||||
umov w3, v0.b[7]
|
||||
umov w12, v0.b[13]
|
||||
umov w2, v0.b[14]
|
||||
umov w9, v0.b[11]
|
||||
umov w11, v0.b[1]
|
||||
umov w4, v0.b[0]
|
||||
umov w16, v0.b[4]
|
||||
add x3, x3, 768
|
||||
add x1, x1, 512
|
||||
add x12, x12, 256
|
||||
umov w8, v0.b[5]
|
||||
umov w6, v0.b[2]
|
||||
umov w7, v0.b[15]
|
||||
add x9, x9, 768
|
||||
add x2, x2, 512
|
||||
add x11, x11, 256
|
||||
ldr w15, [x20, x3, lsl 2]
|
||||
ldr w10, [x20, x4, lsl 2]
|
||||
umov w13, v0.b[8]
|
||||
ldr w14, [x20, x12, lsl 2]
|
||||
umov w5, v0.b[9]
|
||||
ldr w1, [x20, x1, lsl 2]
|
||||
umov w3, v0.b[6]
|
||||
ldr w12, [x20, x9, lsl 2]
|
||||
umov w4, v0.b[3]
|
||||
ldr w9, [x20, x16, lsl 2]
|
||||
eor w1, w1, w15
|
||||
ldr w2, [x20, x2, lsl 2]
|
||||
eor w10, w10, w14
|
||||
ldr w11, [x20, x11, lsl 2]
|
||||
eor w1, w1, w10
|
||||
add x8, x8, 256
|
||||
add x6, x6, 512
|
||||
add x7, x7, 768
|
||||
eor w2, w2, w12
|
||||
fmov s28, w1
|
||||
eor w1, w9, w11
|
||||
eor w1, w2, w1
|
||||
umov w9, v0.b[12]
|
||||
ldr w2, [x20, x13, lsl 2]
|
||||
add x5, x5, 256
|
||||
ldr w8, [x20, x8, lsl 2]
|
||||
ins v28.s[1], w1
|
||||
ldr w6, [x20, x6, lsl 2]
|
||||
add x3, x3, 512
|
||||
ldr w7, [x20, x7, lsl 2]
|
||||
add x4, x4, 768
|
||||
eor w2, w2, w8
|
||||
ldr w1, [x20, x9, lsl 2]
|
||||
eor w6, w6, w7
|
||||
ldr w3, [x20, x3, lsl 2]
|
||||
eor w2, w2, w6
|
||||
ldr w4, [x20, x4, lsl 2]
|
||||
ldr w5, [x20, x5, lsl 2]
|
||||
ins v28.s[2], w2
|
||||
eor w0, w1, w5
|
||||
eor w1, w3, w4
|
||||
eor w0, w0, w1
|
||||
ins v28.s[3], w0
|
||||
eor v0.16b, v1.16b, v28.16b
|
||||
ret
|
||||
|
||||
DECL(randomx_program_aarch64_aes_lut_pointers):
|
||||
.fill 2, 8, 0
|
||||
|
||||
|
||||
# Input parameters
|
||||
|
||||
@@ -38,9 +38,18 @@ extern "C" {
|
||||
void randomx_program_aarch64_cacheline_align_mask1();
|
||||
void randomx_program_aarch64_cacheline_align_mask2();
|
||||
void randomx_program_aarch64_update_spMix1();
|
||||
void randomx_program_aarch64_v2_FE_mix();
|
||||
void randomx_program_aarch64_v1_FE_mix();
|
||||
void randomx_program_aarch64_v2_FE_mix_soft_aes();
|
||||
void randomx_program_aarch64_aes_lut_pointers();
|
||||
void randomx_program_aarch64_vm_instructions_end_light();
|
||||
void randomx_program_aarch64_vm_instructions_end_light_tweak();
|
||||
void randomx_program_aarch64_light_cacheline_align_mask();
|
||||
void randomx_program_aarch64_light_dataset_offset();
|
||||
void randomx_program_aarch64_vm_instructions_end_v1();
|
||||
void randomx_program_aarch64_vm_instructions_end_v2();
|
||||
void randomx_program_aarch64_vm_instructions_end_light_v1();
|
||||
void randomx_program_aarch64_vm_instructions_end_light_v2();
|
||||
void randomx_init_dataset_aarch64();
|
||||
void randomx_init_dataset_aarch64_end();
|
||||
void randomx_calc_dataset_item_aarch64();
|
||||
|
||||
@@ -39,6 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "crypto/randomx/program.hpp"
|
||||
#include "crypto/randomx/reciprocal.h"
|
||||
#include "crypto/randomx/virtual_memory.hpp"
|
||||
#include "crypto/randomx/soft_aes.h"
|
||||
#include "crypto/common/VirtualMemory.h"
|
||||
|
||||
|
||||
@@ -253,10 +254,12 @@ namespace randomx {
|
||||
static const uint8_t* codePrologue = (uint8_t*)&randomx_riscv64_prologue;
|
||||
static const uint8_t* codeLoopBegin = (uint8_t*)&randomx_riscv64_loop_begin;
|
||||
static const uint8_t* codeDataRead = (uint8_t*)&randomx_riscv64_data_read;
|
||||
static const uint8_t* codeDataRead2 = (uint8_t*)&randomx_riscv64_data_read_v2_tweak;
|
||||
static const uint8_t* codeDataReadLight = (uint8_t*)&randomx_riscv64_data_read_light;
|
||||
static const uint8_t* codeDataReadLight1 = (uint8_t*)&randomx_riscv64_data_read_light_v1;
|
||||
static const uint8_t* codeDataReadLight2 = (uint8_t*)&randomx_riscv64_data_read_light_v2;
|
||||
static const uint8_t* codeFixLoopCall = (uint8_t*)&randomx_riscv64_fix_loop_call;
|
||||
static const uint8_t* codeSpadStore = (uint8_t*)&randomx_riscv64_spad_store;
|
||||
static const uint8_t* codeSpadStoreHardAes = (uint8_t*)&randomx_riscv64_spad_store_hardaes;
|
||||
static const uint8_t* codeSpadStoreSoftAes = (uint8_t*)&randomx_riscv64_spad_store_softaes;
|
||||
static const uint8_t* codeLoopEnd = (uint8_t*)&randomx_riscv64_loop_end;
|
||||
static const uint8_t* codeFixContinueLoop = (uint8_t*)&randomx_riscv64_fix_continue_loop;
|
||||
@@ -272,9 +275,13 @@ namespace randomx {
|
||||
static const int32_t sizeDataInit = codePrologue - codeDataInit;
|
||||
static const int32_t sizePrologue = codeLoopBegin - codePrologue;
|
||||
static const int32_t sizeLoopBegin = codeDataRead - codeLoopBegin;
|
||||
static const int32_t sizeDataRead = codeDataReadLight - codeDataRead;
|
||||
static const int32_t sizeDataReadLight = codeSpadStore - codeDataReadLight;
|
||||
static const int32_t sizeSpadStore = codeSpadStoreHardAes - codeSpadStore;
|
||||
static const int32_t sizeDataRead = codeDataRead2 - codeDataRead;
|
||||
static const int32_t sizeDataRead2 = codeDataReadLight - codeDataRead2;
|
||||
static const int32_t sizeDataReadLight = codeDataReadLight1 - codeDataReadLight;
|
||||
static const int32_t sizeDataReadLight1 = codeDataReadLight2 - codeDataReadLight1;
|
||||
static const int32_t sizeDataReadLight2 = codeFixLoopCall - codeDataReadLight2;
|
||||
static const int32_t sizeFixLoopCall = codeSpadStore - codeFixLoopCall;
|
||||
static const int32_t sizeSpadStore = codeSpadStoreSoftAes - codeSpadStore;
|
||||
static const int32_t sizeSpadStoreSoftAes = codeLoopEnd - codeSpadStoreSoftAes;
|
||||
static const int32_t sizeLoopEnd = codeEpilogue - codeLoopEnd;
|
||||
static const int32_t sizeEpilogue = codeSoftAes - codeEpilogue;
|
||||
@@ -284,7 +291,6 @@ namespace randomx {
|
||||
static const int32_t sizeSshPrefetch = codeSshEnd - codeSshPrefetch;
|
||||
|
||||
static const int32_t offsetFixDataCall = codeFixDataCall - codeDataInit;
|
||||
static const int32_t offsetFixLoopCall = codeFixLoopCall - codeDataReadLight;
|
||||
static const int32_t offsetFixContinueLoop = codeFixContinueLoop - codeLoopEnd;
|
||||
|
||||
static const int32_t LoopTopPos = LiteralPoolSize + sizeDataInit + sizePrologue;
|
||||
@@ -479,8 +485,15 @@ namespace randomx {
|
||||
static void emitProgramPrefix(CompilerState& state, Program& prog, ProgramConfiguration& pcfg) {
|
||||
state.codePos = RandomXCodePos;
|
||||
state.rcpCount = 0;
|
||||
|
||||
state.emitAt(LiteralPoolOffset + sizeLiterals, pcfg.eMask[0]);
|
||||
state.emitAt(LiteralPoolOffset + sizeLiterals + 8, pcfg.eMask[1]);
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES) {
|
||||
state.emitAt(LiteralPoolOffset + sizeLiterals + 16, (uint64_t) &lutEnc[2][0]);
|
||||
state.emitAt(LiteralPoolOffset + sizeLiterals + 24, (uint64_t) &lutDec[2][0]);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < RegistersCount; ++i) {
|
||||
state.registerUsage[i] = -1;
|
||||
}
|
||||
@@ -493,7 +506,13 @@ namespace randomx {
|
||||
}
|
||||
|
||||
static void emitProgramSuffix(CompilerState& state, ProgramConfiguration& pcfg) {
|
||||
state.emit(codeSpadStore, sizeSpadStore);
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES) {
|
||||
state.emit(codeSpadStoreSoftAes, sizeSpadStoreSoftAes);
|
||||
}
|
||||
else {
|
||||
state.emit(codeSpadStore, sizeSpadStore);
|
||||
}
|
||||
|
||||
int32_t fixPos = state.codePos;
|
||||
state.emit(codeLoopEnd, sizeLoopEnd);
|
||||
//xor x26, x{readReg0}, x{readReg1}
|
||||
@@ -502,6 +521,10 @@ namespace randomx {
|
||||
//j LoopTop
|
||||
emitJump(state, 0, fixPos, LoopTopPos);
|
||||
state.emit(codeEpilogue, sizeEpilogue);
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES) {
|
||||
state.emit(codeSoftAes, sizeSoftAes);
|
||||
}
|
||||
}
|
||||
|
||||
static void generateSuperscalarCode(CodeBuffer& buf, Instruction isn, bool lastLiteral) {
|
||||
@@ -669,6 +692,9 @@ namespace randomx {
|
||||
state.emit(codeDataRead, sizeDataRead);
|
||||
//xor x8, x{readReg2}, x{readReg3}
|
||||
state.emitAt(fixPos, rvi(rv64::XOR, Tmp1Reg, regR(pcfg.readReg2), regR(pcfg.readReg3)));
|
||||
int32_t fixPos2 = state.codePos;
|
||||
state.emit(codeDataRead2, sizeDataRead2);
|
||||
state.emitAt(fixPos2, (uint16_t)(RandomX_CurrentConfig.Tweak_V2_PREFETCH ? 0x1402 : 0x0001));
|
||||
emitProgramSuffix(state, pcfg);
|
||||
clearCache(state);
|
||||
}
|
||||
@@ -691,7 +717,14 @@ namespace randomx {
|
||||
state.emitAt(fixPos + 4, rv64::LUI | (uimm << 12) | rvrd(Tmp2Reg));
|
||||
//addi x9, x9, {limm}
|
||||
state.emitAt(fixPos + 8, rvi(rv64::ADDI, Tmp2Reg, Tmp2Reg, limm));
|
||||
fixPos += offsetFixLoopCall;
|
||||
if (RandomX_CurrentConfig.Tweak_V2_PREFETCH) {
|
||||
state.emit(codeDataReadLight2, sizeDataReadLight2);
|
||||
}
|
||||
else {
|
||||
state.emit(codeDataReadLight1, sizeDataReadLight1);
|
||||
}
|
||||
fixPos = state.codePos;
|
||||
state.emit(codeFixLoopCall, sizeFixLoopCall);
|
||||
//jal x1, SuperscalarHash
|
||||
emitJump(state, ReturnReg, fixPos, SuperScalarHashOffset);
|
||||
emitProgramSuffix(state, pcfg);
|
||||
@@ -1175,10 +1208,22 @@ namespace randomx {
|
||||
//c.or x8, x9
|
||||
state.emit(rvc(rv64::C_OR, Tmp1Reg + OffsetXC, Tmp2Reg + OffsetXC));
|
||||
#endif
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
//andi x9, x8, 240
|
||||
state.emit(rvi(rv64::ANDI, Tmp2Reg, Tmp1Reg, 240));
|
||||
//c.bnez x9, +12
|
||||
state.emit(uint16_t(0xE491));
|
||||
}
|
||||
//c.andi x8, 12
|
||||
state.emit(rvc(rv64::C_ANDI, Tmp1Reg + OffsetXC, 12));
|
||||
}
|
||||
else {
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
//andi x9, x{src}, 240
|
||||
state.emit(rvi(rv64::ANDI, Tmp2Reg, regR(isn.src), 240));
|
||||
//c.bnez x9, +14
|
||||
state.emit(uint16_t(0xE499));
|
||||
}
|
||||
//and x8, x{src}, 12
|
||||
state.emit(rvi(rv64::ANDI, Tmp1Reg, regR(isn.src), 12));
|
||||
}
|
||||
|
||||
@@ -40,10 +40,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.global DECL(randomx_riscv64_prologue)
|
||||
.global DECL(randomx_riscv64_loop_begin)
|
||||
.global DECL(randomx_riscv64_data_read)
|
||||
.global DECL(randomx_riscv64_data_read_v2_tweak)
|
||||
.global DECL(randomx_riscv64_data_read_light)
|
||||
.global DECL(randomx_riscv64_data_read_light_v1)
|
||||
.global DECL(randomx_riscv64_data_read_light_v2)
|
||||
.global DECL(randomx_riscv64_fix_loop_call)
|
||||
.global DECL(randomx_riscv64_spad_store)
|
||||
.global DECL(randomx_riscv64_spad_store_hardaes)
|
||||
.global DECL(randomx_riscv64_spad_store_softaes)
|
||||
.global DECL(randomx_riscv64_loop_end)
|
||||
.global DECL(randomx_riscv64_fix_continue_loop)
|
||||
@@ -408,7 +410,9 @@ DECL(randomx_riscv64_data_read):
|
||||
slli x8, x8, 32
|
||||
srli x8, x8, 32
|
||||
#endif
|
||||
/* update "mx" */
|
||||
DECL(randomx_riscv64_data_read_v2_tweak):
|
||||
slli x8, x8, 32 /* JIT compiler will replace it with "nop" for RandomX v1 */
|
||||
/* update "mp" */
|
||||
xor x25, x25, x8
|
||||
/* read dataset and update registers */
|
||||
ld x8, 0(x7)
|
||||
@@ -456,13 +460,22 @@ DECL(randomx_riscv64_data_read_light):
|
||||
slli x25, x25, 32
|
||||
or x25, x25, x31
|
||||
#endif
|
||||
DECL(randomx_riscv64_data_read_light_v1):
|
||||
slli x8, x8, 32
|
||||
/* update "mx" */
|
||||
/* update "mp" */
|
||||
xor x25, x25, x8
|
||||
/* the next dataset item */
|
||||
and x7, x25, x1
|
||||
srli x7, x7, 6
|
||||
add x7, x7, x9
|
||||
DECL(randomx_riscv64_data_read_light_v2):
|
||||
/* the next dataset item */
|
||||
and x7, x25, x1
|
||||
srli x7, x7, 6
|
||||
add x7, x7, x9
|
||||
and x8, x8, x1
|
||||
/* update "mp" */
|
||||
xor x25, x25, x8
|
||||
DECL(randomx_riscv64_fix_loop_call):
|
||||
jal superscalar_hash /* JIT compiler will adjust the offset */
|
||||
xor x16, x16, x8
|
||||
@@ -536,9 +549,6 @@ DECL(randomx_riscv64_spad_store):
|
||||
sd x30, 56(x26)
|
||||
fmv.d.x f7, x30
|
||||
|
||||
DECL(randomx_riscv64_spad_store_hardaes):
|
||||
nop /* not implemented */
|
||||
|
||||
DECL(randomx_riscv64_spad_store_softaes):
|
||||
/* store integer registers */
|
||||
sd x16, 0(x27)
|
||||
|
||||
@@ -36,10 +36,12 @@ extern "C" {
|
||||
void randomx_riscv64_prologue();
|
||||
void randomx_riscv64_loop_begin();
|
||||
void randomx_riscv64_data_read();
|
||||
void randomx_riscv64_data_read_v2_tweak();
|
||||
void randomx_riscv64_data_read_light();
|
||||
void randomx_riscv64_data_read_light_v1();
|
||||
void randomx_riscv64_data_read_light_v2();
|
||||
void randomx_riscv64_fix_loop_call();
|
||||
void randomx_riscv64_spad_store();
|
||||
void randomx_riscv64_spad_store_hardaes();
|
||||
void randomx_riscv64_spad_store_softaes();
|
||||
void randomx_riscv64_loop_end();
|
||||
void randomx_riscv64_fix_continue_loop();
|
||||
|
||||
@@ -34,12 +34,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "crypto/randomx/reciprocal.h"
|
||||
#include "crypto/randomx/superscalar.hpp"
|
||||
#include "crypto/randomx/program.hpp"
|
||||
#include "crypto/randomx/soft_aes.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
|
||||
namespace randomx {
|
||||
|
||||
#define ADDR(x) ((uint8_t*) &(x))
|
||||
#define DIST(x, y) (ADDR(y) - ADDR(x))
|
||||
|
||||
#define JUMP(offset) (0x6F | (((offset) & 0x7FE) << 20) | (((offset) & 0x800) << 9) | ((offset) & 0xFF000))
|
||||
|
||||
void* generateDatasetInitVectorRV64(uint8_t* buf, SuperscalarProgram* programs, size_t num_programs)
|
||||
{
|
||||
uint8_t* p = buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_sshash_generated_instructions);
|
||||
@@ -94,6 +98,10 @@ void* generateDatasetInitVectorRV64(uint8_t* buf, SuperscalarProgram* programs,
|
||||
|
||||
case SuperscalarInstructionType::IROR_C:
|
||||
{
|
||||
#ifdef __riscv_zvkb
|
||||
// 57 30 00 52 vror.vi v0, v0, 0
|
||||
EMIT(0x52003057 | (dst << 7) | (dst << 20) | ((imm32 & 31) << 15) | ((imm32 & 32) << 21));
|
||||
#else // __riscv_zvkb
|
||||
const uint32_t shift_right = imm32 & 63;
|
||||
const uint32_t shift_left = 64 - shift_right;
|
||||
|
||||
@@ -121,6 +129,7 @@ void* generateDatasetInitVectorRV64(uint8_t* buf, SuperscalarProgram* programs,
|
||||
|
||||
// 57 00 20 2B vor.vv v0, v18, v0
|
||||
EMIT(0x2B200057 | (dst << 7) | (dst << 15));
|
||||
#endif // __riscv_zvkb
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -200,8 +209,7 @@ void* generateDatasetInitVectorRV64(uint8_t* buf, SuperscalarProgram* programs,
|
||||
|
||||
// Emit "J randomx_riscv64_vector_sshash_generated_instructions_end" instruction
|
||||
const uint8_t* e = buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_sshash_generated_instructions_end);
|
||||
const uint32_t k = e - p;
|
||||
const uint32_t j = 0x6F | ((k & 0x7FE) << 20) | ((k & 0x800) << 9) | (k & 0xFF000);
|
||||
const uint32_t j = JUMP(e - p);
|
||||
memcpy(p, &j, 4);
|
||||
|
||||
char* result = (char*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_sshash_dataset_init));
|
||||
@@ -318,6 +326,26 @@ void* generateProgramVectorRV64(uint8_t* buf, Program& prog, ProgramConfiguratio
|
||||
params[3] = RandomX_CurrentConfig.DatasetBaseSize - 64;
|
||||
params[4] = (1 << RandomX_ConfigurationBase::JumpBits) - 1;
|
||||
|
||||
const bool hasAES = xmrig::Cpu::info()->hasAES();
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES && !hasAES) {
|
||||
params[5] = (uint64_t) &lutEnc[2][0];
|
||||
params[6] = (uint64_t) &lutDec[2][0];
|
||||
params[7] = (uint64_t) lutEncIndex;
|
||||
params[8] = (uint64_t) lutDecIndex;
|
||||
|
||||
uint32_t* p1 = (uint32_t*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_v2_soft_aes_init));
|
||||
|
||||
// Restore vsetivli zero, 4, e32, m1, ta, ma
|
||||
*p1 = 0xCD027057;
|
||||
}
|
||||
else {
|
||||
uint32_t* p1 = (uint32_t*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_v2_soft_aes_init));
|
||||
|
||||
// Emit "J randomx_riscv64_vector_program_main_loop" instruction
|
||||
*p1 = JUMP(DIST(randomx_riscv64_vector_program_v2_soft_aes_init, randomx_riscv64_vector_program_main_loop));
|
||||
}
|
||||
|
||||
uint64_t* imul_rcp_literals = (uint64_t*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_imul_rcp_literals));
|
||||
uint64_t* cur_literal = imul_rcp_literals;
|
||||
|
||||
@@ -333,6 +361,16 @@ void* generateProgramVectorRV64(uint8_t* buf, Program& prog, ProgramConfiguratio
|
||||
*mx_xor = mx_xor_value;
|
||||
*mx_xor_light = mx_xor_value;
|
||||
|
||||
// "slli x5, x5, 32" for RandomX v2, "nop" for RandomX v1
|
||||
const uint16_t mp_reg_value = RandomX_CurrentConfig.Tweak_V2_PREFETCH ? 0x1282 : 0x0001;
|
||||
|
||||
memcpy(((uint8_t*)mx_xor) + 8, &mp_reg_value, sizeof(mp_reg_value));
|
||||
memcpy(((uint8_t*)mx_xor_light) + 8, &mp_reg_value, sizeof(mp_reg_value));
|
||||
|
||||
// "srli x5, x14, 32" for RandomX v2, "srli x5, x14, 0" for RandomX v1
|
||||
const uint32_t mp_reg_value2 = RandomX_CurrentConfig.Tweak_V2_PREFETCH ? 0x02075293 : 0x00075293;
|
||||
memcpy(((uint8_t*)mx_xor) + 14, &mp_reg_value2, sizeof(mp_reg_value2));
|
||||
|
||||
if (entryDataInitScalar) {
|
||||
void* light_mode_data = buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_main_loop_light_mode_data);
|
||||
|
||||
@@ -355,44 +393,6 @@ void* generateProgramVectorRV64(uint8_t* buf, Program& prog, ProgramConfiguratio
|
||||
|
||||
uint8_t* last_modified[RegistersCount] = { p, p, p, p, p, p, p, p };
|
||||
|
||||
uint8_t readReg01[RegistersCount] = {};
|
||||
|
||||
readReg01[pcfg.readReg0] = 1;
|
||||
readReg01[pcfg.readReg1] = 1;
|
||||
|
||||
uint32_t scratchpad_prefetch_pos = 0;
|
||||
|
||||
for (int32_t i = static_cast<int32_t>(prog.getSize()) - 1; i >= 0; --i) {
|
||||
Instruction instr = prog(i);
|
||||
|
||||
const InstructionType inst_type = static_cast<InstructionType>(inst_map[instr.opcode]);
|
||||
|
||||
if (inst_type == InstructionType::CBRANCH) {
|
||||
scratchpad_prefetch_pos = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst_type < InstructionType::FSWAP_R) {
|
||||
const uint32_t src = instr.src % RegistersCount;
|
||||
const uint32_t dst = instr.dst % RegistersCount;
|
||||
|
||||
if ((inst_type == InstructionType::ISWAP_R) && (src != dst) && (readReg01[src] || readReg01[dst])) {
|
||||
scratchpad_prefetch_pos = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((inst_type == InstructionType::IMUL_RCP) && readReg01[dst] && !isZeroOrPowerOf2(instr.getImm32())) {
|
||||
scratchpad_prefetch_pos = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (readReg01[dst]) {
|
||||
scratchpad_prefetch_pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0, n = prog.getSize(); i < n; ++i) {
|
||||
Instruction instr = prog(i);
|
||||
|
||||
@@ -793,10 +793,24 @@ void* generateProgramVectorRV64(uint8_t* buf, Program& prog, ProgramConfiguratio
|
||||
emit32(0x0062E2B3);
|
||||
#endif // __riscv_zbb
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
// andi x6, x5, 120
|
||||
emit32(0x0782F313);
|
||||
// bnez x6, +24
|
||||
emit32(0x00031C63);
|
||||
}
|
||||
|
||||
// andi x5, x5, 6
|
||||
emit32(0x0062F293);
|
||||
}
|
||||
else {
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
// andi x6, x20 + src, 120
|
||||
emit32(0x078A7313 + (src << 15));
|
||||
// bnez x6, +24
|
||||
emit32(0x00031C63);
|
||||
}
|
||||
|
||||
// andi x5, x20 + src, 6
|
||||
emit32(0x006A7293 + (src << 15));
|
||||
}
|
||||
@@ -846,19 +860,12 @@ void* generateProgramVectorRV64(uint8_t* buf, Program& prog, ProgramConfiguratio
|
||||
}
|
||||
break;
|
||||
|
||||
case InstructionType::NOP:
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
// Prefetch scratchpad lines for the next main loop iteration
|
||||
// scratchpad_prefetch_pos is a conservative estimate of the earliest place in the code where we can do it
|
||||
if (i == scratchpad_prefetch_pos) {
|
||||
uint8_t* e = (uint8_t*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_scratchpad_prefetch_end));
|
||||
const size_t n = e - ((uint8_t*)spaddr_xor2);
|
||||
|
||||
memcpy(p, spaddr_xor2, n);
|
||||
p += n;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* e;
|
||||
@@ -872,8 +879,26 @@ void* generateProgramVectorRV64(uint8_t* buf, Program& prog, ProgramConfiguratio
|
||||
e = buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_main_loop_instructions_end);
|
||||
}
|
||||
|
||||
const uint32_t k = e - p;
|
||||
emit32(0x6F | ((k & 0x7FE) << 20) | ((k & 0x800) << 9) | (k & 0xFF000));
|
||||
emit32(JUMP(e - p));
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES) {
|
||||
uint32_t* p1 = (uint32_t*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_main_loop_fe_mix));
|
||||
|
||||
if (hasAES) {
|
||||
// Restore vsetivli zero, 4, e32, m1, ta, ma
|
||||
*p1 = 0xCD027057;
|
||||
}
|
||||
else {
|
||||
// Emit "J randomx_riscv64_vector_program_main_loop_fe_mix_v2_soft_aes" instruction
|
||||
*p1 = JUMP(DIST(randomx_riscv64_vector_program_main_loop_fe_mix, randomx_riscv64_vector_program_main_loop_fe_mix_v2_soft_aes));
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32_t* p1 = (uint32_t*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_main_loop_fe_mix));
|
||||
|
||||
// Emit "J randomx_riscv64_vector_program_main_loop_fe_mix_v1" instruction
|
||||
*p1 = JUMP(DIST(randomx_riscv64_vector_program_main_loop_fe_mix, randomx_riscv64_vector_program_main_loop_fe_mix_v1));
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
char* p1 = (char*)(buf + DIST(randomx_riscv64_vector_code_begin, randomx_riscv64_vector_program_params));
|
||||
|
||||
@@ -66,16 +66,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.global DECL(randomx_riscv64_vector_program_params)
|
||||
.global DECL(randomx_riscv64_vector_program_imul_rcp_literals)
|
||||
.global DECL(randomx_riscv64_vector_program_begin)
|
||||
.global DECL(randomx_riscv64_vector_program_v2_soft_aes_init)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_instructions)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_instructions_end)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_mx_xor)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_spaddr_xor)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_fe_mix)
|
||||
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_light_mode_data)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_instructions_end_light_mode)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_mx_xor_light_mode)
|
||||
.global DECL(randomx_riscv64_vector_program_scratchpad_prefetch)
|
||||
.global DECL(randomx_riscv64_vector_program_scratchpad_prefetch_end)
|
||||
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_fe_mix_v1)
|
||||
.global DECL(randomx_riscv64_vector_program_main_loop_fe_mix_v2_soft_aes)
|
||||
|
||||
.global DECL(randomx_riscv64_vector_program_end)
|
||||
|
||||
@@ -376,12 +381,21 @@ v12 = E 'and' mask = 0x00ffffffffffffff'00ffffffffffffff
|
||||
v13 = E 'or' mask = 0x3*00000000******'3*00000000******
|
||||
v14 = scale mask = 0x80f0000000000000'80f0000000000000
|
||||
|
||||
v15 = unused
|
||||
v15 = all zeroes
|
||||
v16 = temporary
|
||||
v17 = unused
|
||||
v18 = temporary
|
||||
|
||||
v19-v31 = unused
|
||||
v19 = unused
|
||||
v20 = randomx_aes_lut_enc_index[0]
|
||||
v21 = randomx_aes_lut_enc_index[1]
|
||||
v22 = randomx_aes_lut_enc_index[2]
|
||||
v23 = randomx_aes_lut_enc_index[3]
|
||||
v24 = randomx_aes_lut_dec_index[0]
|
||||
v25 = randomx_aes_lut_dec_index[1]
|
||||
v26 = randomx_aes_lut_dec_index[2]
|
||||
v27 = randomx_aes_lut_dec_index[3]
|
||||
v28-v31 = temporary in aesenc_soft/aesdec_soft
|
||||
*/
|
||||
|
||||
.balign 8
|
||||
@@ -391,6 +405,11 @@ DECL(randomx_riscv64_vector_program_params):
|
||||
// JIT compiler will adjust these values for different RandomX variants
|
||||
randomx_masks: .dword 16376, 262136, 2097144, 2147483584, 255
|
||||
|
||||
randomx_aes_lut_enc_ptr: .dword 0
|
||||
randomx_aes_lut_dec_ptr: .dword 0
|
||||
randomx_aes_lut_enc_index_ptr: .dword 0
|
||||
randomx_aes_lut_dec_index_ptr: .dword 0
|
||||
|
||||
DECL(randomx_riscv64_vector_program_imul_rcp_literals):
|
||||
|
||||
imul_rcp_literals: .fill RANDOMX_PROGRAM_MAX_SIZE, 8, 0
|
||||
@@ -508,7 +527,44 @@ DECL(randomx_riscv64_vector_program_begin):
|
||||
fld f30, 192(x18)
|
||||
fld f31, 200(x18)
|
||||
|
||||
randomx_riscv64_vector_program_main_loop:
|
||||
// Set v15 to zero
|
||||
vxor.vv v15, v15, v15
|
||||
|
||||
DECL(randomx_riscv64_vector_program_v2_soft_aes_init):
|
||||
// JIT compiler will place a jump to the main loop here if needed
|
||||
|
||||
// Load randomx_aes_lut_enc_index/randomx_aes_lut_dec_index
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
|
||||
lla x5, randomx_aes_lut_enc_index_ptr
|
||||
ld x5, (x5)
|
||||
vle32.v v20, (x5)
|
||||
|
||||
addi x6, x5, 32
|
||||
vle32.v v21, (x6)
|
||||
|
||||
addi x6, x5, 64
|
||||
vle32.v v22, (x6)
|
||||
|
||||
addi x6, x5, 96
|
||||
vle32.v v23, (x6)
|
||||
|
||||
lla x5, randomx_aes_lut_dec_index_ptr
|
||||
ld x5, (x5)
|
||||
vle32.v v24, (x5)
|
||||
|
||||
addi x6, x5, 32
|
||||
vle32.v v25, (x6)
|
||||
|
||||
addi x6, x5, 64
|
||||
vle32.v v26, (x6)
|
||||
|
||||
addi x6, x5, 96
|
||||
vle32.v v27, (x6)
|
||||
|
||||
vsetivli zero, 2, e64, m1, ta, ma
|
||||
|
||||
DECL(randomx_riscv64_vector_program_main_loop):
|
||||
and x5, x15, x9 // x5 = spAddr0 & 64-byte aligned L3 mask
|
||||
add x5, x5, x12 // x5 = &scratchpad[spAddr0 & 64-byte aligned L3 mask]
|
||||
|
||||
@@ -610,12 +666,13 @@ DECL(randomx_riscv64_vector_program_main_loop_instructions_end):
|
||||
|
||||
DECL(randomx_riscv64_vector_program_main_loop_mx_xor):
|
||||
xor x5, x24, x26 // x5 = readReg2 ^ readReg3 (JIT compiler will substitute the actual registers)
|
||||
|
||||
and x5, x5, x19 // x5 = (readReg2 ^ readReg3) & dataset mask
|
||||
xor x14, x14, x5 // mx ^= (readReg2 ^ readReg3) & dataset mask
|
||||
slli x5, x5, 32 // JIT compiler will replace it with "nop" for v1
|
||||
xor x14, x14, x5 // mp ^= (readReg2 ^ readReg3) & dataset mask
|
||||
|
||||
and x5, x14, x19 // x5 = mx & dataset mask
|
||||
add x5, x5, x11 // x5 = &dataset[mx & dataset mask]
|
||||
srli x5, x14, 32 // JIT compiler will replace it with "srli x5, x14, 0" for v1
|
||||
and x5, x5, x19 // x5 = mp & dataset mask
|
||||
add x5, x5, x11 // x5 = &dataset[mp & dataset mask]
|
||||
|
||||
#ifdef __riscv_zicbop
|
||||
prefetch.r (x5)
|
||||
@@ -643,7 +700,24 @@ DECL(randomx_riscv64_vector_program_main_loop_mx_xor):
|
||||
ld x6, 56(x5)
|
||||
xor x27, x27, x6
|
||||
|
||||
randomx_riscv64_vector_program_main_loop_swap_mx_ma:
|
||||
DECL(randomx_riscv64_vector_program_scratchpad_prefetch):
|
||||
xor x5, x20, x22 // spAddr0-spAddr1 = readReg0 ^ readReg1 (JIT compiler will substitute the actual registers)
|
||||
srli x6, x5, 32 // x6 = spAddr1
|
||||
|
||||
and x5, x5, x9 // x5 = spAddr0 & 64-byte aligned L3 mask
|
||||
and x6, x6, x9 // x6 = spAddr1 & 64-byte aligned L3 mask
|
||||
|
||||
c.add x5, x12 // x5 = &scratchpad[spAddr0 & 64-byte aligned L3 mask]
|
||||
c.add x6, x12 // x6 = &scratchpad[spAddr1 & 64-byte aligned L3 mask]
|
||||
|
||||
#ifdef __riscv_zicbop
|
||||
prefetch.r (x5)
|
||||
prefetch.r (x6)
|
||||
#else
|
||||
ld x5, (x5)
|
||||
ld x6, (x6)
|
||||
#endif
|
||||
|
||||
// swap mx <-> ma
|
||||
#ifdef __riscv_zbb
|
||||
rori x14, x14, 32
|
||||
@@ -674,11 +748,47 @@ DECL(randomx_riscv64_vector_program_main_loop_spaddr_xor):
|
||||
xor x15, x20, x22 // spAddr0-spAddr1 = readReg0 ^ readReg1 (JIT compiler will substitute the actual registers)
|
||||
|
||||
// store registers f0-f3 to the scratchpad (f0-f3 are first combined with e0-e3)
|
||||
vxor.vv v0, v0, v4
|
||||
|
||||
// v2 FE mix code is the main code path
|
||||
// JIT compiler will place a jump to v1 or v2 soft AES code here if needed
|
||||
DECL(randomx_riscv64_vector_program_main_loop_fe_mix):
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
|
||||
// f0 = aesenc(f0, e0), f1 = aesdec(f1, e0), f2 = aesenc(f2, e0), f3 = aesdec(f3, e0)
|
||||
vaesem.vv v0, v4
|
||||
vaesdm.vv v1, v15
|
||||
vaesem.vv v2, v4
|
||||
vaesdm.vv v3, v15
|
||||
vxor.vv v1, v1, v4
|
||||
vxor.vv v3, v3, v4
|
||||
|
||||
// f0 = aesenc(f0, e1), f1 = aesdec(f1, e1), f2 = aesenc(f2, e1), f3 = aesdec(f3, e1)
|
||||
vaesem.vv v0, v5
|
||||
vaesdm.vv v1, v15
|
||||
vaesem.vv v2, v5
|
||||
vaesdm.vv v3, v15
|
||||
vxor.vv v1, v1, v5
|
||||
vxor.vv v2, v2, v6
|
||||
vxor.vv v3, v3, v5
|
||||
|
||||
// f0 = aesenc(f0, e2), f1 = aesdec(f1, e2), f2 = aesenc(f2, e2), f3 = aesdec(f3, e2)
|
||||
vaesem.vv v0, v6
|
||||
vaesdm.vv v1, v15
|
||||
vaesem.vv v2, v6
|
||||
vaesdm.vv v3, v15
|
||||
vxor.vv v1, v1, v6
|
||||
vxor.vv v3, v3, v6
|
||||
|
||||
// f0 = aesenc(f0, e3), f1 = aesdec(f1, e3), f2 = aesenc(f2, e3), f3 = aesdec(f3, e3)
|
||||
vaesem.vv v0, v7
|
||||
vaesdm.vv v1, v15
|
||||
vaesem.vv v2, v7
|
||||
vaesdm.vv v3, v15
|
||||
vxor.vv v1, v1, v7
|
||||
vxor.vv v3, v3, v7
|
||||
|
||||
vsetivli zero, 2, e64, m1, ta, ma
|
||||
|
||||
randomx_riscv64_vector_program_main_loop_fe_store:
|
||||
vse64.v v0, (x5)
|
||||
|
||||
addi x6, x5, 16
|
||||
@@ -767,6 +877,7 @@ DECL(randomx_riscv64_vector_program_main_loop_instructions_end_light_mode):
|
||||
DECL(randomx_riscv64_vector_program_main_loop_mx_xor_light_mode):
|
||||
xor x5, x24, x26 // x5 = readReg2 ^ readReg3 (JIT compiler will substitute the actual registers)
|
||||
and x5, x5, x19 // x5 = (readReg2 ^ readReg3) & dataset mask
|
||||
slli x5, x5, 32 // JIT compiler will replace it with "nop" for v1
|
||||
xor x14, x14, x5 // mx ^= (readReg2 ^ readReg3) & dataset mask
|
||||
|
||||
// Save all registers modified when calling dataset_init_scalar_func_ptr
|
||||
@@ -847,27 +958,132 @@ DECL(randomx_riscv64_vector_program_main_loop_mx_xor_light_mode):
|
||||
|
||||
addi sp, sp, 192
|
||||
|
||||
j randomx_riscv64_vector_program_main_loop_swap_mx_ma
|
||||
j randomx_riscv64_vector_program_scratchpad_prefetch
|
||||
|
||||
DECL(randomx_riscv64_vector_program_scratchpad_prefetch):
|
||||
xor x5, x20, x22 // spAddr0-spAddr1 = readReg0 ^ readReg1 (JIT compiler will substitute the actual registers)
|
||||
srli x6, x5, 32 // x6 = spAddr1
|
||||
DECL(randomx_riscv64_vector_program_main_loop_fe_mix_v1):
|
||||
vxor.vv v0, v0, v4
|
||||
vxor.vv v1, v1, v5
|
||||
vxor.vv v2, v2, v6
|
||||
vxor.vv v3, v3, v7
|
||||
j randomx_riscv64_vector_program_main_loop_fe_store
|
||||
|
||||
and x5, x5, x9 // x5 = spAddr0 & 64-byte aligned L3 mask
|
||||
and x6, x6, x9 // x6 = spAddr1 & 64-byte aligned L3 mask
|
||||
/*
|
||||
aesenc middle round
|
||||
|
||||
c.add x5, x12 // x5 = &scratchpad[spAddr0 & 64-byte aligned L3 mask]
|
||||
c.add x6, x12 // x6 = &scratchpad[spAddr1 & 64-byte aligned L3 mask]
|
||||
x5 = pointer to aesenc LUT
|
||||
v16 = input and return value
|
||||
*/
|
||||
.macro aesenc_soft input, key
|
||||
vsetivli zero, 16, e8, m1, ta, ma
|
||||
|
||||
#ifdef __riscv_zicbop
|
||||
prefetch.r (x5)
|
||||
prefetch.r (x6)
|
||||
#else
|
||||
vrgather.vv v28, \input, v20
|
||||
vrgather.vv v29, \input, v21
|
||||
vrgather.vv v30, \input, v22
|
||||
vrgather.vv v31, \input, v23
|
||||
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
|
||||
vsll.vi v28, v28, 2
|
||||
vsll.vi v29, v29, 2
|
||||
vsll.vi v30, v30, 2
|
||||
vsll.vi v31, v31, 2
|
||||
|
||||
addi x6, x5, -2048
|
||||
vluxei32.v v28, (x6), v28
|
||||
|
||||
addi x6, x5, -1024
|
||||
vluxei32.v v29, (x6), v29
|
||||
|
||||
vluxei32.v v30, (x5), v30
|
||||
|
||||
addi x6, x5, 1024
|
||||
vluxei32.v v31, (x6), v31
|
||||
|
||||
vxor.vv v28, v28, v29
|
||||
vxor.vv v30, v30, v31
|
||||
vxor.vv \input, v28, v30
|
||||
vxor.vv \input, \input, \key
|
||||
.endm
|
||||
|
||||
/*
|
||||
aesdec middle round
|
||||
|
||||
x5 = pointer to aesdec LUT
|
||||
v16 = input and return value
|
||||
*/
|
||||
.macro aesdec_soft input, key
|
||||
vsetivli zero, 16, e8, m1, ta, ma
|
||||
|
||||
vrgather.vv v28, \input, v24
|
||||
vrgather.vv v29, \input, v25
|
||||
vrgather.vv v30, \input, v26
|
||||
vrgather.vv v31, \input, v27
|
||||
|
||||
vsetivli zero, 4, e32, m1, ta, ma
|
||||
|
||||
vsll.vi v28, v28, 2
|
||||
vsll.vi v29, v29, 2
|
||||
vsll.vi v30, v30, 2
|
||||
vsll.vi v31, v31, 2
|
||||
|
||||
addi x6, x5, -2048
|
||||
vluxei32.v v28, (x6), v28
|
||||
|
||||
addi x6, x5, -1024
|
||||
vluxei32.v v29, (x6), v29
|
||||
|
||||
vluxei32.v v30, (x5), v30
|
||||
|
||||
addi x6, x5, 1024
|
||||
vluxei32.v v31, (x6), v31
|
||||
|
||||
vxor.vv v28, v28, v29
|
||||
vxor.vv v30, v30, v31
|
||||
vxor.vv \input, v28, v30
|
||||
vxor.vv \input, \input, \key
|
||||
.endm
|
||||
|
||||
DECL(randomx_riscv64_vector_program_main_loop_fe_mix_v2_soft_aes):
|
||||
// save x5
|
||||
vmv.s.x v16, x5
|
||||
|
||||
lla x5, randomx_aes_lut_enc_ptr
|
||||
ld x5, (x5)
|
||||
ld x6, (x6)
|
||||
#endif
|
||||
|
||||
DECL(randomx_riscv64_vector_program_scratchpad_prefetch_end):
|
||||
// f0 = aesenc(f0, e0), f0 = aesenc(f0, e1), f0 = aesenc(f0, e2), f0 = aesenc(f0, e3)
|
||||
aesenc_soft v0, v4
|
||||
aesenc_soft v0, v5
|
||||
aesenc_soft v0, v6
|
||||
aesenc_soft v0, v7
|
||||
|
||||
// f2 = aesenc(f2, e0), f2 = aesenc(f2, e1), f2 = aesenc(f2, e2), f2 = aesenc(f2, e3)
|
||||
aesenc_soft v2, v4
|
||||
aesenc_soft v2, v5
|
||||
aesenc_soft v2, v6
|
||||
aesenc_soft v2, v7
|
||||
|
||||
lla x5, randomx_aes_lut_dec_ptr
|
||||
ld x5, (x5)
|
||||
|
||||
// f1 = aesdec(f1, e0), f1 = aesdec(f1, e1), f1 = aesdec(f1, e2), f1 = aesdec(f1, e3)
|
||||
aesdec_soft v1, v4
|
||||
aesdec_soft v1, v5
|
||||
aesdec_soft v1, v6
|
||||
aesdec_soft v1, v7
|
||||
|
||||
// f3 = aesdec(f3, e0), f3 = aesdec(f3, e1), f3 = aesdec(f3, e2), f3 = aesdec(f3, e3)
|
||||
aesdec_soft v3, v4
|
||||
aesdec_soft v3, v5
|
||||
aesdec_soft v3, v6
|
||||
aesdec_soft v3, v7
|
||||
|
||||
// Set vector registers back to 2x64 bit
|
||||
vsetivli zero, 2, e64, m1, ta, ma
|
||||
|
||||
// restore x5
|
||||
vmv.x.s x5, v16
|
||||
|
||||
j randomx_riscv64_vector_program_main_loop_fe_store
|
||||
|
||||
DECL(randomx_riscv64_vector_program_end):
|
||||
|
||||
|
||||
@@ -57,16 +57,21 @@ void randomx_riscv64_vector_sshash_end();
|
||||
void randomx_riscv64_vector_program_params();
|
||||
void randomx_riscv64_vector_program_imul_rcp_literals();
|
||||
void randomx_riscv64_vector_program_begin();
|
||||
void randomx_riscv64_vector_program_v2_soft_aes_init();
|
||||
void randomx_riscv64_vector_program_main_loop();
|
||||
void randomx_riscv64_vector_program_main_loop_instructions();
|
||||
void randomx_riscv64_vector_program_main_loop_instructions_end();
|
||||
void randomx_riscv64_vector_program_main_loop_mx_xor();
|
||||
void randomx_riscv64_vector_program_main_loop_spaddr_xor();
|
||||
void randomx_riscv64_vector_program_main_loop_fe_mix();
|
||||
void randomx_riscv64_vector_program_main_loop_light_mode_data();
|
||||
void randomx_riscv64_vector_program_main_loop_instructions_end_light_mode();
|
||||
void randomx_riscv64_vector_program_main_loop_mx_xor_light_mode();
|
||||
void randomx_riscv64_vector_program_end();
|
||||
void randomx_riscv64_vector_program_scratchpad_prefetch();
|
||||
void randomx_riscv64_vector_program_scratchpad_prefetch_end();
|
||||
|
||||
void randomx_riscv64_vector_program_main_loop_fe_mix_v1();
|
||||
void randomx_riscv64_vector_program_main_loop_fe_mix_v2_soft_aes();
|
||||
|
||||
void randomx_riscv64_vector_code_end();
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "crypto/randomx/reciprocal.h"
|
||||
#include "crypto/randomx/superscalar.hpp"
|
||||
#include "crypto/randomx/virtual_memory.hpp"
|
||||
#include "crypto/randomx/soft_aes.h"
|
||||
#include "crypto/rx/Profiler.h"
|
||||
|
||||
#ifdef XMRIG_FIX_RYZEN
|
||||
@@ -116,6 +117,7 @@ namespace randomx {
|
||||
#define codeLoopLoadXOP ADDR(randomx_program_loop_load_xop)
|
||||
#define codeProgramStart ADDR(randomx_program_start)
|
||||
#define codeReadDataset ADDR(randomx_program_read_dataset)
|
||||
#define codeReadDatasetV2 ADDR(randomx_program_read_dataset_v2)
|
||||
#define codeReadDatasetLightSshInit ADDR(randomx_program_read_dataset_sshash_init)
|
||||
#define codeReadDatasetLightSshFin ADDR(randomx_program_read_dataset_sshash_fin)
|
||||
#define codeDatasetInit ADDR(randomx_dataset_init)
|
||||
@@ -125,6 +127,8 @@ namespace randomx {
|
||||
#define codeDatasetInitAVX2SshLoad ADDR(randomx_dataset_init_avx2_ssh_load)
|
||||
#define codeDatasetInitAVX2SshPrefetch ADDR(randomx_dataset_init_avx2_ssh_prefetch)
|
||||
#define codeLoopStore ADDR(randomx_program_loop_store)
|
||||
#define codeLoopStoreHardAES ADDR(randomx_program_loop_store_hard_aes)
|
||||
#define codeLoopStoreSoftAES ADDR(randomx_program_loop_store_soft_aes)
|
||||
#define codeLoopEnd ADDR(randomx_program_loop_end)
|
||||
#define codeEpilogue ADDR(randomx_program_epilogue)
|
||||
#define codeProgramEnd ADDR(randomx_program_end)
|
||||
@@ -136,10 +140,13 @@ namespace randomx {
|
||||
#define prologueSize (codeLoopBegin - codePrologue)
|
||||
#define loopLoadSize (codeLoopLoadXOP - codeLoopLoad)
|
||||
#define loopLoadXOPSize (codeProgramStart - codeLoopLoadXOP)
|
||||
#define readDatasetSize (codeReadDatasetLightSshInit - codeReadDataset)
|
||||
#define readDatasetSize (codeReadDatasetV2 - codeReadDataset)
|
||||
#define readDatasetV2Size (codeReadDatasetLightSshInit - codeReadDatasetV2)
|
||||
#define readDatasetLightInitSize (codeReadDatasetLightSshFin - codeReadDatasetLightSshInit)
|
||||
#define readDatasetLightFinSize (codeLoopStore - codeReadDatasetLightSshFin)
|
||||
#define loopStoreSize (codeLoopEnd - codeLoopStore)
|
||||
#define loopStoreSize (codeLoopStoreHardAES - codeLoopStore)
|
||||
#define loopStoreHardAESSize (codeLoopStoreSoftAES - codeLoopStoreHardAES)
|
||||
#define loopStoreSoftAESSize (codeLoopEnd - codeLoopStoreSoftAES)
|
||||
#define datasetInitSize (codeDatasetInitAVX2Prologue - codeDatasetInit)
|
||||
#define datasetInitAVX2PrologueSize (codeDatasetInitAVX2LoopEnd - codeDatasetInitAVX2Prologue)
|
||||
#define datasetInitAVX2LoopEndSize (codeDatasetInitAVX2Epilogue - codeDatasetInitAVX2LoopEnd)
|
||||
@@ -223,6 +230,8 @@ namespace randomx {
|
||||
JitCompilerX86::JitCompilerX86(bool hugePagesEnable, bool optimizedInitDatasetEnable) {
|
||||
BranchesWithin32B = xmrig::Cpu::info()->jccErratum();
|
||||
|
||||
hasAES = xmrig::Cpu::info()->hasAES();
|
||||
|
||||
hasAVX = xmrig::Cpu::info()->hasAVX();
|
||||
hasAVX2 = xmrig::Cpu::info()->hasAVX2();
|
||||
|
||||
@@ -341,7 +350,14 @@ namespace randomx {
|
||||
vm_flags = flags;
|
||||
|
||||
generateProgramPrologue(prog, pcfg);
|
||||
emit(codeReadDataset, readDatasetSize, code, codePos);
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_PREFETCH) {
|
||||
emit(codeReadDatasetV2, readDatasetV2Size, code, codePos);
|
||||
}
|
||||
else {
|
||||
emit(codeReadDataset, readDatasetSize, code, codePos);
|
||||
}
|
||||
|
||||
generateProgramEpilogue(prog, pcfg);
|
||||
}
|
||||
|
||||
@@ -424,8 +440,15 @@ namespace randomx {
|
||||
|
||||
void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) {
|
||||
codePos = ADDR(randomx_program_prologue_first_load) - ADDR(randomx_program_prologue);
|
||||
*(uint32_t*)(code + codePos + 4) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
|
||||
*(uint32_t*)(code + codePos + 14) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES && !hasAES) {
|
||||
*(uint64_t*)(code + codePos + 9) = reinterpret_cast<uint64_t>(lutEnc);
|
||||
*(uint64_t*)(code + codePos + 27) = reinterpret_cast<uint64_t>(lutDec);
|
||||
}
|
||||
|
||||
*(uint32_t*)(code + codePos + 47) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
|
||||
*(uint32_t*)(code + codePos + 57) = RandomX_CurrentConfig.ScratchpadL3Mask64_Calculated;
|
||||
|
||||
if (hasAVX) {
|
||||
uint32_t* p = (uint32_t*)(code + codePos + 61);
|
||||
*p = (*p & 0xFF000000U) | 0x0077F8C5U; // vzeroupper
|
||||
@@ -476,8 +499,21 @@ namespace randomx {
|
||||
*(uint64_t*)(code + codePos) = 0xc03349c08b49ull + (static_cast<uint64_t>(pcfg.readReg0) << 16) + (static_cast<uint64_t>(pcfg.readReg1) << 40);
|
||||
codePos += 6;
|
||||
emit(RandomX_CurrentConfig.codePrefetchScratchpadTweaked, RandomX_CurrentConfig.codePrefetchScratchpadTweakedSize, code, codePos);
|
||||
memcpy(code + codePos, codeLoopStore, loopStoreSize);
|
||||
codePos += loopStoreSize;
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_AES) {
|
||||
if (hasAES) {
|
||||
memcpy(code + codePos, codeLoopStoreHardAES, loopStoreHardAESSize);
|
||||
codePos += loopStoreHardAESSize;
|
||||
}
|
||||
else {
|
||||
memcpy(code + codePos, codeLoopStoreSoftAES, loopStoreSoftAESSize);
|
||||
codePos += loopStoreSoftAESSize;
|
||||
}
|
||||
}
|
||||
else {
|
||||
memcpy(code + codePos, codeLoopStore, loopStoreSize);
|
||||
codePos += loopStoreSize;
|
||||
}
|
||||
|
||||
if (BranchesWithin32B) {
|
||||
const uint32_t branch_begin = static_cast<uint32_t>(codePos);
|
||||
@@ -1307,7 +1343,7 @@ namespace randomx {
|
||||
uint8_t* const p = code;
|
||||
int32_t t = prevCFROUND;
|
||||
|
||||
if (t > prevFPOperation) {
|
||||
if ((t > prevFPOperation) && !RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
if (vm_flags & RANDOMX_FLAG_AMD) {
|
||||
memcpy(p + t, NOP26, 26);
|
||||
}
|
||||
@@ -1326,14 +1362,38 @@ namespace randomx {
|
||||
*(uint32_t*)(p + pos + 3) = 0x00C8C148 + (rotate << 24);
|
||||
|
||||
if (vm_flags & RANDOMX_FLAG_AMD) {
|
||||
*(uint64_t*)(p + pos + 7) = 0x742024443B0CE083ULL;
|
||||
*(uint64_t*)(p + pos + 15) = 0x8900EB0414AE0F0AULL;
|
||||
*(uint32_t*)(p + pos + 23) = 0x202444;
|
||||
pos += 26;
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
*(uint32_t*)(p + pos + 7) = 0x1375F0A8;
|
||||
pos += 11;
|
||||
}
|
||||
else {
|
||||
pos += 7;
|
||||
}
|
||||
*(uint64_t*)(p + pos) = 0x742024443B0CE083ULL;
|
||||
*(uint64_t*)(p + pos + 8) = 0x8900EB0414AE0F0AULL;
|
||||
*(uint32_t*)(p + pos + 16) = 0x202444;
|
||||
pos += 19;
|
||||
}
|
||||
else {
|
||||
*(uint64_t*)(p + pos + 7) = 0x0414AE0F0CE083ULL;
|
||||
pos += 14;
|
||||
pos += 7;
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
if (BranchesWithin32B) {
|
||||
const uint32_t branch_begin = pos & 31;
|
||||
|
||||
// If the jump crosses or touches 32-byte boundary, align it
|
||||
if (branch_begin >= 28) {
|
||||
const uint32_t alignment_size = 32 - branch_begin;
|
||||
emit(NOPX[alignment_size - 1], alignment_size, code, pos);
|
||||
}
|
||||
}
|
||||
|
||||
*(uint32_t*)(p + pos) = 0x0775F0A8;
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
*(uint64_t*)(p + pos) = 0x0414AE0F0CE083ULL;
|
||||
pos += 7;
|
||||
}
|
||||
|
||||
codePos = pos;
|
||||
@@ -1343,7 +1403,7 @@ namespace randomx {
|
||||
uint8_t* const p = code;
|
||||
int32_t t = prevCFROUND;
|
||||
|
||||
if (t > prevFPOperation) {
|
||||
if ((t > prevFPOperation) && !RandomX_CurrentConfig.Tweak_V2_CFROUND){
|
||||
if (vm_flags & RANDOMX_FLAG_AMD) {
|
||||
memcpy(p + t, NOP25, 25);
|
||||
}
|
||||
@@ -1361,14 +1421,38 @@ namespace randomx {
|
||||
*(uint64_t*)(p + pos) = 0xC0F0FBC3C4ULL | (src << 32) | (rotate << 40);
|
||||
|
||||
if (vm_flags & RANDOMX_FLAG_AMD) {
|
||||
*(uint64_t*)(p + pos + 6) = 0x742024443B0CE083ULL;
|
||||
*(uint64_t*)(p + pos + 14) = 0x8900EB0414AE0F0AULL;
|
||||
*(uint32_t*)(p + pos + 22) = 0x202444;
|
||||
pos += 25;
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
*(uint32_t*)(p + pos + 6) = 0x1375F0A8;
|
||||
pos += 10;
|
||||
}
|
||||
else {
|
||||
pos += 6;
|
||||
}
|
||||
*(uint64_t*)(p + pos) = 0x742024443B0CE083ULL;
|
||||
*(uint64_t*)(p + pos + 8) = 0x8900EB0414AE0F0AULL;
|
||||
*(uint32_t*)(p + pos + 16) = 0x202444;
|
||||
pos += 19;
|
||||
}
|
||||
else {
|
||||
*(uint64_t*)(p + pos + 6) = 0x0414AE0F0CE083ULL;
|
||||
pos += 13;
|
||||
pos += 6;
|
||||
|
||||
if (RandomX_CurrentConfig.Tweak_V2_CFROUND) {
|
||||
if (BranchesWithin32B) {
|
||||
const uint32_t branch_begin = pos & 31;
|
||||
|
||||
// If the jump crosses or touches 32-byte boundary, align it
|
||||
if (branch_begin >= 28) {
|
||||
const uint32_t alignment_size = 32 - branch_begin;
|
||||
emit(NOPX[alignment_size - 1], alignment_size, code, pos);
|
||||
}
|
||||
}
|
||||
|
||||
*(uint32_t*)(p + pos) = 0x0775F0A8;
|
||||
pos += 4;
|
||||
}
|
||||
|
||||
*(uint64_t*)(p + pos) = 0x0414AE0F0CE083ULL;
|
||||
pos += 7;
|
||||
}
|
||||
|
||||
codePos = pos;
|
||||
|
||||
@@ -97,6 +97,7 @@ namespace randomx {
|
||||
# endif
|
||||
|
||||
bool BranchesWithin32B = false;
|
||||
bool hasAES;
|
||||
bool hasAVX;
|
||||
bool hasAVX2;
|
||||
bool initDatasetAVX2;
|
||||
|
||||
@@ -48,9 +48,12 @@
|
||||
.global DECL(randomx_program_loop_load_xop)
|
||||
.global DECL(randomx_program_start)
|
||||
.global DECL(randomx_program_read_dataset)
|
||||
.global DECL(randomx_program_read_dataset_v2)
|
||||
.global DECL(randomx_program_read_dataset_sshash_init)
|
||||
.global DECL(randomx_program_read_dataset_sshash_fin)
|
||||
.global DECL(randomx_program_loop_store)
|
||||
.global DECL(randomx_program_loop_store_hard_aes)
|
||||
.global DECL(randomx_program_loop_store_soft_aes)
|
||||
.global DECL(randomx_program_loop_end)
|
||||
.global DECL(randomx_dataset_init)
|
||||
.global DECL(randomx_dataset_init_avx2_prologue)
|
||||
@@ -101,19 +104,23 @@ DECL(randomx_program_prologue):
|
||||
movapd xmm15, xmmword ptr [scaleMask+rip]
|
||||
|
||||
DECL(randomx_program_prologue_first_load):
|
||||
sub rsp, 248
|
||||
mov rdx, 0x1111111111111111
|
||||
mov [rsp+232], rdx ;# aes_lut_enc
|
||||
mov rdx, 0x1111111111111111
|
||||
mov [rsp+240], rdx ;# aes_lut_dec
|
||||
mov rdx, rax
|
||||
and eax, RANDOMX_SCRATCHPAD_MASK
|
||||
ror rdx, 32
|
||||
and edx, RANDOMX_SCRATCHPAD_MASK
|
||||
sub rsp, 40
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov dword ptr [rsp], 0x9FC0
|
||||
mov dword ptr [rsp+4], 0xBFC0
|
||||
mov dword ptr [rsp+8], 0xDFC0
|
||||
mov dword ptr [rsp+12], 0xFFC0
|
||||
mov dword ptr [rsp+32], -1
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jmp DECL(randomx_program_imul_rcp_store)
|
||||
|
||||
.balign 64
|
||||
@@ -139,6 +146,9 @@ DECL(randomx_program_start):
|
||||
DECL(randomx_program_read_dataset):
|
||||
#include "asm/program_read_dataset.inc"
|
||||
|
||||
DECL(randomx_program_read_dataset_v2):
|
||||
#include "asm/program_read_dataset_v2.inc"
|
||||
|
||||
DECL(randomx_program_read_dataset_sshash_init):
|
||||
#include "asm/program_read_dataset_sshash_init.inc"
|
||||
|
||||
@@ -148,6 +158,12 @@ DECL(randomx_program_read_dataset_sshash_fin):
|
||||
DECL(randomx_program_loop_store):
|
||||
#include "asm/program_loop_store.inc"
|
||||
|
||||
DECL(randomx_program_loop_store_hard_aes):
|
||||
#include "asm/program_loop_store_hard_aes.inc"
|
||||
|
||||
DECL(randomx_program_loop_store_soft_aes):
|
||||
#include "asm/program_loop_store_soft_aes.inc"
|
||||
|
||||
DECL(randomx_program_loop_end):
|
||||
nop
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ PUBLIC randomx_program_loop_load
|
||||
PUBLIC randomx_program_loop_load_xop
|
||||
PUBLIC randomx_program_start
|
||||
PUBLIC randomx_program_read_dataset
|
||||
PUBLIC randomx_program_read_dataset_v2
|
||||
PUBLIC randomx_program_read_dataset_sshash_init
|
||||
PUBLIC randomx_program_read_dataset_sshash_fin
|
||||
PUBLIC randomx_dataset_init
|
||||
@@ -48,6 +49,8 @@ PUBLIC randomx_dataset_init_avx2_epilogue
|
||||
PUBLIC randomx_dataset_init_avx2_ssh_load
|
||||
PUBLIC randomx_dataset_init_avx2_ssh_prefetch
|
||||
PUBLIC randomx_program_loop_store
|
||||
PUBLIC randomx_program_loop_store_hard_aes
|
||||
PUBLIC randomx_program_loop_store_soft_aes
|
||||
PUBLIC randomx_program_loop_end
|
||||
PUBLIC randomx_program_epilogue
|
||||
PUBLIC randomx_sshash_load
|
||||
@@ -90,19 +93,23 @@ randomx_program_prologue PROC
|
||||
randomx_program_prologue ENDP
|
||||
|
||||
randomx_program_prologue_first_load PROC
|
||||
sub rsp, 248
|
||||
mov rdx, 01111111111111111h
|
||||
mov [rsp+232], rdx ;# aes_lut_enc
|
||||
mov rdx, 01111111111111111h
|
||||
mov [rsp+240], rdx ;# aes_lut_dec
|
||||
mov rdx, rax
|
||||
and eax, RANDOMX_SCRATCHPAD_MASK
|
||||
ror rdx, 32
|
||||
and edx, RANDOMX_SCRATCHPAD_MASK
|
||||
sub rsp, 40
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
mov dword ptr [rsp], 9FC0h
|
||||
mov dword ptr [rsp+4], 0BFC0h
|
||||
mov dword ptr [rsp+8], 0DFC0h
|
||||
mov dword ptr [rsp+12], 0FFC0h
|
||||
mov dword ptr [rsp+32], -1
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
jmp randomx_program_imul_rcp_store
|
||||
randomx_program_prologue_first_load ENDP
|
||||
|
||||
@@ -135,6 +142,10 @@ randomx_program_read_dataset PROC
|
||||
include asm/program_read_dataset.inc
|
||||
randomx_program_read_dataset ENDP
|
||||
|
||||
randomx_program_read_dataset_v2 PROC
|
||||
include asm/program_read_dataset_v2.inc
|
||||
randomx_program_read_dataset_v2 ENDP
|
||||
|
||||
randomx_program_read_dataset_sshash_init PROC
|
||||
include asm/program_read_dataset_sshash_init.inc
|
||||
randomx_program_read_dataset_sshash_init ENDP
|
||||
@@ -147,6 +158,14 @@ randomx_program_loop_store PROC
|
||||
include asm/program_loop_store.inc
|
||||
randomx_program_loop_store ENDP
|
||||
|
||||
randomx_program_loop_store_hard_aes PROC
|
||||
include asm/program_loop_store_hard_aes.inc
|
||||
randomx_program_loop_store_hard_aes ENDP
|
||||
|
||||
randomx_program_loop_store_soft_aes PROC
|
||||
include asm/program_loop_store_soft_aes.inc
|
||||
randomx_program_loop_store_soft_aes ENDP
|
||||
|
||||
randomx_program_loop_end PROC
|
||||
nop
|
||||
randomx_program_loop_end ENDP
|
||||
|
||||
@@ -40,9 +40,12 @@ extern "C" {
|
||||
void randomx_program_loop_load_xop();
|
||||
void randomx_program_start();
|
||||
void randomx_program_read_dataset();
|
||||
void randomx_program_read_dataset_v2();
|
||||
void randomx_program_read_dataset_sshash_init();
|
||||
void randomx_program_read_dataset_sshash_fin();
|
||||
void randomx_program_loop_store();
|
||||
void randomx_program_loop_store_hard_aes();
|
||||
void randomx_program_loop_store_soft_aes();
|
||||
void randomx_program_loop_end();
|
||||
void randomx_dataset_init();
|
||||
void randomx_dataset_init_avx2_prologue();
|
||||
|
||||
@@ -50,6 +50,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <cassert>
|
||||
|
||||
#include "crypto/rx/Profiler.h"
|
||||
#include "base/net/stratum/Job.h"
|
||||
|
||||
RandomX_ConfigurationMoneroV2::RandomX_ConfigurationMoneroV2()
|
||||
{
|
||||
ProgramSize = 384;
|
||||
|
||||
Tweak_V2_CFROUND = 1;
|
||||
Tweak_V2_AES = 1;
|
||||
Tweak_V2_PREFETCH = 1;
|
||||
Tweak_V2_COMMITMENT = 1;
|
||||
}
|
||||
|
||||
RandomX_ConfigurationWownero::RandomX_ConfigurationWownero()
|
||||
{
|
||||
@@ -150,6 +161,10 @@ RandomX_ConfigurationBase::RandomX_ConfigurationBase()
|
||||
, RANDOMX_FREQ_CFROUND(1)
|
||||
, RANDOMX_FREQ_ISTORE(16)
|
||||
, RANDOMX_FREQ_NOP(0)
|
||||
, Tweak_V2_CFROUND(0)
|
||||
, Tweak_V2_AES(0)
|
||||
, Tweak_V2_PREFETCH(0)
|
||||
, Tweak_V2_COMMITMENT(0)
|
||||
{
|
||||
fillAes4Rx4_Key[0] = rx_set_int_vec_i128(0x99e5d23f, 0x2f546d2b, 0xd1833ddb, 0x6421aadd);
|
||||
fillAes4Rx4_Key[1] = rx_set_int_vec_i128(0xa5dfcde5, 0x06f79d53, 0xb6913f55, 0xb20e3450);
|
||||
@@ -367,6 +382,7 @@ typedef void(randomx::JitCompilerX86::* InstructionGeneratorX86_2)(const randomx
|
||||
}
|
||||
|
||||
RandomX_ConfigurationMonero RandomX_MoneroConfig;
|
||||
RandomX_ConfigurationMoneroV2 RandomX_MoneroConfigV2;
|
||||
RandomX_ConfigurationWownero RandomX_WowneroConfig;
|
||||
RandomX_ConfigurationArqma RandomX_ArqmaConfig;
|
||||
RandomX_ConfigurationGraft RandomX_GraftConfig;
|
||||
@@ -614,4 +630,11 @@ extern "C" {
|
||||
machine->hashAndFill(output, tempHash);
|
||||
}
|
||||
|
||||
void randomx_calculate_commitment(const void* input, size_t inputSize, const void* hash_in, void* com_out) {
|
||||
uint8_t buf[xmrig::Job::kMaxBlobSize + RANDOMX_HASH_SIZE];
|
||||
memcpy(buf, input, inputSize);
|
||||
memcpy(buf + inputSize, hash_in, RANDOMX_HASH_SIZE);
|
||||
rx_blake2b_wrapper::run(com_out, RANDOMX_HASH_SIZE, buf, inputSize + RANDOMX_HASH_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,6 +125,11 @@ struct RandomX_ConfigurationBase
|
||||
|
||||
rx_vec_i128 fillAes4Rx4_Key[8];
|
||||
|
||||
uint32_t Tweak_V2_CFROUND : 1;
|
||||
uint32_t Tweak_V2_AES : 1;
|
||||
uint32_t Tweak_V2_PREFETCH : 1;
|
||||
uint32_t Tweak_V2_COMMITMENT : 1;
|
||||
|
||||
uint8_t codeSshPrefetchTweaked[20];
|
||||
uint8_t codePrefetchScratchpadTweaked[28];
|
||||
uint32_t codePrefetchScratchpadTweakedSize;
|
||||
@@ -143,6 +148,7 @@ struct RandomX_ConfigurationBase
|
||||
};
|
||||
|
||||
struct RandomX_ConfigurationMonero : public RandomX_ConfigurationBase {};
|
||||
struct RandomX_ConfigurationMoneroV2 : public RandomX_ConfigurationBase { RandomX_ConfigurationMoneroV2(); };
|
||||
struct RandomX_ConfigurationWownero : public RandomX_ConfigurationBase { RandomX_ConfigurationWownero(); };
|
||||
struct RandomX_ConfigurationArqma : public RandomX_ConfigurationBase { RandomX_ConfigurationArqma(); };
|
||||
struct RandomX_ConfigurationGraft : public RandomX_ConfigurationBase { RandomX_ConfigurationGraft(); };
|
||||
@@ -150,6 +156,7 @@ struct RandomX_ConfigurationSafex : public RandomX_ConfigurationBase { RandomX_C
|
||||
struct RandomX_ConfigurationYada : public RandomX_ConfigurationBase { RandomX_ConfigurationYada(); };
|
||||
|
||||
extern RandomX_ConfigurationMonero RandomX_MoneroConfig;
|
||||
extern RandomX_ConfigurationMoneroV2 RandomX_MoneroConfigV2;
|
||||
extern RandomX_ConfigurationWownero RandomX_WowneroConfig;
|
||||
extern RandomX_ConfigurationArqma RandomX_ArqmaConfig;
|
||||
extern RandomX_ConfigurationGraft RandomX_GraftConfig;
|
||||
@@ -231,7 +238,7 @@ RANDOMX_EXPORT unsigned long randomx_dataset_item_count(void);
|
||||
*
|
||||
* @param dataset is a pointer to a previously allocated randomx_dataset structure. Must not be NULL.
|
||||
* @param cache is a pointer to a previously allocated and initialized randomx_cache structure. Must not be NULL.
|
||||
* @param startItem is the item number where intialization should start.
|
||||
* @param startItem is the item number where initialization should start.
|
||||
* @param itemCount is the number of items that should be initialized.
|
||||
*/
|
||||
RANDOMX_EXPORT void randomx_init_dataset(randomx_dataset *dataset, randomx_cache *cache, unsigned long startItem, unsigned long itemCount);
|
||||
@@ -318,6 +325,17 @@ RANDOMX_EXPORT void randomx_calculate_hash(randomx_vm *machine, const void *inpu
|
||||
RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, uint64_t (&tempHash)[8], const void* input, size_t inputSize);
|
||||
RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, uint64_t (&tempHash)[8], const void* nextInput, size_t nextInputSize, void* output);
|
||||
|
||||
/**
|
||||
* Calculate a RandomX commitment from a RandomX hash and its input.
|
||||
*
|
||||
* @param input is a pointer to memory that was hashed. Must not be NULL.
|
||||
* @param inputSize is the number of bytes in the input.
|
||||
* @param hash_in is the output from randomx_calculate_hash* (RANDOMX_HASH_SIZE bytes).
|
||||
* @param com_out is a pointer to memory where the commitment will be stored. Must not
|
||||
* be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing.
|
||||
*/
|
||||
RANDOMX_EXPORT void randomx_calculate_commitment(const void* input, size_t inputSize, const void* hash_in, void* com_out);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -29,15 +29,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "crypto/randomx/soft_aes.h"
|
||||
|
||||
alignas(64) uint32_t lutEnc0[256];
|
||||
alignas(64) uint32_t lutEnc1[256];
|
||||
alignas(64) uint32_t lutEnc2[256];
|
||||
alignas(64) uint32_t lutEnc3[256];
|
||||
|
||||
alignas(64) uint32_t lutDec0[256];
|
||||
alignas(64) uint32_t lutDec1[256];
|
||||
alignas(64) uint32_t lutDec2[256];
|
||||
alignas(64) uint32_t lutDec3[256];
|
||||
alignas(64) uint32_t lutEnc[4][256];
|
||||
alignas(64) uint32_t lutDec[4][256];
|
||||
|
||||
alignas(64) uint8_t lutEncIndex[4][32];
|
||||
alignas(64) uint8_t lutDecIndex[4][32];
|
||||
@@ -102,10 +95,10 @@ static struct SAESInitializer
|
||||
p[2] = s;
|
||||
p[3] = mul_gf2(s, 3);
|
||||
|
||||
lutEnc0[i] = w; w = (w << 8) | (w >> 24);
|
||||
lutEnc1[i] = w; w = (w << 8) | (w >> 24);
|
||||
lutEnc2[i] = w; w = (w << 8) | (w >> 24);
|
||||
lutEnc3[i] = w;
|
||||
lutEnc[0][i] = w; w = (w << 8) | (w >> 24);
|
||||
lutEnc[1][i] = w; w = (w << 8) | (w >> 24);
|
||||
lutEnc[2][i] = w; w = (w << 8) | (w >> 24);
|
||||
lutEnc[3][i] = w;
|
||||
|
||||
s = sbox_reverse[i];
|
||||
p[0] = mul_gf2(s, 0xe);
|
||||
@@ -113,10 +106,10 @@ static struct SAESInitializer
|
||||
p[2] = mul_gf2(s, 0xd);
|
||||
p[3] = mul_gf2(s, 0xb);
|
||||
|
||||
lutDec0[i] = w; w = (w << 8) | (w >> 24);
|
||||
lutDec1[i] = w; w = (w << 8) | (w >> 24);
|
||||
lutDec2[i] = w; w = (w << 8) | (w >> 24);
|
||||
lutDec3[i] = w;
|
||||
lutDec[0][i] = w; w = (w << 8) | (w >> 24);
|
||||
lutDec[1][i] = w; w = (w << 8) | (w >> 24);
|
||||
lutDec[2][i] = w; w = (w << 8) | (w >> 24);
|
||||
lutDec[3][i] = w;
|
||||
}
|
||||
|
||||
memset(lutEncIndex, -1, sizeof(lutEncIndex));
|
||||
|
||||
@@ -32,14 +32,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <stdint.h>
|
||||
#include "crypto/randomx/intrin_portable.h"
|
||||
|
||||
extern uint32_t lutEnc0[256];
|
||||
extern uint32_t lutEnc1[256];
|
||||
extern uint32_t lutEnc2[256];
|
||||
extern uint32_t lutEnc3[256];
|
||||
extern uint32_t lutDec0[256];
|
||||
extern uint32_t lutDec1[256];
|
||||
extern uint32_t lutDec2[256];
|
||||
extern uint32_t lutDec3[256];
|
||||
extern uint32_t lutEnc[4][256];
|
||||
extern uint32_t lutDec[4][256];
|
||||
|
||||
extern uint8_t lutEncIndex[4][32];
|
||||
extern uint8_t lutDecIndex[4][32];
|
||||
@@ -52,25 +46,25 @@ FORCE_INLINE rx_vec_i128 aesenc<1>(rx_vec_i128 in, rx_vec_i128 key) {
|
||||
volatile uint8_t s[16];
|
||||
memcpy((void*) s, &in, 16);
|
||||
|
||||
uint32_t s0 = lutEnc0[s[ 0]];
|
||||
uint32_t s1 = lutEnc0[s[ 4]];
|
||||
uint32_t s2 = lutEnc0[s[ 8]];
|
||||
uint32_t s3 = lutEnc0[s[12]];
|
||||
uint32_t s0 = lutEnc[0][s[ 0]];
|
||||
uint32_t s1 = lutEnc[0][s[ 4]];
|
||||
uint32_t s2 = lutEnc[0][s[ 8]];
|
||||
uint32_t s3 = lutEnc[0][s[12]];
|
||||
|
||||
s0 ^= lutEnc1[s[ 5]];
|
||||
s1 ^= lutEnc1[s[ 9]];
|
||||
s2 ^= lutEnc1[s[13]];
|
||||
s3 ^= lutEnc1[s[ 1]];
|
||||
s0 ^= lutEnc[1][s[ 5]];
|
||||
s1 ^= lutEnc[1][s[ 9]];
|
||||
s2 ^= lutEnc[1][s[13]];
|
||||
s3 ^= lutEnc[1][s[ 1]];
|
||||
|
||||
s0 ^= lutEnc2[s[10]];
|
||||
s1 ^= lutEnc2[s[14]];
|
||||
s2 ^= lutEnc2[s[ 2]];
|
||||
s3 ^= lutEnc2[s[ 6]];
|
||||
s0 ^= lutEnc[2][s[10]];
|
||||
s1 ^= lutEnc[2][s[14]];
|
||||
s2 ^= lutEnc[2][s[ 2]];
|
||||
s3 ^= lutEnc[2][s[ 6]];
|
||||
|
||||
s0 ^= lutEnc3[s[15]];
|
||||
s1 ^= lutEnc3[s[ 3]];
|
||||
s2 ^= lutEnc3[s[ 7]];
|
||||
s3 ^= lutEnc3[s[11]];
|
||||
s0 ^= lutEnc[3][s[15]];
|
||||
s1 ^= lutEnc[3][s[ 3]];
|
||||
s2 ^= lutEnc[3][s[ 7]];
|
||||
s3 ^= lutEnc[3][s[11]];
|
||||
|
||||
return rx_xor_vec_i128(rx_set_int_vec_i128(s3, s2, s1, s0), key);
|
||||
}
|
||||
@@ -80,25 +74,25 @@ FORCE_INLINE rx_vec_i128 aesdec<1>(rx_vec_i128 in, rx_vec_i128 key) {
|
||||
volatile uint8_t s[16];
|
||||
memcpy((void*) s, &in, 16);
|
||||
|
||||
uint32_t s0 = lutDec0[s[ 0]];
|
||||
uint32_t s1 = lutDec0[s[ 4]];
|
||||
uint32_t s2 = lutDec0[s[ 8]];
|
||||
uint32_t s3 = lutDec0[s[12]];
|
||||
uint32_t s0 = lutDec[0][s[ 0]];
|
||||
uint32_t s1 = lutDec[0][s[ 4]];
|
||||
uint32_t s2 = lutDec[0][s[ 8]];
|
||||
uint32_t s3 = lutDec[0][s[12]];
|
||||
|
||||
s0 ^= lutDec1[s[13]];
|
||||
s1 ^= lutDec1[s[ 1]];
|
||||
s2 ^= lutDec1[s[ 5]];
|
||||
s3 ^= lutDec1[s[ 9]];
|
||||
s0 ^= lutDec[1][s[13]];
|
||||
s1 ^= lutDec[1][s[ 1]];
|
||||
s2 ^= lutDec[1][s[ 5]];
|
||||
s3 ^= lutDec[1][s[ 9]];
|
||||
|
||||
s0 ^= lutDec2[s[10]];
|
||||
s1 ^= lutDec2[s[14]];
|
||||
s2 ^= lutDec2[s[ 2]];
|
||||
s3 ^= lutDec2[s[ 6]];
|
||||
s0 ^= lutDec[2][s[10]];
|
||||
s1 ^= lutDec[2][s[14]];
|
||||
s2 ^= lutDec[2][s[ 2]];
|
||||
s3 ^= lutDec[2][s[ 6]];
|
||||
|
||||
s0 ^= lutDec3[s[ 7]];
|
||||
s1 ^= lutDec3[s[11]];
|
||||
s2 ^= lutDec3[s[15]];
|
||||
s3 ^= lutDec3[s[ 3]];
|
||||
s0 ^= lutDec[3][s[ 7]];
|
||||
s1 ^= lutDec[3][s[11]];
|
||||
s2 ^= lutDec[3][s[15]];
|
||||
s3 ^= lutDec[3][s[ 3]];
|
||||
|
||||
return rx_xor_vec_i128(rx_set_int_vec_i128(s3, s2, s1, s0), key);
|
||||
}
|
||||
@@ -113,10 +107,10 @@ FORCE_INLINE rx_vec_i128 aesenc<2>(rx_vec_i128 in, rx_vec_i128 key) {
|
||||
s3 = rx_vec_i128_x(in);
|
||||
|
||||
rx_vec_i128 out = rx_set_int_vec_i128(
|
||||
(lutEnc0[s0 & 0xff] ^ lutEnc1[(s3 >> 8) & 0xff] ^ lutEnc2[(s2 >> 16) & 0xff] ^ lutEnc3[s1 >> 24]),
|
||||
(lutEnc0[s1 & 0xff] ^ lutEnc1[(s0 >> 8) & 0xff] ^ lutEnc2[(s3 >> 16) & 0xff] ^ lutEnc3[s2 >> 24]),
|
||||
(lutEnc0[s2 & 0xff] ^ lutEnc1[(s1 >> 8) & 0xff] ^ lutEnc2[(s0 >> 16) & 0xff] ^ lutEnc3[s3 >> 24]),
|
||||
(lutEnc0[s3 & 0xff] ^ lutEnc1[(s2 >> 8) & 0xff] ^ lutEnc2[(s1 >> 16) & 0xff] ^ lutEnc3[s0 >> 24])
|
||||
(lutEnc[0][s0 & 0xff] ^ lutEnc[1][(s3 >> 8) & 0xff] ^ lutEnc[2][(s2 >> 16) & 0xff] ^ lutEnc[3][s1 >> 24]),
|
||||
(lutEnc[0][s1 & 0xff] ^ lutEnc[1][(s0 >> 8) & 0xff] ^ lutEnc[2][(s3 >> 16) & 0xff] ^ lutEnc[3][s2 >> 24]),
|
||||
(lutEnc[0][s2 & 0xff] ^ lutEnc[1][(s1 >> 8) & 0xff] ^ lutEnc[2][(s0 >> 16) & 0xff] ^ lutEnc[3][s3 >> 24]),
|
||||
(lutEnc[0][s3 & 0xff] ^ lutEnc[1][(s2 >> 8) & 0xff] ^ lutEnc[2][(s1 >> 16) & 0xff] ^ lutEnc[3][s0 >> 24])
|
||||
);
|
||||
|
||||
return rx_xor_vec_i128(out, key);
|
||||
@@ -132,10 +126,10 @@ FORCE_INLINE rx_vec_i128 aesdec<2>(rx_vec_i128 in, rx_vec_i128 key) {
|
||||
s3 = rx_vec_i128_x(in);
|
||||
|
||||
rx_vec_i128 out = rx_set_int_vec_i128(
|
||||
(lutDec0[s0 & 0xff] ^ lutDec1[(s1 >> 8) & 0xff] ^ lutDec2[(s2 >> 16) & 0xff] ^ lutDec3[s3 >> 24]),
|
||||
(lutDec0[s1 & 0xff] ^ lutDec1[(s2 >> 8) & 0xff] ^ lutDec2[(s3 >> 16) & 0xff] ^ lutDec3[s0 >> 24]),
|
||||
(lutDec0[s2 & 0xff] ^ lutDec1[(s3 >> 8) & 0xff] ^ lutDec2[(s0 >> 16) & 0xff] ^ lutDec3[s1 >> 24]),
|
||||
(lutDec0[s3 & 0xff] ^ lutDec1[(s0 >> 8) & 0xff] ^ lutDec2[(s1 >> 16) & 0xff] ^ lutDec3[s2 >> 24])
|
||||
(lutDec[0][s0 & 0xff] ^ lutDec[1][(s1 >> 8) & 0xff] ^ lutDec[2][(s2 >> 16) & 0xff] ^ lutDec[3][s3 >> 24]),
|
||||
(lutDec[0][s1 & 0xff] ^ lutDec[1][(s2 >> 8) & 0xff] ^ lutDec[2][(s3 >> 16) & 0xff] ^ lutDec[3][s0 >> 24]),
|
||||
(lutDec[0][s2 & 0xff] ^ lutDec[1][(s3 >> 8) & 0xff] ^ lutDec[2][(s0 >> 16) & 0xff] ^ lutDec[3][s1 >> 24]),
|
||||
(lutDec[0][s3 & 0xff] ^ lutDec[1][(s0 >> 8) & 0xff] ^ lutDec[2][(s1 >> 16) & 0xff] ^ lutDec[3][s2 >> 24])
|
||||
);
|
||||
|
||||
return rx_xor_vec_i128(out, key);
|
||||
|
||||
13
src/crypto/randomx/tests/riscv64_zvkb.s
Normal file
13
src/crypto/randomx/tests/riscv64_zvkb.s
Normal file
@@ -0,0 +1,13 @@
|
||||
/* RISC-V - test if the vector bit manipulation extension is present */
|
||||
|
||||
.text
|
||||
.option arch, rv64gcv_zvkb
|
||||
.global main
|
||||
|
||||
main:
|
||||
vsetivli zero, 8, e32, m1, ta, ma
|
||||
vror.vv v0, v0, v0
|
||||
vror.vx v0, v0, x5
|
||||
vror.vi v0, v0, 1
|
||||
li x10, 0
|
||||
ret
|
||||
12
src/crypto/randomx/tests/riscv64_zvkned.s
Normal file
12
src/crypto/randomx/tests/riscv64_zvkned.s
Normal file
@@ -0,0 +1,12 @@
|
||||
/* RISC-V - test if the vector bit manipulation extension is present */
|
||||
|
||||
.text
|
||||
.option arch, rv64gcv_zvkned
|
||||
.global main
|
||||
|
||||
main:
|
||||
vsetivli zero, 8, e32, m1, ta, ma
|
||||
vaesem.vv v0, v0
|
||||
vaesdm.vv v0, v0
|
||||
li x10, 0
|
||||
ret
|
||||
@@ -61,6 +61,17 @@ namespace randomx {
|
||||
# if defined(XMRIG_ARM) || defined(XMRIG_RISCV)
|
||||
memcpy(reg.f, config.eMask, sizeof(config.eMask));
|
||||
# endif
|
||||
|
||||
const uint8_t* p = mem.memory;
|
||||
|
||||
// dataset prefetch for the first iteration of the main loop
|
||||
rx_prefetch_nta(p + (mem.ma & (RandomX_ConfigurationBase::DatasetBaseSize - 64)));
|
||||
|
||||
// dataset prefetch for the second iteration of the main loop (RandomX v2)
|
||||
if (RandomX_CurrentConfig.Tweak_V2_PREFETCH) {
|
||||
rx_prefetch_nta(p + (mem.mx & (RandomX_ConfigurationBase::DatasetBaseSize - 64)));
|
||||
}
|
||||
|
||||
compiler.getProgramFunc()(reg, mem, scratchpad, RandomX_CurrentConfig.ProgramIterations);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,10 +77,13 @@ namespace randomx {
|
||||
|
||||
executeBytecode(bytecode, scratchpad, config);
|
||||
|
||||
mem.mx ^= nreg.r[config.readReg2] ^ nreg.r[config.readReg3];
|
||||
mem.mx &= CacheLineAlignMask;
|
||||
datasetPrefetch(datasetOffset + mem.mx);
|
||||
datasetRead(datasetOffset + mem.ma, nreg.r);
|
||||
const uint64_t readPtr = datasetOffset + (mem.ma & CacheLineAlignMask);
|
||||
|
||||
auto& mp = RandomX_CurrentConfig.Tweak_V2_PREFETCH ? mem.ma : mem.mx;
|
||||
mp ^= nreg.r[config.readReg2] ^ nreg.r[config.readReg3];
|
||||
|
||||
datasetPrefetch(datasetOffset + (mp & CacheLineAlignMask));
|
||||
datasetRead(readPtr, nreg.r);
|
||||
std::swap(mem.mx, mem.ma);
|
||||
|
||||
for (unsigned i = 0; i < RegistersCount; ++i)
|
||||
|
||||
@@ -32,6 +32,9 @@ xmrig::Algorithm::Id xmrig::RxAlgo::apply(Algorithm::Id algorithm)
|
||||
const RandomX_ConfigurationBase *xmrig::RxAlgo::base(Algorithm::Id algorithm)
|
||||
{
|
||||
switch (algorithm) {
|
||||
case Algorithm::RX_V2:
|
||||
return &RandomX_MoneroConfigV2;
|
||||
|
||||
case Algorithm::RX_WOW:
|
||||
return &RandomX_WowneroConfig;
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "crypto/rx/RxConfig.h"
|
||||
#include "crypto/randomx/randomx.h"
|
||||
#include "3rdparty/rapidjson/document.h"
|
||||
#include "backend/cpu/Cpu.h"
|
||||
#include "base/io/json/Json.h"
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <uv.h>
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -183,11 +185,20 @@ rapidjson::Value xmrig::RxConfig::toJSON(rapidjson::Document &doc) const
|
||||
#ifdef XMRIG_FEATURE_HWLOC
|
||||
std::vector<uint32_t> xmrig::RxConfig::nodeset() const
|
||||
{
|
||||
auto info = Cpu::info();
|
||||
|
||||
constexpr uint64_t dataset_mem = RandomX_ConfigurationBase::DatasetBaseSize + RandomX_ConfigurationBase::DatasetExtraSize;
|
||||
constexpr uint64_t cache_mem = RandomX_ConfigurationBase::ArgonMemory * 1024;
|
||||
const uint64_t threads_mem = info->threads() << 21;
|
||||
|
||||
const uint64_t freem_mem = uv_get_free_memory();
|
||||
|
||||
if (!m_nodeset.empty()) {
|
||||
return m_nodeset;
|
||||
return (freem_mem > m_nodeset.size() * dataset_mem + cache_mem + threads_mem) ? m_nodeset : std::vector<uint32_t>();
|
||||
}
|
||||
|
||||
return (m_numa && Cpu::info()->nodes() > 1) ? Cpu::info()->nodeset() : std::vector<uint32_t>();
|
||||
const uint64_t n = info->nodes();
|
||||
return (m_numa && (n > 1) && (freem_mem > n * dataset_mem + cache_mem + threads_mem)) ? Cpu::info()->nodeset() : std::vector<uint32_t>();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ public:
|
||||
inline RxSeed(const Algorithm &algorithm, const Buffer &seed) : m_algorithm(algorithm), m_data(seed) {}
|
||||
inline RxSeed(const Job &job) : m_algorithm(job.algorithm()), m_data(job.seed()) {}
|
||||
|
||||
inline bool isEqual(const Job &job) const { return m_algorithm == job.algorithm() && m_data == job.seed(); }
|
||||
inline bool isEqual(const RxSeed &other) const { return m_algorithm == other.m_algorithm && m_data == other.m_data; }
|
||||
inline bool isEqual(const Job &job) const { return isEqualSeedAlgo(job.algorithm()) && m_data == job.seed(); }
|
||||
inline bool isEqual(const RxSeed &other) const { return isEqualSeedAlgo(other.m_algorithm) && m_data == other.m_data; }
|
||||
inline const Algorithm &algorithm() const { return m_algorithm; }
|
||||
inline const Buffer &data() const { return m_data; }
|
||||
|
||||
@@ -60,6 +60,12 @@ public:
|
||||
private:
|
||||
Algorithm m_algorithm;
|
||||
Buffer m_data;
|
||||
|
||||
inline bool isEqualSeedAlgo(Algorithm other) const {
|
||||
return (m_algorithm == other) ||
|
||||
((m_algorithm == Algorithm::RX_0) && (other == Algorithm::RX_V2)) ||
|
||||
((m_algorithm == Algorithm::RX_V2) && (other == Algorithm::RX_0));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "base/tools/String.h"
|
||||
#include "base/net/stratum/Job.h"
|
||||
|
||||
#include "crypto/randomx/randomx.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
@@ -43,7 +45,7 @@ class JobResult
|
||||
public:
|
||||
JobResult() = delete;
|
||||
|
||||
inline JobResult(const Job &job, uint64_t nonce, const uint8_t *result, const uint8_t* header_hash = nullptr, const uint8_t *mix_hash = nullptr, const uint8_t* miner_signature = nullptr) :
|
||||
inline JobResult(const Job &job, uint64_t nonce, const uint8_t *result, const uint8_t* header_hash = nullptr, const uint8_t *mix_hash = nullptr, const uint8_t* extra_data = nullptr) :
|
||||
algorithm(job.algorithm()),
|
||||
index(job.index()),
|
||||
clientId(job.clientId()),
|
||||
@@ -62,9 +64,15 @@ public:
|
||||
memcpy(m_mixHash, mix_hash, sizeof(m_mixHash));
|
||||
}
|
||||
|
||||
if (miner_signature) {
|
||||
m_hasMinerSignature = true;
|
||||
memcpy(m_minerSignature, miner_signature, sizeof(m_minerSignature));
|
||||
if (extra_data) {
|
||||
if (algorithm == Algorithm::RX_V2) {
|
||||
m_hasCommitment = true;
|
||||
memcpy(m_extraData, extra_data, RANDOMX_HASH_SIZE);
|
||||
}
|
||||
else if (algorithm == Algorithm::RX_WOW) {
|
||||
m_hasMinerSignature = true;
|
||||
memcpy(m_extraData, extra_data, RANDOMX_HASH_SIZE * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +93,8 @@ public:
|
||||
inline const uint8_t *headerHash() const { return m_headerHash; }
|
||||
inline const uint8_t *mixHash() const { return m_mixHash; }
|
||||
|
||||
inline const uint8_t *minerSignature() const { return m_hasMinerSignature ? m_minerSignature : nullptr; }
|
||||
inline const uint8_t *minerSignature() const { return m_hasMinerSignature ? m_extraData : nullptr; }
|
||||
inline const uint8_t *commitment() const { return m_hasCommitment ? m_extraData : nullptr; }
|
||||
|
||||
const Algorithm algorithm;
|
||||
const uint8_t index;
|
||||
@@ -100,8 +109,10 @@ private:
|
||||
uint8_t m_headerHash[32] = { 0 };
|
||||
uint8_t m_mixHash[32] = { 0 };
|
||||
|
||||
uint8_t m_minerSignature[64] = { 0 };
|
||||
uint8_t m_extraData[RANDOMX_HASH_SIZE * 2] = { 0 };
|
||||
|
||||
bool m_hasMinerSignature = false;
|
||||
bool m_hasCommitment = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -339,9 +339,9 @@ void xmrig::JobResults::submit(const Job &job, uint32_t nonce, const uint8_t *re
|
||||
}
|
||||
|
||||
|
||||
void xmrig::JobResults::submit(const Job& job, uint32_t nonce, const uint8_t* result, const uint8_t* miner_signature)
|
||||
void xmrig::JobResults::submit(const Job& job, uint32_t nonce, const uint8_t* result, const uint8_t* extra_data)
|
||||
{
|
||||
submit(JobResult(job, nonce, result, nullptr, nullptr, miner_signature));
|
||||
submit(JobResult(job, nonce, result, nullptr, nullptr, extra_data));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
static void setListener(IJobResultListener *listener, bool hwAES);
|
||||
static void stop();
|
||||
static void submit(const Job &job, uint32_t nonce, const uint8_t *result);
|
||||
static void submit(const Job& job, uint32_t nonce, const uint8_t* result, const uint8_t* miner_signature);
|
||||
static void submit(const Job& job, uint32_t nonce, const uint8_t* result, const uint8_t* extra_data);
|
||||
static void submit(const JobResult &result);
|
||||
|
||||
# if defined(XMRIG_FEATURE_OPENCL) || defined(XMRIG_FEATURE_CUDA)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* XMRig
|
||||
* Copyright (c) 2018-2025 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2025 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
* Copyright (c) 2018-2026 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2016-2026 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
@@ -11,15 +11,15 @@
|
||||
#define APP_ID "xmrig"
|
||||
#define APP_NAME "XMRig"
|
||||
#define APP_DESC "XMRig miner"
|
||||
#define APP_VERSION "6.25.1-dev"
|
||||
#define APP_VERSION "6.26.0"
|
||||
#define APP_DOMAIN "xmrig.com"
|
||||
#define APP_SITE "www.xmrig.com"
|
||||
#define APP_COPYRIGHT "Copyright (C) 2016-2025 xmrig.com"
|
||||
#define APP_COPYRIGHT "Copyright (C) 2016-2026 xmrig.com"
|
||||
#define APP_KIND "miner"
|
||||
|
||||
#define APP_VER_MAJOR 6
|
||||
#define APP_VER_MINOR 25
|
||||
#define APP_VER_PATCH 1
|
||||
#define APP_VER_MINOR 26
|
||||
#define APP_VER_PATCH 0
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# if (_MSC_VER >= 1950)
|
||||
|
||||
Reference in New Issue
Block a user